mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 01:11:51 -04:00
netdev_register_kobject() calls device_add(), which emits KOBJ_ADD and
wakes udev, but register_netdevice() only makes the device findable by
name later, in list_netdevice(). A udev worker that reacts to the uevent
can therefore run against a device that no lookup can find yet.
This used to be harmless because the ethtool ioctl took the rtnl_lock
when looking the device up, and register_netdevice() runs under rtnl, so
the worker simply blocked until registration finished. The commit in the
fixes tag moved the lookup out from under rtnl for ops-locked drivers.
Now there is a short window in register_netdevice() between
netdev_register_kobject() until list_netdevice() when the device is not
findable by name.
This was reproduced with the mlx5 driver on a kernel with KASAN enabled
during devlink reload: systemd-udevd's net_driver builtin gets -ENODEV
from ETHTOOL_GDRVINFO, which was preventing interface renaming.
Suppress the uevent in netdev_register_kobject() and emit it from
register_netdevice() next to rtmsg_ifinfo(). This is the last point in
register_netdevice() where no error can happen, so only fully registered
devices are announced: the registration error paths never reach it, and
the device_del() that unwinds them stays silent as well, leaving
userspace with neither an add nor a remove.
Fixes: f994752b11 ("net: ethtool: optionally skip rtnl_lock on IOCTL path")
Signed-off-by: Dragos Tatulea <dtatulea@nvidia.com>
Reviewed-by: Shahar Shitrit <shshitrit@nvidia.com>
Link: https://patch.msgid.link/20260806080758.2039586-2-dtatulea@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
19 lines
652 B
C
19 lines
652 B
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef __NET_SYSFS_H__
|
|
#define __NET_SYSFS_H__
|
|
|
|
int __init netdev_kobject_init(void);
|
|
int netdev_register_kobject(struct net_device *);
|
|
void netdev_uevent_add(struct net_device *dev);
|
|
void netdev_unregister_kobject(struct net_device *);
|
|
int net_rx_queue_update_kobjects(struct net_device *, int old_num, int new_num);
|
|
int netdev_queue_update_kobjects(struct net_device *net,
|
|
int old_num, int new_num);
|
|
int netdev_change_owner(struct net_device *, const struct net *net_old,
|
|
const struct net *net_new);
|
|
|
|
extern struct mutex rps_default_mask_mutex;
|
|
|
|
DECLARE_STATIC_KEY_FALSE(skb_defer_disable_key);
|
|
#endif
|