Skip to content

Commit 67ea41d

Browse files
edumazetkuba-moo
authored andcommitted
inet6: expand rcu_read_lock() scope in inet6_dump_addr()
I missed that inet6_dump_addr() is calling in6_dump_addrs() from two points. First one under RTNL protection, and second one under rcu_read_lock(). Since we want to remove RTNL use from inet6_dump_addr() very soon, no longer assume in6_dump_addrs() is protected by RTNL (even if this is still the case). Use rcu_read_lock() earlier to fix this lockdep splat: WARNING: suspicious RCU usage 6.8.0-rc5-syzkaller-01618-gf8cbf6bde4c8 #0 Not tainted net/ipv6/addrconf.c:5317 suspicious rcu_dereference_check() usage! other info that might help us debug this: rcu_scheduler_active = 2, debug_locks = 1 3 locks held by syz-executor.2/8834: #0: ffff88802f554678 (nlk_cb_mutex-ROUTE){+.+.}-{3:3}, at: __netlink_dump_start+0x119/0x780 net/netlink/af_netlink.c:2338 #1: ffffffff8f377a88 (rtnl_mutex){+.+.}-{3:3}, at: netlink_dump+0x676/0xda0 net/netlink/af_netlink.c:2265 #2: ffff88807e5f0580 (&ndev->lock){++--}-{2:2}, at: in6_dump_addrs+0xb8/0x1de0 net/ipv6/addrconf.c:5279 stack backtrace: CPU: 1 PID: 8834 Comm: syz-executor.2 Not tainted 6.8.0-rc5-syzkaller-01618-gf8cbf6bde4c8 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/25/2024 Call Trace: <TASK> __dump_stack lib/dump_stack.c:88 [inline] dump_stack_lvl+0x1e7/0x2e0 lib/dump_stack.c:106 lockdep_rcu_suspicious+0x220/0x340 kernel/locking/lockdep.c:6712 in6_dump_addrs+0x1b47/0x1de0 net/ipv6/addrconf.c:5317 inet6_dump_addr+0x1597/0x1690 net/ipv6/addrconf.c:5428 netlink_dump+0x6a6/0xda0 net/netlink/af_netlink.c:2266 __netlink_dump_start+0x59d/0x780 net/netlink/af_netlink.c:2374 netlink_dump_start include/linux/netlink.h:340 [inline] rtnetlink_rcv_msg+0xcf7/0x10d0 net/core/rtnetlink.c:6555 netlink_rcv_skb+0x1e3/0x430 net/netlink/af_netlink.c:2547 netlink_unicast_kernel net/netlink/af_netlink.c:1335 [inline] netlink_unicast+0x7ea/0x980 net/netlink/af_netlink.c:1361 netlink_sendmsg+0x8e0/0xcb0 net/netlink/af_netlink.c:1902 sock_sendmsg_nosec net/socket.c:730 [inline] __sock_sendmsg+0x221/0x270 net/socket.c:745 ____sys_sendmsg+0x525/0x7d0 net/socket.c:2584 ___sys_sendmsg net/socket.c:2638 [inline] __sys_sendmsg+0x2b0/0x3a0 net/socket.c:2667 Fixes: c371893 ("ipv6: anycast: complete RCU handling of struct ifacaddr6") Reported-by: syzbot <[email protected]> Signed-off-by: Eric Dumazet <[email protected]> Reviewed-by: Jiri Pirko <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 1200097 commit 67ea41d

File tree

1 file changed

+4
-4
lines changed

1 file changed

+4
-4
lines changed

net/ipv6/addrconf.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5300,9 +5300,9 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb,
53005300
fillargs->event = RTM_GETMULTICAST;
53015301

53025302
/* multicast address */
5303-
for (ifmca = rtnl_dereference(idev->mc_list);
5303+
for (ifmca = rcu_dereference(idev->mc_list);
53045304
ifmca;
5305-
ifmca = rtnl_dereference(ifmca->next), ip_idx++) {
5305+
ifmca = rcu_dereference(ifmca->next), ip_idx++) {
53065306
if (ip_idx < s_ip_idx)
53075307
continue;
53085308
err = inet6_fill_ifmcaddr(skb, ifmca, fillargs);
@@ -5410,6 +5410,7 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
54105410
s_idx = idx = cb->args[1];
54115411
s_ip_idx = cb->args[2];
54125412

5413+
rcu_read_lock();
54135414
if (cb->strict_check) {
54145415
err = inet6_valid_dump_ifaddr_req(nlh, &fillargs, &tgt_net,
54155416
skb->sk, cb);
@@ -5434,7 +5435,6 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
54345435
}
54355436
}
54365437

5437-
rcu_read_lock();
54385438
cb->seq = inet6_base_seq(tgt_net);
54395439
for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
54405440
idx = 0;
@@ -5456,10 +5456,10 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
54565456
}
54575457
}
54585458
done:
5459-
rcu_read_unlock();
54605459
cb->args[0] = h;
54615460
cb->args[1] = idx;
54625461
put_tgt_net:
5462+
rcu_read_unlock();
54635463
if (fillargs.netnsid >= 0)
54645464
put_net(tgt_net);
54655465

0 commit comments

Comments
 (0)