Skip to content

Commit df43d8b

Browse files
Stanislav Fomichevkuba-moo
Stanislav Fomichev
authored andcommitted
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 <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 2bcf477 commit df43d8b

File tree

9 files changed

+41
-56
lines changed

9 files changed

+41
-56
lines changed

drivers/net/tap.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1017,7 +1017,7 @@ static long tap_ioctl(struct file *file, unsigned int cmd,
10171017
rtnl_unlock();
10181018
return -ENOLINK;
10191019
}
1020-
ret = dev_set_mac_address_user(tap->dev, &sa, NULL);
1020+
ret = dev_set_mac_address(tap->dev, &sa, NULL);
10211021
tap_put_tap_dev(tap);
10221022
rtnl_unlock();
10231023
return ret;

drivers/net/tun.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3175,7 +3175,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
31753175

31763176
case SIOCSIFHWADDR:
31773177
/* Set hw address */
3178-
ret = dev_set_mac_address_user(tun->dev, &ifr.ifr_hwaddr, NULL);
3178+
ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr, NULL);
31793179
break;
31803180

31813181
case TUNGETSNDBUF:

include/linux/netdevice.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2492,7 +2492,7 @@ struct net_device {
24922492
*
24932493
* Protects:
24942494
* @gro_flush_timeout, @napi_defer_hard_irqs, @napi_list,
2495-
* @net_shaper_hierarchy, @reg_state, @threaded
2495+
* @net_shaper_hierarchy, @reg_state, @threaded, @dev_addr
24962496
*
24972497
* Partially protects (writers must hold both @lock and rtnl_lock):
24982498
* @up
@@ -4262,10 +4262,6 @@ int netif_set_mac_address(struct net_device *dev, struct sockaddr *sa,
42624262
struct netlink_ext_ack *extack);
42634263
int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa,
42644264
struct netlink_ext_ack *extack);
4265-
int netif_set_mac_address_user(struct net_device *dev, struct sockaddr *sa,
4266-
struct netlink_ext_ack *extack);
4267-
int dev_set_mac_address_user(struct net_device *dev, struct sockaddr *sa,
4268-
struct netlink_ext_ack *extack);
42694265
int dev_get_mac_address(struct sockaddr *sa, struct net *net, char *dev_name);
42704266
int dev_get_port_parent_id(struct net_device *dev,
42714267
struct netdev_phys_item_id *ppid, bool recurse);

net/core/dev.c

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,6 +1058,28 @@ struct net_device *netdev_get_by_index_lock(struct net *net, int ifindex)
10581058
return __netdev_put_lock(dev);
10591059
}
10601060

1061+
/**
1062+
* netdev_get_by_name_lock() - find a device by its name
1063+
* @net: the applicable net namespace
1064+
* @name: name of device
1065+
*
1066+
* Search for an interface by name. If a valid device
1067+
* with @name is found it will be returned with netdev->lock held.
1068+
* netdev_unlock() must be called to release it.
1069+
*
1070+
* Return: pointer to a device with lock held, NULL if not found.
1071+
*/
1072+
struct net_device *netdev_get_by_name_lock(struct net *net, const char *name)
1073+
{
1074+
struct net_device *dev;
1075+
1076+
dev = dev_get_by_name(net, name);
1077+
if (!dev)
1078+
return NULL;
1079+
1080+
return __netdev_put_lock(dev);
1081+
}
1082+
10611083
struct net_device *
10621084
netdev_xa_find_lock(struct net *net, struct net_device *dev,
10631085
unsigned long *index)
@@ -9589,44 +9611,24 @@ int netif_set_mac_address(struct net_device *dev, struct sockaddr *sa,
95899611
return 0;
95909612
}
95919613

9592-
DECLARE_RWSEM(dev_addr_sem);
9593-
9594-
int netif_set_mac_address_user(struct net_device *dev, struct sockaddr *sa,
9595-
struct netlink_ext_ack *extack)
9596-
{
9597-
int ret;
9598-
9599-
down_write(&dev_addr_sem);
9600-
ret = netif_set_mac_address(dev, sa, extack);
9601-
up_write(&dev_addr_sem);
9602-
return ret;
9603-
}
9604-
96059614
int dev_get_mac_address(struct sockaddr *sa, struct net *net, char *dev_name)
96069615
{
96079616
size_t size = sizeof(sa->sa_data_min);
96089617
struct net_device *dev;
9609-
int ret = 0;
96109618

9611-
down_read(&dev_addr_sem);
9612-
rcu_read_lock();
9619+
dev = netdev_get_by_name_lock(net, dev_name);
9620+
if (!dev)
9621+
return -ENODEV;
96139622

9614-
dev = dev_get_by_name_rcu(net, dev_name);
9615-
if (!dev) {
9616-
ret = -ENODEV;
9617-
goto unlock;
9618-
}
96199623
if (!dev->addr_len)
96209624
memset(sa->sa_data, 0, size);
96219625
else
96229626
memcpy(sa->sa_data, dev->dev_addr,
96239627
min_t(size_t, size, dev->addr_len));
96249628
sa->sa_family = dev->type;
9629+
netdev_unlock(dev);
96259630

9626-
unlock:
9627-
rcu_read_unlock();
9628-
up_read(&dev_addr_sem);
9629-
return ret;
9631+
return 0;
96309632
}
96319633
EXPORT_SYMBOL(dev_get_mac_address);
96329634

net/core/dev.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ netdev_napi_by_id_lock(struct net *net, unsigned int napi_id);
2828
struct net_device *dev_get_by_napi_id(unsigned int napi_id);
2929

3030
struct net_device *netdev_get_by_index_lock(struct net *net, int ifindex);
31+
struct net_device *netdev_get_by_name_lock(struct net *net, const char *name);
3132
struct net_device *__netdev_put_lock(struct net_device *dev);
3233
struct net_device *
3334
netdev_xa_find_lock(struct net *net, struct net_device *dev,
@@ -69,8 +70,6 @@ extern int weight_p;
6970
extern int dev_weight_rx_bias;
7071
extern int dev_weight_tx_bias;
7172

72-
extern struct rw_semaphore dev_addr_sem;
73-
7473
/* rtnl helpers */
7574
extern struct list_head net_todo_list;
7675
void netdev_run_todo(void);

net/core/dev_api.c

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -82,19 +82,6 @@ void dev_set_group(struct net_device *dev, int new_group)
8282
netdev_unlock_ops(dev);
8383
}
8484

85-
int dev_set_mac_address_user(struct net_device *dev, struct sockaddr *sa,
86-
struct netlink_ext_ack *extack)
87-
{
88-
int ret;
89-
90-
netdev_lock_ops(dev);
91-
ret = netif_set_mac_address_user(dev, sa, extack);
92-
netdev_unlock_ops(dev);
93-
94-
return ret;
95-
}
96-
EXPORT_SYMBOL(dev_set_mac_address_user);
97-
9885
/**
9986
* dev_change_net_namespace() - move device to different nethost namespace
10087
* @dev: device
@@ -310,9 +297,9 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa,
310297
{
311298
int ret;
312299

313-
netdev_lock_ops(dev);
300+
netdev_lock(dev);
314301
ret = netif_set_mac_address(dev, sa, extack);
315-
netdev_unlock_ops(dev);
302+
netdev_unlock(dev);
316303

317304
return ret;
318305
}

net/core/dev_ioctl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, void __user *data,
574574
case SIOCSIFHWADDR:
575575
if (dev->addr_len > sizeof(struct sockaddr))
576576
return -EINVAL;
577-
return dev_set_mac_address_user(dev, &ifr->ifr_hwaddr, NULL);
577+
return dev_set_mac_address(dev, &ifr->ifr_hwaddr, NULL);
578578

579579
case SIOCSIFHWBROADCAST:
580580
if (ifr->ifr_hwaddr.sa_family != dev->type)

net/core/net-sysfs.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -262,14 +262,11 @@ static ssize_t address_show(struct device *dev, struct device_attribute *attr,
262262
struct net_device *ndev = to_net_dev(dev);
263263
ssize_t ret = -EINVAL;
264264

265-
down_read(&dev_addr_sem);
266-
267-
rcu_read_lock();
265+
netdev_lock(ndev);
268266
if (dev_isalive(ndev))
269267
ret = sysfs_format_mac(buf, ndev->dev_addr, ndev->addr_len);
270-
rcu_read_unlock();
268+
netdev_unlock(ndev);
271269

272-
up_read(&dev_addr_sem);
273270
return ret;
274271
}
275272
static DEVICE_ATTR_RO(address);

net/core/rtnetlink.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3089,7 +3089,11 @@ static int do_setlink(const struct sk_buff *skb, struct net_device *dev,
30893089
sa->sa_family = dev->type;
30903090
memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]),
30913091
dev->addr_len);
3092-
err = netif_set_mac_address_user(dev, sa, extack);
3092+
if (!netdev_need_ops_lock(dev))
3093+
netdev_lock(dev);
3094+
err = netif_set_mac_address(dev, sa, extack);
3095+
if (!netdev_need_ops_lock(dev))
3096+
netdev_unlock(dev);
30933097
kfree(sa);
30943098
if (err)
30953099
goto errout;

0 commit comments

Comments
 (0)