diff options
author | Lennart Poettering <lennart@poettering.net> | 2023-04-27 16:37:06 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-27 16:37:06 +0200 |
commit | a84e741b36ba0ad1e35b90d0f55753e825b848e8 (patch) | |
tree | b616c1d13a1e472111b88ac391aa565aebfa54bd /src/shared | |
parent | 1a56b0c05dc14fa91f0de24f230d9b9f35cc5b05 (diff) | |
parent | 969f5f3cea437758a1c2bedcdba5eab33482159d (diff) | |
download | systemd-a84e741b36ba0ad1e35b90d0f55753e825b848e8.tar.gz |
Merge pull request #27376 from poettering/subcgroup
pid1: add DelegateSubgroup= option
Diffstat (limited to 'src/shared')
-rw-r--r-- | src/shared/bus-unit-util.c | 3 | ||||
-rw-r--r-- | src/shared/cgroup-setup.c | 76 | ||||
-rw-r--r-- | src/shared/cgroup-setup.h | 1 |
3 files changed, 79 insertions, 1 deletions
diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index ebbd1f7f28..a321179609 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -461,7 +461,8 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons "ManagedOOMSwap", "ManagedOOMMemoryPressure", "ManagedOOMPreference", - "MemoryPressureWatch")) + "MemoryPressureWatch", + "DelegateSubgroup")) return bus_append_string(m, field, eq); if (STR_IN_SET(field, "ManagedOOMMemoryPressureLimit")) { diff --git a/src/shared/cgroup-setup.c b/src/shared/cgroup-setup.c index 65be851014..6f3f9dd939 100644 --- a/src/shared/cgroup-setup.c +++ b/src/shared/cgroup-setup.c @@ -483,6 +483,82 @@ int cg_set_access( return 0; } +struct access_callback_data { + uid_t uid; + gid_t gid; + int error; +}; + +static int access_callback( + RecurseDirEvent event, + const char *path, + int dir_fd, + int inode_fd, + const struct dirent *de, + const struct statx *sx, + void *userdata) { + + struct access_callback_data *d = ASSERT_PTR(userdata); + + if (!IN_SET(event, RECURSE_DIR_ENTER, RECURSE_DIR_ENTRY)) + return RECURSE_DIR_CONTINUE; + + assert(inode_fd >= 0); + + /* fchown() doesn't support O_PATH fds, hence we use the /proc/self/fd/ trick */ + if (chown(FORMAT_PROC_FD_PATH(inode_fd), d->uid, d->gid) < 0) { + log_debug_errno(errno, "Failed to change ownership of '%s', ignoring: %m", ASSERT_PTR(path)); + + if (d->error == 0) /* Return last error to caller */ + d->error = errno; + } + + return RECURSE_DIR_CONTINUE; +} + +int cg_set_access_recursive( + const char *controller, + const char *path, + uid_t uid, + gid_t gid) { + + _cleanup_close_ int fd = -EBADF; + _cleanup_free_ char *fs = NULL; + int r; + + /* A recursive version of cg_set_access(). But note that this one changes ownership of *all* files, + * not just the allowlist that cg_set_access() uses. Use cg_set_access() on the cgroup you want to + * delegate, and cg_set_access_recursive() for any subcrgoups you might want to create below it. */ + + if (!uid_is_valid(uid) && !gid_is_valid(gid)) + return 0; + + r = cg_get_path(controller, path, NULL, &fs); + if (r < 0) + return r; + + fd = open(fs, O_DIRECTORY|O_CLOEXEC|O_RDONLY); + if (fd < 0) + return -errno; + + struct access_callback_data d = { + .uid = uid, + .gid = gid, + }; + + r = recurse_dir(fd, + fs, + /* statx_mask= */ 0, + /* n_depth_max= */ UINT_MAX, + RECURSE_DIR_SAME_MOUNT|RECURSE_DIR_INODE_FD|RECURSE_DIR_TOPLEVEL, + access_callback, + &d); + if (r < 0) + return r; + + return -d.error; +} + int cg_migrate( const char *cfrom, const char *pfrom, diff --git a/src/shared/cgroup-setup.h b/src/shared/cgroup-setup.h index 13f836bd90..1b6f0716c6 100644 --- a/src/shared/cgroup-setup.h +++ b/src/shared/cgroup-setup.h @@ -24,6 +24,7 @@ int cg_attach_fallback(const char *controller, const char *path, pid_t pid); int cg_create_and_attach(const char *controller, const char *path, pid_t pid); int cg_set_access(const char *controller, const char *path, uid_t uid, gid_t gid); +int cg_set_access_recursive(const char *controller, const char *path, uid_t uid, gid_t gid); int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, CGroupFlags flags); int cg_migrate_recursive(const char *cfrom, const char *pfrom, const char *cto, const char *pto, CGroupFlags flags); |