Commit f6ac85a1 authored by Jakub Kicinski's avatar Jakub Kicinski

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.deSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 2e64fe46 b06ada6d
...@@ -736,9 +736,8 @@ config NF_FLOW_TABLE ...@@ -736,9 +736,8 @@ config NF_FLOW_TABLE
config NF_FLOW_TABLE_PROCFS config NF_FLOW_TABLE_PROCFS
bool "Supply flow table statistics in procfs" bool "Supply flow table statistics in procfs"
default y depends on NF_FLOW_TABLE
depends on PROC_FS depends on PROC_FS
depends on SYSCTL
help help
This option enables for the flow table offload statistics This option enables for the flow table offload statistics
to be shown in procfs under net/netfilter/nf_flowtable. to be shown in procfs under net/netfilter/nf_flowtable.
......
...@@ -34,25 +34,23 @@ static noinline void __nft_trace_packet(struct nft_traceinfo *info, ...@@ -34,25 +34,23 @@ static noinline void __nft_trace_packet(struct nft_traceinfo *info,
nft_trace_notify(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_chain *chain,
const struct nft_rule_dp *rule, const struct nft_rule_dp *rule,
enum nft_trace_types type) enum nft_trace_types type)
{ {
if (static_branch_unlikely(&nft_trace_enabled)) { if (static_branch_unlikely(&nft_trace_enabled)) {
const struct nft_pktinfo *pkt = info->pkt;
info->nf_trace = pkt->skb->nf_trace; info->nf_trace = pkt->skb->nf_trace;
info->rule = rule; info->rule = rule;
__nft_trace_packet(info, chain, type); __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)) { if (static_branch_unlikely(&nft_trace_enabled)) {
const struct nft_pktinfo *pkt = info->pkt;
if (info->trace) if (info->trace)
info->nf_trace = pkt->skb->nf_trace; info->nf_trace = pkt->skb->nf_trace;
} }
...@@ -96,7 +94,6 @@ static noinline void __nft_trace_verdict(struct nft_traceinfo *info, ...@@ -96,7 +94,6 @@ static noinline void __nft_trace_verdict(struct nft_traceinfo *info,
const struct nft_chain *chain, const struct nft_chain *chain,
const struct nft_regs *regs) const struct nft_regs *regs)
{ {
const struct nft_pktinfo *pkt = info->pkt;
enum nft_trace_types type; enum nft_trace_types type;
switch (regs->verdict.code) { switch (regs->verdict.code) {
...@@ -110,7 +107,9 @@ static noinline void __nft_trace_verdict(struct nft_traceinfo *info, ...@@ -110,7 +107,9 @@ static noinline void __nft_trace_verdict(struct nft_traceinfo *info,
break; break;
default: default:
type = NFT_TRACETYPE_RULE; type = NFT_TRACETYPE_RULE;
info->nf_trace = pkt->skb->nf_trace;
if (info->trace)
info->nf_trace = info->pkt->skb->nf_trace;
break; break;
} }
...@@ -271,10 +270,10 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv) ...@@ -271,10 +270,10 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv)
switch (regs.verdict.code) { switch (regs.verdict.code) {
case NFT_BREAK: case NFT_BREAK:
regs.verdict.code = NFT_CONTINUE; regs.verdict.code = NFT_CONTINUE;
nft_trace_copy_nftrace(&info); nft_trace_copy_nftrace(pkt, &info);
continue; continue;
case NFT_CONTINUE: case NFT_CONTINUE:
nft_trace_packet(&info, chain, rule, nft_trace_packet(pkt, &info, chain, rule,
NFT_TRACETYPE_RULE); NFT_TRACETYPE_RULE);
continue; continue;
} }
...@@ -318,7 +317,7 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv) ...@@ -318,7 +317,7 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv)
goto next_rule; 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)) if (static_branch_unlikely(&nft_counters_enabled))
nft_update_chain_stats(basechain, pkt); nft_update_chain_stats(basechain, pkt);
......
...@@ -9,8 +9,27 @@ ...@@ -9,8 +9,27 @@
# Kselftest framework requirement - SKIP code is 4. # Kselftest framework requirement - SKIP code is 4.
ksft_skip=4 ksft_skip=4
testns=testns1 testns=testns-$(mktemp -u "XXXXXXXX")
tables="foo bar baz quux" 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 nft --version > /dev/null 2>&1
if [ $? -ne 0 ];then if [ $? -ne 0 ];then
...@@ -59,16 +78,66 @@ done) ...@@ -59,16 +78,66 @@ done)
sleep 1 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 i in $(seq 1 10) ; do ip netns exec "$testns" nft -f "$tmp" & done
for table in $tables;do for table in $tables;do
randsleep=$((RANDOM%10)) randsleep=$((RANDOM%2))
sleep $randsleep 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 done
randsleep=$((RANDOM%10)) check_result $eret "add/delete"
sleep $randsleep
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 pkill -9 ping
...@@ -76,3 +145,5 @@ wait ...@@ -76,3 +145,5 @@ wait
rm -f "$tmp" rm -f "$tmp"
ip netns del "$testns" ip netns del "$testns"
exit $global_ret
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment