From: Jiayuan Chen <jiayuan.chen@linux.dev>
To: netdev@vger.kernel.org
Cc: Jiayuan Chen <jiayuan.chen@shopee.com>,
syzbot+3d8bc31c45e11450f24c@syzkaller.appspotmail.com,
Jiayuan Chen <jiayuan.chen@linux.dev>,
Jiri Pirko <jiri@resnulli.us>,
Andrew Lunn <andrew+netdev@lunn.ch>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
linux-kernel@vger.kernel.org
Subject: [PATCH net v1] team: fix header_ops type confusion with non-Ethernet ports
Date: Sat, 14 Mar 2026 14:23:05 +0800 [thread overview]
Message-ID: <20260314062306.212765-1-jiayuan.chen@linux.dev> (raw)
From: Jiayuan Chen <jiayuan.chen@shopee.com>
Similar to commit 950803f72547 ("bonding: fix type confusion in bond_setup_by_slave()"),
team has the same class of header_ops type confusion.
For non-Ethernet ports, team_setup_by_port() copies port_dev->header_ops
directly. When the team device later calls dev_hard_header()/dev_parse_header(),
these callbacks can run with the team net_device instead of the real lower
device, so netdev_priv(dev) is interpreted as the wrong private type and
can crash.
Fix this by introducing team header_ops wrappers for create/parse, selecting
a team port under RCU, and calling the lower device callbacks with port->dev,
so each callback always sees the correct net_device context.
Reproducer:
set -euxo pipefail
for d in t0 b0 g0 d0; do
ip link del "$d" 2>/dev/null || true
done
modprobe bonding || true
modprobe team || true
modprobe ip_gre || true
modprobe dummy || true
ip link add d0 type dummy
ip addr add 10.10.10.1/24 dev d0
ip link set d0 up
ip link add g0 type gre local 10.10.10.1
ip link add b0 type bond mode active-backup
ip link add t0 type team
ip link set g0 master b0
ip link set b0 master t0
ip link set g0 up
ip link set b0 up
ip link set t0 up
Fixes: 8ff5105a2b9d ("team: add support for queue override by setting queue_id for port")
Reported-by: syzbot+3d8bc31c45e11450f24c@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/all/69b46af7.050a0220.36eb34.000e.GAE@google.com/T/
Cc: Jiayuan Chen <jiayuan.chen@linux.dev>
Signed-off-by: Jiayuan Chen <jiayuan.chen@shopee.com>
---
drivers/net/team/team_core.c | 61 +++++++++++++++++++++++++++++++++++-
1 file changed, 60 insertions(+), 1 deletion(-)
diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c
index b7282f5c9632..737bff5bf5ae 100644
--- a/drivers/net/team/team_core.c
+++ b/drivers/net/team/team_core.c
@@ -2058,6 +2058,65 @@ static const struct ethtool_ops team_ethtool_ops = {
* rt netlink interface
***********************/
+/* Caller must hold rcu_read_lock(). */
+static struct team_port *team_header_port_get_rcu(struct team *team, bool txable)
+{
+ struct team_port *port;
+
+ list_for_each_entry_rcu(port, &team->port_list, list) {
+ if (!txable || team_port_txable(port))
+ return port;
+ }
+
+ return NULL;
+}
+
+static int team_header_create(struct sk_buff *skb, struct net_device *team_dev,
+ unsigned short type, const void *daddr,
+ const void *saddr, unsigned int len)
+{
+ struct team *team = netdev_priv(team_dev);
+ const struct header_ops *port_ops;
+ struct team_port *port;
+ int ret = 0;
+
+ rcu_read_lock();
+ port = team_header_port_get_rcu(team, true);
+ if (port) {
+ port_ops = READ_ONCE(port->dev->header_ops);
+ if (port_ops && port_ops->create)
+ ret = port_ops->create(skb, port->dev,
+ type, daddr, saddr, len);
+ }
+ rcu_read_unlock();
+ return ret;
+}
+
+static int team_header_parse(const struct sk_buff *skb, unsigned char *haddr)
+{
+ struct team *team = netdev_priv(skb->dev);
+ const struct header_ops *port_ops;
+ struct team_port *port;
+ int ret = 0;
+
+ rcu_read_lock();
+ port = team_header_port_get_rcu(team, true);
+ if (!port)
+ port = team_header_port_get_rcu(team, false);
+ if (port) {
+ port_ops = READ_ONCE(port->dev->header_ops);
+ if (port_ops && port_ops->parse)
+ ret = port_ops->parse(skb, haddr);
+ }
+ rcu_read_unlock();
+ return ret;
+}
+
+static const struct header_ops team_header_ops = {
+ .create = team_header_create,
+ .parse = team_header_parse,
+};
+
static void team_setup_by_port(struct net_device *dev,
struct net_device *port_dev)
{
@@ -2066,7 +2125,7 @@ static void team_setup_by_port(struct net_device *dev,
if (port_dev->type == ARPHRD_ETHER)
dev->header_ops = team->header_ops_cache;
else
- dev->header_ops = port_dev->header_ops;
+ dev->header_ops = port_dev->header_ops ? &team_header_ops : NULL;
dev->type = port_dev->type;
dev->hard_header_len = port_dev->hard_header_len;
dev->needed_headroom = port_dev->needed_headroom;
--
2.43.0
next reply other threads:[~2026-03-14 6:23 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-14 6:23 Jiayuan Chen [this message]
2026-03-14 10:19 ` [PATCH net v1] team: fix header_ops type confusion with non-Ethernet ports Eric Dumazet
2026-03-14 11:14 ` Eric Dumazet
2026-03-14 11:41 ` Jiayuan Chen
2026-03-14 11:46 ` Eric Dumazet
2026-03-14 11:51 ` Jiayuan Chen
2026-03-14 11:53 ` Eric Dumazet
2026-03-14 11:57 ` Eric Dumazet
2026-03-14 12:05 ` Jiayuan Chen
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=20260314062306.212765-1-jiayuan.chen@linux.dev \
--to=jiayuan.chen@linux.dev \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=jiayuan.chen@shopee.com \
--cc=jiri@resnulli.us \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=syzbot+3d8bc31c45e11450f24c@syzkaller.appspotmail.com \
/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