netfilter: ebtables: close dangling table module init race

sashiko reported for a related patch:
 In modules like iptable_raw.c, [..], if register_pernet_subsys() fails,
 the rollback might call kfree(rawtable_ops) before [..]
 During this window, could a concurrent userspace process find the globally
 visible template, trigger table_init(), [..]

The table init functions must always register the template last.

Otherwise, set/getsockopt can instantiate a table in a namespace
while the required pernet ops (contain the destructor) isn't available.
This change is also required in x_tables, handled in followup change.

Fixes: 87663c39f8 ("netfilter: ebtables: do not hook tables by default")
Reviewed-by: Tristan Madani <tristan@talencesecurity.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
Florian Westphal 2026-05-06 12:07:19 +02:00 committed by Pablo Neira Ayuso
parent b7f0544d86
commit 92c603fa07
3 changed files with 14 additions and 20 deletions

View File

@ -112,18 +112,16 @@ static struct pernet_operations broute_net_ops = {
static int __init ebtable_broute_init(void)
{
int ret = ebt_register_template(&broute_table, broute_table_init);
int ret = register_pernet_subsys(&broute_net_ops);
if (ret)
return ret;
ret = register_pernet_subsys(&broute_net_ops);
if (ret) {
ebt_unregister_template(&broute_table);
return ret;
}
ret = ebt_register_template(&broute_table, broute_table_init);
if (ret)
unregister_pernet_subsys(&broute_net_ops);
return 0;
return ret;
}
static void __exit ebtable_broute_fini(void)

View File

@ -93,18 +93,16 @@ static struct pernet_operations frame_filter_net_ops = {
static int __init ebtable_filter_init(void)
{
int ret = ebt_register_template(&frame_filter, frame_filter_table_init);
int ret = register_pernet_subsys(&frame_filter_net_ops);
if (ret)
return ret;
ret = register_pernet_subsys(&frame_filter_net_ops);
if (ret) {
ebt_unregister_template(&frame_filter);
return ret;
}
ret = ebt_register_template(&frame_filter, frame_filter_table_init);
if (ret)
unregister_pernet_subsys(&frame_filter_net_ops);
return 0;
return ret;
}
static void __exit ebtable_filter_fini(void)

View File

@ -93,16 +93,14 @@ static struct pernet_operations frame_nat_net_ops = {
static int __init ebtable_nat_init(void)
{
int ret = ebt_register_template(&frame_nat, frame_nat_table_init);
int ret = register_pernet_subsys(&frame_nat_net_ops);
if (ret)
return ret;
ret = register_pernet_subsys(&frame_nat_net_ops);
if (ret) {
ebt_unregister_template(&frame_nat);
return ret;
}
ret = ebt_register_template(&frame_nat, frame_nat_table_init);
if (ret)
unregister_pernet_subsys(&frame_nat_net_ops);
return ret;
}