Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

phonet: Don't hold RTNL for getaddr_dumpit().

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>

authored by

Kuniyuki Iwashima and committed by
Paolo Abeni
b7d2fc9a 8786e98d

+15 -9
+15 -9
net/phonet/pn_netlink.c
··· 127 127 128 128 static int getaddr_dumpit(struct sk_buff *skb, struct netlink_callback *cb) 129 129 { 130 + int addr_idx = 0, addr_start_idx = cb->args[1]; 131 + int dev_idx = 0, dev_start_idx = cb->args[0]; 130 132 struct phonet_device_list *pndevs; 131 133 struct phonet_device *pnd; 132 - int dev_idx = 0, dev_start_idx = cb->args[0]; 133 - int addr_idx = 0, addr_start_idx = cb->args[1]; 134 + int err = 0; 134 135 135 136 pndevs = phonet_device_list(sock_net(skb->sk)); 137 + 136 138 rcu_read_lock(); 137 139 list_for_each_entry_rcu(pnd, &pndevs->list, list) { 140 + DECLARE_BITMAP(addrs, 64); 138 141 u8 addr; 139 142 140 143 if (dev_idx > dev_start_idx) ··· 146 143 continue; 147 144 148 145 addr_idx = 0; 149 - for_each_set_bit(addr, pnd->addrs, 64) { 146 + memcpy(addrs, pnd->addrs, sizeof(pnd->addrs)); 147 + 148 + for_each_set_bit(addr, addrs, 64) { 150 149 if (addr_idx++ < addr_start_idx) 151 150 continue; 152 151 153 - if (fill_addr(skb, pnd->netdev->ifindex, addr << 2, 154 - NETLINK_CB(cb->skb).portid, 155 - cb->nlh->nlmsg_seq, RTM_NEWADDR) < 0) 152 + err = fill_addr(skb, READ_ONCE(pnd->netdev->ifindex), 153 + addr << 2, NETLINK_CB(cb->skb).portid, 154 + cb->nlh->nlmsg_seq, RTM_NEWADDR); 155 + if (err < 0) 156 156 goto out; 157 157 } 158 158 } 159 - 160 159 out: 161 160 rcu_read_unlock(); 161 + 162 162 cb->args[0] = dev_idx; 163 163 cb->args[1] = addr_idx; 164 164 165 - return skb->len; 165 + return err; 166 166 } 167 167 168 168 /* Routes handling */ ··· 304 298 {.owner = THIS_MODULE, .protocol = PF_PHONET, .msgtype = RTM_DELADDR, 305 299 .doit = addr_doit, .flags = RTNL_FLAG_DOIT_UNLOCKED}, 306 300 {.owner = THIS_MODULE, .protocol = PF_PHONET, .msgtype = RTM_GETADDR, 307 - .dumpit = getaddr_dumpit}, 301 + .dumpit = getaddr_dumpit, .flags = RTNL_FLAG_DUMP_UNLOCKED}, 308 302 {.owner = THIS_MODULE, .protocol = PF_PHONET, .msgtype = RTM_NEWROUTE, 309 303 .doit = route_doit}, 310 304 {.owner = THIS_MODULE, .protocol = PF_PHONET, .msgtype = RTM_DELROUTE,