Skip to content

Commit

Permalink
tests: mounts: add some tests to check mount ordering
Browse files Browse the repository at this point in the history
Our previous implementation of idmapped mounts and bind-mount sources
would open all of the source paths before we did any mounts, meaning
that mounts using sources from inside the container rootfs would not be
correct.

This has been fixed with the new on-demand system, and so add some
regression tests.

Signed-off-by: Aleksa Sarai <[email protected]>
  • Loading branch information
cyphar committed Dec 14, 2023
1 parent 3b57e45 commit fa93c8b
Showing 1 changed file with 119 additions and 0 deletions.
119 changes: 119 additions & 0 deletions tests/integration/mounts.bats
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,109 @@ function test_ro_cgroup_mount() {
for line in "${lines[@]}"; do [[ "${line}" == *'ro,'* ]]; done
}

# Parse an "optstring" of the form foo,bar into $is_foo and $is_bar variables.
# Usage: parse_optstring foo,bar foo bar baz
function parse_optstring() {
optstring="$1"
shift

for flag in "$@"; do
is_set=
if grep -wq "$flag" <<<"$optstring"; then
is_set=1
fi
eval "is_$flag=$is_set"
done
}

function config_add_bind_mount() {
src="$1"
dst="$2"
parse_optstring "${3:-}" rbind idmap

bindtype=bind
if [ -n "$is_rbind" ]; then
bindtype=rbind
fi

mappings=""
if [ -n "$is_idmap" ]; then
mappings='
"uidMappings": [{"containerID": 0, "hostID": 100000, "size": 65536}],
"gidMappings": [{"containerID": 0, "hostID": 100000, "size": 65536}],
'
fi

update_config '.mounts += [{
"source": "'"$src"'",
"destination": "'"$dst"'",
"type": "bind",
'"$mappings"'
"options": [ "'"$bindtype"'", "rprivate" ]
}]'
}

# This needs to be placed at the top of the bats file to work around
# a shellcheck bug. See <https://github.com/koalaman/shellcheck/issues/2873>.
function test_mount_order() {
parse_optstring "${1:-}" userns idmap

if [ -n "$is_userns" ]; then
requires root

update_config '.linux.namespaces += [{"type": "user"}]
| .linux.uidMappings += [{"containerID": 0, "hostID": 100000, "size": 65536}]
| .linux.gidMappings += [{"containerID": 0, "hostID": 100000, "size": 65536}]'
remap_rootfs
fi

ctr_src_opts="rbind"
if [ -n "$is_idmap" ]; then
requires root
requires_kernel 5.12
requires_idmap_fs .

ctr_src_opts+=",idmap"
fi

mkdir -p rootfs/{mnt,final}
# Create a set of directories we can create a mount tree with.
for subdir in a/x b/y c/z; do
dir="bind-src/$subdir"
mkdir -p "$dir"
echo "$subdir" >"$dir/file"
# Add a symlink to make sure
topdir="$(dirname "$subdir")"
ln -s "$topdir" "bind-src/sym-$topdir"
done
# In userns tests, make sure that the source directory cannot be accessed,
# to make sure we're exercising the bind-mount source fd logic.
chmod o-rwx bind-src

rootfs="$(pwd)/rootfs"
rm -rf rootfs/mnt
mkdir rootfs/mnt

# Create a bind-mount tree.
config_add_bind_mount "$PWD/bind-src/a" "/mnt"
config_add_bind_mount "$PWD/bind-src/sym-b" "/mnt/x"
config_add_bind_mount "$PWD/bind-src/c" "/mnt/x/y"
config_add_bind_mount "$PWD/bind-src/sym-a" "/mnt/x/y/z"
# Create a recursive bind-mount that uses part of the current tree in the
# container.
config_add_bind_mount "$rootfs/mnt/x" "$rootfs/mnt/x/y/z/x" "$ctr_src_opts"
config_add_bind_mount "$rootfs/mnt/x/y" "$rootfs/mnt/x/y/z" "$ctr_src_opts"
# Finally, bind-mount the whole thing on top of /final.
config_add_bind_mount "$rootfs/mnt" "$rootfs/final" "$ctr_src_opts"

# Check that the entire tree was copied and the mounts were done in the
# expected order.
update_config '.process.args = ["cat", "/final/x/y/z/z/x/y/z/x/file"]'
runc run test_busybox
[ "$status" -eq 0 ]
[[ "$output" == *"a/x"* ]] # the final "file" was from a/x.
}

# https://github.com/opencontainers/runc/issues/3991
@test "runc run [tmpcopyup]" {
mkdir -p rootfs/dir1/dir2
Expand Down Expand Up @@ -108,3 +211,19 @@ function test_ro_cgroup_mount() {
update_config '.linux.namespaces |= if index({"type": "cgroup"}) then . else . + [{"type": "cgroup"}] end'
test_ro_cgroup_mount
}

@test "runc run [mount order, container bind-mount source]" {
test_mount_order
}

@test "runc run [mount order, container bind-mount source] (userns)" {
test_mount_order userns
}

@test "runc run [mount order, container idmap source]" {
test_mount_order idmap
}

@test "runc run [mount order, container idmap source] (userns)" {
test_mount_order userns,idmap
}

0 comments on commit fa93c8b

Please sign in to comment.