Commit a1b7dbca authored by Paolo Abeni's avatar Paolo Abeni
Browse files
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/20240717215214.225394-1-pablo@netfilter.org


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents 269521e2 cbd070a4
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -1459,18 +1459,18 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u,
	if (ret < 0)
		goto out_err;

	/* Bind the ct retriever */
	RCU_INIT_POINTER(svc->pe, pe);
	pe = NULL;

	/* Update the virtual service counters */
	if (svc->port == FTPPORT)
		atomic_inc(&ipvs->ftpsvc_counter);
	else if (svc->port == 0)
		atomic_inc(&ipvs->nullsvc_counter);
	if (svc->pe && svc->pe->conn_out)
	if (pe && pe->conn_out)
		atomic_inc(&ipvs->conn_out_counter);

	/* Bind the ct retriever */
	RCU_INIT_POINTER(svc->pe, pe);
	pe = NULL;

	/* Count only IPv4 services for old get/setsockopt interface */
	if (svc->af == AF_INET)
		ipvs->num_services++;
+2 −1
Original line number Diff line number Diff line
@@ -3420,7 +3420,8 @@ static int ctnetlink_del_expect(struct sk_buff *skb,

		if (cda[CTA_EXPECT_ID]) {
			__be32 id = nla_get_be32(cda[CTA_EXPECT_ID]);
			if (ntohl(id) != (u32)(unsigned long)exp) {

			if (id != nf_expect_get_id(exp)) {
				nf_ct_expect_put(exp);
				return -ENOENT;
			}
+2 −2
Original line number Diff line number Diff line
@@ -434,7 +434,7 @@ bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set,
	res_map  = scratch->map + (map_index ? m->bsize_max : 0);
	fill_map = scratch->map + (map_index ? 0 : m->bsize_max);

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

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

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

	nft_pipapo_for_each_field(f, i, m) {
		bool last = i == m->field_count - 1;
+21 −0
Original line number Diff line number Diff line
@@ -278,4 +278,25 @@ static u64 pipapo_estimate_size(const struct nft_set_desc *desc)
	return size;
}

/**
 * pipapo_resmap_init() - Initialise result map before first use
 * @m:		Matching data, including mapping table
 * @res_map:	Result map
 *
 * Initialize all bits covered by the first field to one, so that after
 * the first step, only the matching bits of the first bit group remain.
 *
 * If other fields have a large bitmap, set remainder of res_map to 0.
 */
static inline void pipapo_resmap_init(const struct nft_pipapo_match *m, unsigned long *res_map)
{
	const struct nft_pipapo_field *f = m->f;
	int i;

	for (i = 0; i < f->bsize; i++)
		res_map[i] = ULONG_MAX;

	for (i = f->bsize; i < m->bsize_max; i++)
		res_map[i] = 0ul;
}
#endif /* _NFT_SET_PIPAPO_H */
+6 −4
Original line number Diff line number Diff line
@@ -1036,6 +1036,7 @@ static int nft_pipapo_avx2_lookup_8b_16(unsigned long *map, unsigned long *fill,

/**
 * nft_pipapo_avx2_lookup_slow() - Fallback function for uncommon field sizes
 * @mdata:	Matching data, including mapping table
 * @map:	Previous match result, used as initial bitmap
 * @fill:	Destination bitmap to be filled with current match result
 * @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,
 * Return: -1 on no match, rule index of match if @last, otherwise first long
 * word index to be checked next (i.e. first filled word).
 */
static int nft_pipapo_avx2_lookup_slow(unsigned long *map, unsigned long *fill,
static int nft_pipapo_avx2_lookup_slow(const struct nft_pipapo_match *mdata,
					unsigned long *map, unsigned long *fill,
					const struct nft_pipapo_field *f,
					int offset, const u8 *pkt,
					bool first, bool last)
@@ -1060,7 +1062,7 @@ static int nft_pipapo_avx2_lookup_slow(unsigned long *map, unsigned long *fill,
	int i, ret = -1, b;

	if (first)
		memset(map, 0xff, bsize * sizeof(*map));
		pipapo_resmap_init(mdata, map);

	for (i = offset; i < bsize; i++) {
		if (f->bb == 8)
@@ -1186,7 +1188,7 @@ bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,
			} else if (f->groups == 16) {
				NFT_SET_PIPAPO_AVX2_LOOKUP(8, 16);
			} else {
				ret = nft_pipapo_avx2_lookup_slow(res, fill, f,
				ret = nft_pipapo_avx2_lookup_slow(m, res, fill, f,
								  ret, rp,
								  first, last);
			}
@@ -1202,7 +1204,7 @@ bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,
			} else if (f->groups == 32) {
				NFT_SET_PIPAPO_AVX2_LOOKUP(4, 32);
			} else {
				ret = nft_pipapo_avx2_lookup_slow(res, fill, f,
				ret = nft_pipapo_avx2_lookup_slow(m, res, fill, f,
								  ret, rp,
								  first, last);
			}
Loading