Skip to content

Commit f6dad62

Browse files
committed
netfilter: nf_tables: add support to destroy operation
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1925492 Upstream Status: commit f80a612 commit f80a612 Author: Fernando Fernandez Mancera <[email protected]> Date: Mon Jan 2 15:42:34 2023 +0100 netfilter: nf_tables: add support to destroy operation Introduce NFT_MSG_DESTROY* message type. The destroy operation performs a delete operation but ignoring the ENOENT errors. This is useful for the transaction semantics, where failing to delete an object which does not exist results in aborting the transaction. This new command allows the transaction to proceed in case the object does not exist. Signed-off-by: Fernando Fernandez Mancera <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]> Signed-off-by: Florian Westphal <[email protected]> Signed-off-by: Phil Sutter <[email protected]>
1 parent fbc09cf commit f6dad62

File tree

2 files changed

+117
-8
lines changed

2 files changed

+117
-8
lines changed

include/uapi/linux/netfilter/nf_tables.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,13 @@ enum nft_verdicts {
9898
* @NFT_MSG_GETFLOWTABLE: get flow table (enum nft_flowtable_attributes)
9999
* @NFT_MSG_DELFLOWTABLE: delete flow table (enum nft_flowtable_attributes)
100100
* @NFT_MSG_GETRULE_RESET: get rules and reset stateful expressions (enum nft_obj_attributes)
101+
* @NFT_MSG_DESTROYTABLE: destroy a table (enum nft_table_attributes)
102+
* @NFT_MSG_DESTROYCHAIN: destroy a chain (enum nft_chain_attributes)
103+
* @NFT_MSG_DESTROYRULE: destroy a rule (enum nft_rule_attributes)
104+
* @NFT_MSG_DESTROYSET: destroy a set (enum nft_set_attributes)
105+
* @NFT_MSG_DESTROYSETELEM: destroy a set element (enum nft_set_elem_attributes)
106+
* @NFT_MSG_DESTROYOBJ: destroy a stateful object (enum nft_object_attributes)
107+
* @NFT_MSG_DESTROYFLOWTABLE: destroy flow table (enum nft_flowtable_attributes)
101108
*/
102109
enum nf_tables_msg_types {
103110
NFT_MSG_NEWTABLE,
@@ -126,6 +133,13 @@ enum nf_tables_msg_types {
126133
NFT_MSG_GETFLOWTABLE,
127134
NFT_MSG_DELFLOWTABLE,
128135
NFT_MSG_GETRULE_RESET,
136+
NFT_MSG_DESTROYTABLE,
137+
NFT_MSG_DESTROYCHAIN,
138+
NFT_MSG_DESTROYRULE,
139+
NFT_MSG_DESTROYSET,
140+
NFT_MSG_DESTROYSETELEM,
141+
NFT_MSG_DESTROYOBJ,
142+
NFT_MSG_DESTROYFLOWTABLE,
129143
NFT_MSG_MAX,
130144
};
131145

net/netfilter/nf_tables_api.c

Lines changed: 103 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1322,6 +1322,10 @@ static int nf_tables_deltable(struct sk_buff *skb, const struct nfnl_info *info,
13221322
}
13231323

13241324
if (IS_ERR(table)) {
1325+
if (PTR_ERR(table) == -ENOENT &&
1326+
NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_DESTROYTABLE)
1327+
return 0;
1328+
13251329
NL_SET_BAD_ATTR(extack, attr);
13261330
return PTR_ERR(table);
13271331
}
@@ -2549,6 +2553,10 @@ static int nf_tables_delchain(struct sk_buff *skb, const struct nfnl_info *info,
25492553
chain = nft_chain_lookup(net, table, attr, genmask);
25502554
}
25512555
if (IS_ERR(chain)) {
2556+
if (PTR_ERR(chain) == -ENOENT &&
2557+
NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_DESTROYCHAIN)
2558+
return 0;
2559+
25522560
NL_SET_BAD_ATTR(extack, attr);
25532561
return PTR_ERR(chain);
25542562
}
@@ -3644,6 +3652,10 @@ static int nf_tables_delrule(struct sk_buff *skb, const struct nfnl_info *info,
36443652
chain = nft_chain_lookup(net, table, nla[NFTA_RULE_CHAIN],
36453653
genmask);
36463654
if (IS_ERR(chain)) {
3655+
if (PTR_ERR(rule) == -ENOENT &&
3656+
NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_DESTROYRULE)
3657+
return 0;
3658+
36473659
NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN]);
36483660
return PTR_ERR(chain);
36493661
}
@@ -3657,6 +3669,10 @@ static int nf_tables_delrule(struct sk_buff *skb, const struct nfnl_info *info,
36573669
if (nla[NFTA_RULE_HANDLE]) {
36583670
rule = nft_rule_lookup(chain, nla[NFTA_RULE_HANDLE]);
36593671
if (IS_ERR(rule)) {
3672+
if (PTR_ERR(rule) == -ENOENT &&
3673+
NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_DESTROYRULE)
3674+
return 0;
3675+
36603676
NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_HANDLE]);
36613677
return PTR_ERR(rule);
36623678
}
@@ -4730,6 +4746,10 @@ static int nf_tables_delset(struct sk_buff *skb, const struct nfnl_info *info,
47304746
}
47314747

47324748
if (IS_ERR(set)) {
4749+
if (PTR_ERR(set) == -ENOENT &&
4750+
NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_DESTROYSET)
4751+
return 0;
4752+
47334753
NL_SET_BAD_ATTR(extack, attr);
47344754
return PTR_ERR(set);
47354755
}
@@ -6585,6 +6605,10 @@ static int nf_tables_delsetelem(struct sk_buff *skb,
65856605

65866606
nla_for_each_nested(attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
65876607
err = nft_del_setelem(&ctx, set, attr);
6608+
if (err == -ENOENT &&
6609+
NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_DESTROYSETELEM)
6610+
continue;
6611+
65886612
if (err < 0) {
65896613
NL_SET_BAD_ATTR(extack, attr);
65906614
break;
@@ -7229,6 +7253,10 @@ static int nf_tables_delobj(struct sk_buff *skb, const struct nfnl_info *info,
72297253
}
72307254

72317255
if (IS_ERR(obj)) {
7256+
if (PTR_ERR(obj) == -ENOENT &&
7257+
NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_DESTROYOBJ)
7258+
return 0;
7259+
72327260
NL_SET_BAD_ATTR(extack, attr);
72337261
return PTR_ERR(obj);
72347262
}
@@ -7859,6 +7887,10 @@ static int nf_tables_delflowtable(struct sk_buff *skb,
78597887
}
78607888

78617889
if (IS_ERR(flowtable)) {
7890+
if (PTR_ERR(flowtable) == -ENOENT &&
7891+
NFNL_MSG_TYPE(info->nlh->nlmsg_type) == NFT_MSG_DESTROYFLOWTABLE)
7892+
return 0;
7893+
78627894
NL_SET_BAD_ATTR(extack, attr);
78637895
return PTR_ERR(flowtable);
78647896
}
@@ -8268,6 +8300,12 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
82688300
.attr_count = NFTA_TABLE_MAX,
82698301
.policy = nft_table_policy,
82708302
},
8303+
[NFT_MSG_DESTROYTABLE] = {
8304+
.call = nf_tables_deltable,
8305+
.type = NFNL_CB_BATCH,
8306+
.attr_count = NFTA_TABLE_MAX,
8307+
.policy = nft_table_policy,
8308+
},
82718309
[NFT_MSG_NEWCHAIN] = {
82728310
.call = nf_tables_newchain,
82738311
.type = NFNL_CB_BATCH,
@@ -8286,6 +8324,12 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
82868324
.attr_count = NFTA_CHAIN_MAX,
82878325
.policy = nft_chain_policy,
82888326
},
8327+
[NFT_MSG_DESTROYCHAIN] = {
8328+
.call = nf_tables_delchain,
8329+
.type = NFNL_CB_BATCH,
8330+
.attr_count = NFTA_CHAIN_MAX,
8331+
.policy = nft_chain_policy,
8332+
},
82898333
[NFT_MSG_NEWRULE] = {
82908334
.call = nf_tables_newrule,
82918335
.type = NFNL_CB_BATCH,
@@ -8310,6 +8354,12 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
83108354
.attr_count = NFTA_RULE_MAX,
83118355
.policy = nft_rule_policy,
83128356
},
8357+
[NFT_MSG_DESTROYRULE] = {
8358+
.call = nf_tables_delrule,
8359+
.type = NFNL_CB_BATCH,
8360+
.attr_count = NFTA_RULE_MAX,
8361+
.policy = nft_rule_policy,
8362+
},
83138363
[NFT_MSG_NEWSET] = {
83148364
.call = nf_tables_newset,
83158365
.type = NFNL_CB_BATCH,
@@ -8328,6 +8378,12 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
83288378
.attr_count = NFTA_SET_MAX,
83298379
.policy = nft_set_policy,
83308380
},
8381+
[NFT_MSG_DESTROYSET] = {
8382+
.call = nf_tables_delset,
8383+
.type = NFNL_CB_BATCH,
8384+
.attr_count = NFTA_SET_MAX,
8385+
.policy = nft_set_policy,
8386+
},
83318387
[NFT_MSG_NEWSETELEM] = {
83328388
.call = nf_tables_newsetelem,
83338389
.type = NFNL_CB_BATCH,
@@ -8346,6 +8402,12 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
83468402
.attr_count = NFTA_SET_ELEM_LIST_MAX,
83478403
.policy = nft_set_elem_list_policy,
83488404
},
8405+
[NFT_MSG_DESTROYSETELEM] = {
8406+
.call = nf_tables_delsetelem,
8407+
.type = NFNL_CB_BATCH,
8408+
.attr_count = NFTA_SET_ELEM_LIST_MAX,
8409+
.policy = nft_set_elem_list_policy,
8410+
},
83498411
[NFT_MSG_GETGEN] = {
83508412
.call = nf_tables_getgen,
83518413
.type = NFNL_CB_RCU,
@@ -8368,6 +8430,12 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
83688430
.attr_count = NFTA_OBJ_MAX,
83698431
.policy = nft_obj_policy,
83708432
},
8433+
[NFT_MSG_DESTROYOBJ] = {
8434+
.call = nf_tables_delobj,
8435+
.type = NFNL_CB_BATCH,
8436+
.attr_count = NFTA_OBJ_MAX,
8437+
.policy = nft_obj_policy,
8438+
},
83718439
[NFT_MSG_GETOBJ_RESET] = {
83728440
.call = nf_tables_getobj,
83738441
.type = NFNL_CB_RCU,
@@ -8392,6 +8460,12 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
83928460
.attr_count = NFTA_FLOWTABLE_MAX,
83938461
.policy = nft_flowtable_policy,
83948462
},
8463+
[NFT_MSG_DESTROYFLOWTABLE] = {
8464+
.call = nf_tables_delflowtable,
8465+
.type = NFNL_CB_BATCH,
8466+
.attr_count = NFTA_FLOWTABLE_MAX,
8467+
.policy = nft_flowtable_policy,
8468+
},
83958469
};
83968470

83978471
static int nf_tables_validate(struct net *net)
@@ -8487,30 +8561,37 @@ static void nft_commit_release(struct nft_trans *trans)
84878561
{
84888562
switch (trans->msg_type) {
84898563
case NFT_MSG_DELTABLE:
8564+
case NFT_MSG_DESTROYTABLE:
84908565
nf_tables_table_destroy(&trans->ctx);
84918566
break;
84928567
case NFT_MSG_NEWCHAIN:
84938568
free_percpu(nft_trans_chain_stats(trans));
84948569
kfree(nft_trans_chain_name(trans));
84958570
break;
84968571
case NFT_MSG_DELCHAIN:
8572+
case NFT_MSG_DESTROYCHAIN:
84978573
nf_tables_chain_destroy(&trans->ctx);
84988574
break;
84998575
case NFT_MSG_DELRULE:
8576+
case NFT_MSG_DESTROYRULE:
85008577
nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans));
85018578
break;
85028579
case NFT_MSG_DELSET:
8580+
case NFT_MSG_DESTROYSET:
85038581
nft_set_destroy(&trans->ctx, nft_trans_set(trans));
85048582
break;
85058583
case NFT_MSG_DELSETELEM:
8584+
case NFT_MSG_DESTROYSETELEM:
85068585
nf_tables_set_elem_destroy(&trans->ctx,
85078586
nft_trans_elem_set(trans),
85088587
nft_trans_elem(trans).priv);
85098588
break;
85108589
case NFT_MSG_DELOBJ:
8590+
case NFT_MSG_DESTROYOBJ:
85118591
nft_obj_destroy(&trans->ctx, nft_trans_obj(trans));
85128592
break;
85138593
case NFT_MSG_DELFLOWTABLE:
8594+
case NFT_MSG_DESTROYFLOWTABLE:
85148595
if (nft_trans_flowtable_update(trans))
85158596
nft_flowtable_hooks_destroy(&nft_trans_flowtable_hooks(trans));
85168597
else
@@ -8913,8 +8994,9 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
89138994
nft_trans_destroy(trans);
89148995
break;
89158996
case NFT_MSG_DELTABLE:
8997+
case NFT_MSG_DESTROYTABLE:
89168998
list_del_rcu(&trans->ctx.table->list);
8917-
nf_tables_table_notify(&trans->ctx, NFT_MSG_DELTABLE);
8999+
nf_tables_table_notify(&trans->ctx, trans->msg_type);
89189000
break;
89199001
case NFT_MSG_NEWCHAIN:
89209002
if (nft_trans_chain_update(trans)) {
@@ -8929,8 +9011,9 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
89299011
}
89309012
break;
89319013
case NFT_MSG_DELCHAIN:
9014+
case NFT_MSG_DESTROYCHAIN:
89329015
nft_chain_del(trans->ctx.chain);
8933-
nf_tables_chain_notify(&trans->ctx, NFT_MSG_DELCHAIN);
9016+
nf_tables_chain_notify(&trans->ctx, trans->msg_type);
89349017
nf_tables_unregister_hook(trans->ctx.net,
89359018
trans->ctx.table,
89369019
trans->ctx.chain);
@@ -8946,10 +9029,11 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
89469029
nft_trans_destroy(trans);
89479030
break;
89489031
case NFT_MSG_DELRULE:
9032+
case NFT_MSG_DESTROYRULE:
89499033
list_del_rcu(&nft_trans_rule(trans)->list);
89509034
nf_tables_rule_notify(&trans->ctx,
89519035
nft_trans_rule(trans),
8952-
NFT_MSG_DELRULE);
9036+
trans->msg_type);
89539037
nft_rule_expr_deactivate(&trans->ctx,
89549038
nft_trans_rule(trans),
89559039
NFT_TRANS_COMMIT);
@@ -8977,9 +9061,10 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
89779061
nft_trans_destroy(trans);
89789062
break;
89799063
case NFT_MSG_DELSET:
9064+
case NFT_MSG_DESTROYSET:
89809065
list_del_rcu(&nft_trans_set(trans)->list);
89819066
nf_tables_set_notify(&trans->ctx, nft_trans_set(trans),
8982-
NFT_MSG_DELSET, GFP_KERNEL);
9067+
trans->msg_type, GFP_KERNEL);
89839068
break;
89849069
case NFT_MSG_NEWSETELEM:
89859070
te = (struct nft_trans_elem *)trans->data;
@@ -8991,11 +9076,12 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
89919076
nft_trans_destroy(trans);
89929077
break;
89939078
case NFT_MSG_DELSETELEM:
9079+
case NFT_MSG_DESTROYSETELEM:
89949080
te = (struct nft_trans_elem *)trans->data;
89959081

89969082
nf_tables_setelem_notify(&trans->ctx, te->set,
89979083
&te->elem,
8998-
NFT_MSG_DELSETELEM);
9084+
trans->msg_type);
89999085
nft_setelem_remove(net, te->set, &te->elem);
90009086
if (!nft_setelem_is_catchall(te->set, &te->elem)) {
90019087
atomic_dec(&te->set->nelems);
@@ -9017,9 +9103,10 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
90179103
}
90189104
break;
90199105
case NFT_MSG_DELOBJ:
9106+
case NFT_MSG_DESTROYOBJ:
90209107
nft_obj_del(nft_trans_obj(trans));
90219108
nf_tables_obj_notify(&trans->ctx, nft_trans_obj(trans),
9022-
NFT_MSG_DELOBJ);
9109+
trans->msg_type);
90239110
break;
90249111
case NFT_MSG_NEWFLOWTABLE:
90259112
if (nft_trans_flowtable_update(trans)) {
@@ -9041,19 +9128,20 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
90419128
nft_trans_destroy(trans);
90429129
break;
90439130
case NFT_MSG_DELFLOWTABLE:
9131+
case NFT_MSG_DESTROYFLOWTABLE:
90449132
if (nft_trans_flowtable_update(trans)) {
90459133
nf_tables_flowtable_notify(&trans->ctx,
90469134
nft_trans_flowtable(trans),
90479135
&nft_trans_flowtable_hooks(trans),
9048-
NFT_MSG_DELFLOWTABLE);
9136+
trans->msg_type);
90499137
nft_unregister_flowtable_net_hooks(net,
90509138
&nft_trans_flowtable_hooks(trans));
90519139
} else {
90529140
list_del_rcu(&nft_trans_flowtable(trans)->list);
90539141
nf_tables_flowtable_notify(&trans->ctx,
90549142
nft_trans_flowtable(trans),
90559143
&nft_trans_flowtable(trans)->hook_list,
9056-
NFT_MSG_DELFLOWTABLE);
9144+
trans->msg_type);
90579145
nft_unregister_flowtable_net_hooks(net,
90589146
&nft_trans_flowtable(trans)->hook_list);
90599147
}
@@ -9149,6 +9237,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
91499237
}
91509238
break;
91519239
case NFT_MSG_DELTABLE:
9240+
case NFT_MSG_DESTROYTABLE:
91529241
nft_clear(trans->ctx.net, trans->ctx.table);
91539242
nft_trans_destroy(trans);
91549243
break;
@@ -9170,6 +9259,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
91709259
}
91719260
break;
91729261
case NFT_MSG_DELCHAIN:
9262+
case NFT_MSG_DESTROYCHAIN:
91739263
trans->ctx.table->use++;
91749264
nft_clear(trans->ctx.net, trans->ctx.chain);
91759265
nft_trans_destroy(trans);
@@ -9184,6 +9274,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
91849274
nft_flow_rule_destroy(nft_trans_flow_rule(trans));
91859275
break;
91869276
case NFT_MSG_DELRULE:
9277+
case NFT_MSG_DESTROYRULE:
91879278
trans->ctx.chain->use++;
91889279
nft_clear(trans->ctx.net, nft_trans_rule(trans));
91899280
nft_rule_expr_activate(&trans->ctx, nft_trans_rule(trans));
@@ -9205,6 +9296,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
92059296
list_del_rcu(&nft_trans_set(trans)->list);
92069297
break;
92079298
case NFT_MSG_DELSET:
9299+
case NFT_MSG_DESTROYSET:
92089300
trans->ctx.table->use++;
92099301
nft_clear(trans->ctx.net, nft_trans_set(trans));
92109302
nft_trans_destroy(trans);
@@ -9220,6 +9312,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
92209312
atomic_dec(&te->set->nelems);
92219313
break;
92229314
case NFT_MSG_DELSETELEM:
9315+
case NFT_MSG_DESTROYSETELEM:
92239316
te = (struct nft_trans_elem *)trans->data;
92249317

92259318
nft_setelem_data_activate(net, te->set, &te->elem);
@@ -9239,6 +9332,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
92399332
}
92409333
break;
92419334
case NFT_MSG_DELOBJ:
9335+
case NFT_MSG_DESTROYOBJ:
92429336
trans->ctx.table->use++;
92439337
nft_clear(trans->ctx.net, nft_trans_obj(trans));
92449338
nft_trans_destroy(trans);
@@ -9255,6 +9349,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
92559349
}
92569350
break;
92579351
case NFT_MSG_DELFLOWTABLE:
9352+
case NFT_MSG_DESTROYFLOWTABLE:
92589353
if (nft_trans_flowtable_update(trans)) {
92599354
list_splice(&nft_trans_flowtable_hooks(trans),
92609355
&nft_trans_flowtable(trans)->hook_list);

0 commit comments

Comments
 (0)