]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
mount-util: add fd_make_mount_point() helper
authorLennart Poettering <lennart@poettering.net>
Fri, 2 Jun 2023 16:23:44 +0000 (18:23 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 2 Jun 2023 16:43:10 +0000 (18:43 +0200)
src/shared/mount-util.c
src/shared/mount-util.h
src/test/test-mount-util.c

index 81b681afa7d76c480956159aff66fdf3a75ae2b1..366f59ee82b530e90c3af14cd33994094501509a 100644 (file)
@@ -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;
index b33e739b42ad915d27ebffe002f63dc8dca5ed83..7214cf1e52e61a9dce23952ce6cea12d9a06ae88 100644 (file)
@@ -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,
index 2529b2f0eee87852e185c01b18271461ed4e8076..021eff1548cec90e0f98a82c1e48032848937b8e 100644 (file)
@@ -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");