diff options
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
| -rw-r--r-- | net/ipv6/tcp_ipv6.c | 12 | 
1 files changed, 9 insertions, 3 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 983ad7a75102..77d723bbe050 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1436,6 +1436,7 @@ static void tcp_v6_fill_cb(struct sk_buff *skb, const struct ipv6hdr *hdr,  static int tcp_v6_rcv(struct sk_buff *skb)  { +	struct sk_buff *skb_to_free;  	int sdif = inet6_sdif(skb);  	const struct tcphdr *th;  	const struct ipv6hdr *hdr; @@ -1562,12 +1563,17 @@ process:  	tcp_segs_in(tcp_sk(sk), skb);  	ret = 0;  	if (!sock_owned_by_user(sk)) { +		skb_to_free = sk->sk_rx_skb_cache; +		sk->sk_rx_skb_cache = NULL;  		ret = tcp_v6_do_rcv(sk, skb); -	} else if (tcp_add_backlog(sk, skb)) { -		goto discard_and_relse; +	} else { +		if (tcp_add_backlog(sk, skb)) +			goto discard_and_relse; +		skb_to_free = NULL;  	}  	bh_unlock_sock(sk); - +	if (skb_to_free) +		__kfree_skb(skb_to_free);  put_and_return:  	if (refcounted)  		sock_put(sk);  | 
