]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
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 adf20b68c77b71e2385b69bea159148e8f53ba12..a9538310be51014d4aeef69d76679bec58cc584a 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;
 }