Skip to content

Commit 29b359c

Browse files
committed
netfilter: nft_set_pipapo: walk over current view on netlink dump
The generation mask can be updated while netlink dump is in progress. The pipapo set backend walk iterator cannot rely on it to infer what view of the datastructure is to be used. Add notation to specify if user wants to read/update the set. Based on patch from Florian Westphal. Fixes: 2b84e21 ("netfilter: nft_set_pipapo: .walk does not deal with generations") Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent 751de20 commit 29b359c

File tree

3 files changed

+23
-2
lines changed

3 files changed

+23
-2
lines changed

include/net/netfilter/nf_tables.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,9 +307,23 @@ static inline void *nft_elem_priv_cast(const struct nft_elem_priv *priv)
307307
return (void *)priv;
308308
}
309309

310+
311+
/**
312+
* enum nft_iter_type - nftables set iterator type
313+
*
314+
* @NFT_ITER_READ: read-only iteration over set elements
315+
* @NFT_ITER_UPDATE: iteration under mutex to update set element state
316+
*/
317+
enum nft_iter_type {
318+
NFT_ITER_UNSPEC,
319+
NFT_ITER_READ,
320+
NFT_ITER_UPDATE,
321+
};
322+
310323
struct nft_set;
311324
struct nft_set_iter {
312325
u8 genmask;
326+
enum nft_iter_type type:8;
313327
unsigned int count;
314328
unsigned int skip;
315329
int err;

net/netfilter/nf_tables_api.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -626,6 +626,7 @@ static void nft_map_deactivate(const struct nft_ctx *ctx, struct nft_set *set)
626626
{
627627
struct nft_set_iter iter = {
628628
.genmask = nft_genmask_next(ctx->net),
629+
.type = NFT_ITER_UPDATE,
629630
.fn = nft_mapelem_deactivate,
630631
};
631632

@@ -5445,6 +5446,7 @@ int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
54455446
}
54465447

54475448
iter.genmask = nft_genmask_next(ctx->net);
5449+
iter.type = NFT_ITER_UPDATE;
54485450
iter.skip = 0;
54495451
iter.count = 0;
54505452
iter.err = 0;
@@ -5518,6 +5520,7 @@ static void nft_map_activate(const struct nft_ctx *ctx, struct nft_set *set)
55185520
{
55195521
struct nft_set_iter iter = {
55205522
.genmask = nft_genmask_next(ctx->net),
5523+
.type = NFT_ITER_UPDATE,
55215524
.fn = nft_mapelem_activate,
55225525
};
55235526

@@ -5892,6 +5895,7 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
58925895
args.skb = skb;
58935896
args.reset = dump_ctx->reset;
58945897
args.iter.genmask = nft_genmask_cur(net);
5898+
args.iter.type = NFT_ITER_READ;
58955899
args.iter.skip = cb->args[0];
58965900
args.iter.count = 0;
58975901
args.iter.err = 0;
@@ -7376,6 +7380,7 @@ static int nft_set_flush(struct nft_ctx *ctx, struct nft_set *set, u8 genmask)
73767380
{
73777381
struct nft_set_iter iter = {
73787382
.genmask = genmask,
7383+
.type = NFT_ITER_UPDATE,
73797384
.fn = nft_setelem_flush,
73807385
};
73817386

@@ -10879,6 +10884,7 @@ static int nf_tables_check_loops(const struct nft_ctx *ctx,
1087910884
continue;
1088010885

1088110886
iter.genmask = nft_genmask_next(ctx->net);
10887+
iter.type = NFT_ITER_UPDATE;
1088210888
iter.skip = 0;
1088310889
iter.count = 0;
1088410890
iter.err = 0;

net/netfilter/nft_set_pipapo.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2115,13 +2115,14 @@ static void nft_pipapo_walk(const struct nft_ctx *ctx, struct nft_set *set,
21152115
struct nft_set_iter *iter)
21162116
{
21172117
struct nft_pipapo *priv = nft_set_priv(set);
2118-
struct net *net = read_pnet(&set->net);
21192118
const struct nft_pipapo_match *m;
21202119
const struct nft_pipapo_field *f;
21212120
unsigned int i, r;
21222121

2122+
WARN_ON_ONCE(iter->type == NFT_ITER_UNSPEC);
2123+
21232124
rcu_read_lock();
2124-
if (iter->genmask == nft_genmask_cur(net))
2125+
if (iter->type == NFT_ITER_READ)
21252126
m = rcu_dereference(priv->match);
21262127
else
21272128
m = priv->clone;

0 commit comments

Comments
 (0)