]> 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>
Tue, 4 Jun 2024 07:18:10 +0000 (09:18 +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>
(cherry picked from commit 2a684833d723e29af0ba772b3e6917492c69e023)

libmount/src/context.c
libmount/src/hook_mount.c
libmount/src/hook_subdir.c
libmount/src/mountP.h

index 5206c1d58797c52105f9f0be90b94453a3048b18..977cf311c47607ac995c9fecfde4f99d3aeb2ef9 100644 (file)
@@ -43,6 +43,8 @@
 
 #include <sys/wait.h>
 
+#include "mount-api-utils.h"
+
 /**
  * mnt_new_context:
  *
@@ -1790,6 +1792,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 f0cc381963dba1dbdabe9b5887b9877e8035adb9..10b226636911dcf91dec993dbf1b634cab7c9127 100644 (file)
@@ -259,43 +259,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__)))
@@ -423,7 +386,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;
@@ -501,7 +464,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;
@@ -638,7 +601,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 7da563b85d4650549c7bf1f30be0993840704c0d..2a2b8c2a491378bab5aadbc0ee549ae96232b2b1 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);
                set_syscall_status(cxt, "open_tree", fd >= 0);
@@ -256,13 +268,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 fcc40bffc599dd904ddd737edac465223a12817d..f437816278d52ede4b1073613b168ae86f16a647 100644 (file)
@@ -692,6 +692,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 */