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.
This commit is contained in:
Yu Watanabe
2023-08-22 23:21:43 +09:00
parent cc7e2dff7e
commit 553e366086
+27 -23
View 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;