Thread (5 messages) flat view 5 messages, 3 authors, 2d ago

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

From: Eric Dumazet <edumazet@google.com>
Date: 2026-08-17 14:00:48

On Mon, Aug 17, 2026 at 2:59 PM Tetsuo Handa
[off-list ref] wrote:
On 2026/08/17 14:26, Eric Dumazet wrote:
quoted
On Mon, Aug 17, 2026 at 6:28 AM Kuniyuki Iwashima [off-list ref] wrote:
quoted
On Sun, Aug 16, 2026 at 4:08 AM Tetsuo Handa
[off-list ref] wrote:
quoted
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()".
quoted
quoted
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?
quoted
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,
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help