Re: [PATCH] net: make sure final 'struct net' free in net_complete_free() is always deferred

Eric Dumazet <[email protected]>
Newsgroups gmane.linux.network
Message-ID <CANn89iKwWFwRxEDvw7eUPD-tKL_dvYrZeye_3be37q6qYzQ15w@mail.gmail.com>
On Mon, Aug 17, 2026 at 2:59 PM Tetsuo Handa
<[email protected]> wrote:
>
> On 2026/08/17 14:26, Eric Dumazet wrote:
> > On Mon, Aug 17, 2026 at 6:28 AM Kuniyuki Iwashima <[email protected]> wrote:
> >>
> >> On Sun, Aug 16, 2026 at 4:08 AM Tetsuo Handa
> >> <[email protected]> wrote:
> >>>
> >>> Since there is no serialization mechanism (e.g. the RTNL lock) between
> >>> llist_add() in net_complete_free() and llist_del_all() in
> >>> net_complete_free(), it is possible that net_complete_free() finds 'struct
> >>> net' as soon as net_complete_free() added it to the defer_free_list.
> >>
> >> Did you see a real issue or is this based on AI report ?
>
> This is a theoretical issue which I noticed while writing
> "[PATCH] net: add missing ref_tracker_dir_exit() to net_passive_dec()".
>
> >>
> >> netns_wq is single thread workqueue.
> >>
>
> There was a typo.
>
>   Since there is no serialization mechanism (e.g. the RTNL lock) between
>   llist_add() in *net_passive_dec()* and llist_del_all() in
>   net_complete_free(), it is possible that net_complete_free() finds 'struct
>   net' as soon as *net_passive_dec()* added it to the defer_free_list.
>
> Old kernels called net_passive_dec() from only netns_wq context, but
> new kernels call net_passive_dec() from not only netns_wq context
> but also other contexts, don't they?
>
> >
> > Indeed, this patch is not needed.
> >
> > pw-bot: reject
>
> Sashiko did a correct review (despite the typo above) and is reporting a pre-existing issue at
> https://sashiko.dev/#/patchset/34f44e8a-9fa4-4cb3-822e-5db54fb6df44%40I-love.SAKURA.ne.jp .

Hi Tetsuo,

Thanks for the clarification.

Regarding the ordering in cleanup_net():
cleanup_net() runs strictly serialized on the single-threaded netns_wq.

For normal namespaces going through dismantle, they are added to
defer_free_list at the very end of cleanup_net(), after net_complete_free()
has already run for that round. If an external context holds an extra
passive reference and drops it later, all pernet exit ops and the
rcu_barrier() have already completed in cleanup_net().

For namespaces that fail early in copy_net_ns(), they were never published
or active, so they never had network traffic or DST entries attached to them.
Moving llist_del_all() before rcu_barrier() in cleanup_net() does not change
anything for these paths.

However, the observation regarding the copy_net_ns() error path is valid:
because failed namespaces never go through __put_net(), net_cleanup_work
is not queued, so a failed net structure can stay on defer_free_list until
another namespace is destroyed.

The proper fix for that benign issue would be to directly free the
struct net in the
copy_net_ns() error path (since it was never active and does not need deferred
freeing), rather than modifying cleanup_net().

Thanks,
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.