Re: [PATCH net-next 2/9] vxlan: vnifilter: free vxlan_vni_group via RCU in vxlan_vnigroup_uninit()
From: Eric Dumazet <edumazet@google.com>
Date: 2026-09-06 15:41:05
On Sat, Sep 5, 2026 at 6:52 AM Kuniyuki Iwashima [off-list ref] wrote:
On Thu, Sep 3, 2026 at 5:08 AM Eric Dumazet [off-list ref] wrote:quoted
vxlan->vnigrp is an RCU-protected pointer accessed locklessly under rcu_read_lock() in vxlan_vnifilter_dump_dev(). Currently, vxlan_vnigroup_uninit() frees struct vxlan_vni_group synchronously via kfree(vg). If a VXLAN device is deleted concurrently with an RTM_GETTUNNEL dump, vxlan_vnifilter_dump_dev() can suffer a use-after-free when reading vg->num_vnis or walking vg->vni_list.In unregister_netdevice_many_notify(), does synchronize_net() after unlist_netdevice() wait for the reader to complete before ->ndo_uninit() ?
Good point. I added this patch after sashiko had a false positive: <quote> @@ -2979,10 +3007,13 @@ static int vxlan_init(struct net_device *dev)
static void vxlan_uninit(struct net_device *dev)
{
struct vxlan_dev *vxlan = netdev_priv(dev);
+ const struct vxlan_config *cfg;
+
+ cfg = rtnl_dereference(vxlan->cfg);
vxlan_mdb_fini(vxlan);
- if (vxlan->cfg.flags & VXLAN_F_VNIFILTER)
+ if (cfg && (cfg->flags & VXLAN_F_VNIFILTER))
vxlan_vnigroup_uninit(vxlan);This is a pre-existing issue, but does this synchronous cleanup cause a
use-after-free for concurrent RCU readers?
Looking at vxlan_vnigroup_uninit() in drivers/net/vxlan/vxlan_vnifilter.c
around line 925, it destroys and frees the RCU-protected vxlan_vni_group
synchronously:
drivers/net/vxlan/vxlan_vnifilter.c:vxlan_vnigroup_uninit() {
...
rhashtable_destroy(&vg->vni_hash);
kfree(vg);
}
Concurrently, a netlink dump for RTM_GETTUNNEL could call
vxlan_vnifilter_dump_dev(), which retrieves the device under RCU and
accesses vxlan->vnigrp via rcu_dereference(). If the vxlan device is
deleted at the same time, unregister_netdevice_many() calls ndo_uninit() ->
vxlan_uninit() -> vxlan_vnigroup_uninit(), which frees vg without waiting
for an RCU grace period.
Could this lead to memory corruption, and should it be using kfree_rcu()
or synchronize_rcu() instead?
</quote>
Sashiko saw vxlan->vnigrp annotated as __rcu and read under
rcu_read_lock() in vxlan_vnifilter_dump_dev(),
and assumed that because vxlan_vnigroup_uninit() directly does
kfree(vg) without an RCU grace period,
a concurrent netlink dump could hit a UAF.
However, Sashiko missed the netdevice unregistration sequence in
net/core/dev.c: unlist_netdevice(dev)
unlinks the device from lookup structures and synchronize_net() waits
for all active readers to complete
before dev->netdev_ops->ndo_uninit() is ever called.
I will drop this patch from V2 then.
Thanks.