Re: [PATCH 0/2] netfilter: fix NULL ops race in iptable lazy init
From: Phil Sutter
Date: Wed Apr 29 2026 - 14:30:23 EST
Hi,
On Wed, Apr 29, 2026 at 05:56:10PM +0000, Tristan Madani wrote:
> From: Tristan Madani <tristan@xxxxxxxxxxxxxxxxxxx>
>
> ipt_register_table() and ip6t_register_table() call xt_register_table()
> which adds the new table to the per-netns list, making it visible to
> other code paths. Only afterwards do they allocate the per-net copy of
> hook ops via kmemdup_array(). This leaves a window where the table is
> findable via xt_find_table() but has ops=NULL.
>
> If cleanup_net runs during this window (racing namespace teardown against
> lazy table init), ipt_unregister_table_pre_exit() /
> ip6t_unregister_table_pre_exit() finds the table and passes the NULL ops
> pointer to nf_unregister_net_hooks(), causing a general protection fault.
>
> Fix both ip_tables.c and ip6_tables.c by moving the ops allocation
> before xt_register_table(), so the table is never in the list with a
> NULL ops pointer.
Is this true? Your patch moves the ops allocation, but new_table->ops is
still assigned after xt_register_table() has returned. AIUI, the race
window is just reduced, not eliminated.
First I thought you could assign to table->ops since xt_register_table()
calls kmemdup(), but 'table' is const.
I guess checking table->ops value in *_pre_exit() is nonsense as well
since *_register_table() still runs in parallel. Do we need
serialization between the two routines?
Cheers, Phil