aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/net/core/dev.c
diff options
context:
space:
mode:
authorStanislav Fomichev <sdf@fomichev.me>2025-03-05 08:37:29 -0800
committerJakub Kicinski <kuba@kernel.org>2025-03-06 12:59:45 -0800
commitdf43d8bf10316a7c3b1e47e3cc0057a54df4a5b8 (patch)
treed31253686f41f2bdad50762ea5b86bf56cc7ad25 /net/core/dev.c
parentnet: ethtool: try to protect all callback with netdev instance lock (diff)
downloadwireguard-linux-df43d8bf10316a7c3b1e47e3cc0057a54df4a5b8.tar.xz
wireguard-linux-df43d8bf10316a7c3b1e47e3cc0057a54df4a5b8.zip
net: replace dev_addr_sem with netdev instance lock
Lockdep reports possible circular dependency in [0]. Instead of fixing the ordering, replace global dev_addr_sem with netdev instance lock. Most of the paths that set/get mac are RTNL protected. Two places where it's not, convert to explicit locking: - sysfs address_show - dev_get_mac_address via dev_ioctl 0: https://netdev-3.bots.linux.dev/vmksft-forwarding-dbg/results/993321/24-router-bridge-1d-lag-sh/stderr Signed-off-by: Stanislav Fomichev <sdf@fomichev.me> Link: https://patch.msgid.link/20250305163732.2766420-12-sdf@fomichev.me Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'net/core/dev.c')
-rw-r--r--net/core/dev.c52
1 files changed, 27 insertions, 25 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 404047d4d943..a0f75a1d1f5a 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1058,6 +1058,28 @@ struct net_device *netdev_get_by_index_lock(struct net *net, int ifindex)
return __netdev_put_lock(dev);
}
+/**
+ * netdev_get_by_name_lock() - find a device by its name
+ * @net: the applicable net namespace
+ * @name: name of device
+ *
+ * Search for an interface by name. If a valid device
+ * with @name is found it will be returned with netdev->lock held.
+ * netdev_unlock() must be called to release it.
+ *
+ * Return: pointer to a device with lock held, NULL if not found.
+ */
+struct net_device *netdev_get_by_name_lock(struct net *net, const char *name)
+{
+ struct net_device *dev;
+
+ dev = dev_get_by_name(net, name);
+ if (!dev)
+ return NULL;
+
+ return __netdev_put_lock(dev);
+}
+
struct net_device *
netdev_xa_find_lock(struct net *net, struct net_device *dev,
unsigned long *index)
@@ -9589,44 +9611,24 @@ int netif_set_mac_address(struct net_device *dev, struct sockaddr *sa,
return 0;
}
-DECLARE_RWSEM(dev_addr_sem);
-
-int netif_set_mac_address_user(struct net_device *dev, struct sockaddr *sa,
- struct netlink_ext_ack *extack)
-{
- int ret;
-
- down_write(&dev_addr_sem);
- ret = netif_set_mac_address(dev, sa, extack);
- up_write(&dev_addr_sem);
- return ret;
-}
-
int dev_get_mac_address(struct sockaddr *sa, struct net *net, char *dev_name)
{
size_t size = sizeof(sa->sa_data_min);
struct net_device *dev;
- int ret = 0;
- down_read(&dev_addr_sem);
- rcu_read_lock();
+ dev = netdev_get_by_name_lock(net, dev_name);
+ if (!dev)
+ return -ENODEV;
- dev = dev_get_by_name_rcu(net, dev_name);
- if (!dev) {
- ret = -ENODEV;
- goto unlock;
- }
if (!dev->addr_len)
memset(sa->sa_data, 0, size);
else
memcpy(sa->sa_data, dev->dev_addr,
min_t(size_t, size, dev->addr_len));
sa->sa_family = dev->type;
+ netdev_unlock(dev);
-unlock:
- rcu_read_unlock();
- up_read(&dev_addr_sem);
- return ret;
+ return 0;
}
EXPORT_SYMBOL(dev_get_mac_address);