hsr: use hsr_for_each_port_rtnl in hsr_port_get_hsr
authorHangbin Liu <liuhangbin@gmail.com>
Fri, 5 Sep 2025 09:15:32 +0000 (09:15 +0000)
committerPaolo Abeni <pabeni@redhat.com>
Thu, 11 Sep 2025 09:49:19 +0000 (11:49 +0200)
hsr_port_get_hsr() iterates over ports using hsr_for_each_port(),
but many of its callers do not hold the required RCU lock.

Switch to hsr_for_each_port_rtnl(), since most callers already hold
the rtnl lock. After review, all callers are covered by either the rtnl
lock or the RCU lock, except hsr_dev_xmit(). Fix this by adding an
RCU read lock there.

Fixes: c5a759117210 ("net/hsr: Use list_head (and rcu) instead of array for slave devices.")
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20250905091533.377443-3-liuhangbin@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
net/hsr/hsr_device.c
net/hsr/hsr_main.c

index bce7b4061ce08bfe5eb1bc4b6e586f52eac95eb8..702da1f9aaa90e2a3c12fba72d400846e60089f9 100644 (file)
@@ -226,6 +226,7 @@ static netdev_tx_t hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev)
        struct hsr_priv *hsr = netdev_priv(dev);
        struct hsr_port *master;
 
+       rcu_read_lock();
        master = hsr_port_get_hsr(hsr, HSR_PT_MASTER);
        if (master) {
                skb->dev = master->dev;
@@ -238,6 +239,8 @@ static netdev_tx_t hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev)
                dev_core_stats_tx_dropped_inc(dev);
                dev_kfree_skb_any(skb);
        }
+       rcu_read_unlock();
+
        return NETDEV_TX_OK;
 }
 
index ac1eb1db1a52b4bfebb998a2b7a15cfc94b70dd8..bc94b07101d80e2645b17488b0fa999cccc2f7f9 100644 (file)
@@ -134,7 +134,7 @@ struct hsr_port *hsr_port_get_hsr(struct hsr_priv *hsr, enum hsr_port_type pt)
 {
        struct hsr_port *port;
 
-       hsr_for_each_port(hsr, port)
+       hsr_for_each_port_rtnl(hsr, port)
                if (port->type == pt)
                        return port;
        return NULL;