chiark / gitweb /
cgroup: support prefix "-" in cgroups whitelisting entries (#4687)
authorDongsu Park <dongsu@endocode.com>
Tue, 29 Nov 2016 19:16:55 +0000 (20:16 +0100)
committerSven Eden <yamakuzure@gmx.net>
Mon, 17 Jul 2017 15:58:35 +0000 (17:58 +0200)
So far elogind-nspawn container has been creating files under
/run/elogind/inaccessible, no matter whether it's running in user
namespace or not. That's fine for regular files, dirs, socks, fifos.
However, it's not for block and character devices, because kernel
doesn't allow them to be created under user namespace. It results
in warnings at booting like that:

====
  Couldn't stat device /run/elogind/inaccessible/chr
  Couldn't stat device /run/elogind/inaccessible/blk
====

Thus we need to have the cgroups whitelisting handler to silently ignore
a file, when the device path is prefixed with "-". That's exactly the
same convention used in directives like ReadOnlyPaths=. Also insert the
prefix "-" to inaccessible entries.

src/core/cgroup.c

index 8f6e5e072a9a55ebe6575785d26284796b87a8a8..e44f729246572d4ecfd653fc4736c10cc0c4eb9d 100644 (file)
@@ -288,21 +288,14 @@ static int lookup_block_device(const char *p, dev_t *dev) {
 static int whitelist_device(const char *path, const char *node, const char *acc) {
         char buf[2+DECIMAL_STR_MAX(dev_t)*2+2+4];
         struct stat st;
-        bool ignore_notfound;
         int r;
 
         assert(path);
         assert(acc);
 
-        if (node[0] == '-') {
-                /* Non-existent paths starting with "-" must be silently ignored */
-                node++;
-                ignore_notfound = true;
-        } else
-                ignore_notfound = false;
-
         if (stat(node, &st) < 0) {
-                if (errno == ENOENT && ignore_notfound)
+                /* path starting with "-" must be silently ignored */
+                if (errno == ENOENT && startswith(node, "-"))
                         return 0;
 
                 return log_warning_errno(errno, "Couldn't stat device %s: %m", node);
@@ -679,7 +672,7 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) {
                 bool has_weight = cgroup_context_has_cpu_weight(c);
                 bool has_shares = cgroup_context_has_cpu_shares(c);
 
-                if (cg_all_unified()) {
+                if (cg_all_unified() > 0) {
                         uint64_t weight;
 
                         if (has_weight)
@@ -859,7 +852,7 @@ static void cgroup_context_apply(Unit *u, CGroupMask mask, ManagerState state) {
         }
 
         if ((mask & CGROUP_MASK_MEMORY) && !is_root) {
-                if (cg_all_unified()) {
+                if (cg_all_unified() > 0) {
                         uint64_t max;
                         uint64_t swap_max = CGROUP_LIMIT_MAX;
 
@@ -1035,7 +1028,7 @@ CGroupMask unit_get_own_mask(Unit *u) {
                 e = unit_get_exec_context(u);
                 if (!e ||
                     exec_context_maintains_privileges(e) ||
-                    cg_all_unified())
+                    cg_all_unified() > 0)
                         return _CGROUP_MASK_ALL;
         }
 
@@ -1262,7 +1255,10 @@ int unit_watch_cgroup(Unit *u) {
                 return 0;
 
         /* Only applies to the unified hierarchy */
-        if (!cg_unified(SYSTEMD_CGROUP_CONTROLLER))
+        r = cg_unified(SYSTEMD_CGROUP_CONTROLLER);
+        if (r < 0)
+                return log_unit_error_errno(u, r, "Failed detect whether the unified hierarchy is used: %m");
+        if (r == 0)
                 return 0;
 
         /* Don't watch the root slice, it's pointless. */
@@ -1682,7 +1678,7 @@ int unit_watch_all_pids(Unit *u) {
         if (!u->cgroup_path)
                 return -ENOENT;
 
-        if (cg_unified(SYSTEMD_CGROUP_CONTROLLER)) /* On unified we can use proper notifications */
+        if (cg_unified(SYSTEMD_CGROUP_CONTROLLER) > 0) /* On unified we can use proper notifications */
                 return 0;
 
         return unit_watch_pids_in_path(u, u->cgroup_path);
@@ -1756,7 +1752,7 @@ static int on_cgroup_inotify_event(sd_event_source *s, int fd, uint32_t revents,
 int manager_setup_cgroup(Manager *m) {
         _cleanup_free_ char *path = NULL;
         CGroupController c;
-        int r;
+        int r, all_unified, systemd_unified;
         char *e;
 
         assert(m);
@@ -1797,22 +1793,25 @@ int manager_setup_cgroup(Manager *m) {
         if (r < 0)
                 return log_error_errno(r, "Cannot find cgroup mount point: %m");
 
-        r = cg_unified_flush();
-        if (r < 0)
-                return log_error_errno(r, "Couldn't determine if we are running in the unified hierarchy: %m");
+        all_unified = cg_all_unified();
+        systemd_unified = cg_unified(SYSTEMD_CGROUP_CONTROLLER);
+
+        if (all_unified < 0 || systemd_unified < 0)
+                return log_error_errno(all_unified < 0 ? all_unified : systemd_unified,
+                                       "Couldn't determine if we are running in the unified hierarchy: %m");
 
-        if (cg_all_unified())
+        if (all_unified > 0)
                 log_debug("Unified cgroup hierarchy is located at %s.", path);
-        else if (cg_unified(SYSTEMD_CGROUP_CONTROLLER))
+        else if (systemd_unified > 0)
                 log_debug("Unified cgroup hierarchy is located at %s. Controllers are on legacy hierarchies.", path);
         else
-                log_debug("Using cgroup controller " SYSTEMD_CGROUP_CONTROLLER_LEGACY ". File system hierarchy is at %s.", path);
+                log_debug("Using cgroup controller " SYSTEMD_CGROUP_CONTROLLER ". File system hierarchy is at %s.", path);
 
         if (!m->test_run) {
                 const char *scope_path;
 
                 /* 3. Install agent */
-                if (cg_unified(SYSTEMD_CGROUP_CONTROLLER)) {
+                if (systemd_unified) {
 
                         /* In the unified hierarchy we can get
                          * cgroup empty notifications via inotify. */
@@ -1890,7 +1889,7 @@ int manager_setup_cgroup(Manager *m) {
                         return log_error_errno(errno, "Failed to open pin file: %m");
 
                 /* 6.  Always enable hierarchical support if it exists... */
-                if (!cg_all_unified())
+                if (!all_unified)
                         (void) cg_set_attribute("memory", "/", "memory.use_hierarchy", "1");
         }
 
@@ -2041,7 +2040,7 @@ int unit_get_memory_current(Unit *u, uint64_t *ret) {
         if ((u->cgroup_realized_mask & CGROUP_MASK_MEMORY) == 0)
                 return -ENODATA;
 
-        if (!cg_all_unified())
+        if (cg_all_unified() <= 0)
                 r = cg_get_attribute("memory", u->cgroup_path, "memory.usage_in_bytes", &v);
         else
                 r = cg_get_attribute("memory", u->cgroup_path, "memory.current", &v);
@@ -2086,7 +2085,7 @@ static int unit_get_cpu_usage_raw(Unit *u, nsec_t *ret) {
         if (!u->cgroup_path)
                 return -ENODATA;
 
-        if (cg_all_unified()) {
+        if (cg_all_unified() > 0) {
                 const char *keys[] = { "usage_usec", NULL };
                 _cleanup_free_ char *val = NULL;
                 uint64_t us;