diff options
| -rw-r--r-- | net/netlink/af_netlink.c | 6 |
1 files changed, 5 insertions, 1 deletions
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; } |
