From 350f8ab8b835a626768c56ff03305987d18a7d8c Mon Sep 17 00:00:00 2001 From: Lingpeng Chen Date: Fri, 6 Mar 2020 18:38:57 +0800 Subject: [PATCH] bpf/sockmap: Read psock ingress_msg before sk_receive_queue commit e7a5f1f1cd0008e5ad379270a8657e121eedb669 upstream 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: 604326b41a6fb ("bpf, sockmap: convert to generic sk_msg interface") Reported-by: Arika Chen Suggested-by: Arika Chen Signed-off-by: Lingpeng Chen Signed-off-by: John Fastabend Signed-off-by: Daniel Borkmann Acked-by: Song Liu Link: https://lore.kernel.org/bpf/20200109014833.18951-1-forrest0579@gmail.com [tonylu: patched modified to match BIG rework between v4.19 and upstream] Signed-off-by: Tony Lu Acked-by: Dust Li Acked-by: Caspar Zhang --- kernel/bpf/sockmap.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/kernel/bpf/sockmap.c b/kernel/bpf/sockmap.c index 0a0f2ec75370..2b762b283c7c 100644 --- a/kernel/bpf/sockmap.c +++ b/kernel/bpf/sockmap.c @@ -931,11 +931,6 @@ static int bpf_tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, struct smap_psock *psock; int copied = 0; - 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); - rcu_read_lock(); psock = smap_psock_sk(sk); if (unlikely(!psock)) @@ -945,6 +940,12 @@ static int bpf_tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, goto out; rcu_read_unlock(); + if (unlikely(flags & MSG_ERRQUEUE)) + return inet_recv_error(sk, msg, len, addr_len); + if (!skb_queue_empty(&sk->sk_receive_queue) && + list_empty(&psock->ingress)) + return tcp_recvmsg(sk, msg, len, nonblock, flags, addr_len); + lock_sock(sk); bytes_ready: while (copied != len) { @@ -1010,7 +1011,7 @@ static int bpf_tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, data = bpf_wait_data(sk, psock, flags, timeo, &err); if (data) { - if (!skb_queue_empty(&sk->sk_receive_queue)) { + if (list_empty(&psock->ingress)) { release_sock(sk); smap_release_sock(psock, sk); copied = tcp_recvmsg(sk, msg, len, nonblock, flags, addr_len); -- GitLab