Commit 280e3a85 authored by David S. Miller's avatar David S. Miller

Merge 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) Insufficient validation of element datatype and length in
   nft_setelem_parse_data(). At least commit 7d740264 updates
   maximum element data area up to 64 bytes when only 16 bytes
   where supported at the time. Support for larger element size
   came later in fdb9c405 though. Picking this older commit
   as Fixes: tag to be safe than sorry.

2) Memleak in pipapo destroy path, reproducible when transaction
   in aborted. This is already triggering in the existing netfilter
   test infrastructure since more recent new tests are covering this
   path.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3d5a2a39 9827a0e6
...@@ -5213,13 +5213,20 @@ static int nft_setelem_parse_data(struct nft_ctx *ctx, struct nft_set *set, ...@@ -5213,13 +5213,20 @@ static int nft_setelem_parse_data(struct nft_ctx *ctx, struct nft_set *set,
struct nft_data *data, struct nft_data *data,
struct nlattr *attr) struct nlattr *attr)
{ {
u32 dtype;
int err; int err;
err = nft_data_init(ctx, data, NFT_DATA_VALUE_MAXLEN, desc, attr); err = nft_data_init(ctx, data, NFT_DATA_VALUE_MAXLEN, desc, attr);
if (err < 0) if (err < 0)
return err; return err;
if (desc->type != NFT_DATA_VERDICT && desc->len != set->dlen) { if (set->dtype == NFT_DATA_VERDICT)
dtype = NFT_DATA_VERDICT;
else
dtype = NFT_DATA_VALUE;
if (dtype != desc->type ||
set->dlen != desc->len) {
nft_data_release(data, desc->type); nft_data_release(data, desc->type);
return -EINVAL; return -EINVAL;
} }
......
...@@ -2125,19 +2125,15 @@ static int nft_pipapo_init(const struct nft_set *set, ...@@ -2125,19 +2125,15 @@ static int nft_pipapo_init(const struct nft_set *set,
} }
/** /**
* nft_pipapo_destroy() - Free private data for set and all committed elements * nft_set_pipapo_match_destroy() - Destroy elements from key mapping array
* @set: nftables API set representation * @set: nftables API set representation
* @m: matching data pointing to key mapping array
*/ */
static void nft_pipapo_destroy(const struct nft_set *set) static void nft_set_pipapo_match_destroy(const struct nft_set *set,
struct nft_pipapo_match *m)
{ {
struct nft_pipapo *priv = nft_set_priv(set);
struct nft_pipapo_match *m;
struct nft_pipapo_field *f; struct nft_pipapo_field *f;
int i, r, cpu; int i, r;
m = rcu_dereference_protected(priv->match, true);
if (m) {
rcu_barrier();
for (i = 0, f = m->f; i < m->field_count - 1; i++, f++) for (i = 0, f = m->f; i < m->field_count - 1; i++, f++)
; ;
...@@ -2152,6 +2148,23 @@ static void nft_pipapo_destroy(const struct nft_set *set) ...@@ -2152,6 +2148,23 @@ static void nft_pipapo_destroy(const struct nft_set *set)
nft_set_elem_destroy(set, e, true); nft_set_elem_destroy(set, e, true);
} }
}
/**
* nft_pipapo_destroy() - Free private data for set and all committed elements
* @set: nftables API set representation
*/
static void nft_pipapo_destroy(const struct nft_set *set)
{
struct nft_pipapo *priv = nft_set_priv(set);
struct nft_pipapo_match *m;
int cpu;
m = rcu_dereference_protected(priv->match, true);
if (m) {
rcu_barrier();
nft_set_pipapo_match_destroy(set, m);
#ifdef NFT_PIPAPO_ALIGN #ifdef NFT_PIPAPO_ALIGN
free_percpu(m->scratch_aligned); free_percpu(m->scratch_aligned);
...@@ -2165,6 +2178,11 @@ static void nft_pipapo_destroy(const struct nft_set *set) ...@@ -2165,6 +2178,11 @@ static void nft_pipapo_destroy(const struct nft_set *set)
} }
if (priv->clone) { if (priv->clone) {
m = priv->clone;
if (priv->dirty)
nft_set_pipapo_match_destroy(set, m);
#ifdef NFT_PIPAPO_ALIGN #ifdef NFT_PIPAPO_ALIGN
free_percpu(priv->clone->scratch_aligned); free_percpu(priv->clone->scratch_aligned);
#endif #endif
......
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