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,