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;
 	}