From: Jiayuan Chen <jiayuan.chen@linux.dev>
To: bpf@vger.kernel.org
Subject: Re: [PATCH bpf 1/2] bpf, sockmap: Stop reporting EPIPE on zero-length skb redirect
Date: Mon, 26 Oct 2026 09:59:00 +0800 [thread overview]
Message-ID: <23181ba7-e4ef-4475-92ee-366e0ca2dcf0@linux.dev> (raw)
In-Reply-To: <20261025-sockmap-bare-fin-v1-1-bb8feae7c4a7@eliskeggs.com>
On 10/26/26 7:41 AM, Eli Skeggs via B4 Relay wrote:
> From: Eli Skeggs <kernel@eliskeggs.com>
>
> A FIN can arrive on a packet with no data. In that case, tcp_read_skb()
> produces an empty skb, and the attached BPF stream_verdict program may
> choose to redirect the skb to another socket. Further data redirected to
> that socket from any socket gets dropped, and the target socket starts
> reporting EPIPE. A userspace application may see that EPIPE and decide
> the socket is no longer usable. For a BPF-based proxy, this can break a
> bidirectional stream, truncating the response instead of leaving the
> socket half-open.
>
> Prior to the introduction of tcp_read_skb(), tcp_read_sock() never
> passed a zero-length skb to its actor, sk_psock_verdict_recv(). When a
> redirected skb landed in sk_psock_backlog(), it was always non-empty.
> tcp_read_skb() deviated from the historical behavior by passing any
> zero-length skbs to recv_actor(), exposing this latent bug by adding
> zero-length skbs to a queue that hadn't previously received them. When
> sk_psock_backlog() encounters a zero-length skb, it interprets ret == 0
> as a hard error, reports EPIPE, and clears the transmit flag.
>
> Treat a return of 0 as success when there is no data to send, while
> continuing to fail on a 0 return with residual bytes. The loop exits
> without incident on an empty skb, and the skb gets cleaned up as usual.
> On an ingress redirect, the empty message is still queued as before, but
> the target socket no longer reports EPIPE.
The target can't receive anything after that though. The empty msg sits
at the head of psock->ingress_msg and nothing ever dequeues it:
__sk_msg_recvmsg()
sge->length == 0 -> copy == 0 -> copied = -EFAULT; goto out;
The goto skips sk_psock_dequeue_msg() at the end of the loop. Then
tcp_bpf_recvmsg_parser() sees -EFAULT, is_next_msg_fin() finds the FIN
flag on the redirected skb and returns 0. Every later recv() hits the
same msg and returns 0 again, while data queued behind it is never read.
Only sk_psock_purge_ingress_msg() on psock teardown frees it.
So the user gets EOF on a socket whose peer never closed, and everything
redirected to it after the FIN is lost. Without a verdict prog on the
target it is worse, tcp_bpf_recvmsg() returns -EFAULT forever.
Since this patch is already about the zero-length skb, can you handle
the ingress side too? E.g. in sk_psock_skb_ingress(), don't queue an
empty msg when len is 0 and the skb was redirected (skb->sk != sk). The
self PASS case must keep its empty msg since is_next_msg_fin() depends
on it.
> Fixes: 965b57b469a5 ("net: Introduce a new proto_ops ->read_skb()")
> Signed-off-by: Eli Skeggs <kernel@eliskeggs.com>
> ---
> net/core/skmsg.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/net/core/skmsg.c b/net/core/skmsg.c
> index df385a5a961e..f9b2e3486cfb 100644
> --- a/net/core/skmsg.c
> +++ b/net/core/skmsg.c
> @@ -716,7 +716,7 @@ static void sk_psock_backlog(struct work_struct *work)
> if (!sock_flag(psock->sk, SOCK_DEAD))
> ret = sk_psock_handle_skb(psock, skb, off,
> len, ingress);
> - if (ret <= 0) {
> + if (ret < 0 || (!ret && len)) {
> if (ret == -EAGAIN) {
> sk_psock_skb_state(psock, state, len, off);
> /* Restore redir info we cleared before */
>
next prev parent reply other threads:[~2026-10-26 1:59 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-25 23:41 [PATCH bpf 0/2] bpf, sockmap: Fix dropped data and EPIPE on empty skb redirect Eli Skeggs via B4 Relay
2026-10-25 23:41 ` [PATCH bpf 1/2] bpf, sockmap: Stop reporting EPIPE on zero-length " Eli Skeggs via B4 Relay
2026-10-26 1:51 ` Alexei Starovoitov
2026-10-26 2:25 ` Eli Skeggs
2026-10-26 1:59 ` Jiayuan Chen [this message]
2026-10-26 3:17 ` Eli Skeggs
2026-10-26 6:32 ` Jiayuan Chen
2026-10-25 23:41 ` [PATCH bpf 2/2] selftests/bpf: Redirect a bare FIN to another socket's egress Eli Skeggs via B4 Relay
2026-10-25 23:55 ` sashiko-bot
2026-10-26 0:28 ` Eli Skeggs
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=23181ba7-e4ef-4475-92ee-366e0ca2dcf0@linux.dev \
--to=jiayuan.chen@linux.dev \
--cc=bpf@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox