* [PATCH] bpf, sockmap: fix cork data loss after redirect
@ 2026-11-14 11:46 Ömer Mete Kaya
2026-11-14 12:13 ` sashiko-bot
2026-11-14 16:34 ` Alexei Starovoitov
0 siblings, 2 replies; 3+ messages in thread
From: Ömer Mete Kaya @ 2026-11-14 11:46 UTC (permalink / raw)
To: John Fastabend, Jakub Sitnicki, Jiayuan Chen
Cc: Eric Dumazet, Neal Cardwell, Kuniyuki Iwashima, David S . Miller,
Jakub Kicinski, Paolo Abeni, Simon Horman, Daniel Borkmann,
Alexei Starovoitov, netdev, bpf, linux-kernel,
Ömer Mete Kaya
In tcp_bpf_send_verdict(), when a corked message is redirected via
__SK_REDIRECT, the cork cleanup path unconditionally frees the entire
message and sets msg to NULL, even when only a partial send was
performed (tosend < total msg size due to apply_bytes).
This prevents the more_data loop at the end of the function from
processing the remaining bytes, silently dropping them. The check:
if (msg &&
msg->sg.data[msg->sg.start].page_link &&
msg->sg.data[msg->sg.start].length)
goto more_data;
can never trigger because msg is always NULL after the cork path.
Fix this by only freeing the cork message when it is fully consumed
or when the redirect failed. When unsent data remains, keep the
message alive so the more_data loop picks up the rest.
Discovered by Sashiko, not triggered, not runtime tested.
Fixes: 604326b41a6f ("bpf, sockmap: convert to generic sk_msg interface")
Signed-off-by: Ömer Mete Kaya <omermetekaya0@gmail.com>
---
net/ipv4/tcp_bpf.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c
index 8cf63a9e7fed..e6a8184aad6a 100644
--- a/net/ipv4/tcp_bpf.c
+++ b/net/ipv4/tcp_bpf.c
@@ -499,9 +499,13 @@ static int tcp_bpf_send_verdict(struct sock *sk, struct sk_psock *psock,
*copied -= free;
}
if (cork) {
- sk_msg_free(sk, msg);
- kfree(msg);
- msg = NULL;
+ if (ret < 0 ||
+ !msg->sg.data[msg->sg.start].page_link ||
+ !msg->sg.data[msg->sg.start].length) {
+ sk_msg_free(sk, msg);
+ kfree(msg);
+ msg = NULL;
+ }
ret = 0;
}
break;
--
2.56.0
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH] bpf, sockmap: fix cork data loss after redirect
2026-11-14 11:46 [PATCH] bpf, sockmap: fix cork data loss after redirect Ömer Mete Kaya
@ 2026-11-14 12:13 ` sashiko-bot
2026-11-14 16:34 ` Alexei Starovoitov
1 sibling, 0 replies; 3+ messages in thread
From: sashiko-bot @ 2026-11-14 12:13 UTC (permalink / raw)
To: Ömer Mete Kaya; +Cc: bpf
Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [High] bpf, sockmap: leak of detached cork sk_msg in
tcp_bpf_send_verdict()
- [Medium] bpf, sockmap: stale msg->cork_bytes re-corks data in
tcp_bpf_send_verdict()
It also noticed 1 related pre-existing issue this patch does not
introduce:
- [High] bpf: memory leak in tcp_bpf_sendmsg() due to cork allocation
failure [1]
--
commit 5eaba7adf21d338926f608cc6e21ea8e9156e647
Author: Ömer Mete Kaya <omermetekaya0@gmail.com>
bpf, sockmap: fix cork data loss after redirect
This commit keeps a corked sk_msg alive across partial __SK_REDIRECT
sends in tcp_bpf_send_verdict() so that remaining bytes can be processed
by the more_data loop.
> diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c
> index 8cf63a9e7fed1..e6a8184aad6a4 100644
> --- a/net/ipv4/tcp_bpf.c
> +++ b/net/ipv4/tcp_bpf.c
> @@ -499,9 +499,13 @@ static int tcp_bpf_send_verdict(struct sock *sk, struct sk_psock *psock,
> *copied -= free;
> }
> if (cork) {
> - sk_msg_free(sk, msg);
> - kfree(msg);
> - msg = NULL;
> + if (ret < 0 ||
> + !msg->sg.data[msg->sg.start].page_link ||
> + !msg->sg.data[msg->sg.start].length) {
> + sk_msg_free(sk, msg);
> + kfree(msg);
> + msg = NULL;
> + }
> ret = 0;
> }
> break;
[Severity: High]
Does keeping msg alive across goto more_data leak the heap-allocated
struct sk_msg when a subsequent iteration does not take __SK_REDIRECT?
When a corked message enters __SK_REDIRECT, tcp_bpf_send_verdict() sets
cork = true and psock->cork = NULL before releasing the socket lock,
leaving msg as the only pointer to that allocation. If a partial
redirect leaves unsent bytes and jumps to more_data, kfree(msg) is only
called in the __SK_REDIRECT branch. If the next iteration instead hits
the re-cork path (which sees !psock->cork, allocates a new psock->cork
and copies msg into it), __SK_PASS, or __SK_DROP, tcp_bpf_send_verdict()
returns without freeing msg:
net/ipv4/tcp_bpf.c:tcp_bpf_send_verdict() {
if (msg->cork_bytes &&
msg->cork_bytes > msg->sg.size && !enospc) {
psock->cork_bytes = msg->cork_bytes - msg->sg.size;
if (!psock->cork) {
psock->cork = kzalloc_obj(*psock->cork,
GFP_ATOMIC | __GFP_NOWARN);
...
}
memcpy(psock->cork, msg, sizeof(*msg));
return 0;
}
}
[Severity: Medium]
Can a stale msg->cork_bytes value also spuriously re-cork the remaining
bytes on the next more_data iteration?
When tcp_bpf_sendmsg() finishes accumulating psock->cork_bytes, it resets
psock->cork_bytes = 0 and psock->eval = __SK_NONE, but leaves
msg_tx->cork_bytes set to the old threshold on psock->cork:
net/ipv4/tcp_bpf.c:tcp_bpf_sendmsg() {
if (psock->cork_bytes) {
if (size > psock->cork_bytes)
psock->cork_bytes = 0;
else
psock->cork_bytes -= size;
if (psock->cork_bytes && !enospc)
goto out_err;
/* All cork bytes are accounted, rerun the prog. */
psock->eval = __SK_NONE;
psock->cork_bytes = 0;
}
}
Once a partial send reduces msg->sg.size below that original
msg->cork_bytes value and loops back to more_data, the check
msg->cork_bytes > msg->sg.size in tcp_bpf_send_verdict() triggers again
and re-corks the residual data even if the BPF verdict program did not
request corking for the remaining bytes.
[Severity: High]
This problem wasn't introduced by this patch, but setting
psock->cork_bytes before checking whether kzalloc_obj() succeeds in
tcp_bpf_send_verdict() [1] leaves psock->cork_bytes non-zero while
psock->cork is NULL on allocation failure. On a subsequent
tcp_bpf_sendmsg() call, msg_tx falls back to the stack-allocated tmp
message, allocates scatterlist pages via sk_msg_alloc(), and then takes
the psock->cork_bytes check to out_err without calling sk_msg_free() on
tmp, leaking the allocated pages.
[1] https://sashiko.dev/#/bug/linux-2ff2eab9-5d5b-4e91-82d9-b38be18677c9
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261114115222.180345-1-omermetekaya0@gmail.com?part=1
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH] bpf, sockmap: fix cork data loss after redirect
2026-11-14 11:46 [PATCH] bpf, sockmap: fix cork data loss after redirect Ömer Mete Kaya
2026-11-14 12:13 ` sashiko-bot
@ 2026-11-14 16:34 ` Alexei Starovoitov
1 sibling, 0 replies; 3+ messages in thread
From: Alexei Starovoitov @ 2026-11-14 16:34 UTC (permalink / raw)
To: Ömer Mete Kaya, John Fastabend, Jakub Sitnicki, Jiayuan Chen
Cc: Eric Dumazet, Neal Cardwell, Kuniyuki Iwashima, David S . Miller,
Jakub Kicinski, Paolo Abeni, Simon Horman, Daniel Borkmann,
netdev, bpf, linux-kernel
On Sat, Nov 14, 2026 at 03:46 AM Ömer Mete Kaya <omermetekaya0@gmail.com> wrote:
> In tcp_bpf_send_verdict(), when a corked message is redirected via
> __SK_REDIRECT, the cork cleanup path unconditionally frees the entire
> message and sets msg to NULL, even when only a partial send was
> performed (tosend < total msg size due to apply_bytes).
It's fixed already. See bpf tree:
commit 13c41b87e4a7 ("bpf, sockmap: Keep the rest of the cork after a redirect")
tcp_bpf_send_verdict() puts the rest back into psock->cork
and goes to more_data.
pw-bot: cr
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-11-14 16:34 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-14 11:46 [PATCH] bpf, sockmap: fix cork data loss after redirect Ömer Mete Kaya
2026-11-14 12:13 ` sashiko-bot
2026-11-14 16:34 ` Alexei Starovoitov
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.