Skip to content
/ linux Public

Commit bce4272

Browse files
Tetsuo HandaSasha Levin
authored andcommitted
team: avoid NETDEV_CHANGEMTU event when unregistering slave
[ Upstream commit bb4c698 ] 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: syzbot+881d65229ca4f9ae8c84@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=881d65229ca4f9ae8c84 Suggested-by: Ido Schimmel <idosch@nvidia.com> Reviewed-by: Jiri Pirko <jiri@nvidia.com> Fixes: 3d249d4 ("net: introduce ethernet teaming device") Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Signed-off-by: Ido Schimmel <idosch@nvidia.com> Acked-by: Stanislav Fomichev <sdf@fomichev.me> Link: https://patch.msgid.link/20260224125709.317574-2-idosch@nvidia.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 54a7013 commit bce4272

File tree

1 file changed

+21
-5
lines changed

1 file changed

+21
-5
lines changed

drivers/net/team/team_core.c

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

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

1294-
static int team_port_del(struct team *team, struct net_device *port_dev)
1294+
static int team_port_del(struct team *team, struct net_device *port_dev, bool unregister)
12951295
{
12961296
struct net_device *dev = team->dev;
12971297
struct team_port *port;
@@ -1329,7 +1329,13 @@ static int team_port_del(struct team *team, struct net_device *port_dev)
13291329
__team_port_change_port_removed(port);
13301330

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

16351641
list_for_each_entry_safe(port, tmp, &team->port_list, list)
1636-
team_port_del(team, port->dev);
1642+
team_port_del(team, port->dev, false);
16371643

16381644
__team_change_mode(team, NULL); /* cleanup */
16391645
__team_options_unregister(team, team_options, ARRAY_SIZE(team_options));
@@ -1932,7 +1938,16 @@ static int team_del_slave(struct net_device *dev, struct net_device *port_dev)
19321938

19331939
ASSERT_RTNL();
19341940

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

19381953
static netdev_features_t team_fix_features(struct net_device *dev,
@@ -2925,7 +2940,7 @@ static int team_device_event(struct notifier_block *unused,
29252940
!!netif_oper_up(port->dev));
29262941
break;
29272942
case NETDEV_UNREGISTER:
2928-
team_del_slave(port->team->dev, dev);
2943+
team_del_slave_on_unregister(port->team->dev, dev);
29292944
break;
29302945
case NETDEV_FEAT_CHANGE:
29312946
if (!port->team->notifier_ctx) {
@@ -2998,3 +3013,4 @@ MODULE_LICENSE("GPL v2");
29983013
MODULE_AUTHOR("Jiri Pirko <jpirko@redhat.com>");
29993014
MODULE_DESCRIPTION("Ethernet team device driver");
30003015
MODULE_ALIAS_RTNL_LINK(DRV_NAME);
3016+
MODULE_IMPORT_NS("NETDEV_INTERNAL");

0 commit comments

Comments
 (0)