Skip to content

Commit cd5125d

Browse files
Florian Westphalummakynes
authored andcommitted
netfilter: nf_tables: split set destruction in deactivate and destroy phase
Splits unbind_set into destroy_set and unbinding operation. Unbinding removes set from lists (so new transaction would not find it anymore) but keeps memory allocated (so packet path continues to work). Rebind function is added to allow unrolling in case transaction that wants to remove set is aborted. Destroy function is added to free the memory, but this could occur outside of transaction in the future. Signed-off-by: Florian Westphal <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent 02b408f commit cd5125d

File tree

5 files changed

+89
-15
lines changed

5 files changed

+89
-15
lines changed

include/net/netfilter/nf_tables.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,9 @@ int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
470470
struct nft_set_binding *binding);
471471
void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
472472
struct nft_set_binding *binding);
473+
void nf_tables_rebind_set(const struct nft_ctx *ctx, struct nft_set *set,
474+
struct nft_set_binding *binding);
475+
void nf_tables_destroy_set(const struct nft_ctx *ctx, struct nft_set *set);
473476

474477
/**
475478
* enum nft_set_extensions - set extension type IDs
@@ -724,7 +727,9 @@ struct nft_expr_type {
724727
* @eval: Expression evaluation function
725728
* @size: full expression size, including private data size
726729
* @init: initialization function
727-
* @destroy: destruction function
730+
* @activate: activate expression in the next generation
731+
* @deactivate: deactivate expression in next generation
732+
* @destroy: destruction function, called after synchronize_rcu
728733
* @dump: function to dump parameters
729734
* @type: expression type
730735
* @validate: validate expression, called during loop detection

net/netfilter/nf_tables_api.c

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ static int nft_delrule_by_chain(struct nft_ctx *ctx)
298298
return 0;
299299
}
300300

301-
static int nft_trans_set_add(struct nft_ctx *ctx, int msg_type,
301+
static int nft_trans_set_add(const struct nft_ctx *ctx, int msg_type,
302302
struct nft_set *set)
303303
{
304304
struct nft_trans *trans;
@@ -318,7 +318,7 @@ static int nft_trans_set_add(struct nft_ctx *ctx, int msg_type,
318318
return 0;
319319
}
320320

321-
static int nft_delset(struct nft_ctx *ctx, struct nft_set *set)
321+
static int nft_delset(const struct nft_ctx *ctx, struct nft_set *set)
322322
{
323323
int err;
324324

@@ -3567,13 +3567,6 @@ static void nft_set_destroy(struct nft_set *set)
35673567
kvfree(set);
35683568
}
35693569

3570-
static void nf_tables_set_destroy(const struct nft_ctx *ctx, struct nft_set *set)
3571-
{
3572-
list_del_rcu(&set->list);
3573-
nf_tables_set_notify(ctx, set, NFT_MSG_DELSET, GFP_ATOMIC);
3574-
nft_set_destroy(set);
3575-
}
3576-
35773570
static int nf_tables_delset(struct net *net, struct sock *nlsk,
35783571
struct sk_buff *skb, const struct nlmsghdr *nlh,
35793572
const struct nlattr * const nla[],
@@ -3668,17 +3661,38 @@ int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
36683661
}
36693662
EXPORT_SYMBOL_GPL(nf_tables_bind_set);
36703663

3671-
void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
3664+
void nf_tables_rebind_set(const struct nft_ctx *ctx, struct nft_set *set,
36723665
struct nft_set_binding *binding)
3666+
{
3667+
if (list_empty(&set->bindings) && nft_set_is_anonymous(set) &&
3668+
nft_is_active(ctx->net, set))
3669+
list_add_tail_rcu(&set->list, &ctx->table->sets);
3670+
3671+
list_add_tail_rcu(&binding->list, &set->bindings);
3672+
}
3673+
EXPORT_SYMBOL_GPL(nf_tables_rebind_set);
3674+
3675+
void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
3676+
struct nft_set_binding *binding)
36733677
{
36743678
list_del_rcu(&binding->list);
36753679

36763680
if (list_empty(&set->bindings) && nft_set_is_anonymous(set) &&
36773681
nft_is_active(ctx->net, set))
3678-
nf_tables_set_destroy(ctx, set);
3682+
list_del_rcu(&set->list);
36793683
}
36803684
EXPORT_SYMBOL_GPL(nf_tables_unbind_set);
36813685

3686+
void nf_tables_destroy_set(const struct nft_ctx *ctx, struct nft_set *set)
3687+
{
3688+
if (list_empty(&set->bindings) && nft_set_is_anonymous(set) &&
3689+
nft_is_active(ctx->net, set)) {
3690+
nf_tables_set_notify(ctx, set, NFT_MSG_DELSET, GFP_ATOMIC);
3691+
nft_set_destroy(set);
3692+
}
3693+
}
3694+
EXPORT_SYMBOL_GPL(nf_tables_destroy_set);
3695+
36823696
const struct nft_set_ext_type nft_set_ext_types[] = {
36833697
[NFT_SET_EXT_KEY] = {
36843698
.align = __alignof__(u32),

net/netfilter/nft_dynset.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,14 +235,31 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
235235
return err;
236236
}
237237

238+
static void nft_dynset_activate(const struct nft_ctx *ctx,
239+
const struct nft_expr *expr)
240+
{
241+
struct nft_dynset *priv = nft_expr_priv(expr);
242+
243+
nf_tables_rebind_set(ctx, priv->set, &priv->binding);
244+
}
245+
246+
static void nft_dynset_deactivate(const struct nft_ctx *ctx,
247+
const struct nft_expr *expr)
248+
{
249+
struct nft_dynset *priv = nft_expr_priv(expr);
250+
251+
nf_tables_unbind_set(ctx, priv->set, &priv->binding);
252+
}
253+
238254
static void nft_dynset_destroy(const struct nft_ctx *ctx,
239255
const struct nft_expr *expr)
240256
{
241257
struct nft_dynset *priv = nft_expr_priv(expr);
242258

243-
nf_tables_unbind_set(ctx, priv->set, &priv->binding);
244259
if (priv->expr != NULL)
245260
nft_expr_destroy(ctx, priv->expr);
261+
262+
nf_tables_destroy_set(ctx, priv->set);
246263
}
247264

248265
static int nft_dynset_dump(struct sk_buff *skb, const struct nft_expr *expr)
@@ -279,6 +296,8 @@ static const struct nft_expr_ops nft_dynset_ops = {
279296
.eval = nft_dynset_eval,
280297
.init = nft_dynset_init,
281298
.destroy = nft_dynset_destroy,
299+
.activate = nft_dynset_activate,
300+
.deactivate = nft_dynset_deactivate,
282301
.dump = nft_dynset_dump,
283302
};
284303

net/netfilter/nft_lookup.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,12 +121,28 @@ static int nft_lookup_init(const struct nft_ctx *ctx,
121121
return 0;
122122
}
123123

124+
static void nft_lookup_activate(const struct nft_ctx *ctx,
125+
const struct nft_expr *expr)
126+
{
127+
struct nft_lookup *priv = nft_expr_priv(expr);
128+
129+
nf_tables_rebind_set(ctx, priv->set, &priv->binding);
130+
}
131+
132+
static void nft_lookup_deactivate(const struct nft_ctx *ctx,
133+
const struct nft_expr *expr)
134+
{
135+
struct nft_lookup *priv = nft_expr_priv(expr);
136+
137+
nf_tables_unbind_set(ctx, priv->set, &priv->binding);
138+
}
139+
124140
static void nft_lookup_destroy(const struct nft_ctx *ctx,
125141
const struct nft_expr *expr)
126142
{
127143
struct nft_lookup *priv = nft_expr_priv(expr);
128144

129-
nf_tables_unbind_set(ctx, priv->set, &priv->binding);
145+
nf_tables_destroy_set(ctx, priv->set);
130146
}
131147

132148
static int nft_lookup_dump(struct sk_buff *skb, const struct nft_expr *expr)
@@ -209,6 +225,8 @@ static const struct nft_expr_ops nft_lookup_ops = {
209225
.size = NFT_EXPR_SIZE(sizeof(struct nft_lookup)),
210226
.eval = nft_lookup_eval,
211227
.init = nft_lookup_init,
228+
.activate = nft_lookup_activate,
229+
.deactivate = nft_lookup_deactivate,
212230
.destroy = nft_lookup_destroy,
213231
.dump = nft_lookup_dump,
214232
.validate = nft_lookup_validate,

net/netfilter/nft_objref.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,12 +155,28 @@ static int nft_objref_map_dump(struct sk_buff *skb, const struct nft_expr *expr)
155155
return -1;
156156
}
157157

158+
static void nft_objref_map_activate(const struct nft_ctx *ctx,
159+
const struct nft_expr *expr)
160+
{
161+
struct nft_objref_map *priv = nft_expr_priv(expr);
162+
163+
nf_tables_rebind_set(ctx, priv->set, &priv->binding);
164+
}
165+
166+
static void nft_objref_map_deactivate(const struct nft_ctx *ctx,
167+
const struct nft_expr *expr)
168+
{
169+
struct nft_objref_map *priv = nft_expr_priv(expr);
170+
171+
nf_tables_unbind_set(ctx, priv->set, &priv->binding);
172+
}
173+
158174
static void nft_objref_map_destroy(const struct nft_ctx *ctx,
159175
const struct nft_expr *expr)
160176
{
161177
struct nft_objref_map *priv = nft_expr_priv(expr);
162178

163-
nf_tables_unbind_set(ctx, priv->set, &priv->binding);
179+
nf_tables_destroy_set(ctx, priv->set);
164180
}
165181

166182
static struct nft_expr_type nft_objref_type;
@@ -169,6 +185,8 @@ static const struct nft_expr_ops nft_objref_map_ops = {
169185
.size = NFT_EXPR_SIZE(sizeof(struct nft_objref_map)),
170186
.eval = nft_objref_map_eval,
171187
.init = nft_objref_map_init,
188+
.activate = nft_objref_map_activate,
189+
.deactivate = nft_objref_map_deactivate,
172190
.destroy = nft_objref_map_destroy,
173191
.dump = nft_objref_map_dump,
174192
};

0 commit comments

Comments
 (0)