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

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

netlink: fix races after skb queueing



As soon as an skb is queued into socket receive_queue, another thread
can consume it, so we are not allowed to reference skb anymore, or risk
use after free.

Signed-off-by: default avatarEric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e34fac1c
Loading
Loading
Loading
Loading
+13 −11
Original line number Diff line number Diff line
@@ -829,12 +829,19 @@ int netlink_attachskb(struct sock *sk, struct sk_buff *skb,
	return 0;
}

int netlink_sendskb(struct sock *sk, struct sk_buff *skb)
static int __netlink_sendskb(struct sock *sk, struct sk_buff *skb)
{
	int len = skb->len;

	skb_queue_tail(&sk->sk_receive_queue, skb);
	sk->sk_data_ready(sk, len);
	return len;
}

int netlink_sendskb(struct sock *sk, struct sk_buff *skb)
{
	int len = __netlink_sendskb(sk, skb);

	sock_put(sk);
	return len;
}
@@ -957,8 +964,7 @@ static int netlink_broadcast_deliver(struct sock *sk, struct sk_buff *skb)
	if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf &&
	    !test_bit(0, &nlk->state)) {
		skb_set_owner_r(skb, sk);
		skb_queue_tail(&sk->sk_receive_queue, skb);
		sk->sk_data_ready(sk, skb->len);
		__netlink_sendskb(sk, skb);
		return atomic_read(&sk->sk_rmem_alloc) > (sk->sk_rcvbuf >> 1);
	}
	return -1;
@@ -1698,10 +1704,8 @@ static int netlink_dump(struct sock *sk)

		if (sk_filter(sk, skb))
			kfree_skb(skb);
		else {
			skb_queue_tail(&sk->sk_receive_queue, skb);
			sk->sk_data_ready(sk, skb->len);
		}
		else
			__netlink_sendskb(sk, skb);
		return 0;
	}

@@ -1715,10 +1719,8 @@ static int netlink_dump(struct sock *sk)

	if (sk_filter(sk, skb))
		kfree_skb(skb);
	else {
		skb_queue_tail(&sk->sk_receive_queue, skb);
		sk->sk_data_ready(sk, skb->len);
	}
	else
		__netlink_sendskb(sk, skb);

	if (cb->done)
		cb->done(cb);