Commit b45d37740cfb for kernel
commit b45d37740cfb4bdfccef3fbd9fd970fd3224438f
Author: Jhonata Poma-Hansen <jhonata.poma@gmail.com>
Date: Tue Oct 27 15:04:01 2026 +0100
netlink: check sk_rcvbuf before charging the dump skb
Since commit ae8f160e7eb2 ("netlink: Fix wraparounds of
sk->sk_rmem_alloc."), netlink_dump() charges the dump skb first and
queues it only if sk_rmem_alloc is still below sk_rcvbuf. Commit
a215b5723922 ("netlink: make sure we allow at least one dump skb")
added an exception for an empty socket.
A dump that starts while something else is still charged to a socket
with a small receive buffer fails with ENOBUFS and stays running.
Every recvmsg() retries it, fails again and sets sk_err, so a reader
that peeks before reading, as libnl does, gets ENOBUFS on the read
after each peek, never consumes the message at the head of the queue
and spins forever.
I hit this with "iw dev wlan0 scan" hanging at 100% CPU on an arm64
board with a 6.6 based kernel (iw 5.19 sets SO_RCVBUF to 8KiB). A
kprobe trace showed the scan dump starting while the NEW_SCAN_RESULTS
notification iw had just read was still charged to its socket,
because iw had preempted the sender before netlink_broadcast()
returned.
Check the limit before charging, as before ae8f160e7eb2, which also
covers the empty socket. netlink_recvmsg() continues a dump only at
or below half of sk_rcvbuf, so the skb is then always queued, and a
dump goes over the limit by at most one skb. Refuse a skb that would
take sk_rmem_alloc past INT_MAX, so the wraparound stays fixed.
Reproduced on net in a KVM guest with a userspace reproducer and the
selftest in the next patch; both pass with this fix.
Fixes: ae8f160e7eb2 ("netlink: Fix wraparounds of sk->sk_rmem_alloc.")
Signed-off-by: Jhonata Poma-Hansen <jhonata.poma@gmail.com>
Reviewed-by: Eric Dumazet <edumazet@kernel.org>
Link: https://patch.msgid.link/20261027-netlink-dump-livelock-v2-1-c4bb05352a33@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index fec2879c497d..1281c42a3456 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -2322,9 +2322,13 @@ static int netlink_dump(struct sock *sk, bool lock_taken)
if (!skb)
goto errout_skb;
+ /* Check the limit before charging the skb: netlink_recvmsg() continues
+ * the dump at or below half of sk_rcvbuf, and the skb must be queued
+ * then. Keep sk_rmem_alloc at or below INT_MAX.
+ */
rcvbuf = READ_ONCE(sk->sk_rcvbuf);
rmem = atomic_add_return(skb->truesize, &sk->sk_rmem_alloc);
- if (rmem != skb->truesize && rmem >= rcvbuf) {
+ if (rmem - skb->truesize >= rcvbuf || rmem > INT_MAX) {
atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
goto errout_skb;
}