From: Suraj Jitindar Singh <surajjs@amazon.com>
To: <stable@vger.kernel.org>
Cc: Pablo Neira Ayuso <pablo@netfilter.org>,
Jozsef Kadlecsik <kadlec@netfilter.org>,
Florian Westphal <fw@strlen.de>,
<netfilter-devel@vger.kernel.org>, <netdev@vger.kernel.org>
Subject: [PATCH 6.1.y] netfilter: nf_tables: make nft_object rhltable per table
Date: Fri, 4 Sep 2026 01:31:02 +0000 [thread overview]
Message-ID: <20260904013102.22326-1-surajjs@amazon.com> (raw)
From: Pablo Neira Ayuso <pablo@netfilter.org>
commit f4f699790590bd0896c48a71e9232a65198f92f0 upstream.
The nft_object rhltable is global, this allows for accessing objects
that are being dismangled from lookup path by other existing netns.
Given the nft_obj_destroy() releases the object inmediately, this might
lead to use-after-free of these objects that are being released.
Make the existing rhltable per table to address this issue to deal with
with the nft_rcv_nl_event() path too.
Update nft_obj_lookup() to take the table as non-const, otherwise,
compiler complains when passing the objname_ht to rhltable_lookup().
Fixes: 4d44175aa5bb ("netfilter: nf_tables: handle nft_object lookups via rhltable")
Suggested-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
[ 6.1: Conflicts in nf_tables_api.c because 6.1 lacks three mainline
refactors: 0be908750162 ("netfilter: nf_tables: pass nft_table to
destroy function", v6.11), e169285f8c56 ("netfilter: nf_tables: do
not store nft_ctx in transaction objects", v6.11) and f80a612dd77c
("netfilter: nf_tables: add support to destroy operation", v6.3).
As a result 6.1's nf_tables_table_destroy() still takes an nft_ctx;
struct nft_trans still embeds an nft_ctx (so the owning table is
trans->ctx.table, not a per-transaction table local); and the commit
path has no NFT_MSG_DESTROYOBJ case. Resolved by destroying the
per-table objname_ht via ctx->table in nf_tables_table_destroy(), and
by passing the owning table trans->ctx.table to nft_obj_del() in the
commit and abort paths; 6.1's single NFT_MSG_DELOBJ case is retained.
The header and all other hunks applied cleanly. ]
Signed-off-by: Suraj Jitindar Singh <surajjs@amazon.com>
---
include/net/netfilter/nf_tables.h | 4 +++-
net/netfilter/nf_tables_api.c | 34 +++++++++++++++----------------
2 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 4e8cf4e13f8f..6c82feab2ad5 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -1211,6 +1211,7 @@ static inline void nft_use_inc_restore(u32 *use)
* @sets: sets in the table
* @objects: stateful objects in the table
* @flowtables: flow tables in the table
+ * @objname_ht: hashtable for objects lookup by name
* @hgenerator: handle generator state
* @handle: table handle
* @use: number of chain references to this table
@@ -1226,6 +1227,7 @@ struct nft_table {
struct list_head sets;
struct list_head objects;
struct list_head flowtables;
+ struct rhltable objname_ht;
u64 hgenerator;
u64 handle;
u32 use;
@@ -1304,7 +1306,7 @@ static inline void *nft_obj_data(const struct nft_object *obj)
#define nft_expr_obj(expr) *((struct nft_object **)nft_expr_priv(expr))
struct nft_object *nft_obj_lookup(const struct net *net,
- const struct nft_table *table,
+ struct nft_table *table,
const struct nlattr *nla, u32 objtype,
u8 genmask);
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 7240f494d83b..71ada0af4c85 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -42,8 +42,6 @@ enum {
NFT_VALIDATE_DO,
};
-static struct rhltable nft_objname_ht;
-
static u32 nft_chain_hash(const void *data, u32 len, u32 seed);
static u32 nft_chain_hash_obj(const void *data, u32 len, u32 seed);
static int nft_chain_hash_cmp(struct rhashtable_compare_arg *, const void *);
@@ -1419,6 +1417,10 @@ static int nf_tables_newtable(struct sk_buff *skb, const struct nfnl_info *info,
if (err)
goto err_chain_ht;
+ err = rhltable_init(&table->objname_ht, &nft_objname_ht_params);
+ if (err < 0)
+ goto err_obj_ht;
+
INIT_LIST_HEAD(&table->chains);
INIT_LIST_HEAD(&table->sets);
INIT_LIST_HEAD(&table->objects);
@@ -1437,6 +1439,8 @@ static int nf_tables_newtable(struct sk_buff *skb, const struct nfnl_info *info,
list_add_tail_rcu(&table->list, &nft_net->tables);
return 0;
err_trans:
+ rhltable_destroy(&table->objname_ht);
+err_obj_ht:
rhltable_destroy(&table->chains_ht);
err_chain_ht:
kfree(table->udata);
@@ -1599,6 +1603,7 @@ static void nf_tables_table_destroy(struct nft_ctx *ctx)
return;
rhltable_destroy(&ctx->table->chains_ht);
+ rhltable_destroy(&ctx->table->objname_ht);
kfree(ctx->table->name);
kfree(ctx->table->udata);
kfree(ctx->table);
@@ -7151,7 +7156,7 @@ void nft_unregister_obj(struct nft_object_type *obj_type)
EXPORT_SYMBOL_GPL(nft_unregister_obj);
struct nft_object *nft_obj_lookup(const struct net *net,
- const struct nft_table *table,
+ struct nft_table *table,
const struct nlattr *nla, u32 objtype,
u8 genmask)
{
@@ -7167,7 +7172,7 @@ struct nft_object *nft_obj_lookup(const struct net *net,
!lockdep_commit_lock_is_held(net));
rcu_read_lock();
- list = rhltable_lookup(&nft_objname_ht, &k, nft_objname_ht_params);
+ list = rhltable_lookup(&table->objname_ht, &k, nft_objname_ht_params);
if (!list)
goto out;
@@ -7446,7 +7451,7 @@ static int nf_tables_newobj(struct sk_buff *skb, const struct nfnl_info *info,
if (err < 0)
goto err_trans;
- err = rhltable_insert(&nft_objname_ht, &obj->rhlhead,
+ err = rhltable_insert(&table->objname_ht, &obj->rhlhead,
nft_objname_ht_params);
if (err < 0)
goto err_obj_ht;
@@ -7642,8 +7647,8 @@ nf_tables_getobj_single(u32 portid, const struct nfnl_info *info,
struct netlink_ext_ack *extack = info->extack;
u8 genmask = nft_genmask_cur(info->net);
u8 family = info->nfmsg->nfgen_family;
- const struct nft_table *table;
struct net *net = info->net;
+ struct nft_table *table;
struct nft_object *obj;
struct sk_buff *skb2;
u32 objtype;
@@ -9310,9 +9315,9 @@ static void nf_tables_commit_chain(struct net *net, struct nft_chain *chain)
nf_tables_commit_chain_free_rules_old(g0);
}
-static void nft_obj_del(struct nft_object *obj)
+static void nft_obj_del(struct nft_table *table, struct nft_object *obj)
{
- rhltable_remove(&nft_objname_ht, &obj->rhlhead, nft_objname_ht_params);
+ rhltable_remove(&table->objname_ht, &obj->rhlhead, nft_objname_ht_params);
list_del_rcu(&obj->list);
}
@@ -9963,7 +9968,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
}
break;
case NFT_MSG_DELOBJ:
- nft_obj_del(nft_trans_obj(trans));
+ nft_obj_del(trans->ctx.table, nft_trans_obj(trans));
nf_tables_obj_notify(&trans->ctx, nft_trans_obj(trans),
NFT_MSG_DELOBJ);
break;
@@ -10222,7 +10227,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
nft_trans_destroy(trans);
} else {
nft_use_dec_restore(&trans->ctx.table->use);
- nft_obj_del(nft_trans_obj(trans));
+ nft_obj_del(trans->ctx.table, nft_trans_obj(trans));
}
break;
case NFT_MSG_DELOBJ:
@@ -10860,7 +10865,7 @@ static void __nft_release_table(struct net *net, struct nft_table *table)
nft_set_destroy(&ctx, set);
}
list_for_each_entry_safe(obj, ne, &table->objects, list) {
- nft_obj_del(obj);
+ nft_obj_del(table, obj);
nft_use_dec(&table->use);
nft_obj_destroy(&ctx, obj);
}
@@ -11023,10 +11028,6 @@ static int __init nf_tables_module_init(void)
if (err < 0)
goto err_netdev_notifier;
- err = rhltable_init(&nft_objname_ht, &nft_objname_ht_params);
- if (err < 0)
- goto err_rht_objname;
-
err = nft_offload_init();
if (err < 0)
goto err_offload;
@@ -11049,8 +11050,6 @@ static int __init nf_tables_module_init(void)
err_netlink_notifier:
nft_offload_exit();
err_offload:
- rhltable_destroy(&nft_objname_ht);
-err_rht_objname:
unregister_netdevice_notifier(&nf_tables_flowtable_notifier);
err_netdev_notifier:
nf_tables_core_module_exit();
@@ -11074,7 +11073,6 @@ static void __exit nf_tables_module_exit(void)
cancel_work_sync(&trans_gc_work);
cancel_work_sync(&trans_destroy_work);
rcu_barrier();
- rhltable_destroy(&nft_objname_ht);
nf_tables_core_module_exit();
}
--
2.47.3
reply other threads:[~2026-09-04 1:31 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260904013102.22326-1-surajjs@amazon.com \
--to=surajjs@amazon.com \
--cc=fw@strlen.de \
--cc=kadlec@netfilter.org \
--cc=netdev@vger.kernel.org \
--cc=netfilter-devel@vger.kernel.org \
--cc=pablo@netfilter.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox