aboutsummaryrefslogtreecommitdiffstats
path: root/libmount/src
diff options
context:
space:
mode:
authorKarel Zak <kzak@redhat.com>2024-06-03 12:33:01 +0200
committerKarel Zak <kzak@redhat.com>2024-06-03 14:45:11 +0200
commit2a684833d723e29af0ba772b3e6917492c69e023 (patch)
tree74c909042240770e9c0b92d8794143a947c323d3 /libmount/src
parent0284eb3a8a6505dd9745b042089046ad368bfe74 (diff)
downloadutil-linux-2a684833d723e29af0ba772b3e6917492c69e023.tar.gz
libmount: fix tree FD usage in subdir hook
* 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>
Diffstat (limited to 'libmount/src')
-rw-r--r--libmount/src/context.c41
-rw-r--r--libmount/src/hook_mount.c43
-rw-r--r--libmount/src/hook_subdir.c31
-rw-r--r--libmount/src/mountP.h3
4 files changed, 66 insertions, 52 deletions
diff --git a/libmount/src/context.c b/libmount/src/context.c
index 332e456e66..c91b0148e1 100644
--- a/libmount/src/context.c
+++ b/libmount/src/context.c
@@ -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
*/
diff --git a/libmount/src/hook_mount.c b/libmount/src/hook_mount.c
index 6b7caff853..cd57bdbcbc 100644
--- a/libmount/src/hook_mount.c
+++ b/libmount/src/hook_mount.c
@@ -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;
diff --git a/libmount/src/hook_subdir.c b/libmount/src/hook_subdir.c
index 65674aa9e8..99c30e1738 100644
--- a/libmount/src/hook_subdir.c
+++ b/libmount/src/hook_subdir.c
@@ -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;
diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h
index d3232bf1c4..b855a90b39 100644
--- a/libmount/src/mountP.h
+++ b/libmount/src/mountP.h
@@ -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 */