chiark / gitweb /
core: rework the Delegate= unit file setting to take a list of controller names
authorLennart Poettering <lennart@poettering.net>
Thu, 9 Nov 2017 14:29:34 +0000 (15:29 +0100)
committerSven Eden <yamakuzure@gmx.net>
Thu, 9 Nov 2017 14:29:34 +0000 (15:29 +0100)
Previously it was not possible to select which controllers to enable for
a unit where Delegate=yes was set, as all controllers were enabled. With
this change, this is made configurable, and thus delegation units can
pick specifically what they want to manage themselves, and what they
don't care about.

src/core/cgroup.c
src/core/cgroup.h

index 33779110deef98871ffc96966623b13e79d90207..f14709c697933c485e4eb1313e292a0c1aebcae3 100644 (file)
@@ -210,6 +210,16 @@ void cgroup_context_dump(CGroupContext *c, FILE* f, const char *prefix) {
                 prefix, cgroup_device_policy_to_string(c->device_policy),
                 prefix, yes_no(c->delegate));
 
+        if (c->delegate) {
+                _cleanup_free_ char *t = NULL;
+
+                (void) cg_mask_to_string(c->delegate_controllers, &t);
+
+                fprintf(f, "%sDelegateController=%s\n",
+                        prefix,
+                        strempty(t));
+        }
+
         LIST_FOREACH(device_allow, a, c->device_allow)
                 fprintf(f,
                         "%sDeviceAllow=%s %s%s%s\n",
@@ -1064,37 +1074,47 @@ CGroupMask unit_get_own_mask(Unit *u) {
         if (!c)
                 return 0;
 
-        /* If delegation is turned on, then turn on all cgroups,
-         * unless we are on the legacy hierarchy and the process we
-         * fork into it is known to drop privileges, and hence
-         * shouldn't get access to the controllers.
+        return cgroup_context_get_mask(c);
+}
+
+CGroupMask unit_get_delegate_mask(Unit *u) {
+        CGroupContext *c;
+
+        /* If delegation is turned on, then turn on selected controllers, unless we are on the legacy hierarchy and the
+         * process we fork into is known to drop privileges, and hence shouldn't get access to the controllers.
          *
-         * Note that on the unified hierarchy it is safe to delegate
-         * controllers to unprivileged services. */
+         * Note that on the unified hierarchy it is safe to delegate controllers to unprivileged services. */
 
-        if (c->delegate) {
+        if (u->type == UNIT_SLICE)
+                return 0;
+
+        c = unit_get_cgroup_context(u);
+        if (!c)
+                return 0;
+
+        if (!c->delegate)
+                return 0;
+
+        if (cg_all_unified() <= 0) {
                 ExecContext *e;
 
                 e = unit_get_exec_context(u);
-                if (!e ||
-                    exec_context_maintains_privileges(e) ||
-                    cg_all_unified() > 0)
-                        return _CGROUP_MASK_ALL;
+                if (e && !exec_context_maintains_privileges(e))
+                        return 0;
         }
 
-        return cgroup_context_get_mask(c);
+        return c->delegate_controllers;
 }
 
 CGroupMask unit_get_members_mask(Unit *u) {
         assert(u);
 
-        /* Returns the mask of controllers all of the unit's children
-         * require, merged */
+        /* Returns the mask of controllers all of the unit's children require, merged */
 
         if (u->cgroup_members_mask_valid)
                 return u->cgroup_members_mask;
 
-        u->cgroup_members_mask = 0;
+        u->cgroup_members_mask = unit_get_delegate_mask(u);
 
         if (u->type == UNIT_SLICE) {
                 void *v;
index be5103f6cfc7513f963aba100f3ef4eb7ac4774b..1f0fefe9d326c802b0346e5ed7eef61ebe735c8c 100644 (file)
@@ -127,6 +127,7 @@ struct CGroupContext {
         uint64_t tasks_max;
 
         bool delegate;
+        CGroupMask delegate_controllers;
 };
 
 /* Used when querying IP accounting data */
@@ -154,8 +155,9 @@ void cgroup_context_free_blockio_device_weight(CGroupContext *c, CGroupBlockIODe
 void cgroup_context_free_blockio_device_bandwidth(CGroupContext *c, CGroupBlockIODeviceBandwidth *b);
 
 CGroupMask unit_get_own_mask(Unit *u);
-CGroupMask unit_get_siblings_mask(Unit *u);
+CGroupMask unit_get_delegate_mask(Unit *u);
 CGroupMask unit_get_members_mask(Unit *u);
+CGroupMask unit_get_siblings_mask(Unit *u);
 CGroupMask unit_get_subtree_mask(Unit *u);
 
 CGroupMask unit_get_target_mask(Unit *u);