Skip to content

Commit a215b57

Browse files
committed
netlink: make sure we allow at least one dump skb
Commit under Fixes tightened up the memory accounting for Netlink sockets. Looks like the accounting is too strict for some existing use cases, Marek reported issues with nl80211 / WiFi iw CLI. To reduce number of iterations Netlink dumps try to allocate messages based on the size of the buffer passed to previous recvmsg() calls. If user space uses a larger buffer in recvmsg() than sk_rcvbuf we will allocate an skb we won't be able to queue. Make sure we always allow at least one skb to be queued. Same workaround is already present in netlink_attachskb(). Alternative would be to cap the allocation size to rcvbuf - rmem_alloc but as I said, the workaround is already present in other places. Reported-by: Marek Szyprowski <[email protected]> Link: https://lore.kernel.org/[email protected] Fixes: ae8f160 ("netlink: Fix wraparounds of sk->sk_rmem_alloc.") Tested-by: Marek Szyprowski <[email protected]> Reviewed-by: Kuniyuki Iwashima <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent a3c4a12 commit a215b57

File tree

1 file changed

+3
-2
lines changed

1 file changed

+3
-2
lines changed

net/netlink/af_netlink.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2258,11 +2258,11 @@ static int netlink_dump(struct sock *sk, bool lock_taken)
22582258
struct netlink_ext_ack extack = {};
22592259
struct netlink_callback *cb;
22602260
struct sk_buff *skb = NULL;
2261+
unsigned int rmem, rcvbuf;
22612262
size_t max_recvmsg_len;
22622263
struct module *module;
22632264
int err = -ENOBUFS;
22642265
int alloc_min_size;
2265-
unsigned int rmem;
22662266
int alloc_size;
22672267

22682268
if (!lock_taken)
@@ -2294,8 +2294,9 @@ static int netlink_dump(struct sock *sk, bool lock_taken)
22942294
if (!skb)
22952295
goto errout_skb;
22962296

2297+
rcvbuf = READ_ONCE(sk->sk_rcvbuf);
22972298
rmem = atomic_add_return(skb->truesize, &sk->sk_rmem_alloc);
2298-
if (rmem >= READ_ONCE(sk->sk_rcvbuf)) {
2299+
if (rmem != skb->truesize && rmem >= rcvbuf) {
22992300
atomic_sub(skb->truesize, &sk->sk_rmem_alloc);
23002301
goto errout_skb;
23012302
}

0 commit comments

Comments
 (0)