neighbour: no longer hold RTNL in neigh_dump_info()
authorEric Dumazet <edumazet@google.com>
Thu, 18 Apr 2024 09:51:06 +0000 (09:51 +0000)
committerDavid S. Miller <davem@davemloft.net>
Fri, 19 Apr 2024 11:39:20 +0000 (12:39 +0100)
neigh_dump_table() is already relying on RCU protection.

pneigh_dump_table() is using its own protection (tbl->lock)

Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/core/neighbour.c

index d8c3ffdee29f12946554330845023459bc07bab2..0805c00c63d434589aeedaf8c40781b822d70b08 100644 (file)
@@ -2723,7 +2723,6 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
        if (filter->dev_idx || filter->master_idx)
                flags |= NLM_F_DUMP_FILTERED;
 
-       rcu_read_lock();
        nht = rcu_dereference(tbl->nht);
 
        for (h = s_h; h < (1 << nht->hash_shift); h++) {
@@ -2747,7 +2746,6 @@ next:
                }
        }
 out:
-       rcu_read_unlock();
        cb->args[1] = h;
        cb->args[2] = idx;
        return err;
@@ -2881,8 +2879,9 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
 
        s_t = cb->args[0];
 
+       rcu_read_lock();
        for (t = 0; t < NEIGH_NR_TABLES; t++) {
-               tbl = rcu_dereference_rtnl(neigh_tables[t]);
+               tbl = rcu_dereference(neigh_tables[t]);
 
                if (!tbl)
                        continue;
@@ -2898,6 +2897,7 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
                if (err < 0)
                        break;
        }
+       rcu_read_unlock();
 
        cb->args[0] = t;
        return err;
@@ -3894,7 +3894,8 @@ static int __init neigh_init(void)
 {
        rtnl_register(PF_UNSPEC, RTM_NEWNEIGH, neigh_add, NULL, 0);
        rtnl_register(PF_UNSPEC, RTM_DELNEIGH, neigh_delete, NULL, 0);
-       rtnl_register(PF_UNSPEC, RTM_GETNEIGH, neigh_get, neigh_dump_info, 0);
+       rtnl_register(PF_UNSPEC, RTM_GETNEIGH, neigh_get, neigh_dump_info,
+                     RTNL_FLAG_DUMP_UNLOCKED);
 
        rtnl_register(PF_UNSPEC, RTM_GETNEIGHTBL, NULL, neightbl_dump_info,
                      0);