]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: fix tree FD usage in subdir hook
authorKarel Zak <kzak@redhat.com>
Mon, 3 Jun 2024 10:33:01 +0000 (12:33 +0200)
committerKarel Zak <kzak@redhat.com>
Mon, 3 Jun 2024 12:45:11 +0000 (14:45 +0200)
* Initialize the tree file descriptor in the hook_subdir.c module if
  it has not been initialized yet. (hook_mount.c does not open the
  tree if the mount.<type> helper will be executed.)

* Move the function to open the tree to context.c to make it more
  generic and usable in more places.

Reported-by: Linus Heckemann <git@sphalerite.org>
Signed-off-by: Karel Zak <kzak@redhat.com>
libmount/src/context.c
libmount/src/hook_mount.c
libmount/src/hook_subdir.c
libmount/src/mountP.h

index 332e456e66bccc41ec5bc076a0cdd22fcaccd69b..c91b0148e1cd4fe7bd5f14f1f4a67233debafb88 100644 (file)
@@ -44,6 +44,8 @@
 #include <stdarg.h>
 #include <sys/wait.h>
 
+#include "mount-api-utils.h"
+
 /**
  * mnt_new_context:
  *
@@ -1791,6 +1793,45 @@ int mnt_context_set_mountdata(struct libmnt_context *cxt, void *data)
        return 0;
 }
 
+#ifdef USE_LIBMOUNT_MOUNTFD_SUPPORT
+int mnt_context_open_tree(struct libmnt_context *cxt, const char *path, unsigned long mflg)
+{
+       unsigned long oflg = OPEN_TREE_CLOEXEC;
+       int rc = 0, fd = -1;
+
+       if (mflg == (unsigned long) -1) {
+               rc = mnt_optlist_get_flags(cxt->optlist, &mflg, cxt->map_linux, 0);
+               if (rc)
+                       return rc;
+       }
+       if (!path) {
+               path = mnt_fs_get_target(cxt->fs);
+               if (!path)
+                       return -EINVAL;
+       }
+
+       /* Classic -oremount,bind,ro is not bind operation, it's just
+        * VFS flags update only */
+       if ((mflg & MS_BIND) && !(mflg & MS_REMOUNT)) {
+               oflg |= OPEN_TREE_CLONE;
+
+               if (mnt_optlist_is_rbind(cxt->optlist))
+                       oflg |= AT_RECURSIVE;
+       }
+
+       if (cxt->force_clone)
+               oflg |= OPEN_TREE_CLONE;
+
+       DBG(CXT, ul_debugobj(cxt, "open_tree(path=%s%s%s)", path,
+                               oflg & OPEN_TREE_CLONE ? " clone" : "",
+                               oflg & AT_RECURSIVE ? " recursive" : ""));
+       fd = open_tree(AT_FDCWD, path, oflg);
+       mnt_context_syscall_save_status(cxt, "open_tree", fd >= 0);
+
+       return fd;
+}
+#endif
+
 /*
  * Translates LABEL/UUID/path to mountable path
  */
index 6b7caff853003189bbe57d6e940f38405113c184..cd57bdbcbc2f7fa0c11f80017879cb3fceb38793 100644 (file)
@@ -255,43 +255,6 @@ static int open_fs_configuration_context(struct libmnt_context *cxt,
        return api->fd_fs;
 }
 
-static int open_mount_tree(struct libmnt_context *cxt, const char *path, unsigned long mflg)
-{
-       unsigned long oflg = OPEN_TREE_CLOEXEC;
-       int rc = 0, fd = -1;
-
-       if (mflg == (unsigned long) -1) {
-               rc = mnt_optlist_get_flags(cxt->optlist, &mflg, cxt->map_linux, 0);
-               if (rc)
-                       return rc;
-       }
-       if (!path) {
-               path = mnt_fs_get_target(cxt->fs);
-               if (!path)
-                       return -EINVAL;
-       }
-
-       /* Classic -oremount,bind,ro is not bind operation, it's just
-        * VFS flags update only */
-       if ((mflg & MS_BIND) && !(mflg & MS_REMOUNT)) {
-               oflg |= OPEN_TREE_CLONE;
-
-               if (mnt_optlist_is_rbind(cxt->optlist))
-                       oflg |= AT_RECURSIVE;
-       }
-
-       if (cxt->force_clone)
-               oflg |= OPEN_TREE_CLONE;
-
-       DBG(HOOK, ul_debug("open_tree(path=%s%s%s)", path,
-                               oflg & OPEN_TREE_CLONE ? " clone" : "",
-                               oflg & AT_RECURSIVE ? " recursive" : ""));
-       fd = open_tree(AT_FDCWD, path, oflg);
-       hookset_set_syscall_status(cxt, "open_tree", fd >= 0);
-
-       return fd;
-}
-
 static int hook_create_mount(struct libmnt_context *cxt,
                        const struct libmnt_hookset *hs,
                        void *data __attribute__((__unused__)))
@@ -419,7 +382,7 @@ static int set_vfsflags(struct libmnt_context *cxt,
        /* fallback only; necessary when init_sysapi() during preparation
         * cannot open the tree -- for example when we call /sbin/mount.<type> */
        if (api->fd_tree < 0 && mnt_fs_get_target(cxt->fs)) {
-               rc = api->fd_tree = open_mount_tree(cxt, NULL, (unsigned long) -1);
+               rc = api->fd_tree = mnt_context_open_tree(cxt, NULL, (unsigned long) -1);
                if (rc < 0)
                        return rc;
                rc = 0;
@@ -497,7 +460,7 @@ static int hook_set_propagation(struct libmnt_context *cxt,
        /* fallback only; necessary when init_sysapi() during preparation
         * cannot open the tree -- for example when we call /sbin/mount.<type> */
        if (api->fd_tree < 0 && mnt_fs_get_target(cxt->fs)) {
-               rc = api->fd_tree = open_mount_tree(cxt, NULL, (unsigned long) -1);
+               rc = api->fd_tree = mnt_context_open_tree(cxt, NULL, (unsigned long) -1);
                if (rc < 0)
                        goto done;
                rc = 0;
@@ -634,7 +597,7 @@ static int init_sysapi(struct libmnt_context *cxt,
                return -ENOMEM;
 
        if (path) {
-               api->fd_tree = open_mount_tree(cxt, path, flags);
+               api->fd_tree = mnt_context_open_tree(cxt, path, flags);
                if (api->fd_tree < 0)
                        goto fail;
 
index 65674aa9e8e68d99889e63a392d6d40a866e551b..99c30e173878c1a26374447fbf72b5ebb1184f96 100644 (file)
@@ -165,17 +165,29 @@ static int tmptgt_cleanup(struct hookset_data *hsd)
 static int do_mount_subdir(
                        struct libmnt_context *cxt,
                        struct hookset_data *hsd,
-                       const char *root,
-                       const char *target)
+                       const char *root)
 {
        int rc = 0;
        const char *subdir = hsd->subdir;
+       const char *target;
 
 #ifdef USE_LIBMOUNT_MOUNTFD_SUPPORT
-       struct libmnt_sysapi *api;
+       struct libmnt_sysapi *api = mnt_context_get_sysapi(cxt);
+
+       /* fallback only; necessary when hook_mount.c during preparation
+        * cannot open the tree -- for example when we call /sbin/mount.<type> */
+       if (api && api->fd_tree < 0) {
+               api->fd_tree = mnt_context_open_tree(cxt, NULL, (unsigned long) -1);
+               if (api->fd_tree < 0)
+                       return api->fd_tree;
+       }
+#endif
+       /* reset to the original mountpoint */
+       mnt_fs_set_target(cxt->fs, hsd->org_target);
+       target = mnt_fs_get_target(cxt->fs);
 
-       api = mnt_context_get_sysapi(cxt);
-       if (api) {
+#ifdef USE_LIBMOUNT_MOUNTFD_SUPPORT
+       if (api && api->fd_tree >= 0) {
                /* FD based way - unfortunately, it's impossible to open
                 * sub-directory on not-yet attached mount. It means
                 * hook_mount.c attaches FS to temporary directory, and we
@@ -186,7 +198,7 @@ static int do_mount_subdir(
                 */
                int fd;
 
-               DBG(HOOK, ul_debug("attach subdir  %s", subdir));
+               DBG(HOOK, ul_debug("attach subdir '%s'", subdir));
                fd = open_tree(api->fd_tree, subdir,
                                        OPEN_TREE_CLOEXEC | OPEN_TREE_CLONE);
                mnt_context_syscall_save_status(cxt, "open_tree", fd >= 0);
@@ -255,13 +267,8 @@ static int hook_mount_post(
        if (!hsd || !hsd->subdir)
                return 0;
 
-       /* reset to the original mountpoint */
-       mnt_fs_set_target(cxt->fs, hsd->org_target);
-
        /* bind subdir to the real target, umount temporary target */
-       rc = do_mount_subdir(cxt, hsd,
-                       MNT_PATH_TMPTGT,
-                       mnt_fs_get_target(cxt->fs));
+       rc = do_mount_subdir(cxt, hsd, MNT_PATH_TMPTGT);
        if (rc)
                return rc;
 
index d3232bf1c44d5dd1b3a9fb808a16d4964258474e..b855a90b3945cc9c028fb5cc53d70f15c9f59642 100644 (file)
@@ -679,6 +679,9 @@ static inline struct libmnt_sysapi *mnt_context_get_sysapi(struct libmnt_context
 {
        return mnt_context_get_hookset_data(cxt, &hookset_mount);
 }
+
+int mnt_context_open_tree(struct libmnt_context *cxt, const char *path, unsigned long mflg);
+
 #endif
 
 #endif /* _LIBMOUNT_PRIVATE_H */