* [PATCH nf 1/3,v3] netfilter: nf_tables: delete flowtable hooks via transaction list
@ 2022-06-02 7:43 Pablo Neira Ayuso
2022-06-02 7:43 ` [PATCH nf 2/3] netfilter: nf_tables: memleak in nft_expr_init() path Pablo Neira Ayuso
2022-06-02 7:43 ` [PATCH nf 3/3] netfilter: nf_tables: always initialize flowtable hook list in transaction Pablo Neira Ayuso
0 siblings, 2 replies; 4+ messages in thread
From: Pablo Neira Ayuso @ 2022-06-02 7:43 UTC (permalink / raw)
To: netfilter-devel
Remove inactive bool field in nft_hook object that was introduced in
abadb2f865d7 ("netfilter: nf_tables: delete devices from flowtable").
Move stale flowtable hooks to transaction list instead.
Deleting twice the same device does not result in ENOENT.
Fixes: abadb2f865d7 ("netfilter: nf_tables: delete devices from flowtable")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
v3: incorrect update of nft_commit_release()
include/net/netfilter/nf_tables.h | 1 -
net/netfilter/nf_tables_api.c | 35 +++++++------------------------
2 files changed, 8 insertions(+), 28 deletions(-)
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 20af9d3557b9..279ae0fff7ad 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -1090,7 +1090,6 @@ struct nft_stats {
struct nft_hook {
struct list_head list;
- bool inactive;
struct nf_hook_ops ops;
struct rcu_head rcu;
};
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 129d3ebd6ce5..5ee4e7b28b61 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -1914,7 +1914,6 @@ static struct nft_hook *nft_netdev_hook_alloc(struct net *net,
goto err_hook_dev;
}
hook->ops.dev = dev;
- hook->inactive = false;
return hook;
@@ -7618,7 +7617,8 @@ static int nft_delflowtable_hook(struct nft_ctx *ctx,
{
const struct nlattr * const *nla = ctx->nla;
struct nft_flowtable_hook flowtable_hook;
- struct nft_hook *this, *hook;
+ struct nft_hook *this, *next, *hook;
+ LIST_HEAD(flowtable_del_list);
struct nft_trans *trans;
int err;
@@ -7627,13 +7627,13 @@ static int nft_delflowtable_hook(struct nft_ctx *ctx,
if (err < 0)
return err;
- list_for_each_entry(this, &flowtable_hook.list, list) {
+ list_for_each_entry_safe(this, next, &flowtable_hook.list, list) {
hook = nft_hook_list_find(&flowtable->hook_list, this);
if (!hook) {
err = -ENOENT;
goto err_flowtable_del_hook;
}
- hook->inactive = true;
+ list_move(&hook->list, &flowtable_del_list);
}
trans = nft_trans_alloc(ctx, NFT_MSG_DELFLOWTABLE,
@@ -7646,6 +7646,7 @@ static int nft_delflowtable_hook(struct nft_ctx *ctx,
nft_trans_flowtable(trans) = flowtable;
nft_trans_flowtable_update(trans) = true;
INIT_LIST_HEAD(&nft_trans_flowtable_hooks(trans));
+ list_splice(&flowtable_del_list, &nft_trans_flowtable_hooks(trans));
nft_flowtable_hook_release(&flowtable_hook);
nft_trans_commit_list_add_tail(ctx->net, trans);
@@ -7653,13 +7654,7 @@ static int nft_delflowtable_hook(struct nft_ctx *ctx,
return 0;
err_flowtable_del_hook:
- list_for_each_entry(this, &flowtable_hook.list, list) {
- hook = nft_hook_list_find(&flowtable->hook_list, this);
- if (!hook)
- break;
-
- hook->inactive = false;
- }
+ list_splice(&flowtable_del_list, &flowtable->hook_list);
nft_flowtable_hook_release(&flowtable_hook);
return err;
@@ -8563,17 +8558,6 @@ void nft_chain_del(struct nft_chain *chain)
list_del_rcu(&chain->list);
}
-static void nft_flowtable_hooks_del(struct nft_flowtable *flowtable,
- struct list_head *hook_list)
-{
- struct nft_hook *hook, *next;
-
- list_for_each_entry_safe(hook, next, &flowtable->hook_list, list) {
- if (hook->inactive)
- list_move(&hook->list, hook_list);
- }
-}
-
static void nf_tables_module_autoload_cleanup(struct net *net)
{
struct nftables_pernet *nft_net = nft_pernet(net);
@@ -8918,8 +8902,6 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
break;
case NFT_MSG_DELFLOWTABLE:
if (nft_trans_flowtable_update(trans)) {
- nft_flowtable_hooks_del(nft_trans_flowtable(trans),
- &nft_trans_flowtable_hooks(trans));
nf_tables_flowtable_notify(&trans->ctx,
nft_trans_flowtable(trans),
&nft_trans_flowtable_hooks(trans),
@@ -9000,7 +8982,6 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
struct nftables_pernet *nft_net = nft_pernet(net);
struct nft_trans *trans, *next;
struct nft_trans_elem *te;
- struct nft_hook *hook;
if (action == NFNL_ABORT_VALIDATE &&
nf_tables_validate(net) < 0)
@@ -9131,8 +9112,8 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
break;
case NFT_MSG_DELFLOWTABLE:
if (nft_trans_flowtable_update(trans)) {
- list_for_each_entry(hook, &nft_trans_flowtable(trans)->hook_list, list)
- hook->inactive = false;
+ list_splice(&nft_trans_flowtable_hooks(trans),
+ &nft_trans_flowtable(trans)->hook_list);
} else {
trans->ctx.table->use++;
nft_clear(trans->ctx.net, nft_trans_flowtable(trans));
--
2.30.2
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH nf 2/3] netfilter: nf_tables: memleak in nft_expr_init() path
2022-06-02 7:43 [PATCH nf 1/3,v3] netfilter: nf_tables: delete flowtable hooks via transaction list Pablo Neira Ayuso
@ 2022-06-02 7:43 ` Pablo Neira Ayuso
2022-06-02 21:30 ` Pablo Neira Ayuso
2022-06-02 7:43 ` [PATCH nf 3/3] netfilter: nf_tables: always initialize flowtable hook list in transaction Pablo Neira Ayuso
1 sibling, 1 reply; 4+ messages in thread
From: Pablo Neira Ayuso @ 2022-06-02 7:43 UTC (permalink / raw)
To: netfilter-devel
Since ed0a0c60f0e5 ("netfilter: nft_quota: move stateful fields out of
expression data"), stateful expressions allocate stateful area via
kmalloc().
Call ->ops->destroy() to release expression stateful information before
releasing the expression.
->ops->deactivate() is also called for safety reasons, no stateful
expressions support for this function.
Fixes: 6cafaf4764a3 ("netfilter: nf_tables: fix memory leak if expr init fails")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nf_tables_api.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 5ee4e7b28b61..017b77067852 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -2904,6 +2904,11 @@ static struct nft_expr *nft_expr_init(const struct nft_ctx *ctx,
return expr;
err_expr_new:
+ if (expr->ops->deactivate)
+ expr->ops->deactivate(ctx, expr, NFT_TRANS_RELEASE);
+ if (expr_info.ops->destroy)
+ expr_info.ops->destroy(ctx, expr);
+
kfree(expr);
err_expr_stateful:
owner = expr_info.ops->type->owner;
--
2.30.2
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH nf 2/3] netfilter: nf_tables: memleak in nft_expr_init() path
2022-06-02 7:43 ` [PATCH nf 2/3] netfilter: nf_tables: memleak in nft_expr_init() path Pablo Neira Ayuso
@ 2022-06-02 21:30 ` Pablo Neira Ayuso
0 siblings, 0 replies; 4+ messages in thread
From: Pablo Neira Ayuso @ 2022-06-02 21:30 UTC (permalink / raw)
To: netfilter-devel
On Thu, Jun 02, 2022 at 09:43:56AM +0200, Pablo Neira Ayuso wrote:
> Since ed0a0c60f0e5 ("netfilter: nft_quota: move stateful fields out of
> expression data"), stateful expressions allocate stateful area via
> kmalloc().
>
> Call ->ops->destroy() to release expression stateful information before
> releasing the expression.
>
> ->ops->deactivate() is also called for safety reasons, no stateful
> expressions support for this function.
>
> Fixes: 6cafaf4764a3 ("netfilter: nf_tables: fix memory leak if expr init fails")
> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
> ---
> net/netfilter/nf_tables_api.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
> index 5ee4e7b28b61..017b77067852 100644
> --- a/net/netfilter/nf_tables_api.c
> +++ b/net/netfilter/nf_tables_api.c
> @@ -2904,6 +2904,11 @@ static struct nft_expr *nft_expr_init(const struct nft_ctx *ctx,
>
> return expr;
> err_expr_new:
> + if (expr->ops->deactivate)
> + expr->ops->deactivate(ctx, expr, NFT_TRANS_RELEASE);
> + if (expr_info.ops->destroy)
> + expr_info.ops->destroy(ctx, expr);
Scratch this patch. Not correct.
nf_tables_newexpr() calls ->init() which if it fails, then it did not
allocate anything.
> +
> kfree(expr);
> err_expr_stateful:
> owner = expr_info.ops->type->owner;
> --
> 2.30.2
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH nf 3/3] netfilter: nf_tables: always initialize flowtable hook list in transaction
2022-06-02 7:43 [PATCH nf 1/3,v3] netfilter: nf_tables: delete flowtable hooks via transaction list Pablo Neira Ayuso
2022-06-02 7:43 ` [PATCH nf 2/3] netfilter: nf_tables: memleak in nft_expr_init() path Pablo Neira Ayuso
@ 2022-06-02 7:43 ` Pablo Neira Ayuso
1 sibling, 0 replies; 4+ messages in thread
From: Pablo Neira Ayuso @ 2022-06-02 7:43 UTC (permalink / raw)
To: netfilter-devel
The hook list is used if nft_trans_flowtable_update(trans) == true. However,
initialize this list for other cases for safety reasons.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
net/netfilter/nf_tables_api.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 017b77067852..fbb6f87c9db6 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -544,6 +544,7 @@ static int nft_trans_flowtable_add(struct nft_ctx *ctx, int msg_type,
if (msg_type == NFT_MSG_NEWFLOWTABLE)
nft_activate_next(ctx->net, flowtable);
+ INIT_LIST_HEAD(&nft_trans_flowtable_hooks(trans));
nft_trans_flowtable(trans) = flowtable;
nft_trans_commit_list_add_tail(ctx->net, trans);
--
2.30.2
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2022-06-02 21:30 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-06-02 7:43 [PATCH nf 1/3,v3] netfilter: nf_tables: delete flowtable hooks via transaction list Pablo Neira Ayuso
2022-06-02 7:43 ` [PATCH nf 2/3] netfilter: nf_tables: memleak in nft_expr_init() path Pablo Neira Ayuso
2022-06-02 21:30 ` Pablo Neira Ayuso
2022-06-02 7:43 ` [PATCH nf 3/3] netfilter: nf_tables: always initialize flowtable hook list in transaction Pablo Neira Ayuso
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.