Skip to content

Commit 68a6729

Browse files
liuhangbingregkh
authored andcommitted
hsr: hold rcu and dev lock for hsr_get_port_ndev
[ Upstream commit 847748f ] hsr_get_port_ndev calls hsr_for_each_port, which need to hold rcu lock. On the other hand, before return the port device, we need to hold the device reference to avoid UaF in the caller function. Suggested-by: Paolo Abeni <pabeni@redhat.com> Fixes: 9c10dd8 ("net: hsr: Create and export hsr_get_port_ndev()") Signed-off-by: Hangbin Liu <liuhangbin@gmail.com> Reviewed-by: Simon Horman <horms@kernel.org> Link: https://patch.msgid.link/20250905091533.377443-4-liuhangbin@gmail.com Signed-off-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 43242ae commit 68a6729

2 files changed

Lines changed: 20 additions & 7 deletions

File tree

drivers/net/ethernet/ti/icssg/icssg_prueth.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -691,7 +691,7 @@ static void icssg_prueth_hsr_fdb_add_del(struct prueth_emac *emac,
691691

692692
static int icssg_prueth_hsr_add_mcast(struct net_device *ndev, const u8 *addr)
693693
{
694-
struct net_device *real_dev;
694+
struct net_device *real_dev, *port_dev;
695695
struct prueth_emac *emac;
696696
u8 vlan_id, i;
697697

@@ -700,11 +700,15 @@ static int icssg_prueth_hsr_add_mcast(struct net_device *ndev, const u8 *addr)
700700

701701
if (is_hsr_master(real_dev)) {
702702
for (i = HSR_PT_SLAVE_A; i < HSR_PT_INTERLINK; i++) {
703-
emac = netdev_priv(hsr_get_port_ndev(real_dev, i));
704-
if (!emac)
703+
port_dev = hsr_get_port_ndev(real_dev, i);
704+
emac = netdev_priv(port_dev);
705+
if (!emac) {
706+
dev_put(port_dev);
705707
return -EINVAL;
708+
}
706709
icssg_prueth_hsr_fdb_add_del(emac, addr, vlan_id,
707710
true);
711+
dev_put(port_dev);
708712
}
709713
} else {
710714
emac = netdev_priv(real_dev);
@@ -716,7 +720,7 @@ static int icssg_prueth_hsr_add_mcast(struct net_device *ndev, const u8 *addr)
716720

717721
static int icssg_prueth_hsr_del_mcast(struct net_device *ndev, const u8 *addr)
718722
{
719-
struct net_device *real_dev;
723+
struct net_device *real_dev, *port_dev;
720724
struct prueth_emac *emac;
721725
u8 vlan_id, i;
722726

@@ -725,11 +729,15 @@ static int icssg_prueth_hsr_del_mcast(struct net_device *ndev, const u8 *addr)
725729

726730
if (is_hsr_master(real_dev)) {
727731
for (i = HSR_PT_SLAVE_A; i < HSR_PT_INTERLINK; i++) {
728-
emac = netdev_priv(hsr_get_port_ndev(real_dev, i));
729-
if (!emac)
732+
port_dev = hsr_get_port_ndev(real_dev, i);
733+
emac = netdev_priv(port_dev);
734+
if (!emac) {
735+
dev_put(port_dev);
730736
return -EINVAL;
737+
}
731738
icssg_prueth_hsr_fdb_add_del(emac, addr, vlan_id,
732739
false);
740+
dev_put(port_dev);
733741
}
734742
} else {
735743
emac = netdev_priv(real_dev);

net/hsr/hsr_device.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -675,9 +675,14 @@ struct net_device *hsr_get_port_ndev(struct net_device *ndev,
675675
struct hsr_priv *hsr = netdev_priv(ndev);
676676
struct hsr_port *port;
677677

678+
rcu_read_lock();
678679
hsr_for_each_port(hsr, port)
679-
if (port->type == pt)
680+
if (port->type == pt) {
681+
dev_hold(port->dev);
682+
rcu_read_unlock();
680683
return port->dev;
684+
}
685+
rcu_read_unlock();
681686
return NULL;
682687
}
683688
EXPORT_SYMBOL(hsr_get_port_ndev);

0 commit comments

Comments
 (0)