1
0
mirror of https://github.com/systemd/systemd synced 2025-10-06 00:13:24 +02:00

nspawn: fix recursive bind mounts

Follow-up for 90fa161b5b

Fixes https://github.com/systemd/systemd/issues/38505
This commit is contained in:
Luca Boccassi
2025-08-07 23:40:54 +01:00
committed by Yu Watanabe
parent 1f05d6a0de
commit c892e33979
2 changed files with 18 additions and 9 deletions

View File

@@ -755,8 +755,8 @@ int mount_all(const char *dest,
return 0;
}
static int parse_mount_bind_options(const char *options, unsigned long *mount_flags, char **mount_opts, RemountIdmapping *idmapping) {
unsigned long flags = *mount_flags;
static int parse_mount_bind_options(const char *options, unsigned long *open_tree_flags, char **mount_opts, RemountIdmapping *idmapping) {
unsigned long flags = *open_tree_flags;
char *opts = NULL;
RemountIdmapping new_idmapping = *idmapping;
int r;
@@ -773,9 +773,9 @@ static int parse_mount_bind_options(const char *options, unsigned long *mount_fl
break;
if (streq(word, "rbind"))
flags |= MS_REC;
flags |= AT_RECURSIVE;
else if (streq(word, "norbind"))
flags &= ~MS_REC;
flags &= ~AT_RECURSIVE;
else if (streq(word, "idmap"))
new_idmapping = REMOUNT_IDMAPPING_HOST_ROOT;
else if (streq(word, "noidmap"))
@@ -789,7 +789,7 @@ static int parse_mount_bind_options(const char *options, unsigned long *mount_fl
"Invalid bind mount option: %s", word);
}
*mount_flags = flags;
*open_tree_flags = flags;
*idmapping = new_idmapping;
/* in the future mount_opts will hold string options for mount(2) */
*mount_opts = opts;
@@ -799,7 +799,7 @@ static int parse_mount_bind_options(const char *options, unsigned long *mount_fl
static int mount_bind(const char *dest, CustomMount *m, uid_t uid_shift, uid_t uid_range) {
_cleanup_free_ char *mount_opts = NULL, *where = NULL;
unsigned long mount_flags = MS_BIND | MS_REC;
unsigned long open_tree_flags = OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC | AT_RECURSIVE;
struct stat source_st, dest_st;
uid_t dest_uid = UID_INVALID;
int r;
@@ -809,7 +809,7 @@ static int mount_bind(const char *dest, CustomMount *m, uid_t uid_shift, uid_t u
assert(m);
if (m->options) {
r = parse_mount_bind_options(m->options, &mount_flags, &mount_opts, &idmapping);
r = parse_mount_bind_options(m->options, &open_tree_flags, &mount_opts, &idmapping);
if (r < 0)
return r;
}
@@ -829,14 +829,14 @@ static int mount_bind(const char *dest, CustomMount *m, uid_t uid_shift, uid_t u
_cleanup_close_ int fd_clone = open_tree_attr_with_fallback(
AT_FDCWD,
m->source,
OPEN_TREE_CLONE|OPEN_TREE_CLOEXEC,
open_tree_flags,
&(struct mount_attr) {
.attr_clr = idmapping != REMOUNT_IDMAPPING_NONE ? MOUNT_ATTR_IDMAP : 0,
});
if (ERRNO_IS_NEG_NOT_SUPPORTED(fd_clone))
/* We can only clear idmapped mounts with open_tree_attr(), but there might not be one in
* the first place, so we keep going if we get a not supported error. */
fd_clone = open_tree(AT_FDCWD, m->source, OPEN_TREE_CLONE|OPEN_TREE_CLOEXEC);
fd_clone = open_tree(AT_FDCWD, m->source, open_tree_flags);
if (fd_clone < 0)
return log_error_errno(errno, "Failed to clone %s: %m", m->source);

View File

@@ -245,6 +245,15 @@ EOF
--bind="$tmpdir:/foo" \
--bind="$tmpdir:/also-foo:noidmap,norbind" \
bash -xec 'test -e /foo/foo; touch /foo/bar; test -e /also-foo/bar'
# --bind= recursive
rm -f "$tmpdir/bar"
mount --bind "$tmpdir/1" "$tmpdir/2"
systemd-nspawn --directory="$root" \
${COVERAGE_BUILD_DIR:+--bind="$COVERAGE_BUILD_DIR"} \
--bind="$tmpdir:/foo" \
--bind="$tmpdir:/also-foo:noidmap,norbind" \
bash -xec 'test -e /foo/2/one; ! test -e /foo/2/two; test -e /also-foo/2/two; ! test -e /also-foo/2/one; test -e /foo/foo; touch /foo/bar; test -e /also-foo/bar'
umount "$tmpdir/2"
test -e "$tmpdir/bar"
# --bind-ro=
systemd-nspawn --directory="$root" \