mirror of
https://github.com/torvalds/linux
synced 2024-09-06 09:51:23 +00:00
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: 4bedf9eee0
("netfilter: nf_tables: fix chain binding transaction logic")
Reported-by: Kevin Rich <kevinrich1337@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Florian Westphal <fw@strlen.de>
This commit is contained in:
parent
f718863aca
commit
0a771f7b26
|
@ -125,15 +125,27 @@ static void nft_immediate_activate(const struct nft_ctx *ctx,
|
||||||
return nft_data_hold(&priv->data, nft_dreg_to_type(priv->dreg));
|
return nft_data_hold(&priv->data, nft_dreg_to_type(priv->dreg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void nft_immediate_chain_deactivate(const struct nft_ctx *ctx,
|
||||||
|
struct nft_chain *chain,
|
||||||
|
enum nft_trans_phase phase)
|
||||||
|
{
|
||||||
|
struct nft_ctx chain_ctx;
|
||||||
|
struct nft_rule *rule;
|
||||||
|
|
||||||
|
chain_ctx = *ctx;
|
||||||
|
chain_ctx.chain = chain;
|
||||||
|
|
||||||
|
list_for_each_entry(rule, &chain->rules, list)
|
||||||
|
nft_rule_expr_deactivate(&chain_ctx, rule, phase);
|
||||||
|
}
|
||||||
|
|
||||||
static void nft_immediate_deactivate(const struct nft_ctx *ctx,
|
static void nft_immediate_deactivate(const struct nft_ctx *ctx,
|
||||||
const struct nft_expr *expr,
|
const struct nft_expr *expr,
|
||||||
enum nft_trans_phase phase)
|
enum nft_trans_phase phase)
|
||||||
{
|
{
|
||||||
const struct nft_immediate_expr *priv = nft_expr_priv(expr);
|
const struct nft_immediate_expr *priv = nft_expr_priv(expr);
|
||||||
const struct nft_data *data = &priv->data;
|
const struct nft_data *data = &priv->data;
|
||||||
struct nft_ctx chain_ctx;
|
|
||||||
struct nft_chain *chain;
|
struct nft_chain *chain;
|
||||||
struct nft_rule *rule;
|
|
||||||
|
|
||||||
if (priv->dreg == NFT_REG_VERDICT) {
|
if (priv->dreg == NFT_REG_VERDICT) {
|
||||||
switch (data->verdict.code) {
|
switch (data->verdict.code) {
|
||||||
|
@ -143,20 +155,17 @@ static void nft_immediate_deactivate(const struct nft_ctx *ctx,
|
||||||
if (!nft_chain_binding(chain))
|
if (!nft_chain_binding(chain))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
chain_ctx = *ctx;
|
|
||||||
chain_ctx.chain = chain;
|
|
||||||
|
|
||||||
list_for_each_entry(rule, &chain->rules, list)
|
|
||||||
nft_rule_expr_deactivate(&chain_ctx, rule, phase);
|
|
||||||
|
|
||||||
switch (phase) {
|
switch (phase) {
|
||||||
case NFT_TRANS_PREPARE_ERROR:
|
case NFT_TRANS_PREPARE_ERROR:
|
||||||
nf_tables_unbind_chain(ctx, chain);
|
nf_tables_unbind_chain(ctx, chain);
|
||||||
fallthrough;
|
nft_deactivate_next(ctx->net, chain);
|
||||||
|
break;
|
||||||
case NFT_TRANS_PREPARE:
|
case NFT_TRANS_PREPARE:
|
||||||
|
nft_immediate_chain_deactivate(ctx, chain, phase);
|
||||||
nft_deactivate_next(ctx->net, chain);
|
nft_deactivate_next(ctx->net, chain);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
nft_immediate_chain_deactivate(ctx, chain, phase);
|
||||||
nft_chain_del(chain);
|
nft_chain_del(chain);
|
||||||
chain->bound = false;
|
chain->bound = false;
|
||||||
nft_use_dec(&chain->table->use);
|
nft_use_dec(&chain->table->use);
|
||||||
|
|
Loading…
Reference in a new issue