From: syzbot <syzbot+705c61d60b091ef42c04@syzkaller.appspotmail.com>
To: linux-kernel@vger.kernel.org
Subject: Re: [syzbot] Re: possible deadlock in team_del_slave (3)
Date: Fri, 16 May 2025 06:55:10 -0700 [thread overview]
Message-ID: <682743be.a00a0220.398d88.020d.GAE@google.com> (raw)
In-Reply-To: <000000000000ffc5d80616fea23d@google.com>
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org.
***
Subject: Re: possible deadlock in team_del_slave (3)
Author: penguin-kernel@i-love.sakura.ne.jp
#syz test
diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c
index d8fc0c79745d..96bbe146b884 100644
--- a/drivers/net/team/team_core.c
+++ b/drivers/net/team/team_core.c
@@ -933,7 +933,7 @@ static bool team_port_find(const struct team *team,
* Enable/disable port by adding to enabled port hashlist and setting
* port->index (Might be racy so reader could see incorrect ifindex when
* processing a flying packet, but that is not a problem). Write guarded
- * by team->lock.
+ * by RTNL.
*/
static void team_port_enable(struct team *team,
struct team_port *port)
@@ -1660,8 +1660,6 @@ static int team_init(struct net_device *dev)
goto err_options_register;
netif_carrier_off(dev);
- lockdep_register_key(&team->team_lock_key);
- __mutex_init(&team->lock, "team->team_lock_key", &team->team_lock_key);
netdev_lockdep_set_classes(dev);
return 0;
@@ -1682,7 +1680,7 @@ static void team_uninit(struct net_device *dev)
struct team_port *port;
struct team_port *tmp;
- mutex_lock(&team->lock);
+ ASSERT_RTNL();
list_for_each_entry_safe(port, tmp, &team->port_list, list)
team_port_del(team, port->dev);
@@ -1691,9 +1689,8 @@ static void team_uninit(struct net_device *dev)
team_mcast_rejoin_fini(team);
team_notify_peers_fini(team);
team_queue_override_fini(team);
- mutex_unlock(&team->lock);
+ ASSERT_RTNL();
netdev_change_features(dev);
- lockdep_unregister_key(&team->team_lock_key);
}
static void team_destructor(struct net_device *dev)
@@ -1814,11 +1811,11 @@ static int team_set_mac_address(struct net_device *dev, void *p)
if (dev->type == ARPHRD_ETHER && !is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
dev_addr_set(dev, addr->sa_data);
- mutex_lock(&team->lock);
+ ASSERT_RTNL();
list_for_each_entry(port, &team->port_list, list)
if (team->ops.port_change_dev_addr)
team->ops.port_change_dev_addr(team, port);
- mutex_unlock(&team->lock);
+ ASSERT_RTNL();
return 0;
}
@@ -1832,7 +1829,7 @@ static int team_change_mtu(struct net_device *dev, int new_mtu)
* Alhough this is reader, it's guarded by team lock. It's not possible
* to traverse list in reverse under rcu_read_lock
*/
- mutex_lock(&team->lock);
+ ASSERT_RTNL();
team->port_mtu_change_allowed = true;
list_for_each_entry(port, &team->port_list, list) {
err = dev_set_mtu(port->dev, new_mtu);
@@ -1843,7 +1840,7 @@ static int team_change_mtu(struct net_device *dev, int new_mtu)
}
}
team->port_mtu_change_allowed = false;
- mutex_unlock(&team->lock);
+ ASSERT_RTNL();
WRITE_ONCE(dev->mtu, new_mtu);
@@ -1853,7 +1850,7 @@ static int team_change_mtu(struct net_device *dev, int new_mtu)
list_for_each_entry_continue_reverse(port, &team->port_list, list)
dev_set_mtu(port->dev, dev->mtu);
team->port_mtu_change_allowed = false;
- mutex_unlock(&team->lock);
+ ASSERT_RTNL();
return err;
}
@@ -1907,20 +1904,20 @@ static int team_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
* Alhough this is reader, it's guarded by team lock. It's not possible
* to traverse list in reverse under rcu_read_lock
*/
- mutex_lock(&team->lock);
+ ASSERT_RTNL();
list_for_each_entry(port, &team->port_list, list) {
err = vlan_vid_add(port->dev, proto, vid);
if (err)
goto unwind;
}
- mutex_unlock(&team->lock);
+ ASSERT_RTNL();
return 0;
unwind:
list_for_each_entry_continue_reverse(port, &team->port_list, list)
vlan_vid_del(port->dev, proto, vid);
- mutex_unlock(&team->lock);
+ ASSERT_RTNL();
return err;
}
@@ -1930,10 +1927,10 @@ static int team_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid)
struct team *team = netdev_priv(dev);
struct team_port *port;
- mutex_lock(&team->lock);
+ ASSERT_RTNL();
list_for_each_entry(port, &team->port_list, list)
vlan_vid_del(port->dev, proto, vid);
- mutex_unlock(&team->lock);
+ ASSERT_RTNL();
return 0;
}
@@ -1955,9 +1952,9 @@ static void team_netpoll_cleanup(struct net_device *dev)
{
struct team *team = netdev_priv(dev);
- mutex_lock(&team->lock);
+ ASSERT_RTNL();
__team_netpoll_cleanup(team);
- mutex_unlock(&team->lock);
+ ASSERT_RTNL();
}
static int team_netpoll_setup(struct net_device *dev)
@@ -1966,7 +1963,7 @@ static int team_netpoll_setup(struct net_device *dev)
struct team_port *port;
int err = 0;
- mutex_lock(&team->lock);
+ ASSERT_RTNL();
list_for_each_entry(port, &team->port_list, list) {
err = __team_port_enable_netpoll(port);
if (err) {
@@ -1974,7 +1971,7 @@ static int team_netpoll_setup(struct net_device *dev)
break;
}
}
- mutex_unlock(&team->lock);
+ ASSERT_RTNL();
return err;
}
#endif
@@ -1985,9 +1982,9 @@ static int team_add_slave(struct net_device *dev, struct net_device *port_dev,
struct team *team = netdev_priv(dev);
int err;
- mutex_lock(&team->lock);
+ ASSERT_RTNL();
err = team_port_add(team, port_dev, extack);
- mutex_unlock(&team->lock);
+ ASSERT_RTNL();
if (!err)
netdev_change_features(dev);
@@ -2000,18 +1997,13 @@ static int team_del_slave(struct net_device *dev, struct net_device *port_dev)
struct team *team = netdev_priv(dev);
int err;
- mutex_lock(&team->lock);
+ ASSERT_RTNL();
err = team_port_del(team, port_dev);
- mutex_unlock(&team->lock);
+ ASSERT_RTNL();
if (err)
return err;
- if (netif_is_team_master(port_dev)) {
- lockdep_unregister_key(&team->team_lock_key);
- lockdep_register_key(&team->team_lock_key);
- lockdep_set_class(&team->lock, &team->team_lock_key);
- }
netdev_change_features(dev);
return err;
@@ -2319,13 +2311,13 @@ static struct team *team_nl_team_get(struct genl_info *info)
}
team = netdev_priv(dev);
- mutex_lock(&team->lock);
+ ASSERT_RTNL();
return team;
}
static void team_nl_team_put(struct team *team)
{
- mutex_unlock(&team->lock);
+ ASSERT_RTNL();
dev_put(team->dev);
}
@@ -2961,11 +2953,9 @@ static void __team_port_change_port_removed(struct team_port *port)
static void team_port_change_check(struct team_port *port, bool linkup)
{
- struct team *team = port->team;
-
- mutex_lock(&team->lock);
+ ASSERT_RTNL();
__team_port_change_check(port, linkup);
- mutex_unlock(&team->lock);
+ ASSERT_RTNL();
}
diff --git a/drivers/net/team/team_mode_activebackup.c b/drivers/net/team/team_mode_activebackup.c
index e0f599e2a51d..4e133451f4d6 100644
--- a/drivers/net/team/team_mode_activebackup.c
+++ b/drivers/net/team/team_mode_activebackup.c
@@ -68,7 +68,7 @@ static void ab_active_port_get(struct team *team, struct team_gsetter_ctx *ctx)
struct team_port *active_port;
active_port = rcu_dereference_protected(ab_priv(team)->active_port,
- lockdep_is_held(&team->lock));
+ rtnl_is_locked());
if (active_port)
ctx->data.u32_val = active_port->dev->ifindex;
else
diff --git a/drivers/net/team/team_mode_loadbalance.c b/drivers/net/team/team_mode_loadbalance.c
index 00f8989c29c0..79ac52d086e0 100644
--- a/drivers/net/team/team_mode_loadbalance.c
+++ b/drivers/net/team/team_mode_loadbalance.c
@@ -302,7 +302,7 @@ static int lb_bpf_func_set(struct team *team, struct team_gsetter_ctx *ctx)
/* Clear old filter data */
__fprog_destroy(lb_priv->ex->orig_fprog);
orig_fp = rcu_dereference_protected(lb_priv->fp,
- lockdep_is_held(&team->lock));
+ rtnl_is_locked());
}
rcu_assign_pointer(lb_priv->fp, fp);
@@ -325,7 +325,7 @@ static void lb_bpf_func_free(struct team *team)
__fprog_destroy(lb_priv->ex->orig_fprog);
fp = rcu_dereference_protected(lb_priv->fp,
- lockdep_is_held(&team->lock));
+ rtnl_is_locked());
bpf_prog_destroy(fp);
}
@@ -336,7 +336,7 @@ static void lb_tx_method_get(struct team *team, struct team_gsetter_ctx *ctx)
char *name;
func = rcu_dereference_protected(lb_priv->select_tx_port_func,
- lockdep_is_held(&team->lock));
+ rtnl_is_locked());
name = lb_select_tx_port_get_name(func);
BUG_ON(!name);
ctx->data.str_val = name;
@@ -471,6 +471,7 @@ static void lb_stats_refresh(struct work_struct *work)
bool changed = false;
int i;
int j;
+ bool locked;
lb_priv_ex = container_of(work, struct lb_priv_ex,
stats.refresh_dw.work);
@@ -478,7 +479,8 @@ static void lb_stats_refresh(struct work_struct *work)
team = lb_priv_ex->team;
lb_priv = get_lb_priv(team);
- if (!mutex_trylock(&team->lock)) {
+ locked = rtnl_is_locked();
+ if (!locked && !rtnl_trylock()) {
schedule_delayed_work(&lb_priv_ex->stats.refresh_dw, 0);
return;
}
@@ -515,7 +517,8 @@ static void lb_stats_refresh(struct work_struct *work)
schedule_delayed_work(&lb_priv_ex->stats.refresh_dw,
(lb_priv_ex->stats.refresh_interval * HZ) / 10);
- mutex_unlock(&team->lock);
+ if (!locked)
+ rtnl_unlock();
}
static void lb_stats_refresh_interval_get(struct team *team,
diff --git a/include/linux/if_team.h b/include/linux/if_team.h
index cdc684e04a2f..ce97d891cf72 100644
--- a/include/linux/if_team.h
+++ b/include/linux/if_team.h
@@ -191,8 +191,6 @@ struct team {
const struct header_ops *header_ops_cache;
- struct mutex lock; /* used for overall locking, e.g. port lists write */
-
/*
* List of enabled ports and their count
*/
@@ -223,7 +221,6 @@ struct team {
atomic_t count_pending;
struct delayed_work dw;
} mcast_rejoin;
- struct lock_class_key team_lock_key;
long mode_priv[TEAM_MODE_PRIV_LONGS];
};
prev parent reply other threads:[~2025-05-16 13:55 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-04-26 11:59 [syzbot] [net?] possible deadlock in team_del_slave (3) syzbot
2024-04-26 14:17 ` Hillf Danton
2024-07-03 11:25 ` Jeongjun Park
2024-07-03 13:41 ` syzbot
2024-07-03 13:44 ` Jeongjun Park
2024-07-03 14:19 ` syzbot
2024-07-03 14:51 ` [PATCH net] team: Fix ABBA deadlock caused by race in team_del_slave Jeongjun Park
2024-07-03 15:18 ` Michal Kubiak
2024-07-03 16:02 ` Jeongjun Park
2024-07-03 16:30 ` Eric Dumazet
2024-07-05 15:17 ` [syzbot] [net?] possible deadlock in team_del_slave (3) Jeongjun Park
2024-07-05 15:19 ` [PATCH net] team: Fix ABBA deadlock caused by race in team_del_slave Jeongjun Park
2024-07-03 15:51 ` [syzbot] [net?] possible deadlock in team_del_slave (3) Jeongjun Park
2024-07-03 16:35 ` syzbot
2024-07-04 10:15 ` Jiri Pirko
2024-07-04 10:43 ` [PATCH net] team: Fix ABBA deadlock caused by race in team_del_slave Jeongjun Park
2024-07-04 10:45 ` [syzbot] [net?] possible deadlock in team_del_slave (3) Jeongjun Park
2024-07-04 16:07 ` syzbot
2024-07-04 11:02 ` Jeongjun Park
2024-07-04 16:28 ` syzbot
2024-07-06 4:13 ` [PATCH net,v2] team: Fix ABBA deadlock caused by race in team_del_slave Jeongjun Park
2024-07-06 15:01 ` Stephen Hemminger
2024-07-07 6:00 ` [PATCH] change list_del to list_del_init in ieee80211_remove_interfaces Jeongjun Park
2024-07-07 6:23 ` [syzbot] [net?] possible deadlock in team_del_slave (3) syzbot
2024-07-07 6:02 ` Jeongjun Park
2024-07-07 6:44 ` syzbot
2024-07-07 6:06 ` Jeongjun Park
2024-07-07 7:04 ` syzbot
2025-05-14 13:18 ` [syzbot] " syzbot
2025-05-16 13:55 ` syzbot [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=682743be.a00a0220.398d88.020d.GAE@google.com \
--to=syzbot+705c61d60b091ef42c04@syzkaller.appspotmail.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox