]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core/namespace: reimplement mount_private_sysfs() in the same logic to mount private...
authorYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 10 Aug 2023 04:58:54 +0000 (13:58 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Tue, 22 Aug 2023 14:21:43 +0000 (23:21 +0900)
Previously, mount_private_sysfs() was implemented by using open_tree()
and move_mount() to keep submounts. But these syscalls are slightly new
and supported since kernel version 5.2.

We already do the same thing for /proc/, but without the new syscalls.
Let's use the same logic to mount private procfs. Then, we can mount
new instance of sysfs with older kernels.

src/core/namespace.c

index d71441367b4c15f787e4535f547195f3bf4bf53e..0c924ca0a89237ede4bf1d7ea972a3f41b0a7cbb 100644 (file)
@@ -1054,29 +1054,6 @@ 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;
 
@@ -1098,6 +1075,33 @@ static int mount_bind_sysfs(const MountEntry *m) {
         return 1;
 }
 
+static int mount_private_sysfs(const MountEntry *m) {
+        const char *entry_path = mount_entry_path(ASSERT_PTR(m));
+        int r, n;
+
+        (void) mkdir_p_label(entry_path, 0755);
+
+        n = umount_recursive(entry_path, 0);
+
+        r = mount_nofollow_verbose(LOG_DEBUG, "sysfs", entry_path, "sysfs", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL);
+        if (ERRNO_IS_NEG_PRIVILEGE(r)) {
+                /* When we do not have enough privileges to mount sysfs, fall back to use existing /sys. */
+
+                if (n > 0)
+                        /* /sys or some of sub-mounts are umounted in the above. Refuse incomplete tree.
+                         * Propagate the original error code returned by mount() in the above. */
+                        return r;
+
+                return mount_bind_sysfs(m);
+
+        } else if (r < 0)
+                return r;
+
+        /* We mounted a new instance now. Let's bind mount the children over now. */
+        (void) bind_mount_submounts("/sys", entry_path);
+        return 0;
+}
+
 static int mount_procfs(const MountEntry *m, const NamespaceInfo *ns_info) {
         _cleanup_free_ char *opts = NULL;
         const char *entry_path;