diff options
Diffstat (limited to 'net/ipv4/tcp_input.c')
| -rw-r--r-- | net/ipv4/tcp_input.c | 27 | 
1 files changed, 15 insertions, 12 deletions
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 3e07a64ca44e..2fd2bc9e3c64 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -4351,19 +4351,20 @@ static void tcp_ofo_queue(struct sock *sk)  static bool tcp_prune_ofo_queue(struct sock *sk);  static int tcp_prune_queue(struct sock *sk); -static int tcp_try_rmem_schedule(struct sock *sk, unsigned int size) +static int tcp_try_rmem_schedule(struct sock *sk, struct sk_buff *skb, +				 unsigned int size)  {  	if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf || -	    !sk_rmem_schedule(sk, size)) { +	    !sk_rmem_schedule(sk, skb, size)) {  		if (tcp_prune_queue(sk) < 0)  			return -1; -		if (!sk_rmem_schedule(sk, size)) { +		if (!sk_rmem_schedule(sk, skb, size)) {  			if (!tcp_prune_ofo_queue(sk))  				return -1; -			if (!sk_rmem_schedule(sk, size)) +			if (!sk_rmem_schedule(sk, skb, size))  				return -1;  		}  	} @@ -4418,7 +4419,7 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb)  	TCP_ECN_check_ce(tp, skb); -	if (unlikely(tcp_try_rmem_schedule(sk, skb->truesize))) { +	if (unlikely(tcp_try_rmem_schedule(sk, skb, skb->truesize))) {  		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPOFODROP);  		__kfree_skb(skb);  		return; @@ -4552,17 +4553,17 @@ static int __must_check tcp_queue_rcv(struct sock *sk, struct sk_buff *skb, int  int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size)  { -	struct sk_buff *skb; +	struct sk_buff *skb = NULL;  	struct tcphdr *th;  	bool fragstolen; -	if (tcp_try_rmem_schedule(sk, size + sizeof(*th))) -		goto err; -  	skb = alloc_skb(size + sizeof(*th), sk->sk_allocation);  	if (!skb)  		goto err; +	if (tcp_try_rmem_schedule(sk, skb, size + sizeof(*th))) +		goto err_free; +  	th = (struct tcphdr *)skb_put(skb, sizeof(*th));  	skb_reset_transport_header(skb);  	memset(th, 0, sizeof(*th)); @@ -4633,7 +4634,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)  		if (eaten <= 0) {  queue_and_out:  			if (eaten < 0 && -			    tcp_try_rmem_schedule(sk, skb->truesize)) +			    tcp_try_rmem_schedule(sk, skb, skb->truesize))  				goto drop;  			eaten = tcp_queue_rcv(sk, skb, 0, &fragstolen); @@ -5475,7 +5476,9 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,  			if (tp->copied_seq == tp->rcv_nxt &&  			    len - tcp_header_len <= tp->ucopy.len) {  #ifdef CONFIG_NET_DMA -				if (tcp_dma_try_early_copy(sk, skb, tcp_header_len)) { +				if (tp->ucopy.task == current && +				    sock_owned_by_user(sk) && +				    tcp_dma_try_early_copy(sk, skb, tcp_header_len)) {  					copied_early = 1;  					eaten = 1;  				} @@ -5602,7 +5605,7 @@ void tcp_finish_connect(struct sock *sk, struct sk_buff *skb)  	tcp_set_state(sk, TCP_ESTABLISHED);  	if (skb != NULL) { -		sk->sk_rx_dst = dst_clone(skb_dst(skb)); +		inet_sk_rx_dst_set(sk, skb);  		security_inet_conn_established(sk, skb);  	}  |