From 66825795b4716f5fd8f61178cb0fc6f92cc096cb Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Sat, 27 Apr 2024 14:25:36 +0800 Subject: [PATCH] core/namespace: modernize mount_private_dev --- src/core/namespace.c | 103 ++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 61 deletions(-) diff --git a/src/core/namespace.c b/src/core/namespace.c index 1c0a204ee2b..27227a4b522 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -976,7 +976,20 @@ add_symlink: return 0; } -static char *settle_runtime_dir(RuntimeScope scope) { +static int bind_mount_device_dir(const char *temporary_mount, const char *dir) { + const char *t; + + assert(temporary_mount); + assert(dir); + assert(path_is_absolute(dir)); + + t = strjoina(temporary_mount, dir); + + (void) mkdir(t, 0755); + return mount_nofollow_verbose(LOG_DEBUG, dir, t, NULL, MS_BIND, NULL); +} + +static char* settle_runtime_dir(RuntimeScope scope) { char *runtime_dir; if (scope != RUNTIME_SCOPE_USER) @@ -1017,8 +1030,8 @@ static int mount_private_dev(MountEntry *m, RuntimeScope scope) { "/dev/urandom\0" "/dev/tty\0"; - _cleanup_free_ char *temporary_mount = NULL; - const char *dev = NULL, *devpts = NULL, *devshm = NULL, *devhugepages = NULL, *devmqueue = NULL, *devlog = NULL, *devptmx = NULL; + _cleanup_(rmdir_and_freep) char *temporary_mount = NULL; + _cleanup_(umount_and_rmdir_and_freep) char *dev = NULL; bool can_mknod = true; int r; @@ -1028,67 +1041,56 @@ static int mount_private_dev(MountEntry *m, RuntimeScope scope) { if (r < 0) return r; - dev = strjoina(temporary_mount, "/dev"); + dev = path_join(temporary_mount, "dev"); + if (!dev) + return -ENOMEM; + (void) mkdir(dev, 0755); r = mount_nofollow_verbose(LOG_DEBUG, "tmpfs", dev, "tmpfs", DEV_MOUNT_OPTIONS, "mode=0755" TMPFS_LIMITS_PRIVATE_DEV); if (r < 0) - goto fail; + return r; r = label_fix_full(AT_FDCWD, dev, "/dev", 0); - if (r < 0) { - log_debug_errno(r, "Failed to fix label of '%s' as /dev: %m", dev); - goto fail; - } - - devpts = strjoina(temporary_mount, "/dev/pts"); - (void) mkdir(devpts, 0755); - r = mount_nofollow_verbose(LOG_DEBUG, "/dev/pts", devpts, NULL, MS_BIND, NULL); if (r < 0) - goto fail; + return log_debug_errno(r, "Failed to fix label of '%s' as /dev/: %m", dev); + + r = bind_mount_device_dir(temporary_mount, "/dev/pts"); + if (r < 0) + return r; /* /dev/ptmx can either be a device node or a symlink to /dev/pts/ptmx. * When /dev/ptmx a device node, /dev/pts/ptmx has 000 permissions making it inaccessible. * Thus, in that case make a clone. * In nspawn and other containers it will be a symlink, in that case make it a symlink. */ r = is_symlink("/dev/ptmx"); - if (r < 0) { - log_debug_errno(r, "Failed to detect whether /dev/ptmx is a symlink or not: %m"); - goto fail; - } else if (r > 0) { - devptmx = strjoina(temporary_mount, "/dev/ptmx"); - if (symlink("pts/ptmx", devptmx) < 0) { - r = log_debug_errno(errno, "Failed to create a symlink '%s' to pts/ptmx: %m", devptmx); - goto fail; - } + if (r < 0) + return log_debug_errno(r, "Failed to detect whether /dev/ptmx is a symlink or not: %m"); + if (r > 0) { + const char *devptmx = strjoina(temporary_mount, "/dev/ptmx"); + if (symlink("pts/ptmx", devptmx) < 0) + return log_debug_errno(errno, "Failed to create symlink '%s' to pts/ptmx: %m", devptmx); } else { r = clone_device_node("/dev/ptmx", temporary_mount, &can_mknod); if (r < 0) - goto fail; + return r; } - devshm = strjoina(temporary_mount, "/dev/shm"); - (void) mkdir(devshm, 0755); - r = mount_nofollow_verbose(LOG_DEBUG, "/dev/shm", devshm, NULL, MS_BIND, NULL); + r = bind_mount_device_dir(temporary_mount, "/dev/shm"); if (r < 0) - goto fail; + return r; - devmqueue = strjoina(temporary_mount, "/dev/mqueue"); - (void) mkdir(devmqueue, 0755); - (void) mount_nofollow_verbose(LOG_DEBUG, "/dev/mqueue", devmqueue, NULL, MS_BIND, NULL); + FOREACH_STRING(d, "/dev/mqueue", "/dev/hugepages") + (void) bind_mount_device_dir(temporary_mount, d); - devhugepages = strjoina(temporary_mount, "/dev/hugepages"); - (void) mkdir(devhugepages, 0755); - (void) mount_nofollow_verbose(LOG_DEBUG, "/dev/hugepages", devhugepages, NULL, MS_BIND, NULL); - - devlog = strjoina(temporary_mount, "/dev/log"); + const char *devlog = strjoina(temporary_mount, "/dev/log"); if (symlink("/run/systemd/journal/dev-log", devlog) < 0) - log_debug_errno(errno, "Failed to create a symlink '%s' to /run/systemd/journal/dev-log, ignoring: %m", devlog); + log_debug_errno(errno, "Failed to create symlink '%s' to /run/systemd/journal/dev-log, ignoring: %m", devlog); NULSTR_FOREACH(d, devnodes) { r = clone_device_node(d, temporary_mount, &can_mknod); /* ENXIO means the *source* is not a device file, skip creation in that case */ if (r < 0 && r != -ENXIO) - goto fail; + return r; } r = dev_setup(temporary_mount, UID_INVALID, GID_INVALID); @@ -1106,31 +1108,10 @@ static int mount_private_dev(MountEntry *m, RuntimeScope scope) { r = mount_nofollow_verbose(LOG_DEBUG, dev, mount_entry_path(m), NULL, MS_MOVE, NULL); if (r < 0) - goto fail; - - (void) rmdir(dev); - (void) rmdir(temporary_mount); + return r; + dev = rmdir_and_free(dev); /* Mount is successfully moved, do not umount() */ return 1; - -fail: - if (devpts) - (void) umount_verbose(LOG_DEBUG, devpts, UMOUNT_NOFOLLOW); - - if (devshm) - (void) umount_verbose(LOG_DEBUG, devshm, UMOUNT_NOFOLLOW); - - if (devhugepages) - (void) umount_verbose(LOG_DEBUG, devhugepages, UMOUNT_NOFOLLOW); - - if (devmqueue) - (void) umount_verbose(LOG_DEBUG, devmqueue, UMOUNT_NOFOLLOW); - - (void) umount_verbose(LOG_DEBUG, dev, UMOUNT_NOFOLLOW); - (void) rmdir(dev); - (void) rmdir(temporary_mount); - - return r; } static int mount_bind_dev(const MountEntry *m) {