]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/nspawn/nspawn-mount.c
util-lib: split string parsing related calls from util.[ch] into parse-util.[ch]
[thirdparty/systemd.git] / src / nspawn / nspawn-mount.c
index 2bca39f45d2fb8a4f4c1e3d0eb81abb91960e1de..5d8172092a651afee094f547647af7998839fd01 100644 (file)
 ***/
 
 #include <sys/mount.h>
+#include <linux/magic.h>
 
-#include "util.h"
-#include "rm-rf.h"
-#include "strv.h"
-#include "path-util.h"
-#include "mkdir.h"
-#include "label.h"
-#include "set.h"
 #include "cgroup-util.h"
-
+#include "escape.h"
+#include "label.h"
+#include "mkdir.h"
 #include "nspawn-mount.h"
+#include "parse-util.h"
+#include "path-util.h"
+#include "rm-rf.h"
+#include "set.h"
+#include "string-util.h"
+#include "strv.h"
+#include "util.h"
 
 CustomMount* custom_mount_add(CustomMount **l, unsigned *n, CustomMountType t) {
         CustomMount *c, *ret;
@@ -216,8 +219,67 @@ static int tmpfs_patch_options(
         return !!buf;
 }
 
+int mount_sysfs(const char *dest) {
+        const char *full, *top, *x;
+        int r;
+
+        top = prefix_roota(dest, "/sys");
+        r = path_check_fstype(top, SYSFS_MAGIC);
+        if (r < 0)
+                return log_error_errno(r, "Failed to determine filesystem type of %s: %m", top);
+        /* /sys might already be mounted as sysfs by the outer child in the
+         * !netns case. In this case, it's all good. Don't touch it because we
+         * don't have the right to do so, see https://github.com/systemd/systemd/issues/1555.
+         */
+        if (r > 0)
+                return 0;
+
+        full = prefix_roota(top, "/full");
+
+        (void) mkdir(full, 0755);
+
+        if (mount("sysfs", full, "sysfs", MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) < 0)
+                return log_error_errno(errno, "Failed to mount sysfs to %s: %m", full);
+
+        FOREACH_STRING(x, "block", "bus", "class", "dev", "devices", "kernel") {
+                _cleanup_free_ char *from = NULL, *to = NULL;
+
+                from = prefix_root(full, x);
+                if (!from)
+                        return log_oom();
+
+                to = prefix_root(top, x);
+                if (!to)
+                        return log_oom();
+
+                (void) mkdir(to, 0755);
+
+                if (mount(from, to, NULL, MS_BIND, NULL) < 0)
+                        return log_error_errno(errno, "Failed to mount /sys/%s into place: %m", x);
+
+                if (mount(NULL, to, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, NULL) < 0)
+                        return log_error_errno(errno, "Failed to mount /sys/%s read-only: %m", x);
+        }
+
+        if (umount(full) < 0)
+                return log_error_errno(errno, "Failed to unmount %s: %m", full);
+
+        if (rmdir(full) < 0)
+                return log_error_errno(errno, "Failed to remove %s: %m", full);
+
+        x = prefix_roota(top, "/fs/kdbus");
+        (void) mkdir(x, 0755);
+
+        if (mount(NULL, top, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, NULL) < 0)
+                return log_error_errno(errno, "Failed to make %s read-only: %m", top);
+
+        return 0;
+}
+
 int mount_all(const char *dest,
-              bool userns, uid_t uid_shift, uid_t uid_range,
+              bool use_userns, bool in_userns,
+              bool use_netns,
+              uid_t uid_shift, uid_t uid_range,
               const char *selinux_apifs_context) {
 
         typedef struct MountPoint {
@@ -227,21 +289,23 @@ int mount_all(const char *dest,
                 const char *options;
                 unsigned long flags;
                 bool fatal;
-                bool userns;
+                bool in_userns;
+                bool use_netns;
         } MountPoint;
 
         static const MountPoint mount_table[] = {
-                { "proc",      "/proc",          "proc",   NULL,        MS_NOSUID|MS_NOEXEC|MS_NODEV,                              true,  true  },
-                { "/proc/sys", "/proc/sys",      NULL,     NULL,        MS_BIND,                                                   true,  true  },   /* Bind mount first */
-                { NULL,        "/proc/sys",      NULL,     NULL,        MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, true,  true  },   /* Then, make it r/o */
-                { "sysfs",     "/sys",           "sysfs",  NULL,        MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV,                    true,  false },
-                { "tmpfs",     "/dev",           "tmpfs",  "mode=755",  MS_NOSUID|MS_STRICTATIME,                                  true,  false },
-                { "tmpfs",     "/dev/shm",       "tmpfs",  "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME,                         true,  false },
-                { "tmpfs",     "/run",           "tmpfs",  "mode=755",  MS_NOSUID|MS_NODEV|MS_STRICTATIME,                         true,  false },
-                { "tmpfs",     "/tmp",           "tmpfs",  "mode=1777", MS_STRICTATIME,                                            true,  false },
+                { "proc",      "/proc",          "proc",   NULL,        MS_NOSUID|MS_NOEXEC|MS_NODEV,                              true,  true, false  },
+                { "/proc/sys", "/proc/sys",      NULL,     NULL,        MS_BIND,                                                   true,  true, false  },   /* Bind mount first */
+                { NULL,        "/proc/sys",      NULL,     NULL,        MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, true,  true, false  },   /* Then, make it r/o */
+                { "tmpfs",     "/sys",           "tmpfs",  "mode=755",  MS_NOSUID|MS_NOEXEC|MS_NODEV,                              true,  false, true },
+                { "sysfs",     "/sys",           "sysfs",  NULL,        MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV,                    true,  false, false },
+                { "tmpfs",     "/dev",           "tmpfs",  "mode=755",  MS_NOSUID|MS_STRICTATIME,                                  true,  false, false },
+                { "tmpfs",     "/dev/shm",       "tmpfs",  "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME,                         true,  false, false },
+                { "tmpfs",     "/run",           "tmpfs",  "mode=755",  MS_NOSUID|MS_NODEV|MS_STRICTATIME,                         true,  false, false },
+                { "tmpfs",     "/tmp",           "tmpfs",  "mode=1777", MS_STRICTATIME,                                            true,  false, false },
 #ifdef HAVE_SELINUX
-                { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL,     MS_BIND,                                                   false, false },  /* Bind mount first */
-                { NULL,              "/sys/fs/selinux", NULL, NULL,     MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, false, false },  /* Then, make it r/o */
+                { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL,     MS_BIND,                                                   false, false, false },  /* Bind mount first */
+                { NULL,              "/sys/fs/selinux", NULL, NULL,     MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, false, false, false },  /* Then, make it r/o */
 #endif
         };
 
@@ -252,7 +316,10 @@ int mount_all(const char *dest,
                 _cleanup_free_ char *where = NULL, *options = NULL;
                 const char *o;
 
-                if (userns != mount_table[k].userns)
+                if (in_userns != mount_table[k].in_userns)
+                        continue;
+
+                if (!use_netns && mount_table[k].use_netns)
                         continue;
 
                 where = prefix_root(dest, mount_table[k].where);
@@ -278,7 +345,7 @@ int mount_all(const char *dest,
 
                 o = mount_table[k].options;
                 if (streq_ptr(mount_table[k].type, "tmpfs")) {
-                        r = tmpfs_patch_options(o, userns, uid_shift, uid_range, selinux_apifs_context, &options);
+                        r = tmpfs_patch_options(o, use_userns, uid_shift, uid_range, selinux_apifs_context, &options);
                         if (r < 0)
                                 return log_oom();
                         if (r > 0)
@@ -534,7 +601,7 @@ static int mount_legacy_cgroup_hierarchy(const char *dest, const char *controlle
         char *to;
         int r;
 
-        to = strjoina(dest, "/sys/fs/cgroup/", hierarchy);
+        to = strjoina(strempty(dest), "/sys/fs/cgroup/", hierarchy);
 
         r = path_is_mount_point(to, 0);
         if (r < 0 && r != -ENOENT)
@@ -569,6 +636,8 @@ static int mount_legacy_cgroups(
 
         cgroup_root = prefix_roota(dest, "/sys/fs/cgroup");
 
+        (void) mkdir_p(cgroup_root, 0755);
+
         /* Mount a tmpfs to /sys/fs/cgroup if it's not mounted there yet. */
         r = path_is_mount_point(cgroup_root, AT_SYMLINK_FOLLOW);
         if (r < 0)
@@ -661,13 +730,15 @@ static int mount_unified_cgroups(const char *dest) {
 
         assert(dest);
 
-        p = strjoina(dest, "/sys/fs/cgroup");
+        p = prefix_roota(dest, "/sys/fs/cgroup");
+
+        (void) mkdir_p(p, 0755);
 
         r = path_is_mount_point(p, AT_SYMLINK_FOLLOW);
         if (r < 0)
                 return log_error_errno(r, "Failed to determine if %s is mounted already: %m", p);
         if (r > 0) {
-                p = strjoina(dest, "/sys/fs/cgroup/cgroup.procs");
+                p = prefix_roota(dest, "/sys/fs/cgroup/cgroup.procs");
                 if (access(p, F_OK) >= 0)
                         return 0;
                 if (errno != ENOENT)