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)
"/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;
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;
- }
+ if (r < 0)
+ return log_debug_errno(r, "Failed to fix label of '%s' as /dev/: %m", dev);
- devpts = strjoina(temporary_mount, "/dev/pts");
- (void) mkdir(devpts, 0755);
- r = mount_nofollow_verbose(LOG_DEBUG, "/dev/pts", devpts, NULL, MS_BIND, NULL);
+ r = bind_mount_device_dir(temporary_mount, "/dev/pts");
if (r < 0)
- goto fail;
+ 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;
-
- devmqueue = strjoina(temporary_mount, "/dev/mqueue");
- (void) mkdir(devmqueue, 0755);
- (void) mount_nofollow_verbose(LOG_DEBUG, "/dev/mqueue", devmqueue, NULL, MS_BIND, NULL);
+ return r;
- devhugepages = strjoina(temporary_mount, "/dev/hugepages");
- (void) mkdir(devhugepages, 0755);
- (void) mount_nofollow_verbose(LOG_DEBUG, "/dev/hugepages", devhugepages, NULL, MS_BIND, NULL);
+ FOREACH_STRING(d, "/dev/mqueue", "/dev/hugepages")
+ (void) bind_mount_device_dir(temporary_mount, d);
- 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);
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) {