Commit f6ac85a1 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'netfilter-followup-fixes-for-net'

Florian Westphal says:

====================
netfilter followup fixes for net

Regressions, since 5.19:
Fix crash when packet tracing is enabled via 'meta nftrace set 1' rule.
Also comes with a test case.

Regressions, this cycle:
Fix Kconfig dependency for the flowtable /proc interface, we want this
to be off by default.
====================

Link: https://lore.kernel.org/r/20220804172629.29748-1-fw@strlen.de


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 2e64fe46 b06ada6d
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -736,9 +736,8 @@ config NF_FLOW_TABLE

config NF_FLOW_TABLE_PROCFS
	bool "Supply flow table statistics in procfs"
	default y
	depends on NF_FLOW_TABLE
	depends on PROC_FS
	depends on SYSCTL
	help
	  This option enables for the flow table offload statistics
	  to be shown in procfs under net/netfilter/nf_flowtable.
+10 −11
Original line number Diff line number Diff line
@@ -34,25 +34,23 @@ static noinline void __nft_trace_packet(struct nft_traceinfo *info,
	nft_trace_notify(info);
}

static inline void nft_trace_packet(struct nft_traceinfo *info,
static inline void nft_trace_packet(const struct nft_pktinfo *pkt,
				    struct nft_traceinfo *info,
				    const struct nft_chain *chain,
				    const struct nft_rule_dp *rule,
				    enum nft_trace_types type)
{
	if (static_branch_unlikely(&nft_trace_enabled)) {
		const struct nft_pktinfo *pkt = info->pkt;

		info->nf_trace = pkt->skb->nf_trace;
		info->rule = rule;
		__nft_trace_packet(info, chain, type);
	}
}

static inline void nft_trace_copy_nftrace(struct nft_traceinfo *info)
static inline void nft_trace_copy_nftrace(const struct nft_pktinfo *pkt,
					  struct nft_traceinfo *info)
{
	if (static_branch_unlikely(&nft_trace_enabled)) {
		const struct nft_pktinfo *pkt = info->pkt;

		if (info->trace)
			info->nf_trace = pkt->skb->nf_trace;
	}
@@ -96,7 +94,6 @@ static noinline void __nft_trace_verdict(struct nft_traceinfo *info,
					 const struct nft_chain *chain,
					 const struct nft_regs *regs)
{
	const struct nft_pktinfo *pkt = info->pkt;
	enum nft_trace_types type;

	switch (regs->verdict.code) {
@@ -110,7 +107,9 @@ static noinline void __nft_trace_verdict(struct nft_traceinfo *info,
		break;
	default:
		type = NFT_TRACETYPE_RULE;
		info->nf_trace = pkt->skb->nf_trace;

		if (info->trace)
			info->nf_trace = info->pkt->skb->nf_trace;
		break;
	}

@@ -271,10 +270,10 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv)
		switch (regs.verdict.code) {
		case NFT_BREAK:
			regs.verdict.code = NFT_CONTINUE;
			nft_trace_copy_nftrace(&info);
			nft_trace_copy_nftrace(pkt, &info);
			continue;
		case NFT_CONTINUE:
			nft_trace_packet(&info, chain, rule,
			nft_trace_packet(pkt, &info, chain, rule,
					 NFT_TRACETYPE_RULE);
			continue;
		}
@@ -318,7 +317,7 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv)
		goto next_rule;
	}

	nft_trace_packet(&info, basechain, NULL, NFT_TRACETYPE_POLICY);
	nft_trace_packet(pkt, &info, basechain, NULL, NFT_TRACETYPE_POLICY);

	if (static_branch_unlikely(&nft_counters_enabled))
		nft_update_chain_stats(basechain, pkt);
+76 −5
Original line number Diff line number Diff line
@@ -9,8 +9,27 @@
# Kselftest framework requirement - SKIP code is 4.
ksft_skip=4

testns=testns1
testns=testns-$(mktemp -u "XXXXXXXX")

tables="foo bar baz quux"
global_ret=0
eret=0
lret=0

check_result()
{
	local r=$1
	local OK="PASS"

	if [ $r -ne 0 ] ;then
		OK="FAIL"
		global_ret=$r
	fi

	echo "$OK: nft $2 test returned $r"

	eret=0
}

nft --version > /dev/null 2>&1
if [ $? -ne 0 ];then
@@ -59,16 +78,66 @@ done)

sleep 1

ip netns exec "$testns" nft -f "$tmp"
for i in $(seq 1 10) ; do ip netns exec "$testns" nft -f "$tmp" & done

for table in $tables;do
	randsleep=$((RANDOM%10))
	randsleep=$((RANDOM%2))
	sleep $randsleep
	ip netns exec "$testns" nft delete table inet $table 2>/dev/null
	ip netns exec "$testns" nft delete table inet $table
	lret=$?
	if [ $lret -ne 0 ]; then
		eret=$lret
	fi
done

randsleep=$((RANDOM%10))
sleep $randsleep
check_result $eret "add/delete"

for i in $(seq 1 10) ; do
	(echo "flush ruleset"; cat "$tmp") | ip netns exec "$testns" nft -f /dev/stdin

	lret=$?
	if [ $lret -ne 0 ]; then
		eret=$lret
	fi
done

check_result $eret "reload"

for i in $(seq 1 10) ; do
	(echo "flush ruleset"; cat "$tmp"
	 echo "insert rule inet foo INPUT meta nftrace set 1"
	 echo "insert rule inet foo OUTPUT meta nftrace set 1"
	 ) | ip netns exec "$testns" nft -f /dev/stdin
	lret=$?
	if [ $lret -ne 0 ]; then
		eret=$lret
	fi

	(echo "flush ruleset"; cat "$tmp"
	 ) | ip netns exec "$testns" nft -f /dev/stdin

	lret=$?
	if [ $lret -ne 0 ]; then
		eret=$lret
	fi
done

check_result $eret "add/delete with nftrace enabled"

echo "insert rule inet foo INPUT meta nftrace set 1" >> $tmp
echo "insert rule inet foo OUTPUT meta nftrace set 1" >> $tmp

for i in $(seq 1 10) ; do
	(echo "flush ruleset"; cat "$tmp") | ip netns exec "$testns" nft -f /dev/stdin

	lret=$?
	if [ $lret -ne 0 ]; then
		eret=1
	fi
done

check_result $lret "add/delete with nftrace enabled"

pkill -9 ping

@@ -76,3 +145,5 @@ wait

rm -f "$tmp"
ip netns del "$testns"

exit $global_ret