From 2192f6acc202df5b11915910b723776b22811286 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Fri, 4 Sep 2026 00:20:08 -0700 Subject: [PATCH 1/2] tests/rootless.sh: rename ROOT to SRC_ROOT Here, ROOT is the root of the runc source tree, while in the integration tests ROOT is a temporary directory which teardown_bundle removes recursively. The variable is not exported, so nothing is broken today, but the name clash is a trap waiting to happen; use a distinct name. Signed-off-by: Kir Kolyshkin --- tests/rootless.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/rootless.sh b/tests/rootless.sh index 61eb2edfe39..9f48f2459cd 100755 --- a/tests/rootless.sh +++ b/tests/rootless.sh @@ -27,7 +27,7 @@ ALL_FEATURES=("idmap" "cgroup") if [ -v RUNC_USE_SYSTEMD ]; then ALL_FEATURES=("idmap") fi -ROOT="$(readlink -f "$(dirname "${BASH_SOURCE[0]}")/..")" +SRC_ROOT="$(readlink -f "$(dirname "${BASH_SOURCE[0]}")/..")" # List of environment variables needed for the tests. # They are usually exported, but since we use ssh below, @@ -182,7 +182,7 @@ features_powerset="$(powerset "${ALL_FEATURES[@]}")" # Make sure we have container images downloaded, as otherwise # rootless user won't be able to write to $TESTDATA. -"$ROOT"/tests/integration/get-images.sh >/dev/null +"$SRC_ROOT"/tests/integration/get-images.sh >/dev/null # Iterate over the powerset of all features. IFS=: @@ -218,10 +218,10 @@ for ROOTLESS_FEATURES in $features_powerset; do # Operation not permitted". Set the correct value explicitly. ssh_env+=("XDG_RUNTIME_DIR=/run/user/$(id -u rootless)") ssh -t -t -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i "$HOME/.ssh/rootless.key" \ - rootless@localhost -- "${ssh_env[@]}" bats -t "$ROOT/tests/integration$ROOTLESS_TESTPATH" + rootless@localhost -- "${ssh_env[@]}" bats -t "$SRC_ROOT/tests/integration$ROOTLESS_TESTPATH" else export "${ENV_LIST[@]}" - sudo -HE -u rootless PATH="$PATH" "$(command -v bats)" -t "$ROOT/tests/integration$ROOTLESS_TESTPATH" + sudo -HE -u rootless PATH="$PATH" "$(command -v bats)" -t "$SRC_ROOT/tests/integration$ROOTLESS_TESTPATH" fi cleanup done From ba97a5311c019dd744b5d8b1c0ef96498544fe73 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Fri, 4 Sep 2026 00:20:08 -0700 Subject: [PATCH 2/2] tests/int: don't remove a directory we did not create teardown_bundle removes $ROOT recursively, guarded only by a check that the variable is set. Since ROOT can be inherited from the environment (setup_bundle overwrites it, but is not called by every test), a stray ROOT in the environment makes the teardown remove an arbitrary directory. Please don't ask me how I know all this. Add some protection: - helpers.bash now unsets ROOT if it comes from the environment; - setup_bundle marks the directory it creates with a marker file, and teardown_bundle only removes a directory which has that marker and is located under $BATS_RUN_TMPDIR. Signed-off-by: Kir Kolyshkin --- tests/integration/helpers.bash | 38 +++++++++++++++++++++++++++++++++- tests/integration/list.bats | 1 + 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/tests/integration/helpers.bash b/tests/integration/helpers.bash index 11d232bb47c..1a9aa6f42f9 100755 --- a/tests/integration/helpers.bash +++ b/tests/integration/helpers.bash @@ -17,6 +17,12 @@ unset IMAGES # Path to binaries compiled from packages in tests/cmd by "make test-binaries"). TESTBINDIR=${INTEGRATION_ROOT}/../cmd/_bin +# ROOT should not be inherited from the environment. +if [ -v ROOT ]; then + echo "helpers.bash: ignoring ROOT set in the environment ($ROOT)" >&2 + unset ROOT +fi + # Some variables may not always be set. Set those to empty value, # if unset, to avoid "unbound variable" error. : "${ROOTLESS_FEATURES:=}" @@ -788,6 +794,31 @@ function wait_pids_gone() { return 1 } +# Name of the marker file, used by make_test_root and is_test_root. +ROOT_MARKER=".runc-integration-test-root" + +# make_test_root creates a directory to be used as $ROOT (or a similar +# per-test directory), marking it as safe to remove in a teardown. +function make_test_root() { + local dir="$1" + + mkdir -p "$dir" + touch "$dir/$ROOT_MARKER" +} + +# is_test_root returns 0 if the argument is a directory created by +# make_test_root, meaning it is safe to remove it recursively. +function is_test_root() { + local dir="${1:-}" + + [ -d "$dir" ] || return 1 + # Must be under the bats-created temporary directory. + [ -n "${BATS_RUN_TMPDIR:-}" ] || return 1 + [[ "$dir" == "$BATS_RUN_TMPDIR"/* ]] || return 1 + # Must contain the marker file. + [ -f "$dir/$ROOT_MARKER" ] +} + function setup_recvtty() { [ ! -v ROOT ] && return 1 # must not be called without ROOT set local dir="$ROOT/tty" @@ -852,6 +883,7 @@ function setup_bundle() { # Root for various container directories (state, tty, bundle). ROOT=$(mktemp -d "$BATS_RUN_TMPDIR/runc.XXXXXX") + make_test_root "$ROOT" mkdir -p "$ROOT/state" "$ROOT/bundle/rootfs" # Directories created by mktemp -d have 0700 permission bits. Tests @@ -887,7 +919,11 @@ function teardown_bundle() { for ct in $(__runc list -q); do __runc delete -f "$ct" done - rm -rf "$ROOT" + if is_test_root "$ROOT"; then + rm -rf "$ROOT" + else + echo "teardown_bundle: refusing to remove $ROOT (no $ROOT_MARKER in it)" >&2 + fi remove_parent check_cgroup_removed } diff --git a/tests/integration/list.bats b/tests/integration/list.bats index e85091548a7..83dfff3ba06 100644 --- a/tests/integration/list.bats +++ b/tests/integration/list.bats @@ -5,6 +5,7 @@ load helpers function setup() { setup_busybox ALT_ROOT="$ROOT/alt" + make_test_root "$ALT_ROOT" mkdir -p "$ALT_ROOT/state" }