Skip to content

Commit e20f733

Browse files
jrfastabborkmann
authored andcommitted
bpf: sockmap, sk_wait_event needed to handle blocking cases
In the recvmsg handler we need to add a wait event to support the blocking use cases. Without this we return zero and may confuse user applications. In the wait event any data received on the sk either via sk_receive_queue or the psock ingress list will wake up the sock. Fixes: fa24669 ("bpf: sockmap, BPF_F_INGRESS flag for BPF_SK_SKB_STREAM_VERDICT") Signed-off-by: John Fastabend <[email protected]> Signed-off-by: Daniel Borkmann <[email protected]>
1 parent ba6b8de commit e20f733

File tree

1 file changed

+44
-0
lines changed

1 file changed

+44
-0
lines changed

kernel/bpf/sockmap.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include <net/tcp.h>
4444
#include <linux/ptr_ring.h>
4545
#include <net/inet_common.h>
46+
#include <linux/sched/signal.h>
4647

4748
#define SOCK_CREATE_FLAG_MASK \
4849
(BPF_F_NUMA_NODE | BPF_F_RDONLY | BPF_F_WRONLY)
@@ -732,6 +733,26 @@ static int bpf_exec_tx_verdict(struct smap_psock *psock,
732733
return err;
733734
}
734735

736+
static int bpf_wait_data(struct sock *sk,
737+
struct smap_psock *psk, int flags,
738+
long timeo, int *err)
739+
{
740+
int rc;
741+
742+
DEFINE_WAIT_FUNC(wait, woken_wake_function);
743+
744+
add_wait_queue(sk_sleep(sk), &wait);
745+
sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
746+
rc = sk_wait_event(sk, &timeo,
747+
!list_empty(&psk->ingress) ||
748+
!skb_queue_empty(&sk->sk_receive_queue),
749+
&wait);
750+
sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
751+
remove_wait_queue(sk_sleep(sk), &wait);
752+
753+
return rc;
754+
}
755+
735756
static int bpf_tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
736757
int nonblock, int flags, int *addr_len)
737758
{
@@ -755,6 +776,7 @@ static int bpf_tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
755776
return tcp_recvmsg(sk, msg, len, nonblock, flags, addr_len);
756777

757778
lock_sock(sk);
779+
bytes_ready:
758780
while (copied != len) {
759781
struct scatterlist *sg;
760782
struct sk_msg_buff *md;
@@ -809,6 +831,28 @@ static int bpf_tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
809831
}
810832
}
811833

834+
if (!copied) {
835+
long timeo;
836+
int data;
837+
int err = 0;
838+
839+
timeo = sock_rcvtimeo(sk, nonblock);
840+
data = bpf_wait_data(sk, psock, flags, timeo, &err);
841+
842+
if (data) {
843+
if (!skb_queue_empty(&sk->sk_receive_queue)) {
844+
release_sock(sk);
845+
smap_release_sock(psock, sk);
846+
copied = tcp_recvmsg(sk, msg, len, nonblock, flags, addr_len);
847+
return copied;
848+
}
849+
goto bytes_ready;
850+
}
851+
852+
if (err)
853+
copied = err;
854+
}
855+
812856
release_sock(sk);
813857
smap_release_sock(psock, sk);
814858
return copied;

0 commit comments

Comments
 (0)