Re: [PATCH net v2] psp: fix NULL genl_sock deref race with concurrent netns teardown

From: Kiran Kella

Date: Thu Jul 23 2026 - 11:53:14 EST


On Tue, Jul 21, 2026 at 8:22 PM Jakub Kicinski <kuba@xxxxxxxxxx> wrote:
>
> On Tue, 7 Jul 2026 11:59:37 -0700 Kiran Kella wrote:
> > The race occurs between network namespace removal and PSP device
> > unregistration. When a netns is deleted while a PSP device associated
> > with that netns is concurrently being removed, psp_dev_unregister()
> > triggers psp_nl_notify_dev() to send a device change notification.
> > Concurrently, cleanup_net() running in the netns workqueue calls
> > genl_pernet_exit(), which sets net->genl_sock to NULL. If
> > genl_pernet_exit() wins the race, two sites in psp_nl_multicast_per_ns()
> > then dereference the NULL socket and crash:
> >
> > CPU 0 (netns teardown) CPU 1 (PSP device unregister)
> > ====================== =============================
> > cleanup_net [workqueue]
> > genl_pernet_exit() psp_dev_unregister()
> > net->genl_sock = NULL psp_nl_notify_dev()
> > psp_nl_multicast_per_ns()
> > build_ntf()
> > -> netlink_has_listeners(NULL)
> > /* crash */
> > genlmsg_multicast_netns()
> > -> nlmsg_multicast_filtered(NULL)
> > /* crash */
>
> Can you explain how you hit this, in reality? Seems like an extreme
> corner case to me.

The crash happened when the following commands are given in quick succession:
- The namespace the VF is in, is removed (ip netns del <ns>)
- VFs are removed (echo 0 > /sys/class/net/<dev>/device/sriov_numvfs)
In the context of the psp_dev_unregister as part of VF dev removal ->
psp_nl_notify_dev(PSP_CMD_DEV_DEL_NTF) -> psp_nl_multicast_per_ns(),
saw NULL pointer dereference of net->genl_sock.

>
> > Both the main_net path (derived from psd->main_netdev) and each
> > assoc_net entry in psd->assoc_dev_list are affected.
>
> I don't see how assoc_dev_list is affected. Assoc dev list has
> a notifier which should serialize the netdev unreg on psd->lock.
> And netdev unreg must happen before the netns dismantle.

ACK.
Actually the crash was observed with the main_net only in
psp_nl_multicast_per_ns().
Agree the psp_netdev_event handling already ensures the dev is removed
from the assoc_dev_list before netns teardown.
Will narrow the fix to main_net only in v4.

> > @@ -62,7 +62,10 @@ psp_nl_multicast_per_ns(struct psp_dev *psd, unsigned int group,
> > struct net *main_net;
> > struct sk_buff *ntf;
> >
> > - main_net = dev_net(psd->main_netdev);
>
> comment like:
>
> /* device may be changing netns in parallel */

ACK

>
> > + main_net = maybe_get_net(dev_net(psd->main_netdev));
>
> not sure how the dev_net() is safe here if we're not holding any
> relevant lock. Do we need rcu?

ACK. Needs rcu.

>
> > + if (!main_net)
> > + return;
> > +
> > xa_init(&sent_nets);
> >
> > list_for_each_entry(entry, &psd->assoc_dev_list, dev_list) {
> > @@ -77,21 +80,23 @@ psp_nl_multicast_per_ns(struct psp_dev *psd, unsigned int group,
> > if (ret == -EBUSY)
> > continue;
> >
> > - ntf = build_ntf(psd, assoc_net, ctx);
> > - if (!ntf)
> > + if (!maybe_get_net(assoc_net))
> > continue;
>
> AFAICT we clear the psd on netns move for assoc dev so I don't think
> this is needed today.

ACK

>
> > - genlmsg_multicast_netns(&psp_nl_family, assoc_net, ntf, 0,
> > - group, GFP_KERNEL);
> > + ntf = build_ntf(psd, assoc_net, ctx);
> > + if (ntf)
> > + genlmsg_multicast_netns(&psp_nl_family, assoc_net, ntf,
> > + 0, group, GFP_KERNEL);
> > + put_net(assoc_net);
> > }
> > xa_destroy(&sent_nets);
> >
> > /* Send to main device netns */
> > ntf = build_ntf(psd, main_net, ctx);
> > - if (!ntf)
> > - return;
> > - genlmsg_multicast_netns(&psp_nl_family, main_net, ntf, 0, group,
> > - GFP_KERNEL);
> > + if (ntf)
> > + genlmsg_multicast_netns(&psp_nl_family, main_net, ntf, 0, group,
> > + GFP_KERNEL);
> > + put_net(main_net);
> > }
> >
> > static struct sk_buff *psp_nl_clone_ntf(struct psp_dev *psd, struct net *net,
>

Attachment: smime.p7s
Description: S/MIME Cryptographic Signature