From fea72cc0336f4d90875cdddc1aa9739dcbb174f5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 3 Sep 2015 13:22:51 +0200 Subject: macro: introduce new PID_TO_PTR macros and make use of them This adds a new PID_TO_PTR() macro, plus PTR_TO_PID() and makes use of it wherever we maintain processes in a hash table. Previously we sometimes used LONG_TO_PTR() and other times ULONG_TO_PTR() for that, hence let's make this more explicit and clean up things. --- src/basic/cgroup-util.c | 10 +++++----- src/basic/macro.h | 3 +++ 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'src/basic') diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 0ebe570bb8..74e1668a17 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -187,7 +187,7 @@ int cg_kill(const char *controller, const char *path, int sig, bool sigcont, boo if (ignore_self && pid == my_pid) continue; - if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid)) + if (set_get(s, PID_TO_PTR(pid)) == PID_TO_PTR(pid)) continue; /* If we haven't killed this process yet, kill @@ -205,7 +205,7 @@ int cg_kill(const char *controller, const char *path, int sig, bool sigcont, boo done = false; - r = set_put(s, LONG_TO_PTR(pid)); + r = set_put(s, PID_TO_PTR(pid)); if (r < 0) { if (ret >= 0) return r; @@ -318,7 +318,7 @@ int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char if (ignore_self && pid == my_pid) continue; - if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid)) + if (set_get(s, PID_TO_PTR(pid)) == PID_TO_PTR(pid)) continue; /* Ignore kernel threads. Since they can only @@ -338,7 +338,7 @@ int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char done = false; - r = set_put(s, LONG_TO_PTR(pid)); + r = set_put(s, PID_TO_PTR(pid)); if (r < 0) { if (ret >= 0) return r; @@ -1898,7 +1898,7 @@ int cg_attach_many_everywhere(CGroupMask supported, const char *path, Set* pids, int r = 0; SET_FOREACH(pidp, pids, i) { - pid_t pid = PTR_TO_LONG(pidp); + pid_t pid = PTR_TO_PID(pidp); int q; q = cg_attach_everywhere(supported, path, pid, path_callback, userdata); diff --git a/src/basic/macro.h b/src/basic/macro.h index 627d768b76..cbc3ca97b8 100644 --- a/src/basic/macro.h +++ b/src/basic/macro.h @@ -298,6 +298,9 @@ static inline unsigned long ALIGN_POWER2(unsigned long u) { #define PTR_TO_GID(p) ((gid_t) (((uintptr_t) (p))-1)) #define GID_TO_PTR(u) ((void*) (((uintptr_t) (u))+1)) +#define PTR_TO_PID(p) ((pid_t) ((uintptr_t) p)) +#define PID_TO_PTR(p) ((void*) ((uintptr_t) p)) + #define memzero(x,l) (memset((x), 0, (l))) #define zero(x) (memzero(&(x), sizeof(x))) -- cgit v1.2.3-54-g00ecf From a1f686daf55636f9446a4c017f2488a35595395e Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 3 Sep 2015 13:29:53 +0200 Subject: util: add new uid_is_valid() call This simply factors out the uid validation checks from parse_uid() and uses them everywhere. This simply verifies that the passed UID is neither 64bit -1 nor 32bit -1. --- src/basic/util.c | 20 ++++++++++++++------ src/basic/util.h | 5 ++++- src/libsystemd/sd-login/sd-login.c | 5 +++++ 3 files changed, 23 insertions(+), 7 deletions(-) (limited to 'src/basic') diff --git a/src/basic/util.c b/src/basic/util.c index f01f5f237b..beec7cb7dd 100644 --- a/src/basic/util.c +++ b/src/basic/util.c @@ -373,6 +373,19 @@ int parse_pid(const char *s, pid_t* ret_pid) { return 0; } +bool uid_is_valid(uid_t uid) { + + /* Some libc APIs use UID_INVALID as special placeholder */ + if (uid == (uid_t) 0xFFFFFFFF) + return false; + + /* A long time ago UIDs where 16bit, hence explicitly avoid the 16bit -1 too */ + if (uid == (uid_t) 0xFFFF) + return false; + + return true; +} + int parse_uid(const char *s, uid_t* ret_uid) { unsigned long ul = 0; uid_t uid; @@ -389,12 +402,7 @@ int parse_uid(const char *s, uid_t* ret_uid) { if ((unsigned long) uid != ul) return -ERANGE; - /* Some libc APIs use UID_INVALID as special placeholder */ - if (uid == (uid_t) 0xFFFFFFFF) - return -ENXIO; - - /* A long time ago UIDs where 16bit, hence explicitly avoid the 16bit -1 too */ - if (uid == (uid_t) 0xFFFF) + if (!uid_is_valid(uid)) return -ENXIO; if (ret_uid) diff --git a/src/basic/util.h b/src/basic/util.h index ff7a00e928..f8e32360f0 100644 --- a/src/basic/util.h +++ b/src/basic/util.h @@ -154,7 +154,10 @@ int parse_size(const char *t, off_t base, off_t *size); int parse_boolean(const char *v) _pure_; int parse_pid(const char *s, pid_t* ret_pid); int parse_uid(const char *s, uid_t* ret_uid); -#define parse_gid(s, ret_uid) parse_uid(s, ret_uid) +#define parse_gid(s, ret_gid) parse_uid(s, ret_gid) + +bool uid_is_valid(uid_t uid); +#define gid_is_valid(gid) uid_is_valid(gid) int safe_atou(const char *s, unsigned *ret_u); int safe_atoi(const char *s, int *ret_i); diff --git a/src/libsystemd/sd-login/sd-login.c b/src/libsystemd/sd-login/sd-login.c index 7d6a4b78cf..6300162ebe 100644 --- a/src/libsystemd/sd-login/sd-login.c +++ b/src/libsystemd/sd-login/sd-login.c @@ -203,6 +203,7 @@ _public_ int sd_uid_get_state(uid_t uid, char**state) { char *s = NULL; int r; + assert_return(uid_is_valid(uid), -EINVAL); assert_return(state, -EINVAL); r = file_of_uid(uid, &p); @@ -230,6 +231,7 @@ _public_ int sd_uid_get_display(uid_t uid, char **session) { _cleanup_free_ char *p = NULL, *s = NULL; int r; + assert_return(uid_is_valid(uid), -EINVAL); assert_return(session, -EINVAL); r = file_of_uid(uid, &p); @@ -257,6 +259,7 @@ _public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) int r; const char *word, *variable, *state; + assert_return(uid_is_valid(uid), -EINVAL); assert_return(seat, -EINVAL); variable = require_active ? "ACTIVE_UID" : "UIDS"; @@ -289,6 +292,8 @@ static int uid_get_array(uid_t uid, const char *variable, char ***array) { char **a; int r; + assert_return(uid_is_valid(uid), -EINVAL); + r = file_of_uid(uid, &p); if (r < 0) return r; -- cgit v1.2.3-54-g00ecf From 569b19d8fedc4525a6c15f1a3ab9c15dcb7c694a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 3 Sep 2015 14:56:26 +0200 Subject: cgroup: move controller to dirname translation into join_path_legacy() Let's simplify things a bit. --- src/basic/cgroup-util.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) (limited to 'src/basic') diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 74e1668a17..8299f6ffd5 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -460,20 +460,23 @@ static const char *controller_to_dirname(const char *controller) { return controller; } -static int join_path_legacy(const char *controller_dn, const char *path, const char *suffix, char **fs) { +static int join_path_legacy(const char *controller, const char *path, const char *suffix, char **fs) { + const char *dn; char *t = NULL; assert(fs); - assert(controller_dn); + assert(controller); + + dn = controller_to_dirname(controller); if (isempty(path) && isempty(suffix)) - t = strappend("/sys/fs/cgroup/", controller_dn); + t = strappend("/sys/fs/cgroup/", dn); else if (isempty(path)) - t = strjoin("/sys/fs/cgroup/", controller_dn, "/", suffix, NULL); + t = strjoin("/sys/fs/cgroup/", dn, "/", suffix, NULL); else if (isempty(suffix)) - t = strjoin("/sys/fs/cgroup/", controller_dn, "/", path, NULL); + t = strjoin("/sys/fs/cgroup/", dn, "/", path, NULL); else - t = strjoin("/sys/fs/cgroup/", controller_dn, "/", path, "/", suffix, NULL); + t = strjoin("/sys/fs/cgroup/", dn, "/", path, "/", suffix, NULL); if (!t) return -ENOMEM; @@ -509,8 +512,8 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch if (!controller) { char *t; - /* If no controller is specified, we assume only the - * path below the controller matters */ + /* If no controller is specified, we return the path + * *below* the controllers, without any prefix. */ if (!path && !suffix) return -EINVAL; @@ -537,14 +540,8 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch if (unified > 0) r = join_path_unified(path, suffix, fs); - else { - const char *dn; - - dn = controller_to_dirname(controller); - - r = join_path_legacy(dn, path, suffix, fs); - } - + else + r = join_path_legacy(controller, path, suffix, fs); if (r < 0) return r; -- cgit v1.2.3-54-g00ecf From ef5c570edfd8afb20e3b04d3711e111a1dea0548 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 3 Sep 2015 18:23:26 +0200 Subject: util: document why parse_uid() returns ENXIO parse_uid() returns EINVAL for invalid strings, but ENXIO for the (uid_t) -1 user ids in order to distinguish these two cases. Document this. --- src/basic/util.c | 5 ++++- src/test/test-util.c | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'src/basic') diff --git a/src/basic/util.c b/src/basic/util.c index beec7cb7dd..86aacad307 100644 --- a/src/basic/util.c +++ b/src/basic/util.c @@ -403,7 +403,10 @@ int parse_uid(const char *s, uid_t* ret_uid) { return -ERANGE; if (!uid_is_valid(uid)) - return -ENXIO; + return -ENXIO; /* we return ENXIO instead of EINVAL + * here, to make it easy to distuingish + * invalid numeric uids invalid + * strings. */ if (ret_uid) *ret_uid = uid; diff --git a/src/test/test-util.c b/src/test/test-util.c index dff38ab6f6..10d8d210d5 100644 --- a/src/test/test-util.c +++ b/src/test/test-util.c @@ -282,6 +282,9 @@ static void test_parse_uid(void) { r = parse_uid("65535", &uid); assert_se(r == -ENXIO); + + r = parse_uid("asdsdas", &uid); + assert_se(r == -EINVAL); } static void test_safe_atou16(void) { -- cgit v1.2.3-54-g00ecf From d7e46e01aca53017cffb659115665be621264b8f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 3 Sep 2015 18:24:57 +0200 Subject: audit: audit calls should return ENODATA when process are not in an audit session ENODATA is how we usually indicate such "missing info" cases, so we should do this here, too. --- src/basic/audit.c | 9 ++++++++- src/libsystemd/sd-bus/bus-creds.c | 8 ++++---- 2 files changed, 12 insertions(+), 5 deletions(-) (limited to 'src/basic') diff --git a/src/basic/audit.c b/src/basic/audit.c index 54148fcf18..1f593aa813 100644 --- a/src/basic/audit.c +++ b/src/basic/audit.c @@ -36,6 +36,11 @@ int audit_session_from_pid(pid_t pid, uint32_t *id) { assert(id); + /* We don't convert ENOENT to ESRCH here, since we can't + * really distuingish between "audit is not available in the + * kernel" and "the process does not exist", both which will + * result in ENOENT. */ + p = procfs_file_alloca(pid, "sessionid"); r = read_one_line_file(p, &s); @@ -47,7 +52,7 @@ int audit_session_from_pid(pid_t pid, uint32_t *id) { return r; if (u == AUDIT_SESSION_INVALID || u <= 0) - return -ENXIO; + return -ENODATA; *id = u; return 0; @@ -68,6 +73,8 @@ int audit_loginuid_from_pid(pid_t pid, uid_t *uid) { return r; r = parse_uid(s, &u); + if (r == -ENXIO) /* the UID was -1 */ + return -ENODATA; if (r < 0) return r; diff --git a/src/libsystemd/sd-bus/bus-creds.c b/src/libsystemd/sd-bus/bus-creds.c index 1c365b7fcd..c3cc2b7212 100644 --- a/src/libsystemd/sd-bus/bus-creds.c +++ b/src/libsystemd/sd-bus/bus-creds.c @@ -1062,8 +1062,8 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) { if (missing & SD_BUS_CREDS_AUDIT_SESSION_ID) { r = audit_session_from_pid(pid, &c->audit_session_id); - if (r == -ENXIO) { - /* ENXIO means: no audit session id assigned */ + if (r == -ENODATA) { + /* ENODATA means: no audit session id assigned */ c->audit_session_id = AUDIT_SESSION_INVALID; c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID; } else if (r < 0) { @@ -1075,8 +1075,8 @@ int bus_creds_add_more(sd_bus_creds *c, uint64_t mask, pid_t pid, pid_t tid) { if (missing & SD_BUS_CREDS_AUDIT_LOGIN_UID) { r = audit_loginuid_from_pid(pid, &c->audit_login_uid); - if (r == -ENXIO) { - /* ENXIO means: no audit login uid assigned */ + if (r == -ENODATA) { + /* ENODATA means: no audit login uid assigned */ c->audit_login_uid = UID_INVALID; c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID; } else if (r < 0) { -- cgit v1.2.3-54-g00ecf From b8725df8b338b13405e430d037f0aac7872ce3d5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 3 Sep 2015 18:27:19 +0200 Subject: cgroup: when comparing agent paths, use path_equal() After all a path is a path is a path and we should use path_equal() to comapre those. --- src/basic/cgroup-util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/basic') diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 8299f6ffd5..3ef96b238e 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -899,7 +899,7 @@ int cg_install_release_agent(const char *controller, const char *agent) { r = write_string_file(fs, agent, 0); if (r < 0) return r; - } else if (!streq(sc, agent)) + } else if (!path_equal(sc, agent)) return -EEXIST; fs = mfree(fs); -- cgit v1.2.3-54-g00ecf From 9a66c87a2386468fd3adc250cd9003644a7a5e6b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 3 Sep 2015 18:28:21 +0200 Subject: cgroup: make sure cg_is_empty_recursive() returns 1 for non-existing cgroups Previously, on the legacy hierarchy a non-existing cgroup was considered identical to an empty one, but the unified hierarchy the check for a non-existing one returned ENOENT. --- src/basic/cgroup-util.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/basic') diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 3ef96b238e..bf897c9b2d 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -1002,6 +1002,8 @@ int cg_is_empty_recursive(const char *controller, const char *path) { return r; r = read_one_line_file(populated, &t); + if (r == -ENOENT) + return 1; if (r < 0) return r; -- cgit v1.2.3-54-g00ecf From 989189eabf420690ca64d4713cea62e79c945d86 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 3 Sep 2015 19:43:15 +0200 Subject: cgroup: fix potential bad memory access --- src/basic/cgroup-util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/basic') diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index bf897c9b2d..77375f3669 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -518,9 +518,9 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch if (!path && !suffix) return -EINVAL; - if (isempty(suffix)) + if (!suffix) t = strdup(path); - else if (isempty(path)) + else if (!path) t = strdup(suffix); else t = strjoin(path, "/", suffix, NULL); -- cgit v1.2.3-54-g00ecf From 1c80e425124457146ab03279e44ba5155d3e1716 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 3 Sep 2015 19:44:02 +0200 Subject: cgroup-util: make cg_pid_get_path() return -ENODATA when controller can't be found If the controller managed by systemd cannot found in /proc/$PID/cgroup, return ENODATA, the usual error for cases where the data being looked for does not exist, even if the process does. --- src/basic/cgroup-util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/basic') diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 77375f3669..812308e243 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -870,7 +870,7 @@ int cg_pid_get_path(const char *controller, pid_t pid, char **path) { return 0; } - return -ENOENT; + return -ENODATA; } int cg_install_release_agent(const char *controller, const char *agent) { -- cgit v1.2.3-54-g00ecf From ba09d9c687986305e5b60f923e85e2ec1e78d979 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 3 Sep 2015 19:46:23 +0200 Subject: cgroup: fix potential access of uninitialized variable --- src/basic/cgroup-util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/basic') diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 812308e243..fe8750d0f3 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -1910,7 +1910,7 @@ int cg_attach_many_everywhere(CGroupMask supported, const char *path, Set* pids, int cg_migrate_everywhere(CGroupMask supported, const char *from, const char *to, cg_migrate_callback_t to_callback, void *userdata) { CGroupController c; - int r, unified; + int r = 0, unified; if (!path_equal(from, to)) { r = cg_migrate_recursive(SYSTEMD_CGROUP_CONTROLLER, from, SYSTEMD_CGROUP_CONTROLLER, to, false, true); -- cgit v1.2.3-54-g00ecf From 5f4c5fef66581383ee852b301db67f687663004c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 3 Sep 2015 19:50:37 +0200 Subject: cgroup: always read the supported controllers from the root cgroup of the local container Otherwise we might end up thinking that we support more controllers than actually enabled for the container we are running in. --- src/basic/cgroup-util.c | 12 ++++++++++-- src/test/test-cgroup-util.c | 12 ++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'src/basic') diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index fe8750d0f3..388bd629ee 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -1981,14 +1981,22 @@ int cg_mask_supported(CGroupMask *ret) { if (unified < 0) return unified; if (unified > 0) { - _cleanup_free_ char *controllers = NULL; + _cleanup_free_ char *root = NULL, *controllers = NULL, *path = NULL; const char *c; /* In the unified hierarchy we can read the supported * and accessible controllers from a the top-level * cgroup attribute */ - r = read_one_line_file("/sys/fs/cgroup/cgroup.controllers", &controllers); + r = cg_get_root_path(&root); + if (r < 0) + return r; + + r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, root, "cgroup.controllers", &path); + if (r < 0) + return r; + + r = read_one_line_file(path, &controllers); if (r < 0) return r; diff --git a/src/test/test-cgroup-util.c b/src/test/test-cgroup-util.c index ecc9d70bf4..ff7e45901c 100644 --- a/src/test/test-cgroup-util.c +++ b/src/test/test-cgroup-util.c @@ -295,6 +295,17 @@ static void test_shift_path(void) { test_shift_path_one("/foobar/waldo", "/fuckfuck", "/foobar/waldo"); } +static void test_mask_supported(void) { + + CGroupMask m; + CGroupController c; + + assert_se(cg_mask_supported(&m) >= 0); + + for (c = 0; c < _CGROUP_CONTROLLER_MAX; c++) + printf("'%s' is supported: %s\n", cgroup_controller_to_string(c), yes_no(m & CGROUP_CONTROLLER_TO_MASK(c))); +} + int main(void) { test_path_decode_unit(); test_path_get_unit(); @@ -309,6 +320,7 @@ int main(void) { test_controller_is_valid(); test_slice_to_path(); test_shift_path(); + test_mask_supported(); return 0; } -- cgit v1.2.3-54-g00ecf From 98e4d8d7635496cbf62c8127ce6a8e8f7604a031 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 3 Sep 2015 20:10:00 +0200 Subject: nspawn: enable all controllers we can for the "payload" subcgroup we create In the unified hierarchy delegating controller access is safe, hence make sure to enable all controllers for the "payload" subcgroup if we create it, so that the container will have all controllers enabled the nspawn service itself has. --- src/basic/cgroup-util.c | 2 +- src/nspawn/nspawn.c | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'src/basic') diff --git a/src/basic/cgroup-util.c b/src/basic/cgroup-util.c index 388bd629ee..a298b29382 100644 --- a/src/basic/cgroup-util.c +++ b/src/basic/cgroup-util.c @@ -2163,7 +2163,7 @@ int cg_enable_everywhere(CGroupMask supported, CGroupMask mask, const char *p) { r = write_string_file(fs, s, 0); if (r < 0) - log_warning_errno(r, "Failed to enable controller %s for %s (%s): %m", n, p, fs); + log_debug_errno(r, "Failed to enable controller %s for %s (%s): %m", n, p, fs); } } diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index a56960506c..1c64c3e771 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -4737,6 +4737,7 @@ static int create_subcgroup(pid_t pid) { _cleanup_free_ char *cgroup = NULL; const char *child; int unified, r; + CGroupMask supported; /* In the unified hierarchy inner nodes may only only contain * subgroups, but not processes. Hence, if we running in the @@ -4756,6 +4757,10 @@ static int create_subcgroup(pid_t pid) { if (unified == 0) return 0; + r = cg_mask_supported(&supported); + if (r < 0) + return log_error_errno(r, "Failed to determine supported controllers: %m"); + r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup); if (r < 0) return log_error_errno(r, "Failed to get our control group: %m"); @@ -4770,6 +4775,8 @@ static int create_subcgroup(pid_t pid) { if (r < 0) return log_error_errno(r, "Failed to create %s subcgroup: %m", child); + /* Try to enable as many controllers as possible for the new payload. */ + (void) cg_enable_everywhere(supported, supported, cgroup); return 0; } -- cgit v1.2.3-54-g00ecf