inet6_rt_notify() can be called under RCU protection only.
This means the route could be changed concurrently
and rt6_fill_node() could return -EMSGSIZE.
Re-size the skb when this happens and retry, removing
one WARN_ON() that syzbot was able to trigger:
WARNING: CPU: 3 PID: 6291 at net/ipv6/route.c:6342 inet6_rt_notify+0x475/0x4b0 net/ipv6/route.c:6342
Modules linked in:
CPU: 3 UID: 0 PID: 6291 Comm: syz.0.77 Not tainted 6.16.0-rc7-syzkaller #0 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
RIP: 0010:inet6_rt_notify+0x475/0x4b0 net/ipv6/route.c:6342
Code: fc ff ff e8 6d 52 ea f7 e9 47 fc ff ff 48 8b 7c 24 08 4c 89 04 24 e8 5a 52 ea f7 4c 8b 04 24 e9 94 fd ff ff e8 9c fe 84 f7 90 <0f> 0b 90 e9 bd fd ff ff e8 6e 52 ea f7 e9 bb fb ff ff 48 89 df e8
RSP: 0018:
ffffc900035cf1d8 EFLAGS:
00010293
RAX:
0000000000000000 RBX:
ffffc900035cf540 RCX:
ffffffff8a36e790
RDX:
ffff88802f7e8000 RSI:
ffffffff8a36e9d4 RDI:
0000000000000005
RBP:
ffff88803c230f00 R08:
0000000000000005 R09:
00000000ffffffa6
R10:
00000000ffffffa6 R11:
0000000000000001 R12:
00000000ffffffa6
R13:
0000000000000900 R14:
ffff888032ea4100 R15:
0000000000000000
FS:
00007fac7b89a6c0(0000) GS:
ffff8880d6a20000(0000) knlGS:
0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0:
0000000080050033
CR2:
00007fac7b899f98 CR3:
0000000034b3f000 CR4:
0000000000352ef0
Call Trace:
<TASK>
ip6_route_mpath_notify+0xde/0x280 net/ipv6/route.c:5356
ip6_route_multipath_add+0x1181/0x1bd0 net/ipv6/route.c:5536
inet6_rtm_newroute+0xe4/0x1a0 net/ipv6/route.c:5647
rtnetlink_rcv_msg+0x95e/0xe90 net/core/rtnetlink.c:6944
netlink_rcv_skb+0x155/0x420 net/netlink/af_netlink.c:2552
netlink_unicast_kernel net/netlink/af_netlink.c:1320 [inline]
netlink_unicast+0x58d/0x850 net/netlink/af_netlink.c:1346
netlink_sendmsg+0x8d1/0xdd0 net/netlink/af_netlink.c:1896
sock_sendmsg_nosec net/socket.c:712 [inline]
__sock_sendmsg net/socket.c:727 [inline]
____sys_sendmsg+0xa95/0xc70 net/socket.c:2566
___sys_sendmsg+0x134/0x1d0 net/socket.c:2620
Fixes: 169fd62799e8 ("ipv6: Get rid of RTNL for SIOCADDRT and RTM_NEWROUTE.")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: syzbot <syzkaller@googlegroups.com>
Link: https://patch.msgid.link/20250725140725.3626540-2-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
void inet6_rt_notify(int event, struct fib6_info *rt, struct nl_info *info,
unsigned int nlm_flags)
{
- struct sk_buff *skb;
struct net *net = info->nl_net;
+ struct sk_buff *skb;
+ size_t sz;
u32 seq;
int err;
seq = info->nlh ? info->nlh->nlmsg_seq : 0;
rcu_read_lock();
-
- skb = nlmsg_new(rt6_nlmsg_size(rt), GFP_ATOMIC);
+ sz = rt6_nlmsg_size(rt);
+retry:
+ skb = nlmsg_new(sz, GFP_ATOMIC);
if (!skb)
goto errout;
err = rt6_fill_node(net, skb, rt, NULL, NULL, NULL, 0,
event, info->portid, seq, nlm_flags);
if (err < 0) {
- /* -EMSGSIZE implies BUG in rt6_nlmsg_size() */
- WARN_ON(err == -EMSGSIZE);
kfree_skb(skb);
+ /* -EMSGSIZE implies needed space grew under us. */
+ if (err == -EMSGSIZE) {
+ sz = max(rt6_nlmsg_size(rt), sz << 1);
+ goto retry;
+ }
goto errout;
}