net: rmnet: annotate data-races around mux_id

priv->mux_id is written under RTNL from rmnet_vnd_newlink() and
rmnet_changelink(), but rmnet_egress_handler() reads it from the
transmit path without any lock.

Likewise ep->mux_id is written under RTNL from rmnet_changelink(),
while rmnet_get_endpoint() reads it from the receive path under
RCU only.

Add the missing READ_ONCE()/WRITE_ONCE() annotations.

While at it, publish ep->mux_id before inserting the endpoint in
its new bucket in rmnet_changelink(). Otherwise a concurrent
rmnet_get_endpoint() walking the new bucket could find the
endpoint still carrying its old mux_id, and drop the packet.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Sean Tranchetti <sean.tranchetti@oss.qualcomm.com>
Reviewed-by: Subash Abhinov Kasiviswanathan <subash.a.kasiviswanathan@oss.qualcomm.com>
Link: https://patch.msgid.link/20260916132231.1780091-3-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Eric Dumazet 2026-09-16 13:22:30 +00:00 committed by Jakub Kicinski
parent c863bf6a7d
commit 0067187dbe
3 changed files with 5 additions and 5 deletions

View File

@ -337,11 +337,11 @@ static int rmnet_changelink(struct net_device *dev, struct nlattr *tb[],
}
hlist_del_init_rcu(&ep->hlnode);
WRITE_ONCE(ep->mux_id, mux_id);
hlist_add_head_rcu(&ep->hlnode,
&port->muxed_ep[mux_id]);
ep->mux_id = mux_id;
priv->mux_id = mux_id;
WRITE_ONCE(priv->mux_id, mux_id);
}
}
@ -433,7 +433,7 @@ struct rmnet_endpoint *rmnet_get_endpoint(struct rmnet_port *port, u8 mux_id)
hlist_for_each_entry_rcu(ep, &port->muxed_ep[mux_id], hlnode,
lockdep_rtnl_is_held()) {
if (ep->mux_id == mux_id)
if (READ_ONCE(ep->mux_id) == mux_id)
return ep;
}

View File

@ -261,7 +261,7 @@ void rmnet_egress_handler(struct sk_buff *skb)
orig_dev = skb->dev;
priv = netdev_priv(orig_dev);
skb->dev = priv->real_dev;
mux_id = priv->mux_id;
mux_id = READ_ONCE(priv->mux_id);
port = rmnet_get_port_rcu(skb->dev);
if (!port)

View File

@ -341,7 +341,7 @@ int rmnet_vnd_newlink(u8 id, struct net_device *rmnet_dev,
rmnet_dev->rtnl_link_ops = &rmnet_link_ops;
priv->mux_id = id;
WRITE_ONCE(priv->mux_id, id);
netdev_dbg(rmnet_dev, "rmnet dev created\n");
}