]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
phonet: Don't hold RTNL for getaddr_dumpit().
authorKuniyuki Iwashima <kuniyu@amazon.com>
Thu, 17 Oct 2024 18:31:36 +0000 (11:31 -0700)
committerPaolo Abeni <pabeni@redhat.com>
Thu, 24 Oct 2024 14:03:40 +0000 (16:03 +0200)
getaddr_dumpit() already relies on RCU and does not need RTNL.

Let's use READ_ONCE() for ifindex and register getaddr_dumpit()
with RTNL_FLAG_DUMP_UNLOCKED.

While at it, the retval of getaddr_dumpit() is changed to combine
NLMSG_DONE and save recvmsg() as done in 58a4ff5d77b1 ("phonet: no
longer hold RTNL in route_dumpit()").

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
net/phonet/pn_netlink.c

index 5996141e258fb7edd620be0eb12ee2970c73e88d..14928fa04675e96ca59a27281c8ab8e50364b9a9 100644 (file)
@@ -127,14 +127,17 @@ nla_put_failure:
 
 static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
 {
+       int addr_idx = 0, addr_start_idx = cb->args[1];
+       int dev_idx = 0, dev_start_idx = cb->args[0];
        struct phonet_device_list *pndevs;
        struct phonet_device *pnd;
-       int dev_idx = 0, dev_start_idx = cb->args[0];
-       int addr_idx = 0, addr_start_idx = cb->args[1];
+       int err = 0;
 
        pndevs = phonet_device_list(sock_net(skb->sk));
+
        rcu_read_lock();
        list_for_each_entry_rcu(pnd, &pndevs->list, list) {
+               DECLARE_BITMAP(addrs, 64);
                u8 addr;
 
                if (dev_idx > dev_start_idx)
@@ -143,23 +146,26 @@ static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
                        continue;
 
                addr_idx = 0;
-               for_each_set_bit(addr, pnd->addrs, 64) {
+               memcpy(addrs, pnd->addrs, sizeof(pnd->addrs));
+
+               for_each_set_bit(addr, addrs, 64) {
                        if (addr_idx++ < addr_start_idx)
                                continue;
 
-                       if (fill_addr(skb, pnd->netdev->ifindex, addr << 2,
-                                        NETLINK_CB(cb->skb).portid,
-                                       cb->nlh->nlmsg_seq, RTM_NEWADDR) < 0)
+                       err = fill_addr(skb, READ_ONCE(pnd->netdev->ifindex),
+                                       addr << 2, NETLINK_CB(cb->skb).portid,
+                                       cb->nlh->nlmsg_seq, RTM_NEWADDR);
+                       if (err < 0)
                                goto out;
                }
        }
-
 out:
        rcu_read_unlock();
+
        cb->args[0] = dev_idx;
        cb->args[1] = addr_idx;
 
-       return skb->len;
+       return err;
 }
 
 /* Routes handling */
@@ -298,7 +304,7 @@ static const struct rtnl_msg_handler phonet_rtnl_msg_handlers[] __initdata_or_mo
        {.owner = THIS_MODULE, .protocol = PF_PHONET, .msgtype = RTM_DELADDR,
         .doit = addr_doit, .flags = RTNL_FLAG_DOIT_UNLOCKED},
        {.owner = THIS_MODULE, .protocol = PF_PHONET, .msgtype = RTM_GETADDR,
-        .dumpit = getaddr_dumpit},
+        .dumpit = getaddr_dumpit, .flags = RTNL_FLAG_DUMP_UNLOCKED},
        {.owner = THIS_MODULE, .protocol = PF_PHONET, .msgtype = RTM_NEWROUTE,
         .doit = route_doit},
        {.owner = THIS_MODULE, .protocol = PF_PHONET, .msgtype = RTM_DELROUTE,