From 553e3660864c657cbfca805d49cbe9f097df4558 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 10 Aug 2023 13:58:54 +0900 Subject: [PATCH] core/namespace: reimplement mount_private_sysfs() in the same logic to mount private procfs 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 | 50 ++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/src/core/namespace.c b/src/core/namespace.c index d71441367b4..0c924ca0a89 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -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; -- 2.39.5