Message ID | 26038a28c21fea5d04d4bd4744c5686d3f2e5504.1591784177.git.sd@queasysnail.net |
---|---|
State | Accepted |
Delegated to: | BPF Maintainers |
Headers | show |
Series | [bpf] bpf: tcp: recv() should return 0 when the peer socket is closed | expand |
On Wed, 10 Jun 2020 12:19:43 +0200 Sabrina Dubroca <sd@queasysnail.net> wrote: > If the peer is closed, we will never get more data, so > tcp_bpf_wait_data will get stuck forever. In case we passed > MSG_DONTWAIT to recv(), we get EAGAIN but we should actually get > 0. > > From man 2 recv: > > RETURN VALUE > > When a stream socket peer has performed an orderly shutdown, the > return value will be 0 (the traditional "end-of-file" return). > > This patch makes tcp_bpf_wait_data always return 1 when the peer > socket has been shutdown. Either we have data available, and it would > have returned 1 anyway, or there isn't, in which case we'll call > tcp_recvmsg which does the right thing in this situation. > > Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface") > Signed-off-by: Sabrina Dubroca <sd@queasysnail.net> > --- > net/ipv4/tcp_bpf.c | 3 +++ > 1 file changed, 3 insertions(+) > > diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c > index 2b915aafda42..7aa68f4aae6c 100644 > --- a/net/ipv4/tcp_bpf.c > +++ b/net/ipv4/tcp_bpf.c > @@ -245,6 +245,9 @@ static int tcp_bpf_wait_data(struct sock *sk, struct sk_psock *psock, > DEFINE_WAIT_FUNC(wait, woken_wake_function); > int ret = 0; > > + if (sk->sk_shutdown & RCV_SHUTDOWN) > + return 1; > + > if (!timeo) > return ret; > Acked-by: Jakub Sitnicki <jakub@cloudflare.com>
On Fri, Jun 12, 2020 at 3:18 AM Jakub Sitnicki <jakub@cloudflare.com> wrote: > > On Wed, 10 Jun 2020 12:19:43 +0200 > Sabrina Dubroca <sd@queasysnail.net> wrote: > > > If the peer is closed, we will never get more data, so > > tcp_bpf_wait_data will get stuck forever. In case we passed > > MSG_DONTWAIT to recv(), we get EAGAIN but we should actually get > > 0. > > > > From man 2 recv: > > > > RETURN VALUE > > > > When a stream socket peer has performed an orderly shutdown, the > > return value will be 0 (the traditional "end-of-file" return). > > > > This patch makes tcp_bpf_wait_data always return 1 when the peer > > socket has been shutdown. Either we have data available, and it would > > have returned 1 anyway, or there isn't, in which case we'll call > > tcp_recvmsg which does the right thing in this situation. > > > > Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface") > > Signed-off-by: Sabrina Dubroca <sd@queasysnail.net> > > --- > > net/ipv4/tcp_bpf.c | 3 +++ > > 1 file changed, 3 insertions(+) > > > > diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c > > index 2b915aafda42..7aa68f4aae6c 100644 > > --- a/net/ipv4/tcp_bpf.c > > +++ b/net/ipv4/tcp_bpf.c > > @@ -245,6 +245,9 @@ static int tcp_bpf_wait_data(struct sock *sk, struct sk_psock *psock, > > DEFINE_WAIT_FUNC(wait, woken_wake_function); > > int ret = 0; > > > > + if (sk->sk_shutdown & RCV_SHUTDOWN) > > + return 1; > > + > > if (!timeo) > > return ret; > > > > Acked-by: Jakub Sitnicki <jakub@cloudflare.com> Applied. Thanks
Alexei Starovoitov wrote: > On Fri, Jun 12, 2020 at 3:18 AM Jakub Sitnicki <jakub@cloudflare.com> wrote: > > > > On Wed, 10 Jun 2020 12:19:43 +0200 > > Sabrina Dubroca <sd@queasysnail.net> wrote: > > > > > If the peer is closed, we will never get more data, so > > > tcp_bpf_wait_data will get stuck forever. In case we passed > > > MSG_DONTWAIT to recv(), we get EAGAIN but we should actually get > > > 0. > > > > > > From man 2 recv: > > > > > > RETURN VALUE > > > > > > When a stream socket peer has performed an orderly shutdown, the > > > return value will be 0 (the traditional "end-of-file" return). > > > > > > This patch makes tcp_bpf_wait_data always return 1 when the peer > > > socket has been shutdown. Either we have data available, and it would > > > have returned 1 anyway, or there isn't, in which case we'll call > > > tcp_recvmsg which does the right thing in this situation. > > > > > > Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface") > > > Signed-off-by: Sabrina Dubroca <sd@queasysnail.net> > > > --- > > > net/ipv4/tcp_bpf.c | 3 +++ > > > 1 file changed, 3 insertions(+) > > > > > > diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c > > > index 2b915aafda42..7aa68f4aae6c 100644 > > > --- a/net/ipv4/tcp_bpf.c > > > +++ b/net/ipv4/tcp_bpf.c > > > @@ -245,6 +245,9 @@ static int tcp_bpf_wait_data(struct sock *sk, struct sk_psock *psock, > > > DEFINE_WAIT_FUNC(wait, woken_wake_function); > > > int ret = 0; > > > > > > + if (sk->sk_shutdown & RCV_SHUTDOWN) > > > + return 1; > > > + > > > if (!timeo) > > > return ret; > > > > > > > Acked-by: Jakub Sitnicki <jakub@cloudflare.com> > > Applied. Thanks Thanks for the patch. LGTM, I guess we should also break the copy loop in __tcp_bpf_recvmsg if RCV_SHUTDOWN is set it looks like TCP stack does. I'll send a follow up thanks!
diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c index 2b915aafda42..7aa68f4aae6c 100644 --- a/net/ipv4/tcp_bpf.c +++ b/net/ipv4/tcp_bpf.c @@ -245,6 +245,9 @@ static int tcp_bpf_wait_data(struct sock *sk, struct sk_psock *psock, DEFINE_WAIT_FUNC(wait, woken_wake_function); int ret = 0; + if (sk->sk_shutdown & RCV_SHUTDOWN) + return 1; + if (!timeo) return ret;
If the peer is closed, we will never get more data, so tcp_bpf_wait_data will get stuck forever. In case we passed MSG_DONTWAIT to recv(), we get EAGAIN but we should actually get 0. From man 2 recv: RETURN VALUE When a stream socket peer has performed an orderly shutdown, the return value will be 0 (the traditional "end-of-file" return). This patch makes tcp_bpf_wait_data always return 1 when the peer socket has been shutdown. Either we have data available, and it would have returned 1 anyway, or there isn't, in which case we'll call tcp_recvmsg which does the right thing in this situation. Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface") Signed-off-by: Sabrina Dubroca <sd@queasysnail.net> --- net/ipv4/tcp_bpf.c | 3 +++ 1 file changed, 3 insertions(+)