]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
tests/shell: bind mount private /var/run/netns in test container
authorThomas Haller <thaller@redhat.com>
Wed, 6 Sep 2023 11:52:18 +0000 (13:52 +0200)
committerFlorian Westphal <fw@strlen.de>
Thu, 7 Sep 2023 17:35:20 +0000 (19:35 +0200)
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@redhat.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
tests/shell/helpers/test-wrapper.sh
tests/shell/run-tests.sh

index fee55e5f9df5ac81950bfaac8acef93f6b052e8d..b8a54ed7444d9bc44a51f2e9bd2664b2376e401a 100755 (executable)
@@ -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=$?
 
index 1af1c0f3013f1400b29976915b44902647e2bd03..97c82991befd23e558eecd715a9c8465e3613995 100755 (executable)
@@ -84,11 +84,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}>: number of jobs for parallel execution. Defaults to \"12\" for parallel run."
        echo "                 Setting this to \"0\" or \"1\", means to run jobs sequentially."
@@ -223,20 +226,39 @@ 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_HAS_UNSHARED_MOUNT=n
        if [ "$NFT_TEST_HAS_REALROOT" = y ] ; then
                # We appear to have real root. So try to unshare
                # without a separate USERNS. CLONE_NEWUSER will break
                # 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 or set NFT_TEST_UNSHARE_CMD"
@@ -245,6 +267,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
@@ -295,6 +318,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")"