cgroup: check whether unified hierarchy is writable
authorChristian Brauner <christian.brauner@ubuntu.com>
Wed, 22 Nov 2017 16:20:35 +0000 (17:20 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Wed, 22 Nov 2017 16:34:25 +0000 (17:34 +0100)
When systemd is running inside a container employing user
namespaces it currently mounts the unified cgroup hierarchy
without being able to write to it. This causes systemd to
freeze during boot.
This patch checks whether the unified cgroup hierarchy
is writable. If it is not it will not mount it.

This solution is based on a patch by Evgeny Vereshchagin.

Closes #6408.
Closes https://github.com/lxc/lxc/issues/1678 .

src/core/mount-setup.c

index adf20b6..a953831 100644 (file)
@@ -29,6 +29,7 @@
 #include "cgroup-util.h"
 #include "dev-setup.h"
 #include "efivars.h"
+#include "fileio.h"
 #include "fs-util.h"
 #include "label.h"
 #include "log.h"
 #include "virt.h"
 
 typedef enum MountMode {
-        MNT_NONE  =        0,
-        MNT_FATAL =        1 <<  0,
-        MNT_IN_CONTAINER = 1 <<  1,
+        MNT_NONE  =           0,
+        MNT_FATAL =           1 <<  0,
+        MNT_IN_CONTAINER =    1 <<  1,
+        MNT_CHECK_WRITABLE  = 1 <<  2,
 } MountMode;
 
 typedef struct MountPoint {
@@ -103,9 +105,9 @@ static const MountPoint mount_table[] = {
         { "tmpfs",       "/sys/fs/cgroup",            "tmpfs",      "mode=755",                MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME,
           cg_is_legacy_wanted, MNT_FATAL|MNT_IN_CONTAINER },
         { "cgroup",      "/sys/fs/cgroup/unified",    "cgroup2",    "nsdelegate",              MS_NOSUID|MS_NOEXEC|MS_NODEV,
-          cg_is_hybrid_wanted, MNT_IN_CONTAINER },
+          cg_is_hybrid_wanted, MNT_IN_CONTAINER|MNT_CHECK_WRITABLE },
         { "cgroup",      "/sys/fs/cgroup/unified",    "cgroup2",    NULL,                      MS_NOSUID|MS_NOEXEC|MS_NODEV,
-          cg_is_hybrid_wanted, MNT_IN_CONTAINER },
+          cg_is_hybrid_wanted, MNT_IN_CONTAINER|MNT_CHECK_WRITABLE },
         { "cgroup",      "/sys/fs/cgroup/systemd",    "cgroup",     "none,name=systemd,xattr", MS_NOSUID|MS_NOEXEC|MS_NODEV,
           cg_is_legacy_wanted, MNT_IN_CONTAINER     },
         { "cgroup",      "/sys/fs/cgroup/systemd",    "cgroup",     "none,name=systemd",       MS_NOSUID|MS_NOEXEC|MS_NODEV,
@@ -202,6 +204,14 @@ static int mount_one(const MountPoint *p, bool relabel) {
         if (relabel)
                 (void) label_fix(p->where, false, false);
 
+        if (p->mode & MNT_CHECK_WRITABLE) {
+                r = access(p->where, W_OK);
+                if (r < 0) {
+                        (void) umount(p->where);
+                        return (p->mode & MNT_FATAL) ? r : 0;
+                }
+        }
+
         return 1;
 }