Skip to content

Commit edafd34

Browse files
author
Paolo Abeni
committed
Merge tag 'nf-25-06-05' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf
Pablo Neira Ayuso says: ==================== Netfilter fixes for net The following patchset contains Netfilter fixes for net: 1) Zero out the remainder in nft_pipapo AVX2 implementation, otherwise next lookup could bogusly report a mismatch. This is followed by two patches to update nft_pipapo selftests to cover for the previous bug. From Florian Westphal. 2) Check for reverse tuple too in case of esoteric NAT collisions for UDP traffic and extend selftest coverage. Also from Florian. netfilter pull request 25-06-05 * tag 'nf-25-06-05' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf: selftests: netfilter: nft_nat.sh: add test for reverse clash with nat netfilter: nf_nat: also check reverse tuple to obtain clashing entry selftests: netfilter: nft_concat_range.sh: add datapath check for map fill bug selftests: netfilter: nft_concat_range.sh: prefer per element counters for testing netfilter: nf_set_pipapo_avx2: fix initial map fill ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
2 parents 8e59d9e + 3c3c324 commit edafd34

File tree

4 files changed

+193
-23
lines changed

4 files changed

+193
-23
lines changed

net/netfilter/nf_nat_core.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ static noinline bool
248248
nf_nat_used_tuple_new(const struct nf_conntrack_tuple *tuple,
249249
const struct nf_conn *ignored_ct)
250250
{
251-
static const unsigned long uses_nat = IPS_NAT_MASK | IPS_SEQ_ADJUST_BIT;
251+
static const unsigned long uses_nat = IPS_NAT_MASK | IPS_SEQ_ADJUST;
252252
const struct nf_conntrack_tuple_hash *thash;
253253
const struct nf_conntrack_zone *zone;
254254
struct nf_conn *ct;
@@ -287,8 +287,14 @@ nf_nat_used_tuple_new(const struct nf_conntrack_tuple *tuple,
287287
zone = nf_ct_zone(ignored_ct);
288288

289289
thash = nf_conntrack_find_get(net, zone, tuple);
290-
if (unlikely(!thash)) /* clashing entry went away */
291-
return false;
290+
if (unlikely(!thash)) {
291+
struct nf_conntrack_tuple reply;
292+
293+
nf_ct_invert_tuple(&reply, tuple);
294+
thash = nf_conntrack_find_get(net, zone, &reply);
295+
if (!thash) /* clashing entry went away */
296+
return false;
297+
}
292298

293299
ct = nf_ct_tuplehash_to_ctrack(thash);
294300

net/netfilter/nft_set_pipapo_avx2.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1113,6 +1113,25 @@ bool nft_pipapo_avx2_estimate(const struct nft_set_desc *desc, u32 features,
11131113
return true;
11141114
}
11151115

1116+
/**
1117+
* pipapo_resmap_init_avx2() - Initialise result map before first use
1118+
* @m: Matching data, including mapping table
1119+
* @res_map: Result map
1120+
*
1121+
* Like pipapo_resmap_init() but do not set start map bits covered by the first field.
1122+
*/
1123+
static inline void pipapo_resmap_init_avx2(const struct nft_pipapo_match *m, unsigned long *res_map)
1124+
{
1125+
const struct nft_pipapo_field *f = m->f;
1126+
int i;
1127+
1128+
/* Starting map doesn't need to be set to all-ones for this implementation,
1129+
* but we do need to zero the remaining bits, if any.
1130+
*/
1131+
for (i = f->bsize; i < m->bsize_max; i++)
1132+
res_map[i] = 0ul;
1133+
}
1134+
11161135
/**
11171136
* nft_pipapo_avx2_lookup() - Lookup function for AVX2 implementation
11181137
* @net: Network namespace
@@ -1171,7 +1190,7 @@ bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,
11711190
res = scratch->map + (map_index ? m->bsize_max : 0);
11721191
fill = scratch->map + (map_index ? 0 : m->bsize_max);
11731192

1174-
/* Starting map doesn't need to be set for this implementation */
1193+
pipapo_resmap_init_avx2(m, res);
11751194

11761195
nft_pipapo_avx2_prepare();
11771196

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

Lines changed: 88 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ display net,port,proto
378378
type_spec ipv4_addr . inet_service . inet_proto
379379
chain_spec ip daddr . udp dport . meta l4proto
380380
dst addr4 port proto
381-
src
381+
src
382382
start 1
383383
count 9
384384
src_delta 9
@@ -419,6 +419,7 @@ table inet filter {
419419
420420
set test {
421421
type ${type_spec}
422+
counter
422423
flags interval,timeout
423424
}
424425
@@ -1158,8 +1159,17 @@ del() {
11581159
fi
11591160
}
11601161

1161-
# Return packet count from 'test' counter in 'inet filter' table
1162+
# Return packet count for elem $1 from 'test' counter in 'inet filter' table
11621163
count_packets() {
1164+
found=0
1165+
for token in $(nft reset element inet filter test "${1}" ); do
1166+
[ ${found} -eq 1 ] && echo "${token}" && return
1167+
[ "${token}" = "packets" ] && found=1
1168+
done
1169+
}
1170+
1171+
# Return packet count from 'test' counter in 'inet filter' table
1172+
count_packets_nomatch() {
11631173
found=0
11641174
for token in $(nft list counter inet filter test); do
11651175
[ ${found} -eq 1 ] && echo "${token}" && return
@@ -1206,6 +1216,10 @@ perf() {
12061216

12071217
# Set MAC addresses, send single packet, check that it matches, reset counter
12081218
send_match() {
1219+
local elem="$1"
1220+
1221+
shift
1222+
12091223
ip link set veth_a address "$(format_mac "${1}")"
12101224
ip -n B link set veth_b address "$(format_mac "${2}")"
12111225

@@ -1216,7 +1230,7 @@ send_match() {
12161230
eval src_"$f"=\$\(format_\$f "${2}"\)
12171231
done
12181232
eval send_\$proto
1219-
if [ "$(count_packets)" != "1" ]; then
1233+
if [ "$(count_packets "$elem")" != "1" ]; then
12201234
err "${proto} packet to:"
12211235
err " $(for f in ${dst}; do
12221236
eval format_\$f "${1}"; printf ' '; done)"
@@ -1242,7 +1256,7 @@ send_nomatch() {
12421256
eval src_"$f"=\$\(format_\$f "${2}"\)
12431257
done
12441258
eval send_\$proto
1245-
if [ "$(count_packets)" != "0" ]; then
1259+
if [ "$(count_packets_nomatch)" != "0" ]; then
12461260
err "${proto} packet to:"
12471261
err " $(for f in ${dst}; do
12481262
eval format_\$f "${1}"; printf ' '; done)"
@@ -1255,13 +1269,51 @@ send_nomatch() {
12551269
fi
12561270
}
12571271

1272+
maybe_send_nomatch() {
1273+
local elem="$1"
1274+
local what="$4"
1275+
1276+
[ $((RANDOM%20)) -gt 0 ] && return
1277+
1278+
dst_addr4="$2"
1279+
dst_port="$3"
1280+
send_udp
1281+
1282+
if [ "$(count_packets_nomatch)" != "0" ]; then
1283+
err "Packet to $dst_addr4:$dst_port did match $what"
1284+
err "$(nft -a list ruleset)"
1285+
return 1
1286+
fi
1287+
}
1288+
1289+
maybe_send_match() {
1290+
local elem="$1"
1291+
local what="$4"
1292+
1293+
[ $((RANDOM%20)) -gt 0 ] && return
1294+
1295+
dst_addr4="$2"
1296+
dst_port="$3"
1297+
send_udp
1298+
1299+
if [ "$(count_packets "{ $elem }")" != "1" ]; then
1300+
err "Packet to $dst_addr4:$dst_port did not match $what"
1301+
err "$(nft -a list ruleset)"
1302+
return 1
1303+
fi
1304+
nft reset counter inet filter test >/dev/null
1305+
nft reset element inet filter test "{ $elem }" >/dev/null
1306+
}
1307+
12581308
# Correctness test template:
12591309
# - add ranged element, check that packets match it
12601310
# - check that packets outside range don't match it
12611311
# - remove some elements, check that packets don't match anymore
12621312
test_correctness_main() {
12631313
range_size=1
12641314
for i in $(seq "${start}" $((start + count))); do
1315+
local elem=""
1316+
12651317
end=$((start + range_size))
12661318

12671319
# Avoid negative or zero-sized port ranges
@@ -1272,15 +1324,16 @@ test_correctness_main() {
12721324
srcstart=$((start + src_delta))
12731325
srcend=$((end + src_delta))
12741326

1275-
add "$(format)" || return 1
1327+
elem="$(format)"
1328+
add "$elem" || return 1
12761329
for j in $(seq "$start" $((range_size / 2 + 1)) ${end}); do
1277-
send_match "${j}" $((j + src_delta)) || return 1
1330+
send_match "$elem" "${j}" $((j + src_delta)) || return 1
12781331
done
12791332
send_nomatch $((end + 1)) $((end + 1 + src_delta)) || return 1
12801333

12811334
# Delete elements now and then
12821335
if [ $((i % 3)) -eq 0 ]; then
1283-
del "$(format)" || return 1
1336+
del "$elem" || return 1
12841337
for j in $(seq "$start" \
12851338
$((range_size / 2 + 1)) ${end}); do
12861339
send_nomatch "${j}" $((j + src_delta)) \
@@ -1572,14 +1625,17 @@ test_timeout() {
15721625

15731626
range_size=1
15741627
for i in $(seq "$start" $((start + count))); do
1628+
local elem=""
1629+
15751630
end=$((start + range_size))
15761631
srcstart=$((start + src_delta))
15771632
srcend=$((end + src_delta))
15781633

1579-
add "$(format)" || return 1
1634+
elem="$(format)"
1635+
add "$elem" || return 1
15801636

15811637
for j in $(seq "$start" $((range_size / 2 + 1)) ${end}); do
1582-
send_match "${j}" $((j + src_delta)) || return 1
1638+
send_match "$elem" "${j}" $((j + src_delta)) || return 1
15831639
done
15841640

15851641
range_size=$((range_size + 1))
@@ -1737,7 +1793,7 @@ test_bug_reload() {
17371793
srcend=$((end + src_delta))
17381794

17391795
for j in $(seq "$start" $((range_size / 2 + 1)) ${end}); do
1740-
send_match "${j}" $((j + src_delta)) || return 1
1796+
send_match "$(format)" "${j}" $((j + src_delta)) || return 1
17411797
done
17421798

17431799
range_size=$((range_size + 1))
@@ -1756,39 +1812,55 @@ test_bug_net_port_proto_match() {
17561812
range_size=1
17571813
for i in $(seq 1 10); do
17581814
for j in $(seq 1 20) ; do
1759-
elem=$(printf "10.%d.%d.0/24 . %d1-%d0 . 6-17 " ${i} ${j} ${i} "$((i+1))")
1815+
local dport=$j
1816+
1817+
elem=$(printf "10.%d.%d.0/24 . %d-%d0 . 6-17 " ${i} ${j} ${dport} "$((dport+1))")
1818+
1819+
# too slow, do not test all addresses
1820+
maybe_send_nomatch "$elem" $(printf "10.%d.%d.1" $i $j) $(printf "%d1" $((dport+1))) "before add" || return 1
17601821

17611822
nft "add element inet filter test { $elem }" || return 1
1823+
1824+
maybe_send_match "$elem" $(printf "10.%d.%d.1" $i $j) $(printf "%d" $dport) "after add" || return 1
1825+
17621826
nft "get element inet filter test { $elem }" | grep -q "$elem"
17631827
if [ $? -ne 0 ];then
17641828
local got=$(nft "get element inet filter test { $elem }")
17651829
err "post-add: should have returned $elem but got $got"
17661830
return 1
17671831
fi
1832+
1833+
maybe_send_nomatch "$elem" $(printf "10.%d.%d.1" $i $j) $(printf "%d1" $((dport+1))) "out-of-range" || return 1
17681834
done
17691835
done
17701836

17711837
# recheck after set was filled
17721838
for i in $(seq 1 10); do
17731839
for j in $(seq 1 20) ; do
1774-
elem=$(printf "10.%d.%d.0/24 . %d1-%d0 . 6-17 " ${i} ${j} ${i} "$((i+1))")
1840+
local dport=$j
1841+
1842+
elem=$(printf "10.%d.%d.0/24 . %d-%d0 . 6-17 " ${i} ${j} ${dport} "$((dport+1))")
17751843

17761844
nft "get element inet filter test { $elem }" | grep -q "$elem"
17771845
if [ $? -ne 0 ];then
17781846
local got=$(nft "get element inet filter test { $elem }")
17791847
err "post-fill: should have returned $elem but got $got"
17801848
return 1
17811849
fi
1850+
1851+
maybe_send_match "$elem" $(printf "10.%d.%d.1" $i $j) $(printf "%d" $dport) "recheck" || return 1
1852+
maybe_send_nomatch "$elem" $(printf "10.%d.%d.1" $i $j) $(printf "%d1" $((dport+1))) "recheck out-of-range" || return 1
17821853
done
17831854
done
17841855

17851856
# random del and re-fetch
17861857
for i in $(seq 1 10); do
17871858
for j in $(seq 1 20) ; do
17881859
local rnd=$((RANDOM%10))
1860+
local dport=$j
17891861
local got=""
17901862

1791-
elem=$(printf "10.%d.%d.0/24 . %d1-%d0 . 6-17 " ${i} ${j} ${i} "$((i+1))")
1863+
elem=$(printf "10.%d.%d.0/24 . %d-%d0 . 6-17 " ${i} ${j} ${dport} "$((dport+1))")
17921864
if [ $rnd -gt 0 ];then
17931865
continue
17941866
fi
@@ -1799,6 +1871,8 @@ test_bug_net_port_proto_match() {
17991871
err "post-delete: query for $elem returned $got instead of error."
18001872
return 1
18011873
fi
1874+
1875+
maybe_send_nomatch "$elem" $(printf "10.%d.%d.1" $i $j) $(printf "%d" $dport) "match after deletion" || return 1
18021876
done
18031877
done
18041878

@@ -1817,7 +1891,7 @@ test_bug_avx2_mismatch()
18171891
dst_addr6="$a2"
18181892
send_icmp6
18191893

1820-
if [ "$(count_packets)" -gt "0" ]; then
1894+
if [ "$(count_packets "{ icmpv6 . $a1 }")" -gt "0" ]; then
18211895
err "False match for $a2"
18221896
return 1
18231897
fi

0 commit comments

Comments
 (0)