From a789f72ed23afeb4324b880c5207d067ff5ff11c Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 20 Apr 2023 18:45:09 +0200 Subject: mount-util: add umount_and_free() helper --- src/shared/mount-util.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/shared') diff --git a/src/shared/mount-util.h b/src/shared/mount-util.h index d63fddeb10..8a84d61622 100644 --- a/src/shared/mount-util.h +++ b/src/shared/mount-util.h @@ -83,6 +83,14 @@ static inline char* umount_and_rmdir_and_free(char *p) { } DEFINE_TRIVIAL_CLEANUP_FUNC(char*, umount_and_rmdir_and_free); +static inline char *umount_and_free(char *p) { + PROTECT_ERRNO; + if (p) + (void) umount_recursive(p, 0); + return mfree(p); +} +DEFINE_TRIVIAL_CLEANUP_FUNC(char*, umount_and_free); + int bind_mount_in_namespace(pid_t target, const char *propagate_path, const char *incoming_path, const char *src, const char *dest, bool read_only, bool make_file_or_directory); int mount_image_in_namespace(pid_t target, const char *propagate_path, const char *incoming_path, const char *src, const char *dest, bool read_only, bool make_file_or_directory, const MountOptions *options, const ImagePolicy *image_policy); -- cgit v1.2.1 From 3690bfb5b2279b75840d19a9b2763b00318b05c7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 15 May 2023 11:35:15 +0200 Subject: namespace: introduce a common dir in /run/ that we can use to see new root fs up on This creates a new dir /run/systemd/mount-rootfs/ early in PID 1 that thus always exists. It's supposed to be used by any code that creates its own mount namespace and then sets up a new root dir to switch into. So far in many cases we used a temporary dir (which needed explicit clean-up) or a purpose-specific fixed dir. Let's create a common dir instead, that always exists (as it is created in PID 1 early on, always). Besides making things more robust, as manual clean-up of the inode is not necessary anymore this also opens the door for unprivileged programs to use the same dir, since it now always exists. Set the access mode to 555 (instead of the otherwise previously used 0755, 0700 or similar), so that unprivileged programs can access it, but we make clear it's not supposed to be written directly to, by anyone, not even root. --- src/shared/mount-setup.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src/shared') diff --git a/src/shared/mount-setup.c b/src/shared/mount-setup.c index a920e8a92a..901c3cd777 100644 --- a/src/shared/mount-setup.c +++ b/src/shared/mount-setup.c @@ -554,6 +554,11 @@ int mount_setup(bool loaded_policy, bool leave_propagation) { (void) mkdir_label("/run/systemd", 0755); (void) mkdir_label("/run/systemd/system", 0755); + /* Make sure there's always a place where sandboxed environments can mount root file systems they are + * about to move into, even when unprivileged, without having to create a temporary one in /tmp/ + * (which they then have to keep track of and clean) */ + (void) mkdir_label("/run/systemd/mount-rootfs", 0555); + /* Make sure we have a mount point to hide in sandboxes */ (void) mkdir_label("/run/credentials", 0755); -- cgit v1.2.1 From a4b3e9423696f604be33b4ab93c4bb5c6c807554 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 15 May 2023 11:49:48 +0200 Subject: dissect-image: port mount_image_privately_interactively() to use /run/systemd/mount-rootfs/ too Let's use the same common directory as the unit logic uses. This means we have less to clean up, and opens the door to eventually allow unprivileged operation of the mount_image_privately_interactively() logic. --- src/shared/dissect-image.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) (limited to 'src/shared') diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index b84ef46442..39f75dd0dd 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -3667,8 +3667,7 @@ int mount_image_privately_interactively( _cleanup_(verity_settings_done) VeritySettings verity = VERITY_SETTINGS_DEFAULT; _cleanup_(loop_device_unrefp) LoopDevice *d = NULL; _cleanup_(dissected_image_unrefp) DissectedImage *dissected_image = NULL; - _cleanup_(rmdir_and_freep) char *created_dir = NULL; - _cleanup_free_ char *temp = NULL; + _cleanup_free_ char *dir = NULL; int r; /* Mounts an OS image at a temporary place, inside a newly created mount namespace of our own. This @@ -3676,7 +3675,6 @@ int mount_image_privately_interactively( * easily. */ assert(image); - assert(ret_directory); assert(ret_loop_device); /* We intend to mount this right-away, hence add the partitions if needed and pin them. */ @@ -3687,10 +3685,6 @@ int mount_image_privately_interactively( if (r < 0) return log_error_errno(r, "Failed to load root hash data: %m"); - r = tempfn_random_child(NULL, program_invocation_short_name, &temp); - if (r < 0) - return log_error_errno(r, "Failed to generate temporary mount directory: %m"); - r = loop_device_make_by_path( image, FLAGS_SET(flags, DISSECT_IMAGE_DEVICE_READ_ONLY) ? O_RDONLY : O_RDWR, @@ -3723,13 +3717,16 @@ int mount_image_privately_interactively( if (r < 0) return log_error_errno(r, "Failed to detach mount namespace: %m"); - r = mkdir_p(temp, 0700); + r = mkdir_p("/run/systemd/mount-rootfs", 0555); if (r < 0) return log_error_errno(r, "Failed to create mount point: %m"); - created_dir = TAKE_PTR(temp); - - r = dissected_image_mount_and_warn(dissected_image, created_dir, UID_INVALID, UID_INVALID, flags); + r = dissected_image_mount_and_warn( + dissected_image, + "/run/systemd/mount-rootfs", + /* uid_shift= */ UID_INVALID, + /* uid_range= */ UID_INVALID, + flags); if (r < 0) return r; @@ -3741,19 +3738,26 @@ int mount_image_privately_interactively( if (r < 0) return log_error_errno(r, "Failed to relinquish DM and loopback block devices: %m"); + if (ret_directory) { + dir = strdup("/run/systemd/mount-rootfs"); + if (!dir) + return log_oom(); + } + if (ret_dir_fd) { _cleanup_close_ int dir_fd = -EBADF; - dir_fd = open(created_dir, O_CLOEXEC|O_DIRECTORY); + dir_fd = open("/run/systemd/mount-rootfs", O_CLOEXEC|O_DIRECTORY); if (dir_fd < 0) return log_error_errno(errno, "Failed to open mount point directory: %m"); *ret_dir_fd = TAKE_FD(dir_fd); } - *ret_directory = TAKE_PTR(created_dir); - *ret_loop_device = TAKE_PTR(d); + if (ret_directory) + *ret_directory = TAKE_PTR(dir); + *ret_loop_device = TAKE_PTR(d); return 0; } -- cgit v1.2.1