Re: [PATCH 0/2] netfilter: fix NULL ops race in iptable lazy init

Phil Sutter
2026-04-29T18:22:55Z

Hi,

On Wed, Apr 29, 2026 at 05:56:10PM +0000, Tristan Madani wrote:
> From: Tristan Madani <tristan@talencesecurity.com>
>
> 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