This is a test case for nft_socket cgroupv2 matching, including support for matching inside a cgroupv2 mount space added in kernel commit 7f3287db6543 ("netfilter: nft_socket: make cgroupsv2 matching work with namespaces"). Test is thus run twice, once in the initial namespace and once with a changed cgroupv2 root. In case we can't create a cgroup or the 2nd half (unshared re-run) fails, indicate SKIP. Signed-off-by: Florian Westphal <fw@xxxxxxxxx> --- tests/shell/testcases/packetpath/cgroupv2 | 143 ++++++++++++++++++ .../packetpath/dumps/cgroupv2.nodump | 0 2 files changed, 143 insertions(+) create mode 100755 tests/shell/testcases/packetpath/cgroupv2 create mode 100644 tests/shell/testcases/packetpath/dumps/cgroupv2.nodump diff --git a/tests/shell/testcases/packetpath/cgroupv2 b/tests/shell/testcases/packetpath/cgroupv2 new file mode 100755 index 000000000000..20bd18ae3b4f --- /dev/null +++ b/tests/shell/testcases/packetpath/cgroupv2 @@ -0,0 +1,143 @@ +#!/bin/bash + +doit="$1" +rc=0 + +# Create hierarchy: +# / -> nft-test1a/nft-test2a +# | `nft-test2b +# `--> nft-test1b/nft-test2a +# test1b/nft-test2a will remain empty and +# should never match, it only exists so we +# can create cgroupv2 match rules. + +if ! socat -h > /dev/null ; then + echo "socat tool is missing" + exit 77 +fi + +if [ ! -r /sys/fs/cgroup/cgroup.procs ] ;then + echo "cgroup filesystem not available" + exit 77 +fi + +cleanup() +{ + echo $$ > "/sys/fs/cgroup/cgroup.procs" + + rmdir "/sys/fs/cgroup/nft-test1a/nft-test2a" + rmdir "/sys/fs/cgroup/nft-test1a/nft-test2b" + rmdir "/sys/fs/cgroup/nft-test1b/nft-test2a" + rmdir "/sys/fs/cgroup/nft-test1a" + rmdir "/sys/fs/cgroup/nft-test1b" + + # nft list is broken after cgroupv2 removal, as nft + # can't find the human-readable names anymore. + $NFT delete table inet testcgrpv2 +} + +do_initial_setup() +{ + trap cleanup EXIT + ip link set lo up + + mkdir -p "/sys/fs/cgroup/nft-test1a/nft-test2a" || exit 1 + mkdir -p "/sys/fs/cgroup/nft-test1b/nft-test2a" || exit 1 + + mkdir "/sys/fs/cgroup/nft-test1a/nft-test2b" || exit 1 + + # After this, we can create cgroupv2 rules for the these cgroups. + # test1a and test2a should match while test1b/test2b should not: +$NFT -f - <<EOF +table inet testcgrpv2 { + counter nft-test1a {} + counter nft-test1a2a {} + counter nft-test1a2b {} + counter nft-test1b {} + counter nft-test1b2a {} + + chain output { + type filter hook output priority 0; + + socket cgroupv2 level 1 "nft-test1a" counter name "nft-test1a" + socket cgroupv2 level 2 "nft-test1a/nft-test2a" counter name "nft-test1a2a" + + # Next must never match + socket cgroupv2 level 2 "nft-test1a/nft-test2b" counter name "nft-test1a2b" + + # Must never match + socket cgroupv2 level 1 "nft-test1b" counter name "nft-test1b" + # Same, must not match. + socket cgroupv2 level 2 "nft-test1b/nft-test2a" counter name "nft-test1b2a" + } +} +EOF +} + +test_counters() +{ + local subtest="$1" + + local t1a="$2" + local t1a2a="$3" + + $NFT list ruleset + + $NFT reset counter inet testcgrpv2 nft-test1a | grep -q "packets $t1a" || rc=1 + $NFT reset counter inet testcgrpv2 nft-test1a2a | grep -q "packets $t1a2a" || rc=2 + + # dummy cgroup counters, must not match. + $NFT reset counter inet testcgrpv2 nft-test1a2b | grep -q 'packets 0' || rc=3 + $NFT reset counter inet testcgrpv2 nft-test1b | grep -q 'packets 0' || rc=4 + $NFT reset counter inet testcgrpv2 nft-test1b2a | grep -q 'packets 0' || rc=5 + + if [ $rc -ne 0 ]; then + echo "Counters did not match expected values fur subtest $subtest, return $rc" + exit $rc + fi +} + +run_test() +{ + echo $$ > "/sys/fs/cgroup/nft-test1a/nft-test2a/cgroup.procs" || exit 2 + socat -u STDIN TCP:127.0.0.1:8880,connect-timeout=4 < /dev/null > /dev/null + + test_counters "a1,a2" 1 1 + + echo $$ > "/sys/fs/cgroup/nft-test1a/cgroup.procs" || exit 2 + socat -u STDIN TCP:127.0.0.1:8880,connect-timeout=4 < /dev/null > /dev/null + test_counters "a1 only" 1 0 +} + + +if [ "$doit" != "setup-done" ];then + mkdir -p "/sys/fs/cgroup/nft-test1a" || exit 77 + + do_initial_setup + run_test + + if [ $rc -ne 0 ]; then + exit $rc + fi + + echo "Re-running test with changed cgroup root" + echo $$ > "/sys/fs/cgroup/nft-test1a/cgroup.procs" || exit 2 + unshare --fork --pid --mount -n -C $0 "setup-done" + rc=$? +else + want_inode=$(stat --printf=%i "/sys/fs/cgroup/nft-test1a/") + mount -t cgroup2 cgroup2 /sys/fs/cgroup + + # /sys/fs/cgroup/ should now match "/sys/fs/cgroup/nft-test1a/cgroup.procs" + rootinode=$(stat --printf=%i "/sys/fs/cgroup/") + + if [ $want_inode -ne $rootinode ] ;then + echo "Failed to remount cgroupv2 fs, wanted inode $want_inode as root node, but got $rootinode" + exit 77 + fi + + do_initial_setup + run_test +fi + +exit $rc diff --git a/tests/shell/testcases/packetpath/dumps/cgroupv2.nodump b/tests/shell/testcases/packetpath/dumps/cgroupv2.nodump new file mode 100644 index 000000000000..e69de29bb2d1 -- 2.45.2