From: Lennart Poettering Date: Fri, 2 Jun 2023 16:23:44 +0000 (+0200) Subject: mount-util: add fd_make_mount_point() helper X-Git-Tag: v254-rc1~298^2~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f9ad896ee2a7c14b6c51bcc26547b82761ec0ab3;p=thirdparty%2Fsystemd.git mount-util: add fd_make_mount_point() helper --- diff --git a/src/shared/mount-util.c b/src/shared/mount-util.c index 81b681afa7d..366f59ee82b 100644 --- a/src/shared/mount-util.c +++ b/src/shared/mount-util.c @@ -1099,6 +1099,24 @@ int make_mount_point(const char *path) { return 1; } +int fd_make_mount_point(int fd) { + int r; + + assert(fd >= 0); + + r = fd_is_mount_point(fd, NULL, 0); + if (r < 0) + return log_debug_errno(r, "Failed to determine whether file descriptor is a mount point: %m"); + if (r > 0) + return 0; + + r = mount_follow_verbose(LOG_DEBUG, FORMAT_PROC_FD_PATH(fd), FORMAT_PROC_FD_PATH(fd), NULL, MS_BIND|MS_REC, NULL); + if (r < 0) + return r; + + return 1; +} + int make_userns(uid_t uid_shift, uid_t uid_range, uid_t owner, RemountIdmapping idmapping) { _cleanup_close_ int userns_fd = -EBADF; _cleanup_free_ char *line = NULL; diff --git a/src/shared/mount-util.h b/src/shared/mount-util.h index b33e739b42a..7214cf1e52e 100644 --- a/src/shared/mount-util.h +++ b/src/shared/mount-util.h @@ -100,6 +100,7 @@ int bind_mount_in_namespace(pid_t target, const char *propagate_path, const char 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); int make_mount_point(const char *path); +int fd_make_mount_point(int fd); typedef enum RemountIdmapping { REMOUNT_IDMAPPING_NONE, diff --git a/src/test/test-mount-util.c b/src/test/test-mount-util.c index 2529b2f0eee..021eff1548c 100644 --- a/src/test/test-mount-util.c +++ b/src/test/test-mount-util.c @@ -519,6 +519,55 @@ TEST(umount_recursive) { } } +TEST(fd_make_mount_point) { + _cleanup_(rm_rf_physical_and_freep) char *t = NULL; + _cleanup_free_ char *s = NULL; + int r; + + if (geteuid() != 0 || have_effective_cap(CAP_SYS_ADMIN) <= 0) { + (void) log_tests_skipped("not running privileged"); + return; + } + + assert_se(mkdtemp_malloc(NULL, &t) >= 0); + + assert_se(asprintf(&s, "%s/somerandomname%" PRIu64, t, random_u64()) >= 0); + assert_se(s); + assert_se(mkdir(s, 0700) >= 0); + + r = safe_fork("(make_mount-point)", + FORK_RESET_SIGNALS | + FORK_CLOSE_ALL_FDS | + FORK_DEATHSIG | + FORK_WAIT | + FORK_REOPEN_LOG | + FORK_LOG | + FORK_NEW_MOUNTNS | + FORK_MOUNTNS_SLAVE, + NULL); + assert_se(r >= 0); + + if (r == 0) { + _cleanup_close_ int fd = -EBADF, fd2 = -EBADF; + + fd = open(s, O_PATH|O_CLOEXEC); + assert_se(fd >= 0); + + assert_se(fd_is_mount_point(fd, NULL, AT_SYMLINK_FOLLOW) == 0); + + assert_se(fd_make_mount_point(fd) > 0); + + /* Reopen the inode so that we end up on the new mount */ + fd2 = open(s, O_PATH|O_CLOEXEC); + + assert_se(fd_is_mount_point(fd2, NULL, AT_SYMLINK_FOLLOW) > 0); + + assert_se(fd_make_mount_point(fd2) == 0); + + _exit(EXIT_SUCCESS); + } +} + static int intro(void) { /* Create a dummy network interface for testing remount_sysfs(). */ (void) system("ip link add dummy-test-mnt type dummy");