Skip to content

Commit 847748f

Browse files
liuhangbinPaolo Abeni
authored andcommitted
hsr: hold rcu and dev lock for hsr_get_port_ndev
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>
1 parent 393c841 commit 847748f

File tree

2 files changed

+20
-7
lines changed

2 files changed

+20
-7
lines changed

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

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

655655
static int icssg_prueth_hsr_add_mcast(struct net_device *ndev, const u8 *addr)
656656
{
657-
struct net_device *real_dev;
657+
struct net_device *real_dev, *port_dev;
658658
struct prueth_emac *emac;
659659
u8 vlan_id, i;
660660

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

664664
if (is_hsr_master(real_dev)) {
665665
for (i = HSR_PT_SLAVE_A; i < HSR_PT_INTERLINK; i++) {
666-
emac = netdev_priv(hsr_get_port_ndev(real_dev, i));
667-
if (!emac)
666+
port_dev = hsr_get_port_ndev(real_dev, i);
667+
emac = netdev_priv(port_dev);
668+
if (!emac) {
669+
dev_put(port_dev);
668670
return -EINVAL;
671+
}
669672
icssg_prueth_hsr_fdb_add_del(emac, addr, vlan_id,
670673
true);
674+
dev_put(port_dev);
671675
}
672676
} else {
673677
emac = netdev_priv(real_dev);
@@ -679,7 +683,7 @@ static int icssg_prueth_hsr_add_mcast(struct net_device *ndev, const u8 *addr)
679683

680684
static int icssg_prueth_hsr_del_mcast(struct net_device *ndev, const u8 *addr)
681685
{
682-
struct net_device *real_dev;
686+
struct net_device *real_dev, *port_dev;
683687
struct prueth_emac *emac;
684688
u8 vlan_id, i;
685689

@@ -688,11 +692,15 @@ static int icssg_prueth_hsr_del_mcast(struct net_device *ndev, const u8 *addr)
688692

689693
if (is_hsr_master(real_dev)) {
690694
for (i = HSR_PT_SLAVE_A; i < HSR_PT_INTERLINK; i++) {
691-
emac = netdev_priv(hsr_get_port_ndev(real_dev, i));
692-
if (!emac)
695+
port_dev = hsr_get_port_ndev(real_dev, i);
696+
emac = netdev_priv(port_dev);
697+
if (!emac) {
698+
dev_put(port_dev);
693699
return -EINVAL;
700+
}
694701
icssg_prueth_hsr_fdb_add_del(emac, addr, vlan_id,
695702
false);
703+
dev_put(port_dev);
696704
}
697705
} else {
698706
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)