Merge pull request #17144 from poettering/mount-nofollow

tree-wide: mostly avoid following symlinks when mounting
This commit is contained in:
Lennart Poettering 2020-09-23 21:46:02 +02:00 committed by GitHub
commit dee1f028f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 368 additions and 250 deletions

4
TODO
View File

@ -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

View File

@ -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");
}

View File

@ -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(

View File

@ -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);

View File

@ -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");

View File

@ -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. */

View File

@ -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;
}

View File

@ -5,6 +5,7 @@
#include <poll.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/xattr.h>
#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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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(

View File

@ -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;
}

View File

@ -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 {

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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;
}

View File

@ -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,

View File

@ -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;
}

View File

@ -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;