Skip to content

Commit 4c975fd

Browse files
Stanislav Fomichevkuba-moo
authored andcommitted
net: hold instance lock during NETDEV_REGISTER/UP
Callers of inetdev_init can come from several places with inconsistent expectation about netdev instance lock. Grab instance lock during REGISTER (plus UP). Also solve the inconsistency with UNREGISTER where it was locked only during move netns path. WARNING: CPU: 10 PID: 1479 at ./include/net/netdev_lock.h:54 __netdev_update_features+0x65f/0xca0 __warn+0x81/0x180 __netdev_update_features+0x65f/0xca0 report_bug+0x156/0x180 handle_bug+0x4f/0x90 exc_invalid_op+0x13/0x60 asm_exc_invalid_op+0x16/0x20 __netdev_update_features+0x65f/0xca0 netif_disable_lro+0x30/0x1d0 inetdev_init+0x12f/0x1f0 inetdev_event+0x48b/0x870 notifier_call_chain+0x38/0xf0 register_netdevice+0x741/0x8b0 register_netdev+0x1f/0x40 mlx5e_probe+0x4e3/0x8e0 [mlx5_core] auxiliary_bus_probe+0x3f/0x90 really_probe+0xc3/0x3a0 __driver_probe_device+0x80/0x150 driver_probe_device+0x1f/0x90 __device_attach_driver+0x7d/0x100 bus_for_each_drv+0x80/0xd0 __device_attach+0xb4/0x1c0 bus_probe_device+0x91/0xa0 device_add+0x657/0x870 Reviewed-by: Jakub Kicinski <[email protected]> Reported-by: Cosmin Ratiu <[email protected]> Fixes: ad7c7b2 ("net: hold netdev instance lock during sysfs operations") Signed-off-by: Stanislav Fomichev <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent d2ccd05 commit 4c975fd

File tree

4 files changed

+15
-15
lines changed

4 files changed

+15
-15
lines changed

include/linux/netdevice.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4192,7 +4192,7 @@ int dev_change_flags(struct net_device *dev, unsigned int flags,
41924192
int netif_set_alias(struct net_device *dev, const char *alias, size_t len);
41934193
int dev_set_alias(struct net_device *, const char *, size_t);
41944194
int dev_get_alias(const struct net_device *, char *, size_t);
4195-
int netif_change_net_namespace(struct net_device *dev, struct net *net,
4195+
int __dev_change_net_namespace(struct net_device *dev, struct net *net,
41964196
const char *pat, int new_ifindex,
41974197
struct netlink_ext_ack *extack);
41984198
int dev_change_net_namespace(struct net_device *dev, struct net *net,

net/core/dev.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1858,7 +1858,9 @@ static int call_netdevice_register_net_notifiers(struct notifier_block *nb,
18581858
int err;
18591859

18601860
for_each_netdev(net, dev) {
1861+
netdev_lock_ops(dev);
18611862
err = call_netdevice_register_notifiers(nb, dev);
1863+
netdev_unlock_ops(dev);
18621864
if (err)
18631865
goto rollback;
18641866
}
@@ -11047,7 +11049,9 @@ int register_netdevice(struct net_device *dev)
1104711049
memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
1104811050

1104911051
/* Notify protocols, that a new device appeared. */
11052+
netdev_lock_ops(dev);
1105011053
ret = call_netdevice_notifiers(NETDEV_REGISTER, dev);
11054+
netdev_unlock_ops(dev);
1105111055
ret = notifier_to_errno(ret);
1105211056
if (ret) {
1105311057
/* Expect explicit free_netdev() on failure */
@@ -12059,7 +12063,7 @@ void unregister_netdev(struct net_device *dev)
1205912063
}
1206012064
EXPORT_SYMBOL(unregister_netdev);
1206112065

12062-
int netif_change_net_namespace(struct net_device *dev, struct net *net,
12066+
int __dev_change_net_namespace(struct net_device *dev, struct net *net,
1206312067
const char *pat, int new_ifindex,
1206412068
struct netlink_ext_ack *extack)
1206512069
{
@@ -12144,11 +12148,12 @@ int netif_change_net_namespace(struct net_device *dev, struct net *net,
1214412148
* And now a mini version of register_netdevice unregister_netdevice.
1214512149
*/
1214612150

12151+
netdev_lock_ops(dev);
1214712152
/* If device is running close it first. */
1214812153
netif_close(dev);
12149-
1215012154
/* And unlink it from device chain */
1215112155
unlist_netdevice(dev);
12156+
netdev_unlock_ops(dev);
1215212157

1215312158
synchronize_net();
1215412159

@@ -12210,11 +12215,12 @@ int netif_change_net_namespace(struct net_device *dev, struct net *net,
1221012215
err = netdev_change_owner(dev, net_old, net);
1221112216
WARN_ON(err);
1221212217

12218+
netdev_lock_ops(dev);
1221312219
/* Add the device back in the hashes */
1221412220
list_netdevice(dev);
12215-
1221612221
/* Notify protocols, that a new device appeared. */
1221712222
call_netdevice_notifiers(NETDEV_REGISTER, dev);
12223+
netdev_unlock_ops(dev);
1221812224

1221912225
/*
1222012226
* Prevent userspace races by waiting until the network

net/core/dev_api.c

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -117,13 +117,7 @@ EXPORT_SYMBOL(dev_set_mac_address_user);
117117
int dev_change_net_namespace(struct net_device *dev, struct net *net,
118118
const char *pat)
119119
{
120-
int ret;
121-
122-
netdev_lock_ops(dev);
123-
ret = netif_change_net_namespace(dev, net, pat, 0, NULL);
124-
netdev_unlock_ops(dev);
125-
126-
return ret;
120+
return __dev_change_net_namespace(dev, net, pat, 0, NULL);
127121
}
128122
EXPORT_SYMBOL_GPL(dev_change_net_namespace);
129123

net/core/rtnetlink.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3025,8 +3025,6 @@ static int do_setlink(const struct sk_buff *skb, struct net_device *dev,
30253025
char ifname[IFNAMSIZ];
30263026
int err;
30273027

3028-
netdev_lock_ops(dev);
3029-
30303028
err = validate_linkmsg(dev, tb, extack);
30313029
if (err < 0)
30323030
goto errout;
@@ -3042,14 +3040,16 @@ static int do_setlink(const struct sk_buff *skb, struct net_device *dev,
30423040

30433041
new_ifindex = nla_get_s32_default(tb[IFLA_NEW_IFINDEX], 0);
30443042

3045-
err = netif_change_net_namespace(dev, tgt_net, pat,
3043+
err = __dev_change_net_namespace(dev, tgt_net, pat,
30463044
new_ifindex, extack);
30473045
if (err)
3048-
goto errout;
3046+
return err;
30493047

30503048
status |= DO_SETLINK_MODIFIED;
30513049
}
30523050

3051+
netdev_lock_ops(dev);
3052+
30533053
if (tb[IFLA_MAP]) {
30543054
struct rtnl_link_ifmap *u_map;
30553055
struct ifmap k_map;

0 commit comments

Comments
 (0)