]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core/namespace: introduce a new namespace mount mode PRIVATE_SYSFS
authorYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 18 Feb 2023 00:44:43 +0000 (09:44 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 23 Feb 2023 06:09:13 +0000 (15:09 +0900)
This is useful when a service running with a new network namespace.

The mount mode is not used yet, but will be used in a later commit.

src/core/namespace.c

index 03889ffd0595bfe747a81722c23144567b571e80..8e3c272f40f6676882d004007afb03adf2b7f1e9 100644 (file)
@@ -61,6 +61,7 @@ typedef enum MountMode {
         PRIVATE_DEV,
         BIND_DEV,
         EMPTY_DIR,
+        PRIVATE_SYSFS,
         BIND_SYSFS,
         PROCFS,
         READONLY,
@@ -233,6 +234,7 @@ static const char * const mount_mode_table[_MOUNT_MODE_MAX] = {
         [PRIVATE_DEV]          = "private-dev",
         [BIND_DEV]             = "bind-dev",
         [EMPTY_DIR]            = "empty",
+        [PRIVATE_SYSFS]        = "private-sysfs",
         [BIND_SYSFS]           = "bind-sysfs",
         [PROCFS]               = "procfs",
         [READONLY]             = "read-only",
@@ -288,7 +290,7 @@ static bool mount_entry_read_only(const MountEntry *p) {
 static bool mount_entry_noexec(const MountEntry *p) {
         assert(p);
 
-        return p->noexec || IN_SET(p->mode, NOEXEC, INACCESSIBLE, BIND_SYSFS, PROCFS);
+        return p->noexec || IN_SET(p->mode, NOEXEC, INACCESSIBLE, PRIVATE_SYSFS, BIND_SYSFS, PROCFS);
 }
 
 static bool mount_entry_exec(const MountEntry *p) {
@@ -1053,6 +1055,29 @@ static int mount_bind_dev(const MountEntry *m) {
         return 1;
 }
 
+static int mount_private_sysfs(const MountEntry *m) {
+        const char *p = mount_entry_path(ASSERT_PTR(m));
+        int r;
+
+        (void) mkdir_p_label(p, 0755);
+
+        r = remount_sysfs(p);
+        if (r < 0 && (ERRNO_IS_PRIVILEGE(r) || ERRNO_IS_NOT_SUPPORTED(r))) {
+                /* Running with an unprivileged user (PrivateUsers=yes), or the kernel seems old. Falling
+                 * back to bind mount the host's version so that we get all child mounts of it, too. */
+
+                log_debug_errno(r, "Failed to remount sysfs on %s, falling back to bind mount: %m", p);
+
+                (void) umount_recursive(p, 0);
+
+                r = mount_nofollow_verbose(LOG_DEBUG, "/sys", p, NULL, MS_BIND|MS_REC, NULL);
+        }
+        if (r < 0)
+                return log_debug_errno(r, "Failed to remount sysfs on %s: %m", p);
+
+        return 1;
+}
+
 static int mount_bind_sysfs(const MountEntry *m) {
         int r;
 
@@ -1483,6 +1508,9 @@ static int apply_one_mount(
         case BIND_DEV:
                 return mount_bind_dev(m);
 
+        case PRIVATE_SYSFS:
+                return mount_private_sysfs(m);
+
         case BIND_SYSFS:
                 return mount_bind_sysfs(m);