mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-11 06:03:57 +08:00
tests: mounts: add some tests to check mount ordering
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 <cyphar@cyphar.com>
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user