Skip to content

Commit bb4c698

Browse files
Tetsuo Handakuba-moo
authored andcommitted
team: avoid NETDEV_CHANGEMTU event when unregistering slave
syzbot is reporting unregister_netdevice: waiting for netdevsim0 to become free. Usage count = 3 ref_tracker: netdev@ffff88807dcf8618 has 1/2 users at __netdev_tracker_alloc include/linux/netdevice.h:4400 [inline] netdev_hold include/linux/netdevice.h:4429 [inline] inetdev_init+0x201/0x4e0 net/ipv4/devinet.c:286 inetdev_event+0x251/0x1610 net/ipv4/devinet.c:1600 notifier_call_chain+0x19d/0x3a0 kernel/notifier.c:85 call_netdevice_notifiers_mtu net/core/dev.c:2318 [inline] netif_set_mtu_ext+0x5aa/0x800 net/core/dev.c:9886 netif_set_mtu+0xd7/0x1b0 net/core/dev.c:9907 dev_set_mtu+0x126/0x260 net/core/dev_api.c:248 team_port_del+0xb07/0xcb0 drivers/net/team/team_core.c:1333 team_del_slave drivers/net/team/team_core.c:1936 [inline] team_device_event+0x207/0x5b0 drivers/net/team/team_core.c:2929 notifier_call_chain+0x19d/0x3a0 kernel/notifier.c:85 call_netdevice_notifiers_extack net/core/dev.c:2281 [inline] call_netdevice_notifiers net/core/dev.c:2295 [inline] __dev_change_net_namespace+0xcb7/0x2050 net/core/dev.c:12592 do_setlink+0x2ce/0x4590 net/core/rtnetlink.c:3060 rtnl_changelink net/core/rtnetlink.c:3776 [inline] __rtnl_newlink net/core/rtnetlink.c:3935 [inline] rtnl_newlink+0x15a9/0x1be0 net/core/rtnetlink.c:4072 rtnetlink_rcv_msg+0x7d5/0xbe0 net/core/rtnetlink.c:6958 netlink_rcv_skb+0x232/0x4b0 net/netlink/af_netlink.c:2550 netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline] netlink_unicast+0x80f/0x9b0 net/netlink/af_netlink.c:1344 netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1894 problem. Ido Schimmel found steps to reproduce ip link add name team1 type team ip link add name dummy1 mtu 1499 master team1 type dummy ip netns add ns1 ip link set dev dummy1 netns ns1 ip -n ns1 link del dev dummy1 and also found that the same issue was fixed in the bond driver in commit f51048c ("bonding: avoid NETDEV_CHANGEMTU event when unregistering slave"). Let's do similar thing for the team driver, with commit ad7c7b2 ("net: hold netdev instance lock during sysfs operations") and commit 303a848 ("net: s/__dev_set_mtu/__netif_set_mtu/") also applied. Reported-by: [email protected] Closes: https://syzkaller.appspot.com/bug?extid=881d65229ca4f9ae8c84 Suggested-by: Ido Schimmel <[email protected]> Reviewed-by: Jiri Pirko <[email protected]> Fixes: 3d249d4 ("net: introduce ethernet teaming device") Signed-off-by: Tetsuo Handa <[email protected]> Signed-off-by: Ido Schimmel <[email protected]> Acked-by: Stanislav Fomichev <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent f975a09 commit bb4c698

1 file changed

Lines changed: 21 additions & 5 deletions

File tree

drivers/net/team/team_core.c

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1292,7 +1292,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev,
12921292

12931293
static void __team_port_change_port_removed(struct team_port *port);
12941294

1295-
static int team_port_del(struct team *team, struct net_device *port_dev)
1295+
static int team_port_del(struct team *team, struct net_device *port_dev, bool unregister)
12961296
{
12971297
struct net_device *dev = team->dev;
12981298
struct team_port *port;
@@ -1330,7 +1330,13 @@ static int team_port_del(struct team *team, struct net_device *port_dev)
13301330
__team_port_change_port_removed(port);
13311331

13321332
team_port_set_orig_dev_addr(port);
1333-
dev_set_mtu(port_dev, port->orig.mtu);
1333+
if (unregister) {
1334+
netdev_lock_ops(port_dev);
1335+
__netif_set_mtu(port_dev, port->orig.mtu);
1336+
netdev_unlock_ops(port_dev);
1337+
} else {
1338+
dev_set_mtu(port_dev, port->orig.mtu);
1339+
}
13341340
kfree_rcu(port, rcu);
13351341
netdev_info(dev, "Port device %s removed\n", portname);
13361342
netdev_compute_master_upper_features(team->dev, true);
@@ -1634,7 +1640,7 @@ static void team_uninit(struct net_device *dev)
16341640
ASSERT_RTNL();
16351641

16361642
list_for_each_entry_safe(port, tmp, &team->port_list, list)
1637-
team_port_del(team, port->dev);
1643+
team_port_del(team, port->dev, false);
16381644

16391645
__team_change_mode(team, NULL); /* cleanup */
16401646
__team_options_unregister(team, team_options, ARRAY_SIZE(team_options));
@@ -1933,7 +1939,16 @@ static int team_del_slave(struct net_device *dev, struct net_device *port_dev)
19331939

19341940
ASSERT_RTNL();
19351941

1936-
return team_port_del(team, port_dev);
1942+
return team_port_del(team, port_dev, false);
1943+
}
1944+
1945+
static int team_del_slave_on_unregister(struct net_device *dev, struct net_device *port_dev)
1946+
{
1947+
struct team *team = netdev_priv(dev);
1948+
1949+
ASSERT_RTNL();
1950+
1951+
return team_port_del(team, port_dev, true);
19371952
}
19381953

19391954
static netdev_features_t team_fix_features(struct net_device *dev,
@@ -2926,7 +2941,7 @@ static int team_device_event(struct notifier_block *unused,
29262941
!!netif_oper_up(port->dev));
29272942
break;
29282943
case NETDEV_UNREGISTER:
2929-
team_del_slave(port->team->dev, dev);
2944+
team_del_slave_on_unregister(port->team->dev, dev);
29302945
break;
29312946
case NETDEV_FEAT_CHANGE:
29322947
if (!port->team->notifier_ctx) {
@@ -2999,3 +3014,4 @@ MODULE_LICENSE("GPL v2");
29993014
MODULE_AUTHOR("Jiri Pirko <[email protected]>");
30003015
MODULE_DESCRIPTION("Ethernet team device driver");
30013016
MODULE_ALIAS_RTNL_LINK(DRV_NAME);
3017+
MODULE_IMPORT_NS("NETDEV_INTERNAL");

0 commit comments

Comments
 (0)