diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c index a750768912b5..e2d714673c2d 100644 --- a/drivers/net/netdevsim/netdev.c +++ b/drivers/net/netdevsim/netdev.c @@ -1213,6 +1213,23 @@ void nsim_destroy(struct netdevsim *ns) ns->page = NULL; } + /* + * Remove all per-port debugfs files before free_netdev() releases + * the netdevsim struct. Files like ethtool/get_err, bpf_offloaded_id, + * etc. store raw pointers into ns (netdev_priv data inside the + * net_device slab). A concurrent reader with the file open could pass + * debugfs_file_get() and then dereference freed memory if these files + * outlive free_netdev(). debugfs_remove_recursive() on the parent ddir + * handles this atomically; the subsequent nsim_dev_port_debugfs_exit() + * call in __nsim_dev_port_del() becomes a harmless no-op. + * + * The three explicitly tracked dentries (vlan_dfs, qr_dfs, pp_dfs) + * are children of ddir and are covered by the recursive removal below, + * so their individual debugfs_remove() calls become no-ops too. + */ + debugfs_remove_recursive(ns->nsim_dev_port->ddir); + ns->nsim_dev_port->ddir = NULL; + free_netdev(dev); }