From cbf05f69587111d88d0dc3b16bb4f9fd934a0f62 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Mon, 11 Aug 2025 13:07:38 +0200 Subject: [PATCH] libmount: add MOVE_MOUNT_BENEATH support Fixes: https://github.com/util-linux/util-linux/issues/2604 Signed-off-by: Karel Zak --- include/mount-api-utils.h | 6 +++++- libmount/docs/libmount-sections.txt | 2 ++ libmount/src/context.c | 26 ++++++++++++++++++++++++++ libmount/src/hook_mount.c | 7 ++++++- libmount/src/libmount.h.in | 3 +++ libmount/src/libmount.sym | 2 ++ libmount/src/mountP.h | 1 + 7 files changed, 45 insertions(+), 2 deletions(-) diff --git a/include/mount-api-utils.h b/include/mount-api-utils.h index 79b50101d..920d6766a 100644 --- a/include/mount-api-utils.h +++ b/include/mount-api-utils.h @@ -65,8 +65,12 @@ static inline int open_tree(int dfd, const char *filename, unsigned int flags) # define MOVE_MOUNT_SET_GROUP 0x00000100 /* Set sharing group instead */ #endif +#ifndef MOVE_MOUNT_BENEATH +# define MOVE_MOUNT_BENEATH 0x00000200 /* Mount beneath top mount */ +#endif + #ifndef MOVE_MOUNT__MASK -# define MOVE_MOUNT__MASK 0x00000077 +# define MOVE_MOUNT__MASK 0x00000377 #endif #if !defined(HAVE_MOVE_MOUNT) && defined(SYS_move_mount) diff --git a/libmount/docs/libmount-sections.txt b/libmount/docs/libmount-sections.txt index 91d778644..607036218 100644 --- a/libmount/docs/libmount-sections.txt +++ b/libmount/docs/libmount-sections.txt @@ -31,6 +31,7 @@ mnt_context_disable_canonicalize mnt_context_disable_helpers mnt_context_disable_mtab mnt_context_disable_swapmatch +mnt_context_enable_beneath mnt_context_enable_exclusive mnt_context_enable_fake mnt_context_enable_force @@ -71,6 +72,7 @@ mnt_context_get_user_mflags mnt_context_helper_executed mnt_context_helper_setopt mnt_context_init_helper +mnt_context_is_beneath mnt_context_is_child mnt_context_is_exclusive mnt_context_is_fake diff --git a/libmount/src/context.c b/libmount/src/context.c index 122d2dbf2..66b5c2d8f 100644 --- a/libmount/src/context.c +++ b/libmount/src/context.c @@ -617,6 +617,32 @@ int mnt_context_is_exclusive(struct libmnt_context *cxt) return cxt->flags & MNT_FL_EXCL ? 1 : 0; } +/** + * mnt_context_enable_beneath + * @cxt: mount context + * @enable: TRUE or FALSE + * + * Enable/disable underlying mount (move). The filesystem is attached beneath the current + * top-level mount of the mountpoint. See mount_move( MOVE_MOUNT_BENEATH ). + * + * Returns: 0 on success, negative number in case of error. + */ +int mnt_context_enable_beneath(struct libmnt_context *cxt, int enable) +{ + return set_flag(cxt, MNT_FL_BENEATH, enable); +} + +/** + * mnt_context_is_beneath: + * @cxt: mount context + * + * Returns: 1 if beneath mount is enabled or 0 + */ +int mnt_context_is_beneath(struct libmnt_context *cxt) +{ + return cxt->flags & MNT_FL_BENEATH ? 1 : 0; +} + /** * mnt_context_enable_fork: * @cxt: mount context diff --git a/libmount/src/hook_mount.c b/libmount/src/hook_mount.c index e1c67990e..77cf51ad3 100644 --- a/libmount/src/hook_mount.c +++ b/libmount/src/hook_mount.c @@ -517,6 +517,7 @@ static int hook_attach_target(struct libmnt_context *cxt, void *data __attribute__((__unused__))) { struct libmnt_sysapi *api; + unsigned int flags; const char *target; int rc = 0; @@ -542,7 +543,11 @@ static int hook_attach_target(struct libmnt_context *cxt, umount2(target, MNT_DETACH); } - rc = move_mount(api->fd_tree, "", AT_FDCWD, target, MOVE_MOUNT_F_EMPTY_PATH); + flags = MOVE_MOUNT_F_EMPTY_PATH; + if (mnt_context_is_beneath(cxt)) + flags |= MOVE_MOUNT_BENEATH; + + rc = move_mount(api->fd_tree, "", AT_FDCWD, target, flags); hookset_set_syscall_status(cxt, "move_mount", rc == 0); if (rc == 0) { diff --git a/libmount/src/libmount.h.in b/libmount/src/libmount.h.in index fbb6c8ff6..04b7b3074 100644 --- a/libmount/src/libmount.h.in +++ b/libmount/src/libmount.h.in @@ -818,6 +818,7 @@ extern int mnt_context_set_optsmode(struct libmnt_context *cxt, int mode); extern int mnt_context_disable_canonicalize(struct libmnt_context *cxt, int disable); extern int mnt_context_enable_onlyonce(struct libmnt_context *cxt, int enable); extern int mnt_context_enable_exclusive(struct libmnt_context *cxt, int enable); +extern int mnt_context_enable_beneath(struct libmnt_context *cxt, int enable); extern int mnt_context_enable_lazy(struct libmnt_context *cxt, int enable); extern int mnt_context_enable_rdonly_umount(struct libmnt_context *cxt, int enable); extern int mnt_context_enable_rwonly_mount(struct libmnt_context *cxt, int enable); @@ -837,6 +838,8 @@ extern int mnt_context_is_onlyonce(struct libmnt_context *cxt) __ul_attribute__((nonnull)); extern int mnt_context_is_exclusive(struct libmnt_context *cxt) __ul_attribute__((nonnull)); +extern int mnt_context_is_beneath(struct libmnt_context *cxt) + __ul_attribute__((nonnull)); extern int mnt_context_is_lazy(struct libmnt_context *cxt) __ul_attribute__((nonnull)); extern int mnt_context_is_rdonly_umount(struct libmnt_context *cxt) diff --git a/libmount/src/libmount.sym b/libmount/src/libmount.sym index 0b0e3bffe..42fefc150 100644 --- a/libmount/src/libmount.sym +++ b/libmount/src/libmount.sym @@ -410,7 +410,9 @@ MOUNT_2_41 { } MOUNT_2_40; MOUNT_2_42 { + mnt_context_enable_beneath; mnt_context_enable_exclusive; + mnt_context_is_beneath; mnt_context_is_exclusive; mnt_monitor_enable_mountinfo; mnt_monitor_enable_fanotify; diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h index 8dc31acad..fb01041f6 100644 --- a/libmount/src/mountP.h +++ b/libmount/src/mountP.h @@ -537,6 +537,7 @@ struct libmnt_context #define MNT_FL_RWONLY_MOUNT (1 << 14) /* explicit mount -w; never try read-only */ #define MNT_FL_ONLYONCE (1 << 15) #define MNT_FL_EXCL (1 << 16) +#define MNT_FL_BENEATH (1 << 17) #define MNT_FL_MOUNTDATA (1 << 20) #define MNT_FL_TAB_APPLIED (1 << 21) /* fstab merged to cxt->fs */ -- 2.47.3