namespace-util: add process_is_owned_by_uid() helper

This commit is contained in:
Lennart Poettering
2025-01-07 23:55:34 +01:00
parent 3d57b6692f
commit 2ade821859
4 changed files with 155 additions and 1 deletions
+55
View File
@@ -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);
}
}