mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	bpf/sockmap: Read psock ingress_msg before sk_receive_queue
Right now in tcp_bpf_recvmsg, sock read data first from sk_receive_queue
if not empty than psock->ingress_msg otherwise. If a FIN packet arrives
and there's also some data in psock->ingress_msg, the data in
psock->ingress_msg will be purged. It is always happen when request to a
HTTP1.0 server like python SimpleHTTPServer since the server send FIN
packet after data is sent out.
Fixes: 604326b41a ("bpf, sockmap: convert to generic sk_msg interface")
Reported-by: Arika Chen <eaglesora@gmail.com>
Suggested-by: Arika Chen <eaglesora@gmail.com>
Signed-off-by: Lingpeng Chen <forrest0579@gmail.com>
Signed-off-by: John Fastabend <john.fastabend@gmail.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Song Liu <songliubraving@fb.com>
Link: https://lore.kernel.org/bpf/20200109014833.18951-1-forrest0579@gmail.com
			
			
This commit is contained in:
		
							parent
							
								
									da29f2d84b
								
							
						
					
					
						commit
						e7a5f1f1cd
					
				
					 1 changed files with 6 additions and 6 deletions
				
			
		| 
						 | 
					@ -121,14 +121,14 @@ int tcp_bpf_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
 | 
				
			||||||
	struct sk_psock *psock;
 | 
						struct sk_psock *psock;
 | 
				
			||||||
	int copied, ret;
 | 
						int copied, ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (unlikely(flags & MSG_ERRQUEUE))
 | 
					 | 
				
			||||||
		return inet_recv_error(sk, msg, len, addr_len);
 | 
					 | 
				
			||||||
	if (!skb_queue_empty(&sk->sk_receive_queue))
 | 
					 | 
				
			||||||
		return tcp_recvmsg(sk, msg, len, nonblock, flags, addr_len);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	psock = sk_psock_get(sk);
 | 
						psock = sk_psock_get(sk);
 | 
				
			||||||
	if (unlikely(!psock))
 | 
						if (unlikely(!psock))
 | 
				
			||||||
		return tcp_recvmsg(sk, msg, len, nonblock, flags, addr_len);
 | 
							return tcp_recvmsg(sk, msg, len, nonblock, flags, addr_len);
 | 
				
			||||||
 | 
						if (unlikely(flags & MSG_ERRQUEUE))
 | 
				
			||||||
 | 
							return inet_recv_error(sk, msg, len, addr_len);
 | 
				
			||||||
 | 
						if (!skb_queue_empty(&sk->sk_receive_queue) &&
 | 
				
			||||||
 | 
						    sk_psock_queue_empty(psock))
 | 
				
			||||||
 | 
							return tcp_recvmsg(sk, msg, len, nonblock, flags, addr_len);
 | 
				
			||||||
	lock_sock(sk);
 | 
						lock_sock(sk);
 | 
				
			||||||
msg_bytes_ready:
 | 
					msg_bytes_ready:
 | 
				
			||||||
	copied = __tcp_bpf_recvmsg(sk, psock, msg, len, flags);
 | 
						copied = __tcp_bpf_recvmsg(sk, psock, msg, len, flags);
 | 
				
			||||||
| 
						 | 
					@ -139,7 +139,7 @@ int tcp_bpf_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
 | 
				
			||||||
		timeo = sock_rcvtimeo(sk, nonblock);
 | 
							timeo = sock_rcvtimeo(sk, nonblock);
 | 
				
			||||||
		data = tcp_bpf_wait_data(sk, psock, flags, timeo, &err);
 | 
							data = tcp_bpf_wait_data(sk, psock, flags, timeo, &err);
 | 
				
			||||||
		if (data) {
 | 
							if (data) {
 | 
				
			||||||
			if (skb_queue_empty(&sk->sk_receive_queue))
 | 
								if (!sk_psock_queue_empty(psock))
 | 
				
			||||||
				goto msg_bytes_ready;
 | 
									goto msg_bytes_ready;
 | 
				
			||||||
			release_sock(sk);
 | 
								release_sock(sk);
 | 
				
			||||||
			sk_psock_put(sk, psock);
 | 
								sk_psock_put(sk, psock);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue