Subject: [PATCH net 6/7] net: tls: fix use-after-free in tls_sw_sendmsg_locked after bpf verdict

From: Jakub Kicinski <[email-masked]>
Date: Wed, 29 Apr 2026 15:29:43 -0700

After bpf_exec_tx_verdict() returns in the zerocopy path, the local
msg_pl/msg_en pointers may be stale. If a BPF program set apply_bytes
such that tls_push_record() splits the open record via
tls_split_open_record(), ctx->open_rec is replaced with the split
remainder while the original record is pushed to the tx_list and may
be freed by tls_tx_records(). The caller's cached msg_pl/msg_en still
reference the old (now-freed) record.

This is triggered when bpf_exec_tx_verdict() returns -ENOSPC (BPF set
cork_bytes > remaining data) after an internal record split: the code
dereferences msg_pl->cork_bytes on the freed record, causing a UAF.

Reported-by: Alessandro G <[email-masked]>
Fixes: 54a3ecaeeeae ("bpf: fix ktls panic with sockmap")
Signed-off-by: Jakub Kicinski <[email-masked]>
---
CC: [email-masked]
CC: [email-masked]
CC: [email-masked]
CC: [email-masked]
CC: [email-masked]
---
 net/tls/tls_sw.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index 600e13effaab..d086b43fc675 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -1157,6 +1157,13 @@ static int tls_sw_sendmsg_locked(struct sock *sk, struct msghdr *msg,
 				else if (ret == -ENOMEM)
 					goto wait_for_memory;
 				else if (ctx->open_rec && ret == -ENOSPC) {
+					/* bpf_exec_tx_verdict() may have
+					 * called tls_split_open_record(),
+					 * freeing the old record. Re-fetch.
+					 */
+					rec = ctx->open_rec;
+					msg_pl = &rec->msg_plaintext;
+					msg_en = &rec->msg_encrypted;
 					if (msg_pl->cork_bytes) {
 						ret = 0;
 						goto send_end;
-- 
2.54.0