From: Florian Westphal Date: Sun, 7 Jul 2024 18:42:15 +0000 (+0200) Subject: tests: shell: add more ruleset validation test cases X-Git-Tag: v1.1.0~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8428710ba713d430777e87e8adb3bc16af9911d2;p=thirdparty%2Fnftables.git tests: shell: add more ruleset validation test cases Passes fine on all tested kernel releases. Same as existing tests, but try harder to fool the validation: 1. Add a ruleset where the jump that that exceeds 16 is "broken", i.e. c0 -> c1 ... -> c8 c9-> c1 ... -> c16 Where c0 is a base chain, with a graph thats really a linear list from c0 to c8 and c9 to c16 is a linear list not connected to the former or a hook point. Then try to link them either directly via jump/goto rule or indirectly with a verdict map. Try both unbound map with element doing 'goto c9' and then trying to add vmap rule to c8 (must fail, creates link). Then try reverse: with empty map, add vmap rule to c8 (should work, no elements...). Then, add map element with jump or goto to c9. This should be rejected. Try the same thing with a tproxy expression in a user-defined chain: attempt to make it reachable from c0 (filter input), which is illegal. Signed-off-by: Florian Westphal --- diff --git a/tests/shell/testcases/transactions/bad_rule_graphs b/tests/shell/testcases/transactions/bad_rule_graphs new file mode 100755 index 00000000..53047c3c --- /dev/null +++ b/tests/shell/testcases/transactions/bad_rule_graphs @@ -0,0 +1,262 @@ +#!/bin/bash + +# test case to attempt to fool ruleset validation. +# Initial ruleset added here is fine, then we try to make the +# ruleset exceed the jump chain depth via jumps, gotos, verdict +# map entries etc, either by having the map loop back to itself, +# jumping back to an earlier chain and so on. +# +# Also check that can't hook up a user-defined chain with a +# restricted expression (here: tproxy, only valid from prerouting +# hook) to the input hook, even if reachable indirectly via vmap. + +bad_ruleset() +{ + ret=$1 + shift + + if [ $ret -eq 0 ];then + echo "Accepted bad ruleset with $@" + $NFT list ruleset + exit 1 + fi +} + +good_ruleset() +{ + ret=$1 + shift + + if [ $ret -ne 0 ];then + echo "Rejected good ruleset with $@" + exit 1 + fi +} + +# add a loop with a vmap statement, either goto or jump, +# both with single rule and delta-transaction that also +# contains valid information. +check_loop() +{ + what=$1 + + $NFT "add element t m { 1.2.3.9 : $what c1 }" + bad_ruleset $? "bound map with $what to backjump should exceed jump stack" + + $NFT "add element t m { 1.2.3.9 : $what c7 }" + bad_ruleset $? "bound map with $what to backjump should exceed jump stack" + + $NFT "add element t m { 1.2.3.9 : $what c8 }" + bad_ruleset $? "bound map with $what to self should exceed jump stack" + + # rule bound to c8, this should not work -- jump stack should be exceeded. + $NFT "add element t m { 1.2.3.9 : jump c9 }" + bad_ruleset $? "bound map with $what should exceed jump stack" + + # rule bound to c8, this should be within jump stack limit + $NFT "add element t m { 1.2.3.9 : jump c10 }" + good_ruleset $? "bound map with $what should not have exceeded jump stack" + +$NFT -f - < vmap -> c8 -> c9" +} + +# 16 jump levels are permitted. +# First ruleset is fine, there is no jump +# from c8 to c9. +$NFT -f - <c9 via vmap expression" + +# delete the mapping again. +$NFT "delete element t m { 1.2.3.9 }" +$NFT "add rule t c8 ip saddr vmap @m" +good_ruleset $? "bind empty map to c8" + +check_loop "jump" +check_loop "goto" + +$NFT "flush chain t c8" +good_ruleset $? "flush chain t c8" + +# should work, c9 not connected to c0 aka filter input. +$NFT "add rule t c9 tcp dport 80 tproxy to :20000 meta mark set 1 accept" +good_ruleset $? "add tproxy expression to c9" +check_bad_expr + +exit $? diff --git a/tests/shell/testcases/transactions/dumps/bad_rule_graphs.json-nft b/tests/shell/testcases/transactions/dumps/bad_rule_graphs.json-nft new file mode 100644 index 00000000..30789211 --- /dev/null +++ b/tests/shell/testcases/transactions/dumps/bad_rule_graphs.json-nft @@ -0,0 +1,201 @@ +{ + "nftables": [ + { + "metainfo": { + "version": "VERSION", + "release_name": "RELEASE_NAME", + "json_schema_version": 1 + } + }, + { + "table": { + "family": "ip", + "name": "t", + "handle": 0 + } + }, + { + "chain": { + "family": "ip", + "table": "t", + "name": "c10", + "handle": 0 + } + }, + { + "chain": { + "family": "ip", + "table": "t", + "name": "c9", + "handle": 0 + } + }, + { + "chain": { + "family": "ip", + "table": "t", + "name": "c8", + "handle": 0 + } + }, + { + "chain": { + "family": "ip", + "table": "t", + "name": "c2", + "handle": 0 + } + }, + { + "chain": { + "family": "ip", + "table": "t", + "name": "c1", + "handle": 0 + } + }, + { + "chain": { + "family": "ip", + "table": "t", + "name": "c0", + "handle": 0, + "type": "filter", + "hook": "input", + "prio": 0, + "policy": "accept" + } + }, + { + "map": { + "family": "ip", + "name": "m", + "table": "t", + "type": "ipv4_addr", + "handle": 0, + "map": "verdict" + } + }, + { + "rule": { + "family": "ip", + "table": "t", + "chain": "c9", + "handle": 0, + "expr": [ + { + "jump": { + "target": "c10" + } + } + ] + } + }, + { + "rule": { + "family": "ip", + "table": "t", + "chain": "c9", + "handle": 0, + "expr": [ + { + "match": { + "op": "==", + "left": { + "payload": { + "protocol": "tcp", + "field": "dport" + } + }, + "right": 80 + } + }, + { + "tproxy": { + "port": 20000 + } + }, + { + "mangle": { + "key": { + "meta": { + "key": "mark" + } + }, + "value": 1 + } + }, + { + "accept": null + } + ] + } + }, + { + "rule": { + "family": "ip", + "table": "t", + "chain": "c8", + "handle": 0, + "expr": [ + { + "jump": { + "target": "c9" + } + } + ] + } + }, + { + "rule": { + "family": "ip", + "table": "t", + "chain": "c1", + "handle": 0, + "expr": [ + { + "jump": { + "target": "c2" + } + } + ] + } + }, + { + "rule": { + "family": "ip", + "table": "t", + "chain": "c1", + "handle": 0, + "expr": [ + { + "vmap": { + "key": { + "payload": { + "protocol": "ip", + "field": "saddr" + } + }, + "data": "@m" + } + } + ] + } + }, + { + "rule": { + "family": "ip", + "table": "t", + "chain": "c0", + "handle": 0, + "expr": [ + { + "jump": { + "target": "c1" + } + } + ] + } + } + ] +} diff --git a/tests/shell/testcases/transactions/dumps/bad_rule_graphs.nft b/tests/shell/testcases/transactions/dumps/bad_rule_graphs.nft new file mode 100644 index 00000000..3a593650 --- /dev/null +++ b/tests/shell/testcases/transactions/dumps/bad_rule_graphs.nft @@ -0,0 +1,30 @@ +table ip t { + map m { + type ipv4_addr : verdict + } + + chain c10 { + } + + chain c9 { + jump c10 + tcp dport 80 tproxy to :20000 meta mark set 0x00000001 accept + } + + chain c8 { + jump c9 + } + + chain c2 { + } + + chain c1 { + jump c2 + ip saddr vmap @m + } + + chain c0 { + type filter hook input priority filter; policy accept; + jump c1 + } +}