diff --git a/TODO b/TODO index 9f123f5626..f19fdcc56b 100644 --- a/TODO +++ b/TODO @@ -20,10 +20,6 @@ Janitorial Clean-ups: Features: -* add wrapper for mount() that uses O_PATH on the destination and than mounts - to /proc/self/fd/xxx so that we basically have a mount() with O_NOFOLLOW like - behaviour. (in case of bind mounts do it on both source and target) - * add root=tmpfs that mounts a tmpfs to /sysroot (to be used in combination with usr=…, for a similar effect as systemd.volatile=yes but without the "hide-out" effect). Also, add root=gpt-auto-late support or so, that is like diff --git a/src/core/automount.c b/src/core/automount.c index 4db763f84e..b0d43a3ef4 100644 --- a/src/core/automount.c +++ b/src/core/automount.c @@ -94,7 +94,7 @@ static void unmount_autofs(Automount *a) { automount_send_ready(a, a->expire_tokens, -EHOSTDOWN); if (a->where) { - r = repeat_unmount(a->where, MNT_DETACH); + r = repeat_unmount(a->where, MNT_DETACH|UMOUNT_NOFOLLOW); if (r < 0) log_error_errno(r, "Failed to unmount: %m"); } @@ -601,10 +601,9 @@ static void automount_enter_waiting(Automount *a) { xsprintf(options, "fd=%i,pgrp="PID_FMT",minproto=5,maxproto=5,direct", p[1], getpgrp()); xsprintf(name, "systemd-"PID_FMT, getpid_cached()); - if (mount(name, a->where, "autofs", 0, options) < 0) { - r = -errno; + r = mount_nofollow(name, a->where, "autofs", 0, options); + if (r < 0) goto fail; - } mounted = true; @@ -648,7 +647,7 @@ fail: safe_close_pair(p); if (mounted) { - r = repeat_unmount(a->where, MNT_DETACH); + r = repeat_unmount(a->where, MNT_DETACH|UMOUNT_NOFOLLOW); if (r < 0) log_error_errno(r, "Failed to unmount, ignoring: %m"); } diff --git a/src/core/execute.c b/src/core/execute.c index 07a4d3610f..fd65dfb3fe 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -67,6 +67,7 @@ #include "memory-util.h" #include "missing_fs.h" #include "mkdir.h" +#include "mount-util.h" #include "mountpoint-util.h" #include "namespace.h" #include "parse-util.h" @@ -2652,11 +2653,13 @@ static int setup_credentials_internal( * the final version to the workspace, and make it writable, so that we can make * changes */ - if (mount(final, workspace, NULL, MS_BIND|MS_REC, NULL) < 0) - return -errno; + r = mount_nofollow_verbose(LOG_DEBUG, final, workspace, NULL, MS_BIND|MS_REC, NULL); + if (r < 0) + return r; - if (mount(NULL, workspace, NULL, MS_BIND|MS_REMOUNT|MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL) < 0) - return -errno; + r = mount_nofollow_verbose(LOG_DEBUG, NULL, workspace, NULL, MS_BIND|MS_REMOUNT|MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL); + if (r < 0) + return r; workspace_mounted = true; } @@ -2669,7 +2672,8 @@ static int setup_credentials_internal( if (try == 0) { /* Try "ramfs" first, since it's not swap backed */ - if (mount("ramfs", workspace, "ramfs", MS_NODEV|MS_NOEXEC|MS_NOSUID, "mode=0700") >= 0) { + r = mount_nofollow_verbose(LOG_DEBUG, "ramfs", workspace, "ramfs", MS_NODEV|MS_NOEXEC|MS_NOSUID, "mode=0700"); + if (r >= 0) { workspace_mounted = true; break; } @@ -2681,20 +2685,22 @@ static int setup_credentials_internal( return -ENOMEM; /* Fall back to "tmpfs" otherwise */ - if (mount("tmpfs", workspace, "tmpfs", MS_NODEV|MS_NOEXEC|MS_NOSUID, opts) >= 0) { + r = mount_nofollow_verbose(LOG_DEBUG, "tmpfs", workspace, "tmpfs", MS_NODEV|MS_NOEXEC|MS_NOSUID, opts); + if (r >= 0) { workspace_mounted = true; break; } } else { /* If that didn't work, try to make a bind mount from the final to the workspace, so that we can make it writable there. */ - if (mount(final, workspace, NULL, MS_BIND|MS_REC, NULL) < 0) { - if (!ERRNO_IS_PRIVILEGE(errno)) /* Propagate anything that isn't a permission problem */ - return -errno; + r = mount_nofollow_verbose(LOG_DEBUG, final, workspace, NULL, MS_BIND|MS_REC, NULL); + if (r < 0) { + if (!ERRNO_IS_PRIVILEGE(r)) /* Propagate anything that isn't a permission problem */ + return r; if (must_mount) /* If we it's not OK to use the plain directory * fallback, propagate all errors too */ - return -errno; + return r; /* If we lack privileges to bind mount stuff, then let's gracefully * proceed for compat with container envs, and just use the final dir @@ -2705,8 +2711,9 @@ static int setup_credentials_internal( } /* Make the new bind mount writable (i.e. drop MS_RDONLY) */ - if (mount(NULL, workspace, NULL, MS_BIND|MS_REMOUNT|MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL) < 0) - return -errno; + r = mount_nofollow_verbose(LOG_DEBUG, NULL, workspace, NULL, MS_BIND|MS_REMOUNT|MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL); + if (r < 0) + return r; workspace_mounted = true; break; @@ -2723,17 +2730,17 @@ static int setup_credentials_internal( if (workspace_mounted) { /* Make workspace read-only now, so that any bind mount we make from it defaults to read-only too */ - if (mount(NULL, workspace, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL) < 0) - return -errno; + r = mount_nofollow_verbose(LOG_DEBUG, NULL, workspace, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL); + if (r < 0) + return r; /* And mount it to the final place, read-only */ - if (final_mounted) { - if (umount2(workspace, MNT_DETACH|UMOUNT_NOFOLLOW) < 0) - return -errno; - } else { - if (mount(workspace, final, NULL, MS_MOVE, NULL) < 0) - return -errno; - } + if (final_mounted) + r = umount_verbose(LOG_DEBUG, workspace, MNT_DETACH|UMOUNT_NOFOLLOW); + else + r = mount_nofollow_verbose(LOG_DEBUG, workspace, final, NULL, MS_MOVE, NULL); + if (r < 0) + return r; } else { _cleanup_free_ char *parent = NULL; @@ -2847,7 +2854,8 @@ static int setup_credentials( * given that the we do this in a privately namespaced short-lived single-threaded process * that no one else sees this should be OK to do.*/ - if (mount(NULL, "/dev", NULL, MS_SLAVE|MS_REC, NULL) < 0) /* Turn off propagation from our namespace to host */ + r = mount_nofollow_verbose(LOG_DEBUG, NULL, "/dev", NULL, MS_SLAVE|MS_REC, NULL); /* Turn off propagation from our namespace to host */ + if (r < 0) goto child_fail; r = setup_credentials_internal( diff --git a/src/core/machine-id-setup.c b/src/core/machine-id-setup.c index 90f03db680..6aecd36fe6 100644 --- a/src/core/machine-id-setup.c +++ b/src/core/machine-id-setup.c @@ -15,6 +15,7 @@ #include "machine-id-setup.h" #include "macro.h" #include "mkdir.h" +#include "mount-util.h" #include "mountpoint-util.h" #include "namespace-util.h" #include "path-util.h" @@ -160,16 +161,18 @@ int machine_id_setup(const char *root, sd_id128_t machine_id, sd_id128_t *ret) { } /* And now, let's mount it over */ - if (mount(run_machine_id, etc_machine_id, NULL, MS_BIND, NULL) < 0) { - (void) unlink_noerrno(run_machine_id); - return log_error_errno(errno, "Failed to mount %s: %m", etc_machine_id); + r = mount_follow_verbose(LOG_ERR, run_machine_id, etc_machine_id, NULL, MS_BIND, NULL); + if (r < 0) { + (void) unlink(run_machine_id); + return r; } log_info("Installed transient %s file.", etc_machine_id); /* Mark the mount read-only */ - if (mount(NULL, etc_machine_id, NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, NULL) < 0) - log_warning_errno(errno, "Failed to make transient %s read-only, ignoring: %m", etc_machine_id); + r = mount_follow_verbose(LOG_WARNING, NULL, etc_machine_id, NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, NULL); + if (r < 0) + return r; finish: if (ret) @@ -227,8 +230,9 @@ int machine_id_commit(const char *root) { if (r < 0) return log_error_errno(r, "Failed to set up new mount namespace: %m"); - if (umount(etc_machine_id) < 0) - return log_error_errno(errno, "Failed to unmount transient %s file in our private namespace: %m", etc_machine_id); + r = umount_verbose(LOG_ERR, etc_machine_id, 0); + if (r < 0) + return r; /* Update a persistent version of etc_machine_id */ r = id128_write(etc_machine_id, ID128_PLAIN, id, true); diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c index 7c177839b3..e1ecb448ea 100644 --- a/src/core/mount-setup.c +++ b/src/core/mount-setup.c @@ -38,6 +38,7 @@ typedef enum MountMode { MNT_FATAL = 1 << 0, MNT_IN_CONTAINER = 1 << 1, MNT_CHECK_WRITABLE = 1 << 2, + MNT_FOLLOW_SYMLINK = 1 << 3, } MountMode; typedef struct MountPoint { @@ -61,9 +62,9 @@ typedef struct MountPoint { #endif static const MountPoint mount_table[] = { - { "sysfs", "/sys", "sysfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, - NULL, MNT_FATAL|MNT_IN_CONTAINER }, { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, + NULL, MNT_FATAL|MNT_IN_CONTAINER|MNT_FOLLOW_SYMLINK }, + { "sysfs", "/sys", "sysfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL, MNT_FATAL|MNT_IN_CONTAINER }, { "devtmpfs", "/dev", "devtmpfs", "mode=755" TMPFS_LIMITS_DEV, MS_NOSUID|MS_NOEXEC|MS_STRICTATIME, NULL, MNT_FATAL|MNT_IN_CONTAINER }, @@ -184,13 +185,13 @@ static int mount_one(const MountPoint *p, bool relabel) { p->type, strna(p->options)); - if (mount(p->what, - p->where, - p->type, - p->flags, - p->options) < 0) { - log_full_errno(priority, errno, "Failed to mount %s at %s: %m", p->type, p->where); - return (p->mode & MNT_FATAL) ? -errno : 0; + if (FLAGS_SET(p->mode, MNT_FOLLOW_SYMLINK)) + r = mount(p->what, p->where, p->type, p->flags, p->options) < 0 ? -errno : 0; + else + r = mount_nofollow(p->what, p->where, p->type, p->flags, p->options); + if (r < 0) { + log_full_errno(priority, r, "Failed to mount %s at %s: %m", p->type, p->where); + return (p->mode & MNT_FATAL) ? r : 0; } /* Relabel again, since we now mounted something fresh here */ @@ -201,7 +202,7 @@ static int mount_one(const MountPoint *p, bool relabel) { if (access(p->where, W_OK) < 0) { r = -errno; - (void) umount(p->where); + (void) umount2(p->where, UMOUNT_NOFOLLOW); (void) rmdir(p->where); log_full_errno(priority, r, "Mount point %s not writable after mounting: %m", p->where); @@ -355,7 +356,7 @@ int mount_cgroup_controllers(void) { } /* Now that we mounted everything, let's make the tmpfs the cgroup file systems are mounted into read-only. */ - (void) mount("tmpfs", "/sys/fs/cgroup", "tmpfs", MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME|MS_RDONLY, "mode=755" TMPFS_LIMITS_SYS_FS_CGROUP); + (void) mount_nofollow("tmpfs", "/sys/fs/cgroup", "tmpfs", MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME|MS_RDONLY, "mode=755" TMPFS_LIMITS_SYS_FS_CGROUP); return 0; } @@ -397,13 +398,13 @@ static int relabel_cgroup_filesystems(void) { return log_error_errno(errno, "Failed to determine mount flags for /sys/fs/cgroup: %m"); if (st.f_flags & ST_RDONLY) - (void) mount(NULL, "/sys/fs/cgroup", NULL, MS_REMOUNT, NULL); + (void) mount_nofollow(NULL, "/sys/fs/cgroup", NULL, MS_REMOUNT, NULL); (void) label_fix("/sys/fs/cgroup", 0); (void) nftw("/sys/fs/cgroup", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL); if (st.f_flags & ST_RDONLY) - (void) mount(NULL, "/sys/fs/cgroup", NULL, MS_REMOUNT|MS_RDONLY, NULL); + (void) mount_nofollow(NULL, "/sys/fs/cgroup", NULL, MS_REMOUNT|MS_RDONLY, NULL); } else if (r < 0) return log_error_errno(r, "Failed to determine whether we are in all unified mode: %m"); diff --git a/src/core/namespace.c b/src/core/namespace.c index f2754f9d02..565dc46826 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -657,13 +657,12 @@ static int clone_device_node( if (r < 0 && errno != EEXIST) return log_debug_errno(errno, "mknod() fallback failed for '%s': %m", d); - /* Fallback to bind-mounting: - * The assumption here is that all used device nodes carry standard - * properties. Specifically, the devices nodes we bind-mount should - * either be owned by root:root or root:tty (e.g. /dev/tty, /dev/ptmx) - * and should not carry ACLs. */ - if (mount(d, dn, NULL, MS_BIND, NULL) < 0) - return log_debug_errno(errno, "Bind mounting failed for '%s': %m", d); + /* Fallback to bind-mounting: The assumption here is that all used device nodes carry standard + * properties. Specifically, the devices nodes we bind-mount should either be owned by root:root or + * root:tty (e.g. /dev/tty, /dev/ptmx) and should not carry ACLs. */ + r = mount_nofollow_verbose(LOG_DEBUG, d, dn, NULL, MS_BIND, NULL); + if (r < 0) + return r; add_symlink: bn = path_startswith(d, "/dev/"); @@ -710,10 +709,10 @@ static int mount_private_dev(MountEntry *m) { dev = strjoina(temporary_mount, "/dev"); (void) mkdir(dev, 0755); - if (mount("tmpfs", dev, "tmpfs", DEV_MOUNT_OPTIONS, "mode=755" TMPFS_LIMITS_DEV) < 0) { - r = log_debug_errno(errno, "Failed to mount tmpfs on '%s': %m", dev); + r = mount_nofollow_verbose(LOG_DEBUG, "tmpfs", dev, "tmpfs", DEV_MOUNT_OPTIONS, "mode=755" TMPFS_LIMITS_DEV); + if (r < 0) goto fail; - } + r = label_fix_container(dev, "/dev", 0); if (r < 0) { log_debug_errno(errno, "Failed to fix label of '%s' as /dev: %m", dev); @@ -722,10 +721,9 @@ static int mount_private_dev(MountEntry *m) { devpts = strjoina(temporary_mount, "/dev/pts"); (void) mkdir(devpts, 0755); - if (mount("/dev/pts", devpts, NULL, MS_BIND, NULL) < 0) { - r = log_debug_errno(errno, "Failed to bind mount /dev/pts on '%s': %m", devpts); + r = mount_nofollow_verbose(LOG_DEBUG, "/dev/pts", devpts, NULL, MS_BIND, NULL); + if (r < 0) goto fail; - } /* /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. @@ -749,21 +747,17 @@ static int mount_private_dev(MountEntry *m) { devshm = strjoina(temporary_mount, "/dev/shm"); (void) mkdir(devshm, 0755); - r = mount("/dev/shm", devshm, NULL, MS_BIND, NULL); - if (r < 0) { - r = log_debug_errno(errno, "Failed to bind mount /dev/shm on '%s': %m", devshm); + r = mount_nofollow_verbose(LOG_DEBUG, "/dev/shm", devshm, NULL, MS_BIND, NULL); + if (r < 0) goto fail; - } devmqueue = strjoina(temporary_mount, "/dev/mqueue"); (void) mkdir(devmqueue, 0755); - if (mount("/dev/mqueue", devmqueue, NULL, MS_BIND, NULL) < 0) - log_debug_errno(errno, "Failed to bind mount /dev/mqueue on '%s', ignoring: %m", devmqueue); + (void) mount_nofollow_verbose(LOG_DEBUG, "/dev/mqueue", devmqueue, NULL, MS_BIND, NULL); devhugepages = strjoina(temporary_mount, "/dev/hugepages"); (void) mkdir(devhugepages, 0755); - if (mount("/dev/hugepages", devhugepages, NULL, MS_BIND, NULL) < 0) - log_debug_errno(errno, "Failed to bind mount /dev/hugepages on '%s', ignoring: %m", devhugepages); + (void) mount_nofollow_verbose(LOG_DEBUG, "/dev/hugepages", devhugepages, NULL, MS_BIND, NULL); devlog = strjoina(temporary_mount, "/dev/log"); if (symlink("/run/systemd/journal/dev-log", devlog) < 0) @@ -791,10 +785,9 @@ static int mount_private_dev(MountEntry *m) { if (r < 0) log_debug_errno(r, "Failed to unmount directories below '%s', ignoring: %m", mount_entry_path(m)); - if (mount(dev, mount_entry_path(m), NULL, MS_MOVE, NULL) < 0) { - r = log_debug_errno(errno, "Failed to move mount point '%s' to '%s': %m", dev, mount_entry_path(m)); + 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); @@ -803,18 +796,18 @@ static int mount_private_dev(MountEntry *m) { fail: if (devpts) - (void) umount(devpts); + (void) umount_verbose(LOG_DEBUG, devpts, UMOUNT_NOFOLLOW); if (devshm) - (void) umount(devshm); + (void) umount_verbose(LOG_DEBUG, devshm, UMOUNT_NOFOLLOW); if (devhugepages) - (void) umount(devhugepages); + (void) umount_verbose(LOG_DEBUG, devhugepages, UMOUNT_NOFOLLOW); if (devmqueue) - (void) umount(devmqueue); + (void) umount_verbose(LOG_DEBUG, devmqueue, UMOUNT_NOFOLLOW); - (void) umount(dev); + (void) umount_verbose(LOG_DEBUG, dev, UMOUNT_NOFOLLOW); (void) rmdir(dev); (void) rmdir(temporary_mount); @@ -837,8 +830,9 @@ static int mount_bind_dev(const MountEntry *m) { if (r > 0) /* make this a NOP if /dev is already a mount point */ return 0; - if (mount("/dev", mount_entry_path(m), NULL, MS_BIND|MS_REC, NULL) < 0) - return log_debug_errno(errno, "Failed to bind mount %s: %m", mount_entry_path(m)); + r = mount_nofollow_verbose(LOG_DEBUG, "/dev", mount_entry_path(m), NULL, MS_BIND|MS_REC, NULL); + if (r < 0) + return r; return 1; } @@ -857,14 +851,16 @@ static int mount_sysfs(const MountEntry *m) { return 0; /* Bind mount the host's version so that we get all child mounts of it, too. */ - if (mount("/sys", mount_entry_path(m), NULL, MS_BIND|MS_REC, NULL) < 0) - return log_debug_errno(errno, "Failed to mount %s: %m", mount_entry_path(m)); + r = mount_nofollow_verbose(LOG_DEBUG, "/sys", mount_entry_path(m), NULL, MS_BIND|MS_REC, NULL); + if (r < 0) + return r; return 1; } static int mount_procfs(const MountEntry *m, const NamespaceInfo *ns_info) { const char *entry_path; + int r; assert(m); assert(ns_info); @@ -896,9 +892,10 @@ static int mount_procfs(const MountEntry *m, const NamespaceInfo *ns_info) { if (!opts) return -ENOMEM; - if (mount("proc", entry_path, "proc", MS_NOSUID|MS_NOEXEC|MS_NODEV, opts) < 0) { - if (errno != EINVAL) - return log_debug_errno(errno, "Failed to mount %s (options=%s): %m", mount_entry_path(m), opts); + r = mount_nofollow_verbose(LOG_DEBUG, "proc", entry_path, "proc", MS_NOSUID|MS_NOEXEC|MS_NODEV, opts); + if (r < 0) { + if (r != -EINVAL) + return r; /* If this failed with EINVAL then this likely means the textual hidepid= stuff is * not supported by the kernel, and thus the per-instance hidepid= neither, which @@ -908,8 +905,9 @@ static int mount_procfs(const MountEntry *m, const NamespaceInfo *ns_info) { return 1; } - if (mount("proc", entry_path, "proc", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL) < 0) - return log_debug_errno(errno, "Failed to mount %s (no options): %m", mount_entry_path(m)); + r = mount_nofollow_verbose(LOG_DEBUG, "proc", entry_path, "proc", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); + if (r < 0) + return r; return 1; } @@ -928,8 +926,9 @@ static int mount_tmpfs(const MountEntry *m) { (void) mkdir_p_label(entry_path, 0755); (void) umount_recursive(entry_path, 0); - if (mount("tmpfs", entry_path, "tmpfs", m->flags, mount_entry_options(m)) < 0) - return log_debug_errno(errno, "Failed to mount %s: %m", entry_path); + r = mount_nofollow_verbose(LOG_DEBUG, "tmpfs", entry_path, "tmpfs", m->flags, mount_entry_options(m)); + if (r < 0) + return r; r = label_fix_container(entry_path, inner_path, 0); if (r < 0) @@ -1172,9 +1171,9 @@ static int apply_mount( assert(what); - if (mount(what, mount_entry_path(m), NULL, MS_BIND|(rbind ? MS_REC : 0), NULL) < 0) { + r = mount_nofollow_verbose(LOG_DEBUG, what, mount_entry_path(m), NULL, MS_BIND|(rbind ? MS_REC : 0), NULL); + if (r < 0) { bool try_again = false; - r = -errno; if (r == -ENOENT && make) { struct stat st; @@ -1202,13 +1201,8 @@ static int apply_mount( } } - if (try_again) { - if (mount(what, mount_entry_path(m), NULL, MS_BIND|(rbind ? MS_REC : 0), NULL) < 0) - r = -errno; - else - r = 0; - } - + if (try_again) + r = mount_nofollow_verbose(LOG_DEBUG, what, mount_entry_path(m), NULL, MS_BIND|(rbind ? MS_REC : 0), NULL); if (r < 0) return log_error_errno(r, "Failed to mount %s to %s: %m", what, mount_entry_path(m)); } @@ -1798,19 +1792,16 @@ int setup_namespace( goto finish; } if (r == 0) { - if (mount(root, root, NULL, MS_BIND|MS_REC, NULL) < 0) { - r = log_debug_errno(errno, "Failed to bind mount '%s': %m", root); + r = mount_nofollow_verbose(LOG_DEBUG, root, root, NULL, MS_BIND|MS_REC, NULL); + if (r < 0) goto finish; - } } } else { - /* Let's mount the main root directory to the root directory to use */ - if (mount("/", root, NULL, MS_BIND|MS_REC, NULL) < 0) { - r = log_debug_errno(errno, "Failed to bind mount '/' on '%s': %m", root); + r = mount_nofollow_verbose(LOG_DEBUG, "/", root, NULL, MS_BIND|MS_REC, NULL); + if (r < 0) goto finish; - } } /* Try to set up the new root directory before mounting anything else there. */ diff --git a/src/home/homework-directory.c b/src/home/homework-directory.c index 7d00da214a..bffeac0a5e 100644 --- a/src/home/homework-directory.c +++ b/src/home/homework-directory.c @@ -61,13 +61,13 @@ int home_activate_directory( /* Create a mount point (even if the directory is already placed correctly), as a way to indicate * this mount point is now "activated". Moreover, we want to set per-user * MS_NOSUID/MS_NOEXEC/MS_NODEV. */ - r = mount_verbose(LOG_ERR, ip, hd, NULL, MS_BIND, NULL); + r = mount_nofollow_verbose(LOG_ERR, ip, hd, NULL, MS_BIND, NULL); if (r < 0) return r; - r = mount_verbose(LOG_ERR, NULL, hd, NULL, MS_BIND|MS_REMOUNT|user_record_mount_flags(h), NULL); + r = mount_nofollow_verbose(LOG_ERR, NULL, hd, NULL, MS_BIND|MS_REMOUNT|user_record_mount_flags(h), NULL); if (r < 0) { - (void) umount_verbose(hd); + (void) umount_verbose(LOG_ERR, hd, UMOUNT_NOFOLLOW); return r; } diff --git a/src/home/homework-luks.c b/src/home/homework-luks.c index b3082f144a..947a559c26 100644 --- a/src/home/homework-luks.c +++ b/src/home/homework-luks.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include "blkid-util.h" @@ -1258,7 +1259,7 @@ int home_prepare_luks( fail: if (mounted) - (void) umount_verbose("/run/systemd/user-home-mount"); + (void) umount_verbose(LOG_ERR, "/run/systemd/user-home-mount", UMOUNT_NOFOLLOW); if (dm_activated) (void) crypt_deactivate(cd, setup->dm_name); @@ -2167,7 +2168,7 @@ int home_create_luks( root_fd = safe_close(root_fd); - r = umount_verbose("/run/systemd/user-home-mount"); + r = umount_verbose(LOG_ERR, "/run/systemd/user-home-mount", UMOUNT_NOFOLLOW); if (r < 0) goto fail; @@ -2237,7 +2238,7 @@ fail: root_fd = safe_close(root_fd); if (mounted) - (void) umount_verbose("/run/systemd/user-home-mount"); + (void) umount_verbose(LOG_WARNING, "/run/systemd/user-home-mount", UMOUNT_NOFOLLOW); if (dm_activated) (void) crypt_deactivate(cd, dm_name); @@ -2339,7 +2340,7 @@ static int ext4_offline_resize_fs(HomeSetup *setup, uint64_t new_size, bool disc } if (setup->undo_mount) { - r = umount_verbose("/run/systemd/user-home-mount"); + r = umount_verbose(LOG_ERR, "/run/systemd/user-home-mount", UMOUNT_NOFOLLOW); if (r < 0) return r; diff --git a/src/home/homework-mount.c b/src/home/homework-mount.c index 51c0a38649..853181b80d 100644 --- a/src/home/homework-mount.c +++ b/src/home/homework-mount.c @@ -38,7 +38,7 @@ int home_mount_node(const char *node, const char *fstype, bool discard, unsigned } else options = discard_option; - r = mount_verbose(LOG_ERR, node, "/run/systemd/user-home-mount", fstype, flags|MS_RELATIME, strempty(options)); + r = mount_nofollow_verbose(LOG_ERR, node, "/run/systemd/user-home-mount", fstype, flags|MS_RELATIME, strempty(options)); if (r < 0) return r; @@ -52,7 +52,7 @@ int home_unshare_and_mount(const char *node, const char *fstype, bool discard, u if (unshare(CLONE_NEWNS) < 0) return log_error_errno(errno, "Couldn't unshare file system namespace: %m"); - r = mount_verbose(LOG_ERR, "/run", "/run", NULL, MS_SLAVE|MS_REC, NULL); /* Mark /run as MS_SLAVE in our new namespace */ + r = mount_nofollow_verbose(LOG_ERR, "/run", "/run", NULL, MS_SLAVE|MS_REC, NULL); /* Mark /run as MS_SLAVE in our new namespace */ if (r < 0) return r; @@ -83,11 +83,11 @@ int home_move_mount(const char *user_name_and_realm, const char *target) { (void) mkdir_p(target, 0700); - r = mount_verbose(LOG_ERR, d, target, NULL, MS_BIND, NULL); + r = mount_nofollow_verbose(LOG_ERR, d, target, NULL, MS_BIND, NULL); if (r < 0) return r; - r = umount_verbose("/run/systemd/user-home-mount"); + r = umount_verbose(LOG_ERR, "/run/systemd/user-home-mount", UMOUNT_NOFOLLOW); if (r < 0) return r; diff --git a/src/home/homework.c b/src/home/homework.c index 986ce2b3f0..14e2002c73 100644 --- a/src/home/homework.c +++ b/src/home/homework.c @@ -291,7 +291,7 @@ int home_setup_undo(HomeSetup *setup) { } if (setup->undo_mount) { - q = umount_verbose("/run/systemd/user-home-mount"); + q = umount_verbose(LOG_DEBUG, "/run/systemd/user-home-mount", UMOUNT_NOFOLLOW); if (q < 0) r = q; } diff --git a/src/login/user-runtime-dir.c b/src/login/user-runtime-dir.c index ab25ebf41b..84d8f1e8fd 100644 --- a/src/login/user-runtime-dir.c +++ b/src/login/user-runtime-dir.c @@ -13,6 +13,7 @@ #include "limits-util.h" #include "main-func.h" #include "mkdir.h" +#include "mount-util.h" #include "mountpoint-util.h" #include "path-util.h" #include "rm-rf.h" @@ -81,14 +82,14 @@ static int user_mkdir_runtime_path( (void) mkdir_label(runtime_path, 0700); - r = mount("tmpfs", runtime_path, "tmpfs", MS_NODEV|MS_NOSUID, options); + r = mount_nofollow_verbose(LOG_DEBUG, "tmpfs", runtime_path, "tmpfs", MS_NODEV|MS_NOSUID, options); if (r < 0) { - if (!ERRNO_IS_PRIVILEGE(errno)) { - r = log_error_errno(errno, "Failed to mount per-user tmpfs directory %s: %m", runtime_path); + if (!ERRNO_IS_PRIVILEGE(r)) { + log_error_errno(r, "Failed to mount per-user tmpfs directory %s: %m", runtime_path); goto fail; } - log_debug_errno(errno, + log_debug_errno(r, "Failed to mount per-user tmpfs directory %s.\n" "Assuming containerized execution, ignoring: %m", runtime_path); diff --git a/src/machine/machine-dbus.c b/src/machine/machine-dbus.c index 8dd4a3294a..931e6d7232 100644 --- a/src/machine/machine-dbus.c +++ b/src/machine/machine-dbus.c @@ -31,6 +31,7 @@ #include "machine.h" #include "missing_capability.h" #include "mkdir.h" +#include "mount-util.h" #include "namespace-util.h" #include "os-util.h" #include "path-util.h" @@ -891,15 +892,17 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu mount_slave_created = true; - if (mount(mount_slave, mount_slave, NULL, MS_BIND, NULL) < 0) { - r = sd_bus_error_set_errnof(error, errno, "Failed to make bind mount %s: %m", mount_slave); + r = mount_nofollow_verbose(LOG_DEBUG, mount_slave, mount_slave, NULL, MS_BIND, NULL); + if (r < 0) { + sd_bus_error_set_errnof(error, r, "Failed to make bind mount %s: %m", mount_slave); goto finish; } mount_slave_mounted = true; - if (mount(NULL, mount_slave, NULL, MS_SLAVE, NULL) < 0) { - r = sd_bus_error_set_errnof(error, errno, "Failed to remount slave %s: %m", mount_slave); + r = mount_nofollow_verbose(LOG_DEBUG, NULL, mount_slave, NULL, MS_SLAVE, NULL); + if (r < 0) { + sd_bus_error_set_errnof(error, r, "Failed to remount slave %s: %m", mount_slave); goto finish; } @@ -916,19 +919,22 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu mount_tmp_created = true; - if (mount(chased_src, mount_tmp, NULL, MS_BIND, NULL) < 0) { - r = sd_bus_error_set_errnof(error, errno, "Failed to mount %s: %m", chased_src); + r = mount_nofollow_verbose(LOG_DEBUG, chased_src, mount_tmp, NULL, MS_BIND, NULL); + if (r < 0) { + sd_bus_error_set_errnof(error, r, "Failed to mount %s: %m", chased_src); goto finish; } mount_tmp_mounted = true; /* Third, we remount the new bind mount read-only if requested. */ - if (read_only) - if (mount(NULL, mount_tmp, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY, NULL) < 0) { - r = sd_bus_error_set_errnof(error, errno, "Failed to remount read-only %s: %m", mount_tmp); + if (read_only) { + r = mount_nofollow_verbose(LOG_DEBUG, NULL, mount_tmp, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY, NULL); + if (r < 0) { + sd_bus_error_set_errnof(error, r, "Failed to remount read-only %s: %m", mount_tmp); goto finish; } + } /* Fourth, we move the new bind mount into the propagation directory. This way it will appear there read-only * right-away. */ @@ -947,8 +953,9 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu mount_outside_created = true; - if (mount(mount_tmp, mount_outside, NULL, MS_MOVE, NULL) < 0) { - r = sd_bus_error_set_errnof(error, errno, "Failed to move %s to %s: %m", mount_tmp, mount_outside); + r = mount_nofollow_verbose(LOG_DEBUG, mount_tmp, mount_outside, NULL, MS_MOVE, NULL); + if (r < 0) { + sd_bus_error_set_errnof(error, r, "Failed to move %s to %s: %m", mount_tmp, mount_outside); goto finish; } @@ -961,7 +968,7 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu (void) unlink(mount_tmp); mount_tmp_created = false; - (void) umount(mount_slave); + (void) umount_verbose(LOG_DEBUG, mount_slave, UMOUNT_NOFOLLOW); mount_slave_mounted = false; (void) rmdir(mount_slave); @@ -1005,10 +1012,9 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu } mount_inside = strjoina("/run/host/incoming/", basename(mount_outside)); - if (mount(mount_inside, dest, NULL, MS_MOVE, NULL) < 0) { - r = log_error_errno(errno, "Failed to mount: %m"); + r = mount_nofollow_verbose(LOG_ERR, mount_inside, dest, NULL, MS_MOVE, NULL); + if (r < 0) goto child_fail; - } _exit(EXIT_SUCCESS); @@ -1038,7 +1044,7 @@ int bus_machine_method_bind_mount(sd_bus_message *message, void *userdata, sd_bu finish: if (mount_outside_mounted) - (void) umount(mount_outside); + (void) umount_verbose(LOG_DEBUG, mount_outside, UMOUNT_NOFOLLOW); if (mount_outside_created) { if (S_ISDIR(st.st_mode)) (void) rmdir(mount_outside); @@ -1047,7 +1053,7 @@ finish: } if (mount_tmp_mounted) - (void) umount(mount_tmp); + (void) umount_verbose(LOG_DEBUG, mount_tmp, UMOUNT_NOFOLLOW); if (mount_tmp_created) { if (S_ISDIR(st.st_mode)) (void) rmdir(mount_tmp); @@ -1056,7 +1062,7 @@ finish: } if (mount_slave_mounted) - (void) umount(mount_slave); + (void) umount_verbose(LOG_DEBUG, mount_slave, UMOUNT_NOFOLLOW); if (mount_slave_created) (void) rmdir(mount_slave); diff --git a/src/nspawn/nspawn-cgroup.c b/src/nspawn/nspawn-cgroup.c index a16ee5c60a..f7b34ccc58 100644 --- a/src/nspawn/nspawn-cgroup.c +++ b/src/nspawn/nspawn-cgroup.c @@ -105,11 +105,11 @@ int sync_cgroup(pid_t pid, CGroupUnified unified_requested, uid_t uid_shift) { return log_error_errno(errno, "Failed to generate temporary mount point for unified hierarchy: %m"); if (unified_controller > 0) - r = mount_verbose(LOG_ERR, "cgroup", tree, "cgroup", - MS_NOSUID|MS_NOEXEC|MS_NODEV, "none,name=systemd,xattr"); + r = mount_nofollow_verbose(LOG_ERR, "cgroup", tree, "cgroup", + MS_NOSUID|MS_NOEXEC|MS_NODEV, "none,name=systemd,xattr"); else - r = mount_verbose(LOG_ERR, "cgroup", tree, "cgroup2", - MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); + r = mount_nofollow_verbose(LOG_ERR, "cgroup", tree, "cgroup2", + MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); if (r < 0) goto finish; @@ -136,7 +136,7 @@ int sync_cgroup(pid_t pid, CGroupUnified unified_requested, uid_t uid_shift) { log_error_errno(r, "Failed to chown() cgroup %s: %m", fn); finish: if (undo_mount) - (void) umount_verbose(tree); + (void) umount_verbose(LOG_ERR, tree, UMOUNT_NOFOLLOW); (void) rmdir(tree); return r; @@ -275,14 +275,14 @@ static int mount_legacy_cgroup_hierarchy( opts = controller; } - r = mount_verbose(LOG_ERR, "cgroup", to, fstype, MS_NOSUID|MS_NOEXEC|MS_NODEV, opts); + r = mount_nofollow_verbose(LOG_ERR, "cgroup", to, fstype, MS_NOSUID|MS_NOEXEC|MS_NODEV, opts); if (r < 0) return r; /* ... hence let's only make the bind mount read-only, not the superblock. */ if (read_only) { - r = mount_verbose(LOG_ERR, NULL, to, NULL, - MS_BIND|MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, NULL); + r = mount_nofollow_verbose(LOG_ERR, NULL, to, NULL, + MS_BIND|MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, NULL); if (r < 0) return r; } @@ -323,8 +323,8 @@ static int mount_legacy_cgns_supported( if (r < 0) return log_oom(); - r = mount_verbose(LOG_ERR, "tmpfs", cgroup_root, "tmpfs", - MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, options); + r = mount_nofollow_verbose(LOG_ERR, "tmpfs", cgroup_root, "tmpfs", + MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, options); if (r < 0) return r; } @@ -391,8 +391,8 @@ skip_controllers: return r; if (!userns) - return mount_verbose(LOG_ERR, NULL, cgroup_root, NULL, - MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME|MS_RDONLY, "mode=755"); + return mount_nofollow_verbose(LOG_ERR, NULL, cgroup_root, NULL, + MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME|MS_RDONLY, "mode=755"); return 0; } @@ -425,8 +425,8 @@ static int mount_legacy_cgns_unsupported( if (r < 0) return log_oom(); - r = mount_verbose(LOG_ERR, "tmpfs", cgroup_root, "tmpfs", - MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, options); + r = mount_nofollow_verbose(LOG_ERR, "tmpfs", cgroup_root, "tmpfs", + MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, options); if (r < 0) return r; } @@ -499,8 +499,8 @@ skip_controllers: if (r < 0) return r; - return mount_verbose(LOG_ERR, NULL, cgroup_root, NULL, - MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME|MS_RDONLY, "mode=755"); + return mount_nofollow_verbose(LOG_ERR, NULL, cgroup_root, NULL, + MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME|MS_RDONLY, "mode=755"); } static int mount_unified_cgroups(const char *dest) { @@ -527,7 +527,7 @@ static int mount_unified_cgroups(const char *dest) { "%s is already mounted but not a unified cgroup hierarchy. Refusing.", p); } - return mount_verbose(LOG_ERR, "cgroup", p, "cgroup2", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); + return mount_nofollow_verbose(LOG_ERR, "cgroup", p, "cgroup2", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); } int mount_cgroups( @@ -554,13 +554,13 @@ static int mount_systemd_cgroup_writable_one(const char *root, const char *own) assert(own); /* Make our own cgroup a (writable) bind mount */ - r = mount_verbose(LOG_ERR, own, own, NULL, MS_BIND, NULL); + r = mount_nofollow_verbose(LOG_ERR, own, own, NULL, MS_BIND, NULL); if (r < 0) return r; /* And then remount the systemd cgroup root read-only */ - return mount_verbose(LOG_ERR, NULL, root, NULL, - MS_BIND|MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, NULL); + return mount_nofollow_verbose(LOG_ERR, NULL, root, NULL, + MS_BIND|MS_REMOUNT|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_RDONLY, NULL); } int mount_systemd_cgroup_writable( diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c index c49ed76979..065099cf39 100644 --- a/src/nspawn/nspawn-mount.c +++ b/src/nspawn/nspawn-mount.c @@ -40,7 +40,9 @@ CustomMount* custom_mount_add(CustomMount **l, size_t *n, CustomMountType t) { ret = *l + *n; (*n)++; - *ret = (CustomMount) { .type = t }; + *ret = (CustomMount) { + .type = t + }; return ret; } @@ -442,8 +444,8 @@ int mount_sysfs(const char *dest, MountSettingsMask mount_settings) { if (FLAGS_SET(mount_settings, MOUNT_APPLY_APIVFS_RO)) extra_flags |= MS_RDONLY; - r = mount_verbose(LOG_ERR, "sysfs", full, "sysfs", - MS_NOSUID|MS_NOEXEC|MS_NODEV|extra_flags, NULL); + r = mount_nofollow_verbose(LOG_ERR, "sysfs", full, "sysfs", + MS_NOSUID|MS_NOEXEC|MS_NODEV|extra_flags, NULL); if (r < 0) return r; @@ -460,17 +462,17 @@ int mount_sysfs(const char *dest, MountSettingsMask mount_settings) { (void) mkdir(to, 0755); - r = mount_verbose(LOG_ERR, from, to, NULL, MS_BIND, NULL); + r = mount_nofollow_verbose(LOG_ERR, from, to, NULL, MS_BIND, NULL); if (r < 0) return r; - r = mount_verbose(LOG_ERR, NULL, to, NULL, - MS_BIND|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT|extra_flags, NULL); + r = mount_nofollow_verbose(LOG_ERR, NULL, to, NULL, + MS_BIND|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT|extra_flags, NULL); if (r < 0) return r; } - r = umount_verbose(full); + r = umount_verbose(LOG_ERR, full, UMOUNT_NOFOLLOW); if (r < 0) return r; @@ -483,8 +485,8 @@ int mount_sysfs(const char *dest, MountSettingsMask mount_settings) { x = prefix_roota(top, "/fs/cgroup"); (void) mkdir_p(x, 0755); - return mount_verbose(LOG_ERR, NULL, top, NULL, - MS_BIND|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT|extra_flags, NULL); + return mount_nofollow_verbose(LOG_ERR, NULL, top, NULL, + MS_BIND|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT|extra_flags, NULL); } int mount_all(const char *dest, @@ -516,7 +518,7 @@ int mount_all(const char *dest, static const MountPoint mount_table[] = { /* First we list inner child mounts (i.e. mounts applied *after* entering user namespacing) */ { "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, - MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_MKDIR }, + MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_MKDIR|MOUNT_FOLLOW_SYMLINKS }, /* we follow symlinks here since not following them requires /proc/ already being mounted, which we don't have here. */ { "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND, MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* Bind mount first ... */ @@ -670,12 +672,14 @@ int mount_all(const char *dest, return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, mount_table[k].what); } - r = mount_verbose(fatal ? LOG_ERR : LOG_DEBUG, - prefixed ?: mount_table[k].what, - where, - mount_table[k].type, - mount_table[k].flags, - o); + r = mount_verbose_full( + fatal ? LOG_ERR : LOG_DEBUG, + prefixed ?: mount_table[k].what, + where, + mount_table[k].type, + mount_table[k].flags, + o, + FLAGS_SET(mount_table[k].mount_settings, MOUNT_FOLLOW_SYMLINKS)); if (r < 0 && fatal) return r; } @@ -771,7 +775,7 @@ static int mount_bind(const char *dest, CustomMount *m) { return log_error_errno(r, "Failed to create mount point %s: %m", where); } - r = mount_verbose(LOG_ERR, m->source, where, NULL, mount_flags, mount_opts); + r = mount_nofollow_verbose(LOG_ERR, m->source, where, NULL, mount_flags, mount_opts); if (r < 0) return r; @@ -807,7 +811,7 @@ static int mount_tmpfs(const char *dest, CustomMount *m, uid_t uid_shift, const return log_oom(); options = r > 0 ? buf : m->options; - return mount_verbose(LOG_ERR, "tmpfs", where, "tmpfs", MS_NODEV|MS_STRICTATIME, options); + return mount_nofollow_verbose(LOG_ERR, "tmpfs", where, "tmpfs", MS_NODEV|MS_STRICTATIME, options); } static char *joined_and_escaped_lower_dirs(char **lower) { @@ -864,7 +868,7 @@ static int mount_overlay(const char *dest, CustomMount *m) { options = strjoina("lowerdir=", lower, ",upperdir=", escaped_source, ",workdir=", escaped_work_dir); } - return mount_verbose(LOG_ERR, "overlay", where, "overlay", m->read_only ? MS_RDONLY : 0, options); + return mount_nofollow_verbose(LOG_ERR, "overlay", where, "overlay", m->read_only ? MS_RDONLY : 0, options); } static int mount_inaccessible(const char *dest, CustomMount *m) { @@ -885,13 +889,13 @@ static int mount_inaccessible(const char *dest, CustomMount *m) { if (r < 0) return m->graceful ? 0 : r; - r = mount_verbose(m->graceful ? LOG_DEBUG : LOG_ERR, source, where, NULL, MS_BIND, NULL); + r = mount_nofollow_verbose(m->graceful ? LOG_DEBUG : LOG_ERR, source, where, NULL, MS_BIND, NULL); if (r < 0) return m->graceful ? 0 : r; - r = mount_verbose(m->graceful ? LOG_DEBUG : LOG_ERR, NULL, where, NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, NULL); + r = mount_nofollow_verbose(m->graceful ? LOG_DEBUG : LOG_ERR, NULL, where, NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, NULL); if (r < 0) { - (void) umount_verbose(where); + (void) umount_verbose(m->graceful ? LOG_DEBUG : LOG_ERR, where, UMOUNT_NOFOLLOW); return m->graceful ? 0 : r; } @@ -914,7 +918,7 @@ static int mount_arbitrary(const char *dest, CustomMount *m) { return log_error_errno(r, "Creating mount point for mount %s failed: %m", where); } - return mount_verbose(LOG_ERR, m->source, where, m->type_argument, 0, m->options); + return mount_nofollow_verbose(LOG_ERR, m->source, where, m->type_argument, 0, m->options); } int mount_custom( @@ -1013,7 +1017,7 @@ static int setup_volatile_state(const char *directory, uid_t uid_shift, const ch if (r > 0) options = buf; - return mount_verbose(LOG_ERR, "tmpfs", p, "tmpfs", MS_STRICTATIME, options); + return mount_nofollow_verbose(LOG_ERR, "tmpfs", p, "tmpfs", MS_STRICTATIME, options); } static int setup_volatile_yes(const char *directory, uid_t uid_shift, const char *selinux_apifs_context) { @@ -1058,7 +1062,7 @@ static int setup_volatile_yes(const char *directory, uid_t uid_shift, const char if (r > 0) options = buf; - r = mount_verbose(LOG_ERR, "tmpfs", template, "tmpfs", MS_STRICTATIME, options); + r = mount_nofollow_verbose(LOG_ERR, "tmpfs", template, "tmpfs", MS_STRICTATIME, options); if (r < 0) goto fail; @@ -1073,7 +1077,7 @@ static int setup_volatile_yes(const char *directory, uid_t uid_shift, const char goto fail; } - r = mount_verbose(LOG_ERR, f, t, NULL, MS_BIND|MS_REC, NULL); + r = mount_nofollow_verbose(LOG_ERR, f, t, NULL, MS_BIND|MS_REC, NULL); if (r < 0) goto fail; @@ -1085,7 +1089,7 @@ static int setup_volatile_yes(const char *directory, uid_t uid_shift, const char goto fail; } - r = mount_verbose(LOG_ERR, template, directory, NULL, MS_MOVE, NULL); + r = mount_nofollow_verbose(LOG_ERR, template, directory, NULL, MS_MOVE, NULL); if (r < 0) goto fail; @@ -1095,10 +1099,11 @@ static int setup_volatile_yes(const char *directory, uid_t uid_shift, const char fail: if (bind_mounted) - (void) umount_verbose(t); + (void) umount_verbose(LOG_ERR, t, UMOUNT_NOFOLLOW); if (tmpfs_mounted) - (void) umount_verbose(template); + (void) umount_verbose(LOG_ERR, template, UMOUNT_NOFOLLOW); + (void) rmdir(template); return r; } @@ -1125,7 +1130,7 @@ static int setup_volatile_overlay(const char *directory, uid_t uid_shift, const if (r > 0) options = buf; - r = mount_verbose(LOG_ERR, "tmpfs", template, "tmpfs", MS_STRICTATIME, options); + r = mount_nofollow_verbose(LOG_ERR, "tmpfs", template, "tmpfs", MS_STRICTATIME, options); if (r < 0) goto finish; @@ -1155,11 +1160,11 @@ static int setup_volatile_overlay(const char *directory, uid_t uid_shift, const } options = strjoina("lowerdir=", escaped_directory, ",upperdir=", escaped_upper, ",workdir=", escaped_work); - r = mount_verbose(LOG_ERR, "overlay", directory, "overlay", 0, options); + r = mount_nofollow_verbose(LOG_ERR, "overlay", directory, "overlay", 0, options); finish: if (tmpfs_mounted) - (void) umount_verbose(template); + (void) umount_verbose(LOG_ERR, template, UMOUNT_NOFOLLOW); (void) rmdir(template); return r; @@ -1265,7 +1270,7 @@ int setup_pivot_root(const char *directory, const char *pivot_root_new, const ch return log_oom(); /* Remount directory_pivot_root_new to make it movable. */ - r = mount_verbose(LOG_ERR, directory_pivot_root_new, directory_pivot_root_new, NULL, MS_BIND, NULL); + r = mount_nofollow_verbose(LOG_ERR, directory_pivot_root_new, directory_pivot_root_new, NULL, MS_BIND, NULL); if (r < 0) goto done; @@ -1282,19 +1287,19 @@ int setup_pivot_root(const char *directory, const char *pivot_root_new, const ch goto done; } - r = mount_verbose(LOG_ERR, directory_pivot_root_new, pivot_tmp, NULL, MS_MOVE, NULL); + r = mount_nofollow_verbose(LOG_ERR, directory_pivot_root_new, pivot_tmp, NULL, MS_MOVE, NULL); if (r < 0) goto done; - r = mount_verbose(LOG_ERR, directory, pivot_tmp_pivot_root_old, NULL, MS_MOVE, NULL); + r = mount_nofollow_verbose(LOG_ERR, directory, pivot_tmp_pivot_root_old, NULL, MS_MOVE, NULL); if (r < 0) goto done; - r = mount_verbose(LOG_ERR, pivot_tmp, directory, NULL, MS_MOVE, NULL); + r = mount_nofollow_verbose(LOG_ERR, pivot_tmp, directory, NULL, MS_MOVE, NULL); if (r < 0) goto done; } else { - r = mount_verbose(LOG_ERR, directory_pivot_root_new, directory, NULL, MS_MOVE, NULL); + r = mount_nofollow_verbose(LOG_ERR, directory_pivot_root_new, directory, NULL, MS_MOVE, NULL); if (r < 0) goto done; } diff --git a/src/nspawn/nspawn-mount.h b/src/nspawn/nspawn-mount.h index 3898c74f18..8f9d094fae 100644 --- a/src/nspawn/nspawn-mount.h +++ b/src/nspawn/nspawn-mount.h @@ -19,6 +19,7 @@ typedef enum MountSettingsMask { MOUNT_MKDIR = 1 << 8, /* if set, make directory to mount over first */ MOUNT_TOUCH = 1 << 9, /* if set, touch file to mount over first */ MOUNT_PREFIX_ROOT = 1 << 10,/* if set, prefix the source path with the container's root directory */ + MOUNT_FOLLOW_SYMLINKS = 1 << 11,/* if set, we'll follow symlinks for the mount target */ } MountSettingsMask; typedef enum CustomMountType { diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 9ab131ef9b..ea5be3f72d 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -1918,9 +1918,9 @@ static int setup_timezone(const char *dest) { if (found == 0) /* missing? */ (void) touch(resolved); - r = mount_verbose(LOG_WARNING, "/etc/localtime", resolved, NULL, MS_BIND, NULL); + r = mount_nofollow_verbose(LOG_WARNING, "/etc/localtime", resolved, NULL, MS_BIND, NULL); if (r >= 0) - return mount_verbose(LOG_ERR, NULL, resolved, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NODEV, NULL); + return mount_nofollow_verbose(LOG_ERR, NULL, resolved, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NODEV, NULL); _fallthrough_; } @@ -2053,9 +2053,9 @@ static int setup_resolv_conf(const char *dest) { if (found == 0) /* missing? */ (void) touch(resolved); - r = mount_verbose(LOG_WARNING, what, resolved, NULL, MS_BIND, NULL); + r = mount_nofollow_verbose(LOG_WARNING, what, resolved, NULL, MS_BIND, NULL); if (r >= 0) - return mount_verbose(LOG_ERR, NULL, resolved, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NODEV, NULL); + return mount_nofollow_verbose(LOG_ERR, NULL, resolved, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NODEV, NULL); /* If that didn't work, let's copy the file */ } @@ -2107,11 +2107,11 @@ static int setup_boot_id(void) { from = TAKE_PTR(path); to = "/proc/sys/kernel/random/boot_id"; - r = mount_verbose(LOG_ERR, from, to, NULL, MS_BIND, NULL); + r = mount_nofollow_verbose(LOG_ERR, from, to, NULL, MS_BIND, NULL); if (r < 0) return r; - return mount_verbose(LOG_ERR, NULL, to, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); + return mount_nofollow_verbose(LOG_ERR, NULL, to, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); } static int copy_devnodes(const char *dest) { @@ -2170,7 +2170,7 @@ static int copy_devnodes(const char *dest) { r = touch(to); if (r < 0) return log_error_errno(r, "touch (%s) failed: %m", to); - r = mount_verbose(LOG_DEBUG, from, to, NULL, MS_BIND, NULL); + r = mount_nofollow_verbose(LOG_DEBUG, from, to, NULL, MS_BIND, NULL); if (r < 0) return log_error_errno(r, "Both mknod and bind mount (%s) failed: %m", to); } @@ -2258,7 +2258,7 @@ static int setup_pts(const char *dest) { if (r < 0) return log_error_errno(r, "Failed to create /dev/pts: %m"); - r = mount_verbose(LOG_ERR, "devpts", p, "devpts", MS_NOSUID|MS_NOEXEC, options); + r = mount_nofollow_verbose(LOG_ERR, "devpts", p, "devpts", MS_NOSUID|MS_NOEXEC, options); if (r < 0) return r; r = userns_lchown(p, 0, 0); @@ -2360,7 +2360,7 @@ static int setup_credentials(const char *root) { return log_error_errno(r, "Failed to create /run/host/credentials: %m"); q = prefix_roota(root, "/run/host/credentials"); - r = mount_verbose(LOG_ERR, NULL, q, "ramfs", MS_NOSUID|MS_NOEXEC|MS_NODEV, "mode=0700"); + r = mount_nofollow_verbose(LOG_ERR, NULL, q, "ramfs", MS_NOSUID|MS_NOEXEC|MS_NODEV, "mode=0700"); if (r < 0) return r; @@ -2397,11 +2397,11 @@ static int setup_credentials(const char *root) { return r; /* Make both mount and superblock read-only now */ - r = mount_verbose(LOG_ERR, NULL, q, NULL, MS_REMOUNT|MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); + r = mount_nofollow_verbose(LOG_ERR, NULL, q, NULL, MS_REMOUNT|MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); if (r < 0) return r; - return mount_verbose(LOG_ERR, NULL, q, NULL, MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, "mode=0500"); + return mount_nofollow_verbose(LOG_ERR, NULL, q, NULL, MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, "mode=0500"); } static int setup_kmsg(int kmsg_socket) { @@ -2429,7 +2429,7 @@ static int setup_kmsg(int kmsg_socket) { from = TAKE_PTR(fifo); - r = mount_verbose(LOG_ERR, from, "/proc/kmsg", NULL, MS_BIND, NULL); + r = mount_nofollow_verbose(LOG_ERR, from, "/proc/kmsg", NULL, MS_BIND, NULL); if (r < 0) return r; @@ -2595,7 +2595,7 @@ static int setup_journal(const char *directory) { if (r < 0) return log_error_errno(r, "Failed to create %s: %m", q); - r = mount_verbose(LOG_DEBUG, p, q, NULL, MS_BIND, NULL); + r = mount_nofollow_verbose(LOG_DEBUG, p, q, NULL, MS_BIND, NULL); if (r < 0) return log_error_errno(errno, "Failed to bind mount journal from host into guest: %m"); @@ -2700,16 +2700,16 @@ static int setup_propagate(const char *root) { return log_error_errno(r, "Failed to create /run/host/incoming: %m"); q = prefix_roota(root, "/run/host/incoming"); - r = mount_verbose(LOG_ERR, p, q, NULL, MS_BIND, NULL); + r = mount_nofollow_verbose(LOG_ERR, p, q, NULL, MS_BIND, NULL); if (r < 0) return r; - r = mount_verbose(LOG_ERR, NULL, q, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY, NULL); + r = mount_nofollow_verbose(LOG_ERR, NULL, q, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY, NULL); if (r < 0) return r; /* machined will MS_MOVE into that directory, and that's only supported for non-shared mounts. */ - return mount_verbose(LOG_ERR, NULL, q, NULL, MS_SLAVE, NULL); + return mount_nofollow_verbose(LOG_ERR, NULL, q, NULL, MS_SLAVE, NULL); } static int setup_machine_id(const char *directory) { @@ -3157,7 +3157,7 @@ static int inner_child( /* Creating a new user namespace means all MS_SHARED mounts become MS_SLAVE. Let's put them * back to MS_SHARED here, since that's what we want as defaults. (This will not reconnect * propagation, but simply create new peer groups for all our mounts). */ - r = mount_verbose(LOG_ERR, NULL, "/", NULL, MS_SHARED|MS_REC, NULL); + r = mount_follow_verbose(LOG_ERR, NULL, "/", NULL, MS_SHARED|MS_REC, NULL); if (r < 0) return r; } @@ -3542,7 +3542,7 @@ static int outer_child( /* Mark everything as slave, so that we still receive mounts from the real root, but don't propagate * mounts to the real root. */ - r = mount_verbose(LOG_ERR, NULL, "/", NULL, MS_SLAVE|MS_REC, NULL); + r = mount_follow_verbose(LOG_ERR, NULL, "/", NULL, MS_SLAVE|MS_REC, NULL); if (r < 0) return r; @@ -3600,7 +3600,7 @@ static int outer_child( * already, and thus don't need to be afraid of colliding with anyone else's mounts).*/ (void) mkdir_p("/run/systemd/nspawn-root", 0755); - r = mount_verbose(LOG_ERR, "/", "/run/systemd/nspawn-root", NULL, MS_BIND|MS_REC, NULL); + r = mount_nofollow_verbose(LOG_ERR, "/", "/run/systemd/nspawn-root", NULL, MS_BIND|MS_REC, NULL); if (r < 0) return r; @@ -3634,7 +3634,7 @@ static int outer_child( /* Make sure we always have a mount that we can move to root later on. */ if (!path_is_mount_point(directory, NULL, 0)) { - r = mount_verbose(LOG_ERR, directory, directory, NULL, MS_BIND|MS_REC, NULL); + r = mount_nofollow_verbose(LOG_ERR, directory, directory, NULL, MS_BIND|MS_REC, NULL); if (r < 0) return r; } @@ -3677,7 +3677,7 @@ static int outer_child( * enable moving the root directory mount to root later on. * https://github.com/systemd/systemd/issues/3847#issuecomment-562735251 */ - r = mount_verbose(LOG_ERR, NULL, directory, NULL, MS_SHARED|MS_REC, NULL); + r = mount_nofollow_verbose(LOG_ERR, NULL, directory, NULL, MS_SHARED|MS_REC, NULL); if (r < 0) return r; diff --git a/src/partition/repart.c b/src/partition/repart.c index b30a6894fb..3e1dcf53eb 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -2691,7 +2691,7 @@ static int partition_copy_files(Partition *p, const char *node) { _exit(EXIT_FAILURE); } - if (mount_verbose(LOG_ERR, node, fs, p->format, MS_NOATIME|MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL) < 0) + if (mount_nofollow_verbose(LOG_ERR, node, fs, p->format, MS_NOATIME|MS_NODEV|MS_NOEXEC|MS_NOSUID, NULL) < 0) _exit(EXIT_FAILURE); if (do_copy_files(p, fs) < 0) diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 3a2200f91e..eaf44f156c 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -1177,7 +1177,7 @@ static int mount_partition( return r; } - r = mount_verbose(LOG_DEBUG, node, p, fstype, MS_NODEV|(rw ? 0 : MS_RDONLY), options); + r = mount_nofollow_verbose(LOG_DEBUG, node, p, fstype, MS_NODEV|(rw ? 0 : MS_RDONLY), options); if (r < 0) return r; diff --git a/src/shared/mount-util.c b/src/shared/mount-util.c index 53fb46e7bc..e0a0315639 100644 --- a/src/shared/mount-util.c +++ b/src/shared/mount-util.c @@ -19,10 +19,60 @@ #include "parse-util.h" #include "path-util.h" #include "set.h" +#include "stat-util.h" #include "stdio-util.h" #include "string-util.h" #include "strv.h" +int mount_fd(const char *source, + int target_fd, + const char *filesystemtype, + unsigned long mountflags, + const void *data) { + + char path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; + + xsprintf(path, "/proc/self/fd/%i", target_fd); + if (mount(source, path, filesystemtype, mountflags, data) < 0) { + if (errno != ENOENT) + return -errno; + + /* ENOENT can mean two things: either that the source is missing, or that /proc/ isn't + * mounted. Check for the latter to generate better error messages. */ + if (proc_mounted() == 0) + return -ENOSYS; + + return -ENOENT; + } + + return 0; +} + +int mount_nofollow( + const char *source, + const char *target, + const char *filesystemtype, + unsigned long mountflags, + const void *data) { + + _cleanup_close_ int fd = -1; + + /* In almost all cases we want to manipulate the mount table without following symlinks, hence + * mount_nofollow() is usually the way to go. The only exceptions are environments where /proc/ is + * not available yet, since we need /proc/self/fd/ for this logic to work. i.e. during the early + * initialization of namespacing/container stuff where /proc is not yet mounted (and maybe even the + * fs to mount) we can only use traditional mount() directly. + * + * Note that this disables following only for the final component of the target, i.e symlinks within + * the path of the target are honoured, as are symlinks in the source path everywhere. */ + + fd = open(target, O_PATH|O_CLOEXEC|O_NOFOLLOW); + if (fd < 0) + return -errno; + + return mount_fd(source, fd, filesystemtype, mountflags, data); +} + int umount_recursive(const char *prefix, int flags) { int n = 0, r; bool again; @@ -79,14 +129,18 @@ static int get_mount_flags( struct libmnt_table *table, const char *path, unsigned long *ret) { + + _cleanup_close_ int fd = -1; struct libmnt_fs *fs; struct statvfs buf; const char *opts; - int r = 0; + int r; /* Get the mount flags for the mountpoint at "path" from "table". We have a fallback using statvfs() * in place (which provides us with mostly the same info), but it's just a fallback, since using it - * means triggering autofs or NFS mounts, which we'd rather avoid needlessly. */ + * means triggering autofs or NFS mounts, which we'd rather avoid needlessly. + * + * This generally doesn't follow symlinks. */ fs = mnt_table_find_target(table, path, MNT_ITER_FORWARD); if (!fs) { @@ -111,7 +165,11 @@ static int get_mount_flags( return 0; fallback: - if (statvfs(path, &buf) < 0) + fd = open(path, O_PATH|O_CLOEXEC|O_NOFOLLOW); + if (fd < 0) + return -errno; + + if (fstatvfs(fd, &buf) < 0) return -errno; /* The statvfs() flags and the mount flags mostly have the same values, but for some cases do @@ -254,14 +312,16 @@ int bind_remount_recursive_with_mountinfo( if (!set_contains(done, simplified) && !set_contains(todo, simplified)) { /* The prefix directory itself is not yet a mount, make it one. */ - if (mount(simplified, simplified, NULL, MS_BIND|MS_REC, NULL) < 0) - return -errno; + r = mount_nofollow(simplified, simplified, NULL, MS_BIND|MS_REC, NULL); + if (r < 0) + return r; orig_flags = 0; (void) get_mount_flags(table, simplified, &orig_flags); - if (mount(NULL, simplified, NULL, (orig_flags & ~flags_mask)|MS_BIND|MS_REMOUNT|new_flags, NULL) < 0) - return -errno; + r = mount_nofollow(NULL, simplified, NULL, (orig_flags & ~flags_mask)|MS_BIND|MS_REMOUNT|new_flags, NULL); + if (r < 0) + return r; log_debug("Made top-level directory %s a mount point.", prefix); @@ -302,8 +362,9 @@ int bind_remount_recursive_with_mountinfo( orig_flags = 0; (void) get_mount_flags(table, x, &orig_flags); - if (mount(NULL, x, NULL, (orig_flags & ~flags_mask)|MS_BIND|MS_REMOUNT|new_flags, NULL) < 0) - return -errno; + r = mount_nofollow(NULL, x, NULL, (orig_flags & ~flags_mask)|MS_BIND|MS_REMOUNT|new_flags, NULL); + if (r < 0) + return r; log_debug("Remounted %s read-only.", x); } @@ -352,8 +413,9 @@ int bind_remount_one_with_mountinfo( /* Try to reuse the original flag set */ (void) get_mount_flags(table, path, &orig_flags); - if (mount(NULL, path, NULL, (orig_flags & ~flags_mask)|MS_BIND|MS_REMOUNT|new_flags, NULL) < 0) - return -errno; + r = mount_nofollow(NULL, path, NULL, (orig_flags & ~flags_mask)|MS_BIND|MS_REMOUNT|new_flags, NULL); + if (r < 0) + return r; return 0; } @@ -548,13 +610,14 @@ static char* mount_flags_to_string(long unsigned flags) { return x; } -int mount_verbose( +int mount_verbose_full( int error_log_level, const char *what, const char *where, const char *type, unsigned long flags, - const char *options) { + const char *options, + bool follow_symlink) { _cleanup_free_ char *fl = NULL, *o = NULL; unsigned long f; @@ -583,17 +646,31 @@ int mount_verbose( else log_debug("Mounting %s on %s (%s \"%s\")...", strna(type), where, strnull(fl), strempty(o)); - if (mount(what, where, type, f, o) < 0) - return log_full_errno(error_log_level, errno, + + if (follow_symlink) + r = mount(what, where, type, f, o) < 0 ? -errno : 0; + else + r = mount_nofollow(what, where, type, f, o); + if (r < 0) + return log_full_errno(error_log_level, r, "Failed to mount %s (type %s) on %s (%s \"%s\"): %m", strna(what), strna(type), where, strnull(fl), strempty(o)); return 0; } -int umount_verbose(const char *what) { +int umount_verbose( + int error_log_level, + const char *what, + int flags) { + + assert(what); + log_debug("Umounting %s...", what); - if (umount(what) < 0) - return log_error_errno(errno, "Failed to unmount %s: %m", what); + + if (umount2(what, flags) < 0) + return log_full_errno(error_log_level, errno, + "Failed to unmount %s: %m", what); + return 0; } diff --git a/src/shared/mount-util.h b/src/shared/mount-util.h index 8fb597e7c0..ba5d6280d2 100644 --- a/src/shared/mount-util.h +++ b/src/shared/mount-util.h @@ -32,6 +32,9 @@ #define TMPFS_LIMITS_ROOTFS TMPFS_LIMITS_VAR #define TMPFS_LIMITS_VOLATILE_STATE TMPFS_LIMITS_VAR +int mount_fd(const char *source, int target_fd, const char *filesystemtype, unsigned long mountflags, const void *data); +int mount_nofollow(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const void *data); + int repeat_unmount(const char *path, int flags); int umount_recursive(const char *target, int flags); int bind_remount_recursive(const char *prefix, unsigned long new_flags, unsigned long flags_mask, char **deny_list); @@ -43,14 +46,39 @@ int mount_move_root(const char *path); DEFINE_TRIVIAL_CLEANUP_FUNC(FILE*, endmntent); #define _cleanup_endmntent_ _cleanup_(endmntentp) -int mount_verbose( +int mount_verbose_full( int error_log_level, const char *what, const char *where, const char *type, unsigned long flags, - const char *options); -int umount_verbose(const char *where); + const char *options, + bool follow_symlink); + +static inline int mount_follow_verbose( + int error_log_level, + const char *what, + const char *where, + const char *type, + unsigned long flags, + const char *options) { + return mount_verbose_full(error_log_level, what, where, type, flags, options, true); +} + +static inline int mount_nofollow_verbose( + int error_log_level, + const char *what, + const char *where, + const char *type, + unsigned long flags, + const char *options) { + return mount_verbose_full(error_log_level, what, where, type, flags, options, false); +} + +int umount_verbose( + int error_log_level, + const char *where, + int flags); int mount_option_mangle( const char *options, diff --git a/src/test/test-udev.c b/src/test/test-udev.c index 006fdb650f..00cab7bb45 100644 --- a/src/test/test-udev.c +++ b/src/test/test-udev.c @@ -45,8 +45,8 @@ static int fake_filesystems(void) { return log_error_errno(r, "Failed to detach mount namespace: %m"); for (size_t i = 0; i < ELEMENTSOF(fakefss); i++) { - r = mount_verbose(fakefss[i].ignore_mount_error ? LOG_NOTICE : LOG_ERR, - fakefss[i].src, fakefss[i].target, NULL, MS_BIND, NULL); + r = mount_nofollow_verbose(fakefss[i].ignore_mount_error ? LOG_NOTICE : LOG_ERR, + fakefss[i].src, fakefss[i].target, NULL, MS_BIND, NULL); if (r < 0 && !fakefss[i].ignore_mount_error) return r; } diff --git a/src/volatile-root/volatile-root.c b/src/volatile-root/volatile-root.c index 6a08464245..04c371077a 100644 --- a/src/volatile-root/volatile-root.c +++ b/src/volatile-root/volatile-root.c @@ -29,7 +29,7 @@ static int make_volatile(const char *path) { if (r < 0) return log_error_errno(r, "Couldn't generate volatile sysroot directory: %m"); - r = mount_verbose(LOG_ERR, "tmpfs", "/run/systemd/volatile-sysroot", "tmpfs", MS_STRICTATIME, "mode=755" TMPFS_LIMITS_ROOTFS); + r = mount_nofollow_verbose(LOG_ERR, "tmpfs", "/run/systemd/volatile-sysroot", "tmpfs", MS_STRICTATIME, "mode=755" TMPFS_LIMITS_ROOTFS); if (r < 0) goto finish_rmdir; @@ -38,7 +38,7 @@ static int make_volatile(const char *path) { goto finish_umount; } - r = mount_verbose(LOG_ERR, old_usr, "/run/systemd/volatile-sysroot/usr", NULL, MS_BIND|MS_REC, NULL); + r = mount_nofollow_verbose(LOG_ERR, old_usr, "/run/systemd/volatile-sysroot/usr", NULL, MS_BIND|MS_REC, NULL); if (r < 0) goto finish_umount; @@ -57,7 +57,7 @@ static int make_volatile(const char *path) { if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) log_warning_errno(errno, "Failed to remount %s MS_SLAVE|MS_REC, ignoring: %m", path); - r = mount_verbose(LOG_ERR, "/run/systemd/volatile-sysroot", path, NULL, MS_MOVE, NULL); + r = mount_nofollow_verbose(LOG_ERR, "/run/systemd/volatile-sysroot", path, NULL, MS_MOVE, NULL); finish_umount: (void) umount_recursive("/run/systemd/volatile-sysroot", 0); @@ -80,7 +80,7 @@ static int make_overlay(const char *path) { if (r < 0) return log_error_errno(r, "Couldn't create overlay sysroot directory: %m"); - r = mount_verbose(LOG_ERR, "tmpfs", "/run/systemd/overlay-sysroot", "tmpfs", MS_STRICTATIME, "mode=755" TMPFS_LIMITS_ROOTFS); + r = mount_nofollow_verbose(LOG_ERR, "tmpfs", "/run/systemd/overlay-sysroot", "tmpfs", MS_STRICTATIME, "mode=755" TMPFS_LIMITS_ROOTFS); if (r < 0) goto finish; @@ -103,11 +103,11 @@ static int make_overlay(const char *path) { } options = strjoina("lowerdir=", escaped_path, ",upperdir=/run/systemd/overlay-sysroot/upper,workdir=/run/systemd/overlay-sysroot/work"); - r = mount_verbose(LOG_ERR, "overlay", path, "overlay", 0, options); + r = mount_nofollow_verbose(LOG_ERR, "overlay", path, "overlay", 0, options); finish: if (tmpfs_mounted) - (void) umount_verbose("/run/systemd/overlay-sysroot"); + (void) umount_verbose(LOG_ERR, "/run/systemd/overlay-sysroot", UMOUNT_NOFOLLOW); (void) rmdir("/run/systemd/overlay-sysroot"); return r;