Re: [PATCH RFC v2] netdevsim: fix UAF by explicitly cleaning up debugfs files
Aleksandr Nogikh <[email protected]>
| Newsgroups | dev.linux.lists.syzbot |
|---|---|
| Message-ID | <CANp29Y4dHrcS6TCKSJbDJDLHbXippnwxXSWEUX2bvs=mpd0zYw@mail.gmail.com> |
On Fri, Jun 19, 2026 at 2:49 PM 'syzbot' via syzkaller-upstream-moderation <[email protected]> wrote: > > A KASAN slab-use-after-free bug was detected in debugfs_u32_get(). The root > cause is a race condition between the destruction of a netdevsim device and > the access to its associated debugfs files. > > When a netdevsim device is destroyed, the teardown happens in > __nsim_dev_port_del(), which calls nsim_destroy() and then > nsim_dev_port_debugfs_exit(). nsim_destroy() calls free_netdev(), which > frees the struct netdevsim memory. However, some debugfs files pointing to > fields inside this struct are only removed later in > nsim_dev_port_debugfs_exit(). This creates a use-after-free window where a > user space program can access the freed memory by reading from the debugfs > files. The same issue exists in the error path of nsim_create(). > > To fix this, explicitly remove the debugfs files and directories created > for the netdevsim instance during its teardown. This is done by adding or > updating teardown functions like nsim_ethtool_teardown() and > nsim_bpf_uninit() to remove their respective debugfs entries before the > underlying memory is freed. This approach ensures that the cleanup is > symmetrical and specifically targets the files associated with the > netdevsim instance being destroyed, without breaking the symmetry of > nsim_dev_port->ddir. > > BUG: KASAN: slab-use-after-free in debugfs_u32_get+0x6c/0x70 > fs/debugfs/file.c:657 > Read of size 4 at addr ffff888196b7db00 by task syz.2.2765/11946 > > Call Trace: > <TASK> > debugfs_u32_get+0x6c/0x70 fs/debugfs/file.c:657 > simple_attr_read+0x227/0x490 fs/libfs.c:1368 > debugfs_attr_read+0x76/0x130 fs/debugfs/file.c:523 > vfs_read+0x213/0xa80 fs/read_write.c:572 > ksys_read+0x150/0x270 fs/read_write.c:717 > do_syscall_64+0x174/0x580 arch/x86/entry/syscall_64.c:94 > entry_SYSCALL_64_after_hwframe+0x77/0x7f > </TASK> > > Freed by task 11226: > kfree+0x1c5/0x640 mm/slub.c:6566 > device_release+0xc4/0x1f0 drivers/base/core.c:-1 > kobject_put+0x222/0x550 lib/kobject.c:737 > __nsim_dev_port_del+0x14e/0x200 drivers/net/netdevsim/dev.c:1547 > nsim_dev_reload_destroy+0x288/0x490 drivers/net/netdevsim/dev.c:1785 > > Fixes: e05b2d141fef ("netdevsim: move netdev creation/destruction to dev probe") > Assisted-by: Gemini:gemini-3.1-pro-preview Gemini:gemini-3-flash-preview syzbot > Reported-by: [email protected] > Closes: https://syzkaller.appspot.com/bug?extid=6c25f4750230faf70be9 > Link: https://syzkaller.appspot.com/ai_job?id=d4f60d9d-c966-4936-8994-4459d20c9153 > To: "Andrew Lunn" <[email protected]> > To: <[email protected]> > To: "David S. Miller" <[email protected]> > To: "Eric Dumazet" <[email protected]> > To: "Jakub Kicinski" <[email protected]> > To: <[email protected]> > To: "Paolo Abeni" <[email protected]> > Cc: <[email protected]> > > --- > v2: > - Switched to a symmetrical cleanup approach by explicitly removing debugfs entries in teardown functions instead of recursive removal of the port directory. > - Added nsim_ethtool_teardown() to remove the ethtool debugfs directory. > - Updated nsim_bpf_uninit() to remove BPF-related debugfs files using debugfs_lookup_and_remove(). > - Called nsim_ethtool_teardown() in nsim_destroy() and the error path of nsim_create(). > > v1: > https://lore.kernel.org/all/[email protected]/T/ > --- > diff --git a/drivers/net/netdevsim/bpf.c b/drivers/net/netdevsim/bpf.c > index 8eebcc933..5b9b1da46 100644 > --- a/drivers/net/netdevsim/bpf.c > +++ b/drivers/net/netdevsim/bpf.c > @@ -653,6 +653,15 @@ int nsim_bpf_init(struct netdevsim *ns) > > void nsim_bpf_uninit(struct netdevsim *ns) > { > + struct dentry *ddir = ns->nsim_dev_port->ddir; > + > + debugfs_lookup_and_remove("bpf_map_accept", ddir); > + debugfs_lookup_and_remove("bpf_xdpoffload_accept", ddir); > + debugfs_lookup_and_remove("bpf_xdpdrv_accept", ddir); > + debugfs_lookup_and_remove("bpf_tc_non_bound_accept", ddir); > + debugfs_lookup_and_remove("bpf_tc_accept", ddir); > + debugfs_lookup_and_remove("bpf_offloaded_id", ddir); Why `debugfs_lookup_and_remove("ethtool", ns->nsim_dev_port->ddir);` was not enough? > + > WARN_ON(ns->xdp.prog); > WARN_ON(ns->xdp_hw.prog); > WARN_ON(ns->bpf_offloaded); > diff --git a/drivers/net/netdevsim/ethtool.c b/drivers/net/netdevsim/ethtool.c > index 36a201533..3a369040c 100644 > --- a/drivers/net/netdevsim/ethtool.c > +++ b/drivers/net/netdevsim/ethtool.c > @@ -271,3 +271,8 @@ void nsim_ethtool_init(struct netdevsim *ns) > debugfs_create_u32("tx_max_pending", 0600, dir, > &ns->ethtool.ring.tx_max_pending); > } > + > +void nsim_ethtool_teardown(struct netdevsim *ns) > +{ > + debugfs_lookup_and_remove("ethtool", ns->nsim_dev_port->ddir); > +} > diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c > index a75076891..9a7db40c9 100644 > --- a/drivers/net/netdevsim/netdev.c > +++ b/drivers/net/netdevsim/netdev.c > @@ -1164,6 +1164,7 @@ struct netdevsim *nsim_create(struct nsim_dev *nsim_dev, > return ns; > > err_free_netdev: > + nsim_ethtool_teardown(ns); > free_netdev(dev); > return ERR_PTR(err); > } > @@ -1177,6 +1178,7 @@ void nsim_destroy(struct netdevsim *ns) > debugfs_remove(ns->vlan_dfs); > debugfs_remove(ns->qr_dfs); > debugfs_remove(ns->pp_dfs); > + nsim_ethtool_teardown(ns); > > if (ns->nb.notifier_call) > unregister_netdevice_notifier_dev_net(ns->netdev, &ns->nb, > diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h > index d909c4160..75b724e18 100644 > --- a/drivers/net/netdevsim/netdevsim.h > +++ b/drivers/net/netdevsim/netdevsim.h > @@ -171,6 +171,7 @@ void nsim_destroy(struct netdevsim *ns); > bool netdev_is_nsim(struct net_device *dev); > > void nsim_ethtool_init(struct netdevsim *ns); > +void nsim_ethtool_teardown(struct netdevsim *ns); > > void nsim_udp_tunnels_debugfs_create(struct nsim_dev *nsim_dev); > int nsim_udp_tunnels_info_create(struct nsim_dev *nsim_dev, > > > base-commit: 8cd9520d35a6c38db6567e97dd93b1f11f185dc6 > -- > This is an AI-generated patch subject to moderation. > Reply with '#syz upstream' to Sign-off the patch as a human author > and send it to the upstream kernel mailing lists. > Reply with '#syz reject' to reject it ('#syz unreject' to undo). > > See https://goo.gle/syzbot-ai-patches for information about AI-generated patches. > You can comment on the patch as usual, syzbot will try to address > the comments and send a new version of the patch if necessary. > syzbot engineers can be reached at [email protected]. > > -- > You received this message because you are subscribed to the Google Groups "syzkaller-upstream-moderation" group. > To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. > To view this discussion visit https://groups.google.com/d/msgid/syzkaller-upstream-moderation/ae062345-5029-4e41-9f06-20d8face5948%40mail.kernel.org.