Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d99927f4 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller
Browse files

net: Fix sock_wfree() race



Commit 2b85a34e
(net: No more expensive sock_hold()/sock_put() on each tx)
opens a window in sock_wfree() where another cpu
might free the socket we are working on.

A fix is to call sk->sk_write_space(sk) while still
holding a reference on sk.

Reported-by: default avatarJike Song <albcamus@gmail.com>
Signed-off-by: default avatarEric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b7058842
Loading
Loading
Loading
Loading
+12 −7
Original line number Diff line number Diff line
@@ -1228,17 +1228,22 @@ void __init sk_init(void)
void sock_wfree(struct sk_buff *skb)
{
	struct sock *sk = skb->sk;
	int res;
	unsigned int len = skb->truesize;

	/* In case it might be waiting for more memory. */
	res = atomic_sub_return(skb->truesize, &sk->sk_wmem_alloc);
	if (!sock_flag(sk, SOCK_USE_WRITE_QUEUE))
	if (!sock_flag(sk, SOCK_USE_WRITE_QUEUE)) {
		/*
		 * Keep a reference on sk_wmem_alloc, this will be released
		 * after sk_write_space() call
		 */
		atomic_sub(len - 1, &sk->sk_wmem_alloc);
		sk->sk_write_space(sk);
		len = 1;
	}
	/*
	 * if sk_wmem_alloc reached 0, we are last user and should
	 * free this sock, as sk_free() call could not do it.
	 * if sk_wmem_alloc reaches 0, we must finish what sk_free()
	 * could not do because of in-flight packets
	 */
	if (res == 0)
	if (atomic_sub_and_test(len, &sk->sk_wmem_alloc))
		__sk_free(sk);
}
EXPORT_SYMBOL(sock_wfree);