Skip to content

Commit a1b7dbc

Browse files
author
Paolo Abeni
committed
Merge tag 'nf-24-07-17' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf
Pablo Neira Ayuso says: ==================== Netfilter/IPVS fixes for net The following patchset contains Netfilter/IPVS fixes for net: 1) Call nf_expect_get_id() to delete expectation by ID. By trial and error it is possible to leak the LSB of the expectation address on x86_64. This bug is a leftover when converting the existing code to use nf_expect_get_id(). 2) Incorrect initialization in pipapo set backend leads to packet mismatches. From Florian Westphal. 3) Extend netfilter's selftests to cover for the pipapo set backend, also from Florian. 4) Fix sparse warning in IPVS when adding service, from Chen Hanxiao. netfilter pull request 24-07-17 * tag 'nf-24-07-17' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf: ipvs: properly dereference pe in ip_vs_add_service selftests: netfilter: add test case for recent mismatch bug netfilter: nf_set_pipapo: fix initial map fill netfilter: ctnetlink: use helper function to calculate expect ID ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
2 parents 269521e + cbd070a commit a1b7dbc

File tree

6 files changed

+111
-13
lines changed

6 files changed

+111
-13
lines changed

net/netfilter/ipvs/ip_vs_ctl.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1459,18 +1459,18 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u,
14591459
if (ret < 0)
14601460
goto out_err;
14611461

1462-
/* Bind the ct retriever */
1463-
RCU_INIT_POINTER(svc->pe, pe);
1464-
pe = NULL;
1465-
14661462
/* Update the virtual service counters */
14671463
if (svc->port == FTPPORT)
14681464
atomic_inc(&ipvs->ftpsvc_counter);
14691465
else if (svc->port == 0)
14701466
atomic_inc(&ipvs->nullsvc_counter);
1471-
if (svc->pe && svc->pe->conn_out)
1467+
if (pe && pe->conn_out)
14721468
atomic_inc(&ipvs->conn_out_counter);
14731469

1470+
/* Bind the ct retriever */
1471+
RCU_INIT_POINTER(svc->pe, pe);
1472+
pe = NULL;
1473+
14741474
/* Count only IPv4 services for old get/setsockopt interface */
14751475
if (svc->af == AF_INET)
14761476
ipvs->num_services++;

net/netfilter/nf_conntrack_netlink.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3420,7 +3420,8 @@ static int ctnetlink_del_expect(struct sk_buff *skb,
34203420

34213421
if (cda[CTA_EXPECT_ID]) {
34223422
__be32 id = nla_get_be32(cda[CTA_EXPECT_ID]);
3423-
if (ntohl(id) != (u32)(unsigned long)exp) {
3423+
3424+
if (id != nf_expect_get_id(exp)) {
34243425
nf_ct_expect_put(exp);
34253426
return -ENOENT;
34263427
}

net/netfilter/nft_set_pipapo.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,7 @@ bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set,
434434
res_map = scratch->map + (map_index ? m->bsize_max : 0);
435435
fill_map = scratch->map + (map_index ? 0 : m->bsize_max);
436436

437-
memset(res_map, 0xff, m->bsize_max * sizeof(*res_map));
437+
pipapo_resmap_init(m, res_map);
438438

439439
nft_pipapo_for_each_field(f, i, m) {
440440
bool last = i == m->field_count - 1;
@@ -542,7 +542,7 @@ static struct nft_pipapo_elem *pipapo_get(const struct net *net,
542542
goto out;
543543
}
544544

545-
memset(res_map, 0xff, m->bsize_max * sizeof(*res_map));
545+
pipapo_resmap_init(m, res_map);
546546

547547
nft_pipapo_for_each_field(f, i, m) {
548548
bool last = i == m->field_count - 1;

net/netfilter/nft_set_pipapo.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,4 +278,25 @@ static u64 pipapo_estimate_size(const struct nft_set_desc *desc)
278278
return size;
279279
}
280280

281+
/**
282+
* pipapo_resmap_init() - Initialise result map before first use
283+
* @m: Matching data, including mapping table
284+
* @res_map: Result map
285+
*
286+
* Initialize all bits covered by the first field to one, so that after
287+
* the first step, only the matching bits of the first bit group remain.
288+
*
289+
* If other fields have a large bitmap, set remainder of res_map to 0.
290+
*/
291+
static inline void pipapo_resmap_init(const struct nft_pipapo_match *m, unsigned long *res_map)
292+
{
293+
const struct nft_pipapo_field *f = m->f;
294+
int i;
295+
296+
for (i = 0; i < f->bsize; i++)
297+
res_map[i] = ULONG_MAX;
298+
299+
for (i = f->bsize; i < m->bsize_max; i++)
300+
res_map[i] = 0ul;
301+
}
281302
#endif /* _NFT_SET_PIPAPO_H */

net/netfilter/nft_set_pipapo_avx2.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,7 @@ static int nft_pipapo_avx2_lookup_8b_16(unsigned long *map, unsigned long *fill,
10361036

10371037
/**
10381038
* nft_pipapo_avx2_lookup_slow() - Fallback function for uncommon field sizes
1039+
* @mdata: Matching data, including mapping table
10391040
* @map: Previous match result, used as initial bitmap
10401041
* @fill: Destination bitmap to be filled with current match result
10411042
* @f: Field, containing lookup and mapping tables
@@ -1051,7 +1052,8 @@ static int nft_pipapo_avx2_lookup_8b_16(unsigned long *map, unsigned long *fill,
10511052
* Return: -1 on no match, rule index of match if @last, otherwise first long
10521053
* word index to be checked next (i.e. first filled word).
10531054
*/
1054-
static int nft_pipapo_avx2_lookup_slow(unsigned long *map, unsigned long *fill,
1055+
static int nft_pipapo_avx2_lookup_slow(const struct nft_pipapo_match *mdata,
1056+
unsigned long *map, unsigned long *fill,
10551057
const struct nft_pipapo_field *f,
10561058
int offset, const u8 *pkt,
10571059
bool first, bool last)
@@ -1060,7 +1062,7 @@ static int nft_pipapo_avx2_lookup_slow(unsigned long *map, unsigned long *fill,
10601062
int i, ret = -1, b;
10611063

10621064
if (first)
1063-
memset(map, 0xff, bsize * sizeof(*map));
1065+
pipapo_resmap_init(mdata, map);
10641066

10651067
for (i = offset; i < bsize; i++) {
10661068
if (f->bb == 8)
@@ -1186,7 +1188,7 @@ bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,
11861188
} else if (f->groups == 16) {
11871189
NFT_SET_PIPAPO_AVX2_LOOKUP(8, 16);
11881190
} else {
1189-
ret = nft_pipapo_avx2_lookup_slow(res, fill, f,
1191+
ret = nft_pipapo_avx2_lookup_slow(m, res, fill, f,
11901192
ret, rp,
11911193
first, last);
11921194
}
@@ -1202,7 +1204,7 @@ bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,
12021204
} else if (f->groups == 32) {
12031205
NFT_SET_PIPAPO_AVX2_LOOKUP(4, 32);
12041206
} else {
1205-
ret = nft_pipapo_avx2_lookup_slow(res, fill, f,
1207+
ret = nft_pipapo_avx2_lookup_slow(m, res, fill, f,
12061208
ret, rp,
12071209
first, last);
12081210
}

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

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ TYPES="net_port port_net net6_port port_proto net6_port_mac net6_port_mac_proto
2727
net6_port_net6_port net_port_mac_proto_net"
2828

2929
# Reported bugs, also described by TYPE_ variables below
30-
BUGS="flush_remove_add reload"
30+
BUGS="flush_remove_add reload net_port_proto_match"
3131

3232
# List of possible paths to pktgen script from kernel tree for performance tests
3333
PKTGEN_SCRIPT_PATHS="
@@ -371,6 +371,22 @@ race_repeat 0
371371
perf_duration 0
372372
"
373373

374+
TYPE_net_port_proto_match="
375+
display net,port,proto
376+
type_spec ipv4_addr . inet_service . inet_proto
377+
chain_spec ip daddr . udp dport . meta l4proto
378+
dst addr4 port proto
379+
src
380+
start 1
381+
count 9
382+
src_delta 9
383+
tools sendip bash
384+
proto udp
385+
386+
race_repeat 0
387+
388+
perf_duration 0
389+
"
374390
# Set template for all tests, types and rules are filled in depending on test
375391
set_template='
376392
flush ruleset
@@ -1555,6 +1571,64 @@ test_bug_reload() {
15551571
nft flush ruleset
15561572
}
15571573

1574+
# - add ranged element, check that packets match it
1575+
# - delete element again, check it is gone
1576+
test_bug_net_port_proto_match() {
1577+
setup veth send_"${proto}" set || return ${ksft_skip}
1578+
rstart=${start}
1579+
1580+
range_size=1
1581+
for i in $(seq 1 10); do
1582+
for j in $(seq 1 20) ; do
1583+
elem=$(printf "10.%d.%d.0/24 . %d1-%d0 . 6-17 " ${i} ${j} ${i} "$((i+1))")
1584+
1585+
nft "add element inet filter test { $elem }" || return 1
1586+
nft "get element inet filter test { $elem }" | grep -q "$elem"
1587+
if [ $? -ne 0 ];then
1588+
local got=$(nft "get element inet filter test { $elem }")
1589+
err "post-add: should have returned $elem but got $got"
1590+
return 1
1591+
fi
1592+
done
1593+
done
1594+
1595+
# recheck after set was filled
1596+
for i in $(seq 1 10); do
1597+
for j in $(seq 1 20) ; do
1598+
elem=$(printf "10.%d.%d.0/24 . %d1-%d0 . 6-17 " ${i} ${j} ${i} "$((i+1))")
1599+
1600+
nft "get element inet filter test { $elem }" | grep -q "$elem"
1601+
if [ $? -ne 0 ];then
1602+
local got=$(nft "get element inet filter test { $elem }")
1603+
err "post-fill: should have returned $elem but got $got"
1604+
return 1
1605+
fi
1606+
done
1607+
done
1608+
1609+
# random del and re-fetch
1610+
for i in $(seq 1 10); do
1611+
for j in $(seq 1 20) ; do
1612+
local rnd=$((RANDOM%10))
1613+
local got=""
1614+
1615+
elem=$(printf "10.%d.%d.0/24 . %d1-%d0 . 6-17 " ${i} ${j} ${i} "$((i+1))")
1616+
if [ $rnd -gt 0 ];then
1617+
continue
1618+
fi
1619+
1620+
nft "delete element inet filter test { $elem }"
1621+
got=$(nft "get element inet filter test { $elem }" 2>/dev/null)
1622+
if [ $? -eq 0 ];then
1623+
err "post-delete: query for $elem returned $got instead of error."
1624+
return 1
1625+
fi
1626+
done
1627+
done
1628+
1629+
nft flush ruleset
1630+
}
1631+
15581632
test_reported_issues() {
15591633
eval test_bug_"${subtest}"
15601634
}

0 commit comments

Comments
 (0)