Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'net-bring-back-dev_addr_sem'

Stanislav Fomichev says:

====================
net: bring back dev_addr_sem

Kohei reports an issue with dev_addr_sem conversion to netdev instance
lock in [0]. Based on the discussion, switching to netdev instance
lock to protect the address might not work for the devices that
are not using netdev ops lock.
Bring dev_addr_sem instance lock back but fix the ordering.

0: https://lore.kernel.org/netdev/20250308203835.60633-2-enjuk@amazon.com
====================

Link: https://patch.msgid.link/20250312190513.1252045-1-sdf@fomichev.me
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

+56 -41
+1 -1
drivers/net/tap.c
··· 1017 1017 rtnl_unlock(); 1018 1018 return -ENOLINK; 1019 1019 } 1020 - ret = dev_set_mac_address(tap->dev, &sa, NULL); 1020 + ret = dev_set_mac_address_user(tap->dev, &sa, NULL); 1021 1021 tap_put_tap_dev(tap); 1022 1022 rtnl_unlock(); 1023 1023 return ret;
+1 -1
drivers/net/tun.c
··· 3193 3193 3194 3194 case SIOCSIFHWADDR: 3195 3195 /* Set hw address */ 3196 - ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr, NULL); 3196 + ret = dev_set_mac_address_user(tun->dev, &ifr.ifr_hwaddr, NULL); 3197 3197 break; 3198 3198 3199 3199 case TUNGETSNDBUF:
+3 -1
include/linux/netdevice.h
··· 2498 2498 * 2499 2499 * Protects: 2500 2500 * @gro_flush_timeout, @napi_defer_hard_irqs, @napi_list, 2501 - * @net_shaper_hierarchy, @reg_state, @threaded, @dev_addr 2501 + * @net_shaper_hierarchy, @reg_state, @threaded 2502 2502 * 2503 2503 * Partially protects (writers must hold both @lock and rtnl_lock): 2504 2504 * @up ··· 4196 4196 struct netlink_ext_ack *extack); 4197 4197 int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa, 4198 4198 struct netlink_ext_ack *extack); 4199 + int dev_set_mac_address_user(struct net_device *dev, struct sockaddr *sa, 4200 + struct netlink_ext_ack *extack); 4199 4201 int dev_get_mac_address(struct sockaddr *sa, struct net *net, char *dev_name); 4200 4202 int dev_get_port_parent_id(struct net_device *dev, 4201 4203 struct netdev_phys_item_id *ppid, bool recurse);
+14 -27
net/core/dev.c
··· 1059 1059 return __netdev_put_lock(dev); 1060 1060 } 1061 1061 1062 - /** 1063 - * netdev_get_by_name_lock() - find a device by its name 1064 - * @net: the applicable net namespace 1065 - * @name: name of device 1066 - * 1067 - * Search for an interface by name. If a valid device 1068 - * with @name is found it will be returned with netdev->lock held. 1069 - * netdev_unlock() must be called to release it. 1070 - * 1071 - * Return: pointer to a device with lock held, NULL if not found. 1072 - */ 1073 - struct net_device *netdev_get_by_name_lock(struct net *net, const char *name) 1074 - { 1075 - struct net_device *dev; 1076 - 1077 - dev = dev_get_by_name(net, name); 1078 - if (!dev) 1079 - return NULL; 1080 - 1081 - return __netdev_put_lock(dev); 1082 - } 1083 - 1084 1062 struct net_device * 1085 1063 netdev_xa_find_lock(struct net *net, struct net_device *dev, 1086 1064 unsigned long *index) ··· 9575 9597 return 0; 9576 9598 } 9577 9599 9600 + DECLARE_RWSEM(dev_addr_sem); 9601 + 9578 9602 int dev_get_mac_address(struct sockaddr *sa, struct net *net, char *dev_name) 9579 9603 { 9580 9604 size_t size = sizeof(sa->sa_data_min); 9581 9605 struct net_device *dev; 9606 + int ret = 0; 9582 9607 9583 - dev = netdev_get_by_name_lock(net, dev_name); 9584 - if (!dev) 9585 - return -ENODEV; 9608 + down_read(&dev_addr_sem); 9609 + rcu_read_lock(); 9586 9610 9611 + dev = dev_get_by_name_rcu(net, dev_name); 9612 + if (!dev) { 9613 + ret = -ENODEV; 9614 + goto unlock; 9615 + } 9587 9616 if (!dev->addr_len) 9588 9617 memset(sa->sa_data, 0, size); 9589 9618 else 9590 9619 memcpy(sa->sa_data, dev->dev_addr, 9591 9620 min_t(size_t, size, dev->addr_len)); 9592 9621 sa->sa_family = dev->type; 9593 - netdev_unlock(dev); 9594 9622 9595 - return 0; 9623 + unlock: 9624 + rcu_read_unlock(); 9625 + up_read(&dev_addr_sem); 9626 + return ret; 9596 9627 } 9597 9628 EXPORT_SYMBOL(dev_get_mac_address); 9598 9629
+2 -1
net/core/dev.h
··· 29 29 struct net_device *dev_get_by_napi_id(unsigned int napi_id); 30 30 31 31 struct net_device *netdev_get_by_index_lock(struct net *net, int ifindex); 32 - struct net_device *netdev_get_by_name_lock(struct net *net, const char *name); 33 32 struct net_device *__netdev_put_lock(struct net_device *dev); 34 33 struct net_device * 35 34 netdev_xa_find_lock(struct net *net, struct net_device *dev, ··· 69 70 extern int weight_p; 70 71 extern int dev_weight_rx_bias; 71 72 extern int dev_weight_tx_bias; 73 + 74 + extern struct rw_semaphore dev_addr_sem; 72 75 73 76 /* rtnl helpers */ 74 77 extern struct list_head net_todo_list;
+17 -2
net/core/dev_api.c
··· 84 84 netdev_unlock_ops(dev); 85 85 } 86 86 87 + int dev_set_mac_address_user(struct net_device *dev, struct sockaddr *sa, 88 + struct netlink_ext_ack *extack) 89 + { 90 + int ret; 91 + 92 + down_write(&dev_addr_sem); 93 + netdev_lock_ops(dev); 94 + ret = netif_set_mac_address(dev, sa, extack); 95 + netdev_unlock_ops(dev); 96 + up_write(&dev_addr_sem); 97 + 98 + return ret; 99 + } 100 + EXPORT_SYMBOL(dev_set_mac_address_user); 101 + 87 102 /** 88 103 * dev_change_net_namespace() - move device to different nethost namespace 89 104 * @dev: device ··· 314 299 { 315 300 int ret; 316 301 317 - netdev_lock(dev); 302 + netdev_lock_ops(dev); 318 303 ret = netif_set_mac_address(dev, sa, extack); 319 - netdev_unlock(dev); 304 + netdev_unlock_ops(dev); 320 305 321 306 return ret; 322 307 }
+1 -1
net/core/dev_ioctl.c
··· 575 575 case SIOCSIFHWADDR: 576 576 if (dev->addr_len > sizeof(struct sockaddr)) 577 577 return -EINVAL; 578 - return dev_set_mac_address(dev, &ifr->ifr_hwaddr, NULL); 578 + return dev_set_mac_address_user(dev, &ifr->ifr_hwaddr, NULL); 579 579 580 580 case SIOCSIFHWBROADCAST: 581 581 if (ifr->ifr_hwaddr.sa_family != dev->type)
+5 -2
net/core/net-sysfs.c
··· 263 263 struct net_device *ndev = to_net_dev(dev); 264 264 ssize_t ret = -EINVAL; 265 265 266 - netdev_lock(ndev); 266 + down_read(&dev_addr_sem); 267 + 268 + rcu_read_lock(); 267 269 if (dev_isalive(ndev)) 268 270 ret = sysfs_format_mac(buf, ndev->dev_addr, ndev->addr_len); 269 - netdev_unlock(ndev); 271 + rcu_read_unlock(); 270 272 273 + up_read(&dev_addr_sem); 271 274 return ret; 272 275 } 273 276 static DEVICE_ATTR_RO(address);
+12 -5
net/core/rtnetlink.c
··· 3088 3088 goto errout; 3089 3089 } 3090 3090 sa->sa_family = dev->type; 3091 + 3092 + netdev_unlock_ops(dev); 3093 + 3094 + /* dev_addr_sem is an outer lock, enforce proper ordering */ 3095 + down_write(&dev_addr_sem); 3096 + netdev_lock_ops(dev); 3097 + 3091 3098 memcpy(sa->sa_data, nla_data(tb[IFLA_ADDRESS]), 3092 3099 dev->addr_len); 3093 - if (!netdev_need_ops_lock(dev)) 3094 - netdev_lock(dev); 3095 3100 err = netif_set_mac_address(dev, sa, extack); 3096 - if (!netdev_need_ops_lock(dev)) 3097 - netdev_unlock(dev); 3098 3101 kfree(sa); 3099 - if (err) 3102 + if (err) { 3103 + up_write(&dev_addr_sem); 3100 3104 goto errout; 3105 + } 3101 3106 status |= DO_SETLINK_MODIFIED; 3107 + 3108 + up_write(&dev_addr_sem); 3102 3109 } 3103 3110 3104 3111 if (tb[IFLA_MTU]) {