xref: /linux/tools/testing/selftests/net/netfilter/nft_audit.sh (revision 8c245fe7dde3bf776253550fc914a36293db4ff3)
1#!/bin/bash
2# SPDX-License-Identifier: GPL-2.0
3#
4# Check that audit logs generated for nft commands are as expected.
5
6SKIP_RC=4
7RC=0
8
9if [ -r /var/run/auditd.pid ];then
10	read pid < /var/run/auditd.pid
11	p=$(pgrep ^auditd$)
12
13	if [ "$pid" -eq "$p" ]; then
14		echo "SKIP: auditd is running"
15		exit $SKIP_RC
16	fi
17fi
18
19nft --version >/dev/null 2>&1 || {
20	echo "SKIP: missing nft tool"
21	exit $SKIP_RC
22}
23
24# nft must be recent enough to support "reset" keyword.
25nft --check -f /dev/stdin >/dev/null 2>&1 <<EOF
26add table t
27add chain t c
28reset rules t c
29EOF
30
31if [ "$?" -ne 0 ];then
32	echo -n "SKIP: nft reset feature test failed: "
33	nft --version
34	exit $SKIP_RC
35fi
36
37# Run everything in a separate network namespace
38[ "${1}" != "run" ] && { unshare -n "${0}" run; exit $?; }
39
40# give other scripts a chance to finish - audit_logread sees all activity
41sleep 1
42
43logfile=$(mktemp)
44rulefile=$(mktemp)
45echo "logging into $logfile"
46./audit_logread >"$logfile" &
47logread_pid=$!
48trap 'kill $logread_pid; rm -f $logfile $rulefile' EXIT
49exec 3<"$logfile"
50
51lsplit='s/^\(.*\) entries=\([^ ]*\) \(.*\)$/pfx="\1"\nval="\2"\nsfx="\3"/'
52summarize_logs() {
53	sum=0
54	while read line; do
55		eval $(sed "$lsplit" <<< "$line")
56		[[ $sum -gt 0 ]] && {
57			[[ "$pfx $sfx" == "$tpfx $tsfx" ]] && {
58				let "sum += val"
59				continue
60			}
61			echo "$tpfx entries=$sum $tsfx"
62		}
63		tpfx="$pfx"
64		tsfx="$sfx"
65		sum=$val
66	done
67	echo "$tpfx entries=$sum $tsfx"
68}
69
70do_test() { # (cmd, log)
71	echo -n "testing for cmd: $1 ... "
72	cat <&3 >/dev/null
73	$1 >/dev/null || exit 1
74	sleep 0.1
75	res=$(diff -a -u <(echo "$2") <(summarize_logs <&3))
76	[ $? -eq 0 ] && { echo "OK"; return; }
77	echo "FAIL"
78	grep -v '^\(---\|+++\|@@\)' <<< "$res"
79	((RC--))
80}
81
82nft flush ruleset
83
84# adding tables, chains and rules
85
86for table in t1 t2; do
87	do_test "nft add table $table" \
88	"table=$table family=2 entries=1 op=nft_register_table"
89
90	do_test "nft add chain $table c1" \
91	"table=$table family=2 entries=1 op=nft_register_chain"
92
93	do_test "nft add chain $table c2; add chain $table c3" \
94	"table=$table family=2 entries=2 op=nft_register_chain"
95
96	cmd="add rule $table c1 counter"
97
98	do_test "nft $cmd" \
99	"table=$table family=2 entries=1 op=nft_register_rule"
100
101	do_test "nft $cmd; $cmd" \
102	"table=$table family=2 entries=2 op=nft_register_rule"
103
104	cmd=""
105	sep=""
106	for chain in c2 c3; do
107		for i in {1..3}; do
108			cmd+="$sep add rule $table $chain counter"
109			sep=";"
110		done
111	done
112	do_test "nft $cmd" \
113	"table=$table family=2 entries=6 op=nft_register_rule"
114done
115
116for ((i = 0; i < 500; i++)); do
117	echo "add rule t2 c3 counter accept comment \"rule $i\""
118done > "$rulefile"
119do_test "nft -f $rulefile" \
120'table=t2 family=2 entries=500 op=nft_register_rule'
121
122# adding sets and elements
123
124settype='type inet_service; counter'
125setelem='{ 22, 80, 443 }'
126setblock="{ $settype; elements = $setelem; }"
127do_test "nft add set t1 s $setblock" \
128"table=t1 family=2 entries=4 op=nft_register_set"
129
130do_test "nft add set t1 s2 $setblock; add set t1 s3 { $settype; }" \
131"table=t1 family=2 entries=5 op=nft_register_set"
132
133do_test "nft add element t1 s3 $setelem" \
134"table=t1 family=2 entries=3 op=nft_register_setelem"
135
136# adding counters
137
138do_test 'nft add counter t1 c1' \
139'table=t1 family=2 entries=1 op=nft_register_obj'
140
141do_test 'nft add counter t2 c1; add counter t2 c2' \
142'table=t2 family=2 entries=2 op=nft_register_obj'
143
144for ((i = 3; i <= 500; i++)); do
145	echo "add counter t2 c$i"
146done > "$rulefile"
147do_test "nft -f $rulefile" \
148'table=t2 family=2 entries=498 op=nft_register_obj'
149
150# adding/updating quotas
151
152do_test 'nft add quota t1 q1 { 10 bytes }' \
153'table=t1 family=2 entries=1 op=nft_register_obj'
154
155do_test 'nft add quota t2 q1 { 10 bytes }; add quota t2 q2 { 10 bytes }' \
156'table=t2 family=2 entries=2 op=nft_register_obj'
157
158for ((i = 3; i <= 500; i++)); do
159	echo "add quota t2 q$i { 10 bytes }"
160done > "$rulefile"
161do_test "nft -f $rulefile" \
162'table=t2 family=2 entries=498 op=nft_register_obj'
163
164# changing the quota value triggers obj update path
165do_test 'nft add quota t1 q1 { 20 bytes }' \
166'table=t1 family=2 entries=1 op=nft_register_obj'
167
168# resetting rules
169
170do_test 'nft reset rules t1 c2' \
171'table=t1 family=2 entries=3 op=nft_reset_rule'
172
173do_test 'nft reset rules table t1' \
174'table=t1 family=2 entries=9 op=nft_reset_rule'
175
176do_test 'nft reset rules t2 c3' \
177'table=t2 family=2 entries=503 op=nft_reset_rule'
178
179do_test 'nft reset rules t2' \
180'table=t2 family=2 entries=509 op=nft_reset_rule'
181
182do_test 'nft reset rules' \
183'table=t1 family=2 entries=9 op=nft_reset_rule
184table=t2 family=2 entries=509 op=nft_reset_rule'
185
186# resetting sets and elements
187
188elem=(22 ",80" ",443")
189relem=""
190for i in {1..3}; do
191	relem+="${elem[((i - 1))]}"
192	do_test "nft reset element t1 s { $relem }" \
193	"table=t1 family=2 entries=$i op=nft_reset_setelem"
194done
195
196do_test 'nft reset set t1 s' \
197'table=t1 family=2 entries=3 op=nft_reset_setelem'
198
199# resetting counters
200
201do_test 'nft reset counter t1 c1' \
202'table=t1 family=2 entries=1 op=nft_reset_obj'
203
204do_test 'nft reset counters t1' \
205'table=t1 family=2 entries=1 op=nft_reset_obj'
206
207do_test 'nft reset counters t2' \
208'table=t2 family=2 entries=500 op=nft_reset_obj'
209
210do_test 'nft reset counters' \
211'table=t1 family=2 entries=1 op=nft_reset_obj
212table=t2 family=2 entries=500 op=nft_reset_obj'
213
214# resetting quotas
215
216do_test 'nft reset quota t1 q1' \
217'table=t1 family=2 entries=1 op=nft_reset_obj'
218
219do_test 'nft reset quotas t1' \
220'table=t1 family=2 entries=1 op=nft_reset_obj'
221
222do_test 'nft reset quotas t2' \
223'table=t2 family=2 entries=500 op=nft_reset_obj'
224
225do_test 'nft reset quotas' \
226'table=t1 family=2 entries=1 op=nft_reset_obj
227table=t2 family=2 entries=500 op=nft_reset_obj'
228
229# deleting rules
230
231readarray -t handles < <(nft -a list chain t1 c1 | \
232			 sed -n 's/.*counter.* handle \(.*\)$/\1/p')
233
234do_test "nft delete rule t1 c1 handle ${handles[0]}" \
235'table=t1 family=2 entries=1 op=nft_unregister_rule'
236
237cmd='delete rule t1 c1 handle'
238do_test "nft $cmd ${handles[1]}; $cmd ${handles[2]}" \
239'table=t1 family=2 entries=2 op=nft_unregister_rule'
240
241do_test 'nft flush chain t1 c2' \
242'table=t1 family=2 entries=3 op=nft_unregister_rule'
243
244do_test 'nft flush table t2' \
245'table=t2 family=2 entries=509 op=nft_unregister_rule'
246
247# deleting chains
248
249do_test 'nft delete chain t2 c2' \
250'table=t2 family=2 entries=1 op=nft_unregister_chain'
251
252# deleting sets and elements
253
254do_test 'nft delete element t1 s { 22 }' \
255'table=t1 family=2 entries=1 op=nft_unregister_setelem'
256
257do_test 'nft delete element t1 s { 80, 443 }' \
258'table=t1 family=2 entries=2 op=nft_unregister_setelem'
259
260do_test 'nft flush set t1 s2' \
261'table=t1 family=2 entries=3 op=nft_unregister_setelem'
262
263do_test 'nft delete set t1 s2' \
264'table=t1 family=2 entries=1 op=nft_unregister_set'
265
266do_test 'nft delete set t1 s3' \
267'table=t1 family=2 entries=1 op=nft_unregister_set'
268
269exit $RC
270