]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net-sysfs: use dev_addr_sem to remove races in address_show()
authorEric Dumazet <edumazet@google.com>
Tue, 13 Feb 2024 06:32:38 +0000 (06:32 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 14 Feb 2024 11:20:13 +0000 (11:20 +0000)
Using dev_base_lock is not preventing from reading garbage.

Use dev_addr_sem instead.

v4: place dev_addr_sem extern in net/core/dev.h (Jakub Kicinski)
Link: https://lore.kernel.org/netdev/20240212175845.10f6680a@kernel.org/
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/core/dev.c
net/core/dev.h
net/core/net-sysfs.c

index 9c95cae9d6ab966c3ad8474921f7acb148a90866..26f93446b743e91528cf788cf861dd947fc16023 100644 (file)
@@ -8993,7 +8993,7 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa,
 }
 EXPORT_SYMBOL(dev_set_mac_address);
 
-static DECLARE_RWSEM(dev_addr_sem);
+DECLARE_RWSEM(dev_addr_sem);
 
 int dev_set_mac_address_user(struct net_device *dev, struct sockaddr *sa,
                             struct netlink_ext_ack *extack)
index a43dfe3de50ee75ee0f4b290b385378ed4a6cfdc..45892267848d7a35a09aea95f04cfd9b72204d3c 100644 (file)
@@ -3,6 +3,7 @@
 #define _NET_CORE_DEV_H
 
 #include <linux/types.h>
+#include <linux/rwsem.h>
 
 struct net;
 struct net_device;
@@ -46,6 +47,8 @@ extern int            weight_p;
 extern int             dev_weight_rx_bias;
 extern int             dev_weight_tx_bias;
 
+extern struct rw_semaphore dev_addr_sem;
+
 /* rtnl helpers */
 extern struct list_head net_todo_list;
 void netdev_run_todo(void);
index 678e4be690821c5cdb933f5e91af2247ebecb830..23ef2df549c3036a702f3be1dca1eda14ee5e76f 100644 (file)
@@ -142,17 +142,21 @@ static ssize_t name_assign_type_show(struct device *dev,
 }
 static DEVICE_ATTR_RO(name_assign_type);
 
-/* use same locking rules as GIFHWADDR ioctl's */
+/* use same locking rules as GIFHWADDR ioctl's (dev_get_mac_address()) */
 static ssize_t address_show(struct device *dev, struct device_attribute *attr,
                            char *buf)
 {
        struct net_device *ndev = to_net_dev(dev);
        ssize_t ret = -EINVAL;
 
-       read_lock(&dev_base_lock);
+       down_read(&dev_addr_sem);
+
+       rcu_read_lock();
        if (dev_isalive(ndev))
                ret = sysfs_format_mac(buf, ndev->dev_addr, ndev->addr_len);
-       read_unlock(&dev_base_lock);
+       rcu_read_unlock();
+
+       up_read(&dev_addr_sem);
        return ret;
 }
 static DEVICE_ATTR_RO(address);