Some tests want to run `ip netns add`, which requires write permissions to /var/run/netns. Also, /var/run/netns would be a systemwide mount path, and shared between the tests. We would want to isolate that. Fix that by bind mount a tmpfs inside the test wrapper, if we appear to have a private mount namespace. Fixes $ ./tests/shell/run-tests.sh -- tests/shell/testcases/netns/0001nft-f_0 Optimally, `ip netns add` would allow to specify a private location for those bind mounts. It seems that iproute2 is build with /var/run/netns, instead the more common /run/netns. Hence, handle /var/run instead of /run. Signed-off-by: Thomas Haller <thaller@xxxxxxxxxx> --- tests/shell/helpers/test-wrapper.sh | 23 +++++++++++++++++++++ tests/shell/run-tests.sh | 32 +++++++++++++++++++++++++---- 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/tests/shell/helpers/test-wrapper.sh b/tests/shell/helpers/test-wrapper.sh index 1390985c7f32..58cf48172fc0 100755 --- a/tests/shell/helpers/test-wrapper.sh +++ b/tests/shell/helpers/test-wrapper.sh @@ -9,10 +9,33 @@ TEST="$1" TESTBASE="$(basename "$TEST")" TESTDIR="$(dirname "$TEST")" +CLEANUP_UMOUNT_RUN_NETNS=n + +cleanup() { + if [ "$CLEANUP_UMOUNT_RUN_NETNS" = y ] ; then + umount "/var/run/netns" || : + fi +} + +trap cleanup EXIT + printf '%s\n' "$TEST" > "$NFT_TEST_TESTTMPDIR/name" read tainted_before < /proc/sys/kernel/tainted +if [ "$NFT_TEST_HAS_UNSHARED_MOUNT" = y ] ; then + # We have a private mount namespace. We will mount /run/netns as a tmpfs, + # this is useful because `ip netns add` wants to add files there. + # + # When running as rootless, this is necessary to get such tests to + # pass. When running rootful, it's still useful to not touch the + # "real" /var/run/netns of the system. + mkdir -p /var/run/netns + if mount -t tmpfs --make-private "/var/run/netns" ; then + CLEANUP_UMOUNT_RUN_NETNS=y + fi +fi + rc_test=0 "$TEST" &> "$NFT_TEST_TESTTMPDIR/testout.log" || rc_test=$? diff --git a/tests/shell/run-tests.sh b/tests/shell/run-tests.sh index d157f14eb9a5..8564d9a08bcb 100755 --- a/tests/shell/run-tests.sh +++ b/tests/shell/run-tests.sh @@ -83,11 +83,14 @@ usage() { echo " By default it is unset, in which case it's autodetected as" echo " \`unshare -f -p\` (for root) or as \`unshare -f -p --mount-proc -U --map-root-user -n\`" echo " for non-root." - echo " When setting this, you may also want to set NFT_TEST_HAS_UNSHARED=" - echo " and NFT_TEST_HAS_REALROOT= accordingly." + echo " When setting this, you may also want to set NFT_TEST_HAS_UNSHARED=," + echo " NFT_TEST_HAS_REALROOT= and NFT_TEST_HAS_UNSHARED_MOUNT= accordingly." echo " NFT_TEST_HAS_UNSHARED=*|y : To indicate to the test whether the test run will be unshared." echo " Test may consider this." echo " This is only honored when \$NFT_TEST_UNSHARE_CMD= is set. Otherwise it's detected." + echo " NFT_TEST_HAS_UNSHARED_MOUNT=*|y : To indicate to the test whether the test run will have a private" + echo " mount namespace." + echo " This is only honored when \$NFT_TEST_UNSHARE_CMD= is set. Otherwise it's detected." echo " NFT_TEST_KEEP_LOGS=*|y: Keep the temp directory. On success, it will be deleted by default." echo " NFT_TEST_JOBS=<NUM}>: by default, run test sequentially. Set to an integer > 1 to" echo " run jobs in parallel. Leaving this unset or at zero means to run jobs sequentially" @@ -225,9 +228,22 @@ if [ -n "${NFT_TEST_UNSHARE_CMD+x}" ] ; then else NFT_TEST_HAS_UNSHARED="$(bool_y "$NFT_TEST_HAS_UNSHARED")" fi + if [ -z "${NFT_TEST_HAS_UNSHARED_MOUNT+x}" ] ; then + NFT_TEST_HAS_UNSHARED_MOUNT=n + if [ "$NFT_TEST_HAS_UNSHARED" == y ] ; then + case "$NFT_TEST_UNSHARE_CMD" in + unshare*-m*|unshare*--mount-proc*) + NFT_TEST_HAS_UNSHARED_MOUNT=y + ;; + esac + fi + else + NFT_TEST_HAS_UNSHARED_MOUNT="$(bool_y "$NFT_TEST_HAS_UNSHARED_MOUNT")" + fi else NFT_TEST_UNSHARE_CMD="" NFT_TEST_HAS_UNSHARED="n" + NFT_TEST_HAS_UNSHARED_MOUNT=n if [ "$NFT_TEST_NO_UNSHARE" != y ] ; then if [ "$NFT_TEST_HAS_REALROOT" = y ] ; then # We appear to have real root. So try to unshare @@ -235,13 +251,19 @@ else # tests that are limited by # /proc/sys/net/core/{wmem_max,rmem_max}. With real # root, we want to test that. - detect_unshare "unshare -f -n -m" || + if detect_unshare "unshare -f -n -m" ; then + NFT_TEST_HAS_UNSHARED_MOUNT=y + else detect_unshare "unshare -f -n" || detect_unshare "unshare -f -p -m --mount-proc -U --map-root-user -n" || detect_unshare "unshare -f -U --map-root-user -n" + fi else - detect_unshare "unshare -f -p -m --mount-proc -U --map-root-user -n" || + if detect_unshare "unshare -f -p -m --mount-proc -U --map-root-user -n" ; then + NFT_TEST_HAS_UNSHARED_MOUNT=y + else detect_unshare "unshare -f -U --map-root-user -n" + fi fi if [ -z "$NFT_TEST_UNSHARE_CMD" ] ; then msg_error "Unshare does not work. Run as root with -U/--no-unshare/NFT_TEST_NO_UNSHARE=y or set NFT_TEST_UNSHARE_CMD" @@ -251,6 +273,7 @@ else fi # If tests wish, they can know whether they are unshared via this variable. export NFT_TEST_HAS_UNSHARED +export NFT_TEST_HAS_UNSHARED_MOUNT # normalize the jobs number to be an integer. case "$NFT_TEST_JOBS" in @@ -274,6 +297,7 @@ msg_info "conf: KMEMLEAK=$(printf '%q' "$KMEMLEAK")" msg_info "conf: NFT_TEST_HAS_REALROOT=$(printf '%q' "$NFT_TEST_HAS_REALROOT")" msg_info "conf: NFT_TEST_UNSHARE_CMD=$(printf '%q' "$NFT_TEST_UNSHARE_CMD")" msg_info "conf: NFT_TEST_HAS_UNSHARED=$(printf '%q' "$NFT_TEST_HAS_UNSHARED")" +msg_info "conf: NFT_TEST_HAS_UNSHARED_MOUNT=$(printf '%q' "$NFT_TEST_HAS_UNSHARED_MOUNT")" msg_info "conf: NFT_TEST_KEEP_LOGS=$(printf '%q' "$NFT_TEST_KEEP_LOGS")" msg_info "conf: NFT_TEST_JOBS=$NFT_TEST_JOBS" msg_info "conf: TMPDIR=$(printf '%q' "$_TMPDIR")" -- 2.41.0