]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: change propagation of /run for X-mount.subdir
authorKarel Zak <kzak@redhat.com>
Thu, 12 Aug 2021 10:12:39 +0000 (12:12 +0200)
committerKarel Zak <kzak@redhat.com>
Thu, 12 Aug 2021 10:12:39 +0000 (12:12 +0200)
We do not need to create a new mount node from /run/mount/tmptgt
(where we mount filesystem root), because /run is already mount
node in all mainstream distros, and we can use MS_PRIVATE for
this top-level directory. There is still fallback if /run is
on root filesystem.

This solution reduces number of mount operations, with the patch the
subdir implementation is:

 * open current namespace from /proc/self/ns/mnt
 * mkdir /run/mount/tmptg (if it does not exist)
 * make /run private by mount(MS_PRIVATE)
 * mount filesystem to /run/mount/tmptg
 * bind mount /run/mount/tmptg/<subdir> to <target>
 * umount /run/mount/tmptg
 * setns() to the original namespace

Signed-off-by: Karel Zak <kzak@redhat.com>
libmount/src/utils.c

index 1a8a29463670e4c8f626383d26cdaff79286d1b4..dc8f7c9eb331314ad5c38811186c4479648e2507 100644 (file)
@@ -1141,17 +1141,12 @@ done:
  */
 int mnt_tmptgt_unshare(int *old_ns_fd)
 {
-       int rc = 0, fd = -1, mounted = 0;
+       int rc = 0, fd = -1;
 
        assert(old_ns_fd);
 
        *old_ns_fd = -1;
 
-       /* create directory */
-       rc = ul_mkdir_p(MNT_PATH_TMPTGT, S_IRWXU);
-       if (rc)
-               goto fail;
-
        /* remember the current namespace */
        fd = open("/proc/self/ns/mnt", O_RDONLY | O_CLOEXEC);
        if (fd < 0)
@@ -1161,25 +1156,30 @@ int mnt_tmptgt_unshare(int *old_ns_fd)
        if (unshare(CLONE_NEWNS) != 0)
                goto fail;
 
-       /* make the directory private */
-       mounted = mount(MNT_PATH_TMPTGT, MNT_PATH_TMPTGT, "none", MS_BIND, NULL) == 0;
-       if (!mounted)
-               goto fail;
-       if (mount("none", MNT_PATH_TMPTGT, NULL, MS_PRIVATE, NULL) != 0)
+       /* create directory */
+       rc = ul_mkdir_p(MNT_PATH_TMPTGT, S_IRWXU);
+       if (rc)
                goto fail;
 
+       /* try to set top-level directory as private, this is possible if
+        * MNT_RUNTIME_TOPDIR (/run) is a separated filesystem. */
+       if (mount("none", MNT_RUNTIME_TOPDIR, NULL, MS_PRIVATE, NULL) != 0) {
+
+               /* failed; create a mountpoint from MNT_PATH_TMPTGT */
+               if (mount(MNT_PATH_TMPTGT, MNT_PATH_TMPTGT, "none", MS_BIND, NULL) != 0)
+                       goto fail;
+               if (mount("none", MNT_PATH_TMPTGT, NULL, MS_PRIVATE, NULL) != 0)
+                       goto fail;
+       }
+
        DBG(UTILS, ul_debug(MNT_PATH_TMPTGT " unshared"));
        *old_ns_fd = fd;
        return 0;
 fail:
        if (rc == 0)
                rc = errno ? -errno : -EINVAL;
-       if (mounted)
-               umount(MNT_PATH_TMPTGT);
-       if (fd >= 0) {
-               setns(fd, CLONE_NEWNS);         /* restore original NS */
-               close(fd);
-       }
+
+       mnt_tmptgt_cleanup(fd);
        DBG(UTILS, ul_debug(MNT_PATH_TMPTGT " unshare failed"));
        return rc;
 }