summaryrefslogtreecommitdiff
path: root/drivers/net/netdevsim
diff options
context:
space:
mode:
authorYousef Alhouseen <alhouseenyousef@gmail.com>2026-06-28 02:28:04 +0200
committerJakub Kicinski <kuba@kernel.org>2026-06-29 18:47:23 -0700
commit2e996ca81f9512c2d39d826a5146e5fe4ab28277 (patch)
tree67a5a43842ec7c95dc60514665e5b5b6a725d44a /drivers/net/netdevsim
parent9facb861dc6b9b9ea9793ef5032a9a826f7a4229 (diff)
netdevsim: remove ethtool debugfs files before freeing netdev
The ethtool debugfs files point directly into struct netdevsim, which is allocated as net_device private data. Their containing port directory is removed only after nsim_destroy() calls free_netdev(). An open simple-attribute file can consequently dereference the freed private data before the directory is removed. KASAN observed this in debugfs_u32_get() during network namespace teardown. Track and remove the ethtool subtree before free_netdev() on both the normal and registration-failure paths. debugfs removal drains active file users before returning. Fixes: ff1f7c17fb20 ("netdevsim: add pause frame stats") Reported-by: syzbot+6c25f4750230faf70be9@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=6c25f4750230faf70be9 Cc: <stable+noautosel@kernel.org> # netdevsim is a test harness, it's never loaded on production systems Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com> Link: https://patch.msgid.link/20260628002804.24214-1-alhouseenyousef@gmail.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers/net/netdevsim')
-rw-r--r--drivers/net/netdevsim/ethtool.c6
-rw-r--r--drivers/net/netdevsim/netdev.c2
-rw-r--r--drivers/net/netdevsim/netdevsim.h2
3 files changed, 10 insertions, 0 deletions
diff --git a/drivers/net/netdevsim/ethtool.c b/drivers/net/netdevsim/ethtool.c
index 9350ba48eb81..025ea79879f3 100644
--- a/drivers/net/netdevsim/ethtool.c
+++ b/drivers/net/netdevsim/ethtool.c
@@ -252,6 +252,7 @@ void nsim_ethtool_init(struct netdevsim *ns)
ns->ethtool.channels = ns->nsim_bus_dev->num_queues;
ethtool = debugfs_create_dir("ethtool", ns->nsim_dev_port->ddir);
+ ns->ethtool_ddir = ethtool;
debugfs_create_u32("get_err", 0600, ethtool, &ns->ethtool.get_err);
debugfs_create_u32("set_err", 0600, ethtool, &ns->ethtool.set_err);
@@ -272,3 +273,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_fini(struct netdevsim *ns)
+{
+ debugfs_remove(ns->ethtool_ddir);
+}
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index 27e5f109f933..4e9d7e10b527 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -1165,6 +1165,7 @@ struct netdevsim *nsim_create(struct nsim_dev *nsim_dev,
return ns;
err_free_netdev:
+ nsim_ethtool_fini(ns);
free_netdev(dev);
return ERR_PTR(err);
}
@@ -1178,6 +1179,7 @@ void nsim_destroy(struct netdevsim *ns)
debugfs_remove(ns->vlan_dfs);
debugfs_remove(ns->qr_dfs);
debugfs_remove(ns->pp_dfs);
+ nsim_ethtool_fini(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 4c9cc96dcec3..64f77f93d937 100644
--- a/drivers/net/netdevsim/netdevsim.h
+++ b/drivers/net/netdevsim/netdevsim.h
@@ -154,6 +154,7 @@ struct netdevsim {
struct dentry *pp_dfs;
struct dentry *qr_dfs;
struct dentry *vlan_dfs;
+ struct dentry *ethtool_ddir;
struct nsim_ethtool ethtool;
struct netdevsim __rcu *peer;
@@ -169,6 +170,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_fini(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,