[PATCH nft] tests/shell: allow running tests as non-root users

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Allow to opt-out from the have-real-root check via

  NFT_TEST_ROOTLESS=1 ./run-tests.sh

For that to be useful, we must also unshare the PID and user namespace
and map the root user inside that namespace.

With that, inside the namespace we look like root. Including having
CAP_NET_ADMIN for the new net namespace. This allows to run the tests as
rootless and most tests will pass.

Note that some tests will fail as rootless. For example, the socket
buffers are limited by /proc/sys/net/core/{wmem_max,rmem_max}, which is
not namespaced. When running as real-root, nftables can raise them
beyond those limits and the tests will pass. Rootless cannot do that and
the test may fail.

Test that don't work without real root should check for
[ "$NFT_TEST_HAVE_REALROOT" != 1 ] and skip gracefully.

Signed-off-by: Thomas Haller <thaller@xxxxxxxxxx>
---
 tests/shell/run-tests.sh | 57 +++++++++++++++++++++++++++++++---------
 1 file changed, 45 insertions(+), 12 deletions(-)

diff --git a/tests/shell/run-tests.sh b/tests/shell/run-tests.sh
index b66ef4fa4d1f..96dd0b0c2fd6 100755
--- a/tests/shell/run-tests.sh
+++ b/tests/shell/run-tests.sh
@@ -1,9 +1,18 @@
 #!/bin/bash
 
-# Configuration
-TESTDIR="./$(dirname $0)/testcases"
-SRC_NFT="$(dirname $0)/../../src/nft"
-DIFF=$(which diff)
+# Environment variables for the user:
+# NFT=<path>                   Path to the nft executable.
+# NFT_TEST_ROOTLESS=0|1:       Whether the test allows to run as rootless. Usually the test
+#                              will require real root permissions. You can set NFT_TEST_ROOTLESS=1
+#                              to run rootless in a separate namespace.
+# NFT_TEST_HAVE_REALROOT=0|1:  To indicate whether the test has real root permissions.
+#                              Usually, you don't need this and it gets autodetected.
+#                              Note that without real root, certain tests may not work.
+#                              For example, due to limited /proc/sys/net/core/{wmem_max,rmem_max}.
+#                              Such test should check for [ "$NFT_TEST_HAVE_REALROOT" != 1 ] and
+#                              skip (not fail) in such an environment.
+# NFT_TEST_NO_UNSHARE=0|1:     Usually, the test will run in a separate namespace.
+#                              You can opt-out from that by setting NFT_TEST_NO_UNSHARE=1.
 
 msg_error() {
 	echo "E: $1 ..." >&2
@@ -18,18 +27,42 @@ msg_info() {
 	echo "I: $1"
 }
 
-if [ "$(id -u)" != "0" ] ; then
+if [ "$NFT_TEST_HAVE_REALROOT" = "" ] ; then
+	# The caller can set NFT_TEST_HAVE_REALROOT to indicate us whether we
+	# have real root. They usually don't need, and we detect it now based
+	# on `id -u`. Note that we may unshare below, so the check inside the
+	# new namespace won't be conclusive. We thus only detect once and export
+	# the result.
+	export NFT_TEST_HAVE_REALROOT="$(test "$(id -u)" = "0" && echo 1 || echo 0)"
+fi
+
+if [ "$NFT_TEST_HAVE_REALROOT" != 1 -a "$NFT_TEST_ROOTLESS" != 1 ] ; then
+	# By default, we require real-root, unless the user explicitly opts-in
+	# to proceed via NFT_TEST_ROOTLESS=1.
 	msg_error "this requires root!"
 fi
 
-if [ "${1}" != "run" ]; then
-	if unshare -f -n true; then
-		unshare -n "${0}" run $@
-		exit $?
-	fi
-	msg_warn "cannot run in own namespace, connectivity might break"
+if [ "$NFT_TEST_NO_UNSHARE" = 1 ]; then
+	# The user opts-out from unshare. Proceed without.
+	:
+elif [ "$_NFT_TEST_IS_UNSHARED" = 1 ]; then
+	# We are inside the unshared environment. Don't unshare again.
+	# Continue.
+	:
+else
+	# Unshare. This works both as rootless and with real root. Inside
+	# the user namespace we will map the root user, so we appear to have
+	# root. Check for [ "$NFT_TEST_HAVE_REALROOT" != 1 ] to know when
+	# not having real root.
+	export _NFT_TEST_IS_UNSHARED=1
+	unshare -f --map-root-user -U -p -n "$0" "$@"
+	exit $?
 fi
-shift
+
+# Configuration
+TESTDIR="./$(dirname $0)/testcases"
+SRC_NFT="$(dirname $0)/../../src/nft"
+DIFF=$(which diff)
 
 [ -z "$NFT" ] && NFT=$SRC_NFT
 ${NFT} > /dev/null 2>&1
-- 
2.41.0




[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux