namespace-util: add process_is_owned_by_uid() helper
This commit is contained in:
@@ -95,10 +95,18 @@ assert_cc(MS_LAZYTIME == (1<<25));
|
||||
#endif
|
||||
|
||||
/* linux/nsfs.h */
|
||||
#ifndef NS_GET_NSTYPE /* d95fa3c76a66b6d76b1e109ea505c55e66360f3c (4.11) */
|
||||
#ifndef NS_GET_USERNS /* 6786741dbf99e44fb0c0ed85a37582b8a26f1c3b (4.9) */
|
||||
#define NS_GET_USERNS _IO(0xb7, 0x1)
|
||||
#endif
|
||||
|
||||
#ifndef NS_GET_NSTYPE /* e5ff5ce6e20ee22511398bb31fb912466cf82a36 (4.11) */
|
||||
#define NS_GET_NSTYPE _IO(0xb7, 0x3)
|
||||
#endif
|
||||
|
||||
#ifndef NS_GET_OWNER_UID /* d95fa3c76a66b6d76b1e109ea505c55e66360f3c (4.11) */
|
||||
#define NS_GET_OWNER_UID _IO(0xb7, 0x4)
|
||||
#endif
|
||||
|
||||
#ifndef FS_PROJINHERIT_FL
|
||||
# define FS_PROJINHERIT_FL 0x20000000
|
||||
#else
|
||||
|
||||
@@ -708,3 +708,58 @@ int userns_get_base_uid(int userns_fd, uid_t *ret_uid, gid_t *ret_gid) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int process_is_owned_by_uid(const PidRef *pidref, uid_t uid) {
|
||||
assert(uid_is_valid(uid));
|
||||
|
||||
int r;
|
||||
|
||||
/* Checks if the specified process either is owned directly by the specified user, or if it is inside
|
||||
* a user namespace owned by it. */
|
||||
|
||||
uid_t process_uid;
|
||||
r = pidref_get_uid(pidref, &process_uid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (process_uid == uid)
|
||||
return true;
|
||||
|
||||
_cleanup_close_ int userns_fd = -EBADF;
|
||||
userns_fd = pidref_namespace_open_by_type(pidref, NAMESPACE_USER);
|
||||
if (userns_fd == -ENOPKG) /* If userns is not supported, then they don't matter for ownership */
|
||||
return false;
|
||||
if (userns_fd < 0)
|
||||
return userns_fd;
|
||||
|
||||
for (unsigned iteration = 0;; iteration++) {
|
||||
uid_t ns_uid;
|
||||
|
||||
/* This process is in our own userns? Then we are done, in our own userns only the UIDs
|
||||
* themselves matter. */
|
||||
r = is_our_namespace(userns_fd, NAMESPACE_USER);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r > 0)
|
||||
return false;
|
||||
|
||||
if (ioctl(userns_fd, NS_GET_OWNER_UID, &ns_uid) < 0)
|
||||
return -errno;
|
||||
if (ns_uid == uid)
|
||||
return true;
|
||||
|
||||
/* Paranoia check */
|
||||
if (iteration > 16)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(ELOOP), "Giving up while tracing parents of user namespaces after %u steps.", iteration);
|
||||
|
||||
/* Go up the tree */
|
||||
_cleanup_close_ int parent_fd = ioctl(userns_fd, NS_GET_USERNS);
|
||||
if (parent_fd < 0) {
|
||||
if (errno == EPERM) /* EPERM means we left our own userns */
|
||||
return false;
|
||||
|
||||
return -errno;
|
||||
}
|
||||
|
||||
close_and_replace(userns_fd, parent_fd);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,3 +93,5 @@ int parse_userns_uid_range(const char *s, uid_t *ret_uid_shift, uid_t *ret_uid_r
|
||||
int is_idmapping_supported(const char *path);
|
||||
|
||||
int userns_get_base_uid(int userns_fd, uid_t *ret_uid, gid_t *ret_gid);
|
||||
|
||||
int process_is_owned_by_uid(const PidRef *pidref, uid_t uid);
|
||||
|
||||
Reference in New Issue
Block a user