Skip to content

Commit 0a771f7

Browse files
ummakynesFlorian Westphal
authored andcommitted
netfilter: nf_tables: skip immediate deactivate in _PREPARE_ERROR
On error when building the rule, the immediate expression unbinds the chain, hence objects can be deactivated by the transaction records. Otherwise, it is possible to trigger the following warning: WARNING: CPU: 3 PID: 915 at net/netfilter/nf_tables_api.c:2013 nf_tables_chain_destroy+0x1f7/0x210 [nf_tables] CPU: 3 PID: 915 Comm: chain-bind-err- Not tainted 6.1.39 #1 RIP: 0010:nf_tables_chain_destroy+0x1f7/0x210 [nf_tables] Fixes: 4bedf9e ("netfilter: nf_tables: fix chain binding transaction logic") Reported-by: Kevin Rich <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]> Signed-off-by: Florian Westphal <[email protected]>
1 parent f718863 commit 0a771f7

File tree

1 file changed

+18
-9
lines changed

1 file changed

+18
-9
lines changed

net/netfilter/nft_immediate.c

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -125,15 +125,27 @@ static void nft_immediate_activate(const struct nft_ctx *ctx,
125125
return nft_data_hold(&priv->data, nft_dreg_to_type(priv->dreg));
126126
}
127127

128+
static void nft_immediate_chain_deactivate(const struct nft_ctx *ctx,
129+
struct nft_chain *chain,
130+
enum nft_trans_phase phase)
131+
{
132+
struct nft_ctx chain_ctx;
133+
struct nft_rule *rule;
134+
135+
chain_ctx = *ctx;
136+
chain_ctx.chain = chain;
137+
138+
list_for_each_entry(rule, &chain->rules, list)
139+
nft_rule_expr_deactivate(&chain_ctx, rule, phase);
140+
}
141+
128142
static void nft_immediate_deactivate(const struct nft_ctx *ctx,
129143
const struct nft_expr *expr,
130144
enum nft_trans_phase phase)
131145
{
132146
const struct nft_immediate_expr *priv = nft_expr_priv(expr);
133147
const struct nft_data *data = &priv->data;
134-
struct nft_ctx chain_ctx;
135148
struct nft_chain *chain;
136-
struct nft_rule *rule;
137149

138150
if (priv->dreg == NFT_REG_VERDICT) {
139151
switch (data->verdict.code) {
@@ -143,20 +155,17 @@ static void nft_immediate_deactivate(const struct nft_ctx *ctx,
143155
if (!nft_chain_binding(chain))
144156
break;
145157

146-
chain_ctx = *ctx;
147-
chain_ctx.chain = chain;
148-
149-
list_for_each_entry(rule, &chain->rules, list)
150-
nft_rule_expr_deactivate(&chain_ctx, rule, phase);
151-
152158
switch (phase) {
153159
case NFT_TRANS_PREPARE_ERROR:
154160
nf_tables_unbind_chain(ctx, chain);
155-
fallthrough;
161+
nft_deactivate_next(ctx->net, chain);
162+
break;
156163
case NFT_TRANS_PREPARE:
164+
nft_immediate_chain_deactivate(ctx, chain, phase);
157165
nft_deactivate_next(ctx->net, chain);
158166
break;
159167
default:
168+
nft_immediate_chain_deactivate(ctx, chain, phase);
160169
nft_chain_del(chain);
161170
chain->bound = false;
162171
nft_use_dec(&chain->table->use);

0 commit comments

Comments
 (0)