From: sashiko-bot@kernel.org
To: "Sechang Lim" <rhkrqnwk98@gmail.com>
Cc: bpf@vger.kernel.org
Subject: Re: [PATCH net] tls: fix use-after-free in tls_sw_sendmsg() cork error path
Date: Sat, 06 Jun 2026 21:48:16 +0000 [thread overview]
Message-ID: <20260606214816.EDF991F00893@smtp.kernel.org> (raw)
In-Reply-To: <20260605214802.1647008-1-rhkrqnwk98@gmail.com>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
New issues:
- [High] Rolling back a split record causes iterator corruption and integer underflow.
Pre-existing issues:
- [High] Incomplete Use-After-Free fix leaves dangling `msg_en` pointer in error paths.
- [High] Silent data loss when `-ENOMEM` is returned and memory wait fails.
- [High] Memory leak of remainder record when asynchronous encryption returns `-EINPROGRESS`.
--
commit 660863238de21d269b42799c777dacfb8d63bed1
Author: Sechang Lim <rhkrqnwk98@gmail.com>
tls: fix use-after-free in tls_sw_sendmsg() cork error path
This commit attempts to fix a use-after-free in tls_sw_sendmsg_locked()
by re-fetching the msg_pl pointer from ctx->open_rec after
bpf_exec_tx_verdict() returns -ENOSPC and the record is split.
> diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
> --- a/net/tls/tls_sw.c
> +++ b/net/tls/tls_sw.c
[ ... ]
> @@ -1161,10 +1161,11 @@ static int tls_sw_sendmsg_locked(struct sock *sk, struct msghdr *msg,
> if (ret) {
> if (ret == -EINPROGRESS)
> num_async++;
> else if (ret == -ENOMEM)
> goto wait_for_memory;
> else if (ctx->open_rec && ret == -ENOSPC) {
> + msg_pl = &ctx->open_rec->msg_plaintext;
> if (msg_pl->cork_bytes) {
> ret = 0;
> goto send_end;
> }
> goto rollback_iter;
> } else if (ret != -EAGAIN)
> goto send_end;
> }
[ ... ]
> rollback_iter:
> copied -= try_to_copy;
> sk_msg_sg_copy_clear(msg_pl, first);
> iov_iter_revert(&msg->msg_iter,
> msg_pl->sg.size - orig_size);
[Severity: High]
When jumping to rollback_iter after the record is successfully split,
does msg_pl->sg.size - orig_size underflow?
Because msg_pl was updated to point to the new smaller remainder record,
msg_pl->sg.size is now smaller than the pre-split orig_size. This
subtraction results in a large positive value being passed to
iov_iter_revert(), corrupting the iterator state.
Additionally, sk_msg_sg_copy_clear() is called with the pre-split first
index, which is invalid for the new msg_pl scatterlist array. Does this
corrupt the remainder record?
[ ... ]
> fallback_to_reg_send:
> sk_msg_trim(sk, msg_pl, orig_size);
> }
>
> required_size = msg_pl->sg.size + try_to_copy;
>
> ret = tls_clone_plaintext_msg(sk, required_size);
> if (ret) {
> if (ret != -ENOSPC)
> goto send_end;
>
> /* Adjust try_to_copy according to the amount that was
> * actually allocated. The difference is due
> * to max sg elements limit
> */
> try_to_copy -= required_size - msg_pl->sg.size;
> full_record = true;
> sk_msg_trim(sk, msg_en,
> msg_pl->sg.size + prot->overhead_size);
[Severity: High]
This is a pre-existing issue, but does this leave the msg_en pointer
dangling?
The patch fixes the use-after-free for msg_pl, but msg_en is not
re-fetched. If the original record was queued and potentially freed by
tls_tx_records(), dereferencing msg_en here in the fallback path
results in a use-after-free identical to the one fixed for msg_pl.
[ ... ]
> wait_for_memory:
> ret = sk_stream_wait_memory(sk, &timeo);
> if (ret) {
> trim_sgl:
> if (ctx->open_rec)
> tls_trim_both_msgs(sk, orig_size);
> goto send_end;
> }
[Severity: High]
This is a pre-existing issue, but does this cause silent data loss if
sk_stream_wait_memory() fails?
In the zero-copy path, the copied variable is incremented by
try_to_copy before bpf_exec_tx_verdict() is called. If
bpf_exec_tx_verdict() returns -ENOMEM, we jump to wait_for_memory.
If the wait is interrupted (for example, by a signal), it jumps to
trim_sgl and drops the appended bytes via tls_trim_both_msgs(). However,
copied is never decremented to reflect this drop, leading userspace to
believe bytes were buffered or sent when they were actually discarded.
> if (ctx->open_rec && msg_en->sg.size < required_size)
> goto alloc_encrypted;
[Severity: High]
This is a pre-existing issue, but can this also trigger a use-after-free
on msg_en?
If bpf_exec_tx_verdict() returns -ENOMEM after the record was split and
queued, the code jumps directly to wait_for_memory without updating
msg_en. When sk_stream_wait_memory() resumes, msg_en->sg.size is
dereferenced, but it may point to the freed original record.
While reviewing this area, I also noticed a pre-existing issue in
tls_push_record() in the same file:
[Severity: High]
This is a pre-existing issue, but does this leak the tmp remainder
record when asynchronous encryption returns -EINPROGRESS?
tls_push_record() allocates a tmp remainder record when splitting:
net/tls/tls_sw.c:tls_push_record() {
...
if (split) {
tmp = tls_split_open_record(sk, rec, &orig_end, &msg_pl, &msg_en,
&copied, &zc_frame, &bpf_strp);
...
rc = tls_do_encryption(sk, tls_ctx, ctx, req, req_size, copied,
record_type);
if (rc < 0) {
if (rc != -EINPROGRESS) {
tls_err_abort(sk, -EBADMSG);
if (split) {
...
tls_merge_open_record(sk, rec, tmp, orig_end);
}
}
ctx->async_capable = 1;
return rc;
}
}
If tls_do_encryption() returns -EINPROGRESS, the function returns
immediately. The newly allocated tmp record is never assigned to
ctx->open_rec, never merged back, and never queued. Are the tmp record
and its allocations permanently leaked here?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260605214802.1647008-1-rhkrqnwk98@gmail.com?part=1
next prev parent reply other threads:[~2026-06-06 21:48 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-05 21:48 [PATCH net] tls: fix use-after-free in tls_sw_sendmsg() cork error path Sechang Lim
2026-06-06 21:48 ` sashiko-bot [this message]
2026-06-09 15:25 ` abaci-kreproducer
2026-06-09 21:57 ` Jakub Kicinski
2026-06-09 21:58 ` Jakub Kicinski
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=20260606214816.EDF991F00893@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=rhkrqnwk98@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