Skip to content

Commit 2854378

Browse files
author
Paolo Abeni
committed
Florian Westphal says: ==================== netfilter: updates for net The following patchset contains Netfilter fixes for *net*: 1) Fix crash (call recursion) when nftables synproxy extension is used in an object map. When this feature was added in v5.4 the required hook call validation was forgotten. Fix from Fernando Fernandez Mancera. 2) bridge br_vlan_fill_forward_path_pvid uses incorrect rcu_dereference_protected(); we only have rcu read lock but not RTNL. Fix from Eric Woudstra. Last two patches address flakes in two existing selftests. netfilter pull request nf-25-10-08 * tag 'nf-25-10-08' of https://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf: selftests: netfilter: query conntrack state to check for port clash resolution selftests: netfilter: nft_fib.sh: fix spurious test failures bridge: br_vlan_fill_forward_path_pvid: use br_vlan_group_rcu() netfilter: nft_objref: validate objref and objrefmap expressions ==================== Link: https://patch.msgid.link/20251008125942.25056-1-fw@strlen.de Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2 parents 2c95a75 + e84945b commit 2854378

File tree

4 files changed

+89
-23
lines changed

4 files changed

+89
-23
lines changed

net/bridge/br_vlan.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1457,7 +1457,7 @@ void br_vlan_fill_forward_path_pvid(struct net_bridge *br,
14571457
if (!br_opt_get(br, BROPT_VLAN_ENABLED))
14581458
return;
14591459

1460-
vg = br_vlan_group(br);
1460+
vg = br_vlan_group_rcu(br);
14611461

14621462
if (idx >= 0 &&
14631463
ctx->vlan[idx].proto == br->vlan_proto) {

net/netfilter/nft_objref.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,35 @@ void nft_objref_eval(const struct nft_expr *expr,
2222
obj->ops->eval(obj, regs, pkt);
2323
}
2424

25+
static int nft_objref_validate_obj_type(const struct nft_ctx *ctx, u32 type)
26+
{
27+
unsigned int hooks;
28+
29+
switch (type) {
30+
case NFT_OBJECT_SYNPROXY:
31+
if (ctx->family != NFPROTO_IPV4 &&
32+
ctx->family != NFPROTO_IPV6 &&
33+
ctx->family != NFPROTO_INET)
34+
return -EOPNOTSUPP;
35+
36+
hooks = (1 << NF_INET_LOCAL_IN) | (1 << NF_INET_FORWARD);
37+
38+
return nft_chain_validate_hooks(ctx->chain, hooks);
39+
default:
40+
break;
41+
}
42+
43+
return 0;
44+
}
45+
46+
static int nft_objref_validate(const struct nft_ctx *ctx,
47+
const struct nft_expr *expr)
48+
{
49+
struct nft_object *obj = nft_objref_priv(expr);
50+
51+
return nft_objref_validate_obj_type(ctx, obj->ops->type->type);
52+
}
53+
2554
static int nft_objref_init(const struct nft_ctx *ctx,
2655
const struct nft_expr *expr,
2756
const struct nlattr * const tb[])
@@ -93,6 +122,7 @@ static const struct nft_expr_ops nft_objref_ops = {
93122
.activate = nft_objref_activate,
94123
.deactivate = nft_objref_deactivate,
95124
.dump = nft_objref_dump,
125+
.validate = nft_objref_validate,
96126
.reduce = NFT_REDUCE_READONLY,
97127
};
98128

@@ -197,6 +227,14 @@ static void nft_objref_map_destroy(const struct nft_ctx *ctx,
197227
nf_tables_destroy_set(ctx, priv->set);
198228
}
199229

230+
static int nft_objref_map_validate(const struct nft_ctx *ctx,
231+
const struct nft_expr *expr)
232+
{
233+
const struct nft_objref_map *priv = nft_expr_priv(expr);
234+
235+
return nft_objref_validate_obj_type(ctx, priv->set->objtype);
236+
}
237+
200238
static const struct nft_expr_ops nft_objref_map_ops = {
201239
.type = &nft_objref_type,
202240
.size = NFT_EXPR_SIZE(sizeof(struct nft_objref_map)),
@@ -206,6 +244,7 @@ static const struct nft_expr_ops nft_objref_map_ops = {
206244
.deactivate = nft_objref_map_deactivate,
207245
.destroy = nft_objref_map_destroy,
208246
.dump = nft_objref_map_dump,
247+
.validate = nft_objref_map_validate,
209248
.reduce = NFT_REDUCE_READONLY,
210249
};
211250

tools/testing/selftests/net/netfilter/nf_nat_edemux.sh

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,31 @@ cleanup()
1717

1818
checktool "socat -h" "run test without socat"
1919
checktool "iptables --version" "run test without iptables"
20+
checktool "conntrack --version" "run test without conntrack"
2021

2122
trap cleanup EXIT
2223

24+
connect_done()
25+
{
26+
local ns="$1"
27+
local port="$2"
28+
29+
ip netns exec "$ns" ss -nt -o state established "dport = :$port" | grep -q "$port"
30+
}
31+
32+
check_ctstate()
33+
{
34+
local ns="$1"
35+
local dp="$2"
36+
37+
if ! ip netns exec "$ns" conntrack --get -s 192.168.1.2 -d 192.168.1.1 -p tcp \
38+
--sport 10000 --dport "$dp" --state ESTABLISHED > /dev/null 2>&1;then
39+
echo "FAIL: Did not find expected state for dport $2"
40+
ip netns exec "$ns" bash -c 'conntrack -L; conntrack -S; ss -nt'
41+
ret=1
42+
fi
43+
}
44+
2345
setup_ns ns1 ns2
2446

2547
# Connect the namespaces using a veth pair
@@ -44,15 +66,18 @@ socatpid=$!
4466
ip netns exec "$ns2" sysctl -q net.ipv4.ip_local_port_range="10000 10000"
4567

4668
# add a virtual IP using DNAT
47-
ip netns exec "$ns2" iptables -t nat -A OUTPUT -d 10.96.0.1/32 -p tcp --dport 443 -j DNAT --to-destination 192.168.1.1:5201
69+
ip netns exec "$ns2" iptables -t nat -A OUTPUT -d 10.96.0.1/32 -p tcp --dport 443 -j DNAT --to-destination 192.168.1.1:5201 || exit 1
4870

4971
# ... and route it to the other namespace
5072
ip netns exec "$ns2" ip route add 10.96.0.1 via 192.168.1.1
5173

52-
# add a persistent connection from the other namespace
53-
ip netns exec "$ns2" socat -t 10 - TCP:192.168.1.1:5201 > /dev/null &
74+
# listener should be up by now, wait if it isn't yet.
75+
wait_local_port_listen "$ns1" 5201 tcp
5476

55-
sleep 1
77+
# add a persistent connection from the other namespace
78+
sleep 10 | ip netns exec "$ns2" socat -t 10 - TCP:192.168.1.1:5201 > /dev/null &
79+
cpid0=$!
80+
busywait "$BUSYWAIT_TIMEOUT" connect_done "$ns2" "5201"
5681

5782
# ip daddr:dport will be rewritten to 192.168.1.1 5201
5883
# NAT must reallocate source port 10000 because
@@ -71,26 +96,25 @@ fi
7196
ip netns exec "$ns1" iptables -t nat -A PREROUTING -p tcp --dport 5202 -j REDIRECT --to-ports 5201
7297
ip netns exec "$ns1" iptables -t nat -A PREROUTING -p tcp --dport 5203 -j REDIRECT --to-ports 5201
7398

74-
sleep 5 | ip netns exec "$ns2" socat -t 5 -u STDIN TCP:192.168.1.1:5202,connect-timeout=5 >/dev/null &
99+
sleep 5 | ip netns exec "$ns2" socat -T 5 -u STDIN TCP:192.168.1.1:5202,connect-timeout=5 >/dev/null &
100+
cpid1=$!
75101

76-
# if connect succeeds, client closes instantly due to EOF on stdin.
77-
# if connect hangs, it will time out after 5s.
78-
echo | ip netns exec "$ns2" socat -t 3 -u STDIN TCP:192.168.1.1:5203,connect-timeout=5 >/dev/null &
102+
sleep 5 | ip netns exec "$ns2" socat -T 5 -u STDIN TCP:192.168.1.1:5203,connect-timeout=5 >/dev/null &
79103
cpid2=$!
80104

81-
time_then=$(date +%s)
82-
wait $cpid2
83-
rv=$?
84-
time_now=$(date +%s)
105+
busywait "$BUSYWAIT_TIMEOUT" connect_done "$ns2" 5202
106+
busywait "$BUSYWAIT_TIMEOUT" connect_done "$ns2" 5203
85107

86-
# Check how much time has elapsed, expectation is for
87-
# 'cpid2' to connect and then exit (and no connect delay).
88-
delta=$((time_now - time_then))
108+
check_ctstate "$ns1" 5202
109+
check_ctstate "$ns1" 5203
89110

90-
if [ $delta -lt 2 ] && [ $rv -eq 0 ]; then
111+
kill $socatpid $cpid0 $cpid1 $cpid2
112+
socatpid=0
113+
114+
if [ $ret -eq 0 ]; then
91115
echo "PASS: could connect to service via redirected ports"
92116
else
93-
echo "FAIL: socat cannot connect to service via redirect ($delta seconds elapsed, returned $rv)"
117+
echo "FAIL: socat cannot connect to service via redirect"
94118
ret=1
95119
fi
96120

tools/testing/selftests/net/netfilter/nft_fib.sh

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -256,12 +256,12 @@ test_ping_unreachable() {
256256
local daddr4=$1
257257
local daddr6=$2
258258

259-
if ip netns exec "$ns1" ping -c 1 -w 1 -q "$daddr4" > /dev/null; then
259+
if ip netns exec "$ns1" ping -c 1 -W 0.1 -q "$daddr4" > /dev/null; then
260260
echo "FAIL: ${ns1} could reach $daddr4" 1>&2
261261
return 1
262262
fi
263263

264-
if ip netns exec "$ns1" ping -c 1 -w 1 -q "$daddr6" > /dev/null; then
264+
if ip netns exec "$ns1" ping -c 1 -W 0.1 -q "$daddr6" > /dev/null; then
265265
echo "FAIL: ${ns1} could reach $daddr6" 1>&2
266266
return 1
267267
fi
@@ -437,14 +437,17 @@ check_type()
437437
local addr="$3"
438438
local type="$4"
439439
local count="$5"
440+
local lret=0
440441

441442
[ -z "$count" ] && count=1
442443

443444
if ! ip netns exec "$nsrouter" nft get element inet t "$setname" { "$iifname" . "$addr" . "$type" } |grep -q "counter packets $count";then
444-
echo "FAIL: did not find $iifname . $addr . $type in $setname"
445+
echo "FAIL: did not find $iifname . $addr . $type in $setname with $count packets"
445446
ip netns exec "$nsrouter" nft list set inet t "$setname"
446447
ret=1
447-
return 1
448+
# do not fail right away, delete entry if it exists so later test that
449+
# checks for unwanted keys don't get confused by this *expected* key.
450+
lret=1
448451
fi
449452

450453
# delete the entry, this allows to check if anything unexpected appeared
@@ -456,7 +459,7 @@ check_type()
456459
return 1
457460
fi
458461

459-
return 0
462+
return $lret
460463
}
461464

462465
check_local()

0 commit comments

Comments
 (0)