summaryrefslogtreecommitdiff
path: root/src/shared
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2023-04-27 16:37:06 +0200
committerGitHub <noreply@github.com>2023-04-27 16:37:06 +0200
commita84e741b36ba0ad1e35b90d0f55753e825b848e8 (patch)
treeb616c1d13a1e472111b88ac391aa565aebfa54bd /src/shared
parent1a56b0c05dc14fa91f0de24f230d9b9f35cc5b05 (diff)
parent969f5f3cea437758a1c2bedcdba5eab33482159d (diff)
downloadsystemd-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.c3
-rw-r--r--src/shared/cgroup-setup.c76
-rw-r--r--src/shared/cgroup-setup.h1
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);