BPF List
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Ömer Mete Kaya" <omermetekaya0@gmail.com>
Cc: bpf@vger.kernel.org
Subject: Re: [PATCH] bpf, sockmap: fix cork data loss after redirect
Date: Sat, 14 Nov 2026 12:13:12 +0000	[thread overview]
Message-ID: <sashiko-outbox-214497@kernel.org> (raw)
In-Reply-To: <20261114115222.180345-1-omermetekaya0@gmail.com>

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

      reply	other threads:[~2026-11-14 12:13 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-14 11:46 [PATCH] bpf, sockmap: fix cork data loss after redirect Ömer Mete Kaya
2026-11-14 12:13 ` sashiko-bot [this message]

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=sashiko-outbox-214497@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=omermetekaya0@gmail.com \
    --cc=sashiko-reviews@lists.linux.dev \
    /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