]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: (subdir) restrict for real mounts only
authorKarel Zak <kzak@redhat.com>
Wed, 9 Apr 2025 10:15:57 +0000 (12:15 +0200)
committerKarel Zak <kzak@redhat.com>
Mon, 26 May 2025 09:27:31 +0000 (11:27 +0200)
It's now possible to use, for example, for bind operations, but it
does not make sense as you can specify the target with the
subdirectory.

Signed-off-by: Karel Zak <kzak@redhat.com>
(cherry picked from commit 437a271f7108f689d350f1b3d837490d3d283c3c)

libmount/src/hook_subdir.c
sys-utils/mount.8.adoc

index 1e5d79958a5cfe5d3b082689f050cd8e94380d3a..7cbb2c88d465a5f80ab67a0c145f7c39739826f0 100644 (file)
@@ -313,6 +313,7 @@ static int is_subdir_required(struct libmnt_context *cxt, int *rc, char **subdir
        struct libmnt_optlist *ol;
        struct libmnt_opt *opt;
        const char *dir = NULL;
+       unsigned long flags = 0;
 
        assert(cxt);
        assert(rc);
@@ -328,16 +329,26 @@ static int is_subdir_required(struct libmnt_context *cxt, int *rc, char **subdir
                return 0;
 
        dir = mnt_opt_get_value(opt);
-
        if (!dir || !*dir) {
                DBG(HOOK, ul_debug("failed to parse X-mount.subdir '%s'", dir));
                *rc = -MNT_ERR_MOUNTOPT;
-       } else {
-               *subdir = strdup(dir);
-               if (!*subdir)
-                       *rc = -ENOMEM;
+               return 0;
+       }
+
+       *rc = mnt_optlist_get_flags(ol, &flags, cxt->map_linux, 0);
+       if (*rc)
+               return 0;
+
+       if (flags & MS_REMOUNT || flags & MS_BIND || flags & MS_MOVE
+           || mnt_context_propagation_only(cxt)) {
+               DBG(HOOK, ul_debug("ignore subdir= (bind/move/remount/..)"));
+               return 0;
        }
 
+       *subdir = strdup(dir);
+       if (!*subdir)
+               *rc = -ENOMEM;
+
        return *rc == 0;
 }
 
index 6a17cd5eb63a07a492af86679d479cecd36849f6..d9ce31fd4d9db2a0ae6d305c35bc5c00db5484fd 100644 (file)
@@ -763,8 +763,10 @@ Note that *mount*(8) still sanitizes and canonicalizes the source and target pat
 *X-mount.noloop*::
 Do not create and mount a loop device, even if the source of the mount is a regular file.
 
-*X-mount.subdir=*__directory__::
-Allow mounting sub-directory from a filesystem instead of the root directory. For now, this feature is implemented by temporary filesystem root directory mount in unshared namespace and then bind the sub-directory to the final mount point and umount the root of the filesystem. The sub-directory mount shows up atomically for the rest of the system although it is implemented by multiple *mount*(2) syscalls.
+**X-mount.subdir=**_directory_::
+Allow mounting a subdirectory of a filesystem instead of the root directory. This is effective only when a new instance of a filesystem is attached to the system. The option is silently ignored for operations like remount, bind mount, or move.
++
+For now, this feature is implemented by a temporary filesystem root-directory mount in an unshared namespace and then binding the sub-directory to the final mount point and unmounting the root of the filesystem. The sub-directory mount shows up atomically for the rest of the system although it is implemented by multiple *mount*(2) syscalls.
 +
 Note that this feature will not work in session with an unshared private mount namespace (after *unshare --mount*) on old kernels or with *mount*(8) without support for file-descriptors-based mount kernel API. In this case, you need *unshare --mount --propagation shared*.
 +