CVE-2024-26582: Verified Reproduction
CVE-2024-26582: Linux kernel kTLS Use-After-Free
CVE-2024-26582 is verified against torvalds/linux · github. Affected versions: Linux 6.2.0 through 6.6.18; also 6.1.x before 6.1.82, 6.7.x before 6.7.7. Vulnerability class: Use-After-Free. This high reproduction includes runnable sandbox proof, artifacts, and a plain-text agent view under REPRO-2026-00265.
What Is CVE-2024-26582?
CVE-2024-26582 is a high-severity use-after-free vulnerability in the Linux kernel's in-kernel TLS (kTLS) software receive path in net/tls/tls_sw.c. Pruva reproduced it (reproduction REPRO-2026-00265).
CVE-2024-26582 Severity & CVSS Score
CVE-2024-26582 is rated high severity, with a CVSS base score of 7.8 out of 10.
High — serious impact or readily exploitable. Prioritize remediation.
Affected torvalds/linux Versions
torvalds/linux · github versions Linux 6.2.0 through 6.6.18; also 6.1.x before 6.1.82, 6.7.x before 6.7.7 are affected.
How to Reproduce CVE-2024-26582
pruva-verify REPRO-2026-00265 curl -O https://www.pruva.dev/api/v1/reproductions/REPRO-2026-00265/artifacts/bundle/repro/reproduction_steps.sh && chmod +x reproduction_steps.sh && ./reproduction_steps.sh Proof of Reproduction for CVE-2024-26582
- reached the target end-to-end
- crash observed
- on the real production code path
- high confidence
kTLS session with async decryption and partial read pattern
- tls_sw_recvmsg
- tls_decrypt_sg (clear_skb path, darg.zc=false)
- tls_do_decryption (async via cryptd)
- tls_decrypt_done (frees clear_skb pages via put_page, bug: sgout!=sgin check)
- process_rx_list (accesses freed pages, KASAN UAF)
How the agent worked
Root Cause and Exploit Chain for CVE-2024-26582
CVE-2024-26582 is a use-after-free vulnerability in the Linux kernel's in-kernel TLS (kTLS) software receive path (net/tls/tls_sw.c). When a kTLS session uses asynchronous decryption and the receiving application performs a partial read (reading fewer bytes than the TLS record size), the tls_decrypt_done() completion callback incorrectly frees pages belonging to the clear_skb buffer. These freed pages are subsequently accessed by process_rx_list() when the application reads the remaining data, triggering a use-after-free. The fix (commit 32b55c5ff9103b8508c1e04bfa5a08c64e7a925f) adds a free_sgout flag to track whether tls_decrypt_sg() actually allocated the destination pages, and only frees them when they were newly allocated.
- Package/component affected: Linux kernel kTLS software implementation (
net/tls/tls_sw.c) - Affected versions: Linux 6.2.0 through 6.6.18 (fixed in 6.6.19+, 6.7.7+, 6.1.82+, 6.8-rc3)
- Risk level: High — kernel-space use-after-free can lead to memory corruption, information leaks, or potentially privilege escalation
- Consequences: An attacker who can establish a kTLS session and control the read pattern (partial reads) can trigger premature page freeing, leading to use-after-free when the freed pages are accessed. With page poisoning or KASAN, this manifests as data corruption or sanitizer reports. Without sanitizers, this could lead to silent memory corruption or exploitation.
Impact Parity
- Disclosed/claimed maximum impact: Memory corruption (use-after-free in kernel space)
- Reproduced impact from this run: Memory corruption confirmed via KASAN use-after-free report and data corruption (page poisoning). The KASAN report shows a read of freed memory in
copyout()called fromprocess_rx_list()→tls_sw_recvmsg(). Data mismatch detected when freed pages are poisoned. - Parity:
full— the claimed memory corruption impact is fully reproduced with KASAN detection and data corruption evidence. - Not demonstrated: Code execution / privilege escalation (the UAF is demonstrated as memory corruption, not exploit chain to code execution).
Root Cause
The vulnerability is in tls_decrypt_done() in net/tls/tls_sw.c. This function is the async completion callback for AEAD decryption in the kTLS software receive path.
The bug: tls_decrypt_done() uses the check if (sgout != sgin) to determine whether to free destination pages. This check was intended to distinguish in-place decryption (where destination and source scatterlists are the same, so no pages should be freed) from non-in-place decryption (where destination pages were allocated and should be freed). However, the check is incorrect because sgout != sgin is also true when sgout points to pages from clear_skb (allocated by tls_alloc_clrtxt_skb()), not just when pages were newly allocated by tls_decrypt_sg().
The flow:
tls_sw_recvmsg()is called with a partial read (len < record_size)darg.zc = falsebecauseto_decrypt > len(record doesn't fit in user buffer)tls_decrypt_sg()takes theclear_skbpath: allocatesclear_skbwith pages, setssgoutto point toclear_skbpagestls_do_decryption()starts async decryption (returns-EINPROGRESSviacryptdworkqueue)- The
clear_skbis placed onctx->rx_listfor later processing tls_decrypt_async_wait()waits for async completiontls_decrypt_done()is called from the workqueue → seessgout != sgin→ callsput_page()onclear_skbpages → pages freed whileclear_skbstill references them- On the next
recv()call,process_rx_list()reads from theclear_skb→ accesses freed pages → use-after-free
The fix (commit 32b55c5ff9103b8508c1e04bfa5a08c64e7a925f):
- Adds
bool free_sgouttostruct tls_decrypt_ctx - Sets
dctx->free_sgout = !!pagesintls_decrypt_sg()(only true when pages were actually allocated) - Changes the check in
tls_decrypt_done()fromif (sgout != sgin)toif (dctx->free_sgout)
Reproduction Steps
- Reference:
bundle/repro/reproduction_steps.sh - What the script does:
- Downloads Linux kernel v6.6.18 source
- Applies GCC 15 compatibility patches (adds
-std=gnu11to REALMODE_CFLAGS, boot/compressed, and EFI libstub Makefiles) - Patches
crypto/simd.cto force AEAD decrypt operations through thecryptdworkqueue (simulating async crypto behavior that occurs with hardware crypto accelerators or in contexts where SIMD is unavailable) - Creates two kernel builds: vulnerable (fix reverted) and fixed (fix present)
- Both builds include
CONFIG_TLS=y,CONFIG_KASAN=y,CONFIG_CRYPTO_AES_NI_INTEL=y,CONFIG_PAGE_POISONING=y - Creates a minimal initramfs with a static kTLS test program that:
- Establishes a loopback TCP connection
- Configures kTLS with AES-128-GCM (TLS 1.2)
- Sends 4096-byte records and performs partial reads (100 bytes then 3996 bytes)
- Checks for data corruption
- Boots both kernels in QEMU (TCG mode,
-cpu maxfor AES-NI) withpage_poison=1 - Captures serial console output for KASAN reports and corruption detection
- Expected evidence:
- Vulnerable kernel:
BUG: KASAN: use-after-free in copyout+Data MISMATCH - corruption detected!+BUG: Bad page state - Fixed kernel: No KASAN reports, no corruption, test completes normally
- Vulnerable kernel:
Evidence
- Vulnerable kernel log:
bundle/logs/qemu-vuln-ktls.log - Fixed kernel log:
bundle/logs/qemu-fixed-ktls.log - Reproduction script log:
bundle/logs/reproduction_steps.log
Key excerpts from vulnerable kernel:
[ 4.956611] BUG: KASAN: use-after-free in copyout+0x2d/0x50
[ 4.957007] Read of size 100 at addr ff1100000186000d by task init/58
[ 4.957072] Call Trace:
[ 4.957072] copyout+0x2d/0x50
[ 4.957072] _copy_to_iter+0x15b/0x1070
[ 4.957072] __skb_datagram_iter+0x3c7/0x890
[ 4.957072] skb_copy_datagram_iter+0x2f/0x120
[ 4.957072] process_rx_list+0x2b5/0x5f0
[ 4.957072] tls_sw_recvmsg+0x1081/0x17b0
[kTLS] Data MISMATCH - corruption detected!
[ 4.969549] BUG: Bad page state in process init pfn:02efc
Key excerpts from fixed kernel (negative control):
[kTLS] Data matches (no corruption observed yet)
[kTLS] Completed 20 iterations
[kTLS] Test complete. If KASAN is enabled, check dmesg for UAF report.
(No KASAN reports, no corruption, no bad page state)
Environment details:
- Kernel: Linux 6.6.18 (v6.6.18 with fix reverted for vulnerable, fix present for fixed)
- Compiler: GCC 15.2.0 with
-std=gnu11compatibility patches - QEMU: QEMU 10.2.1, TCG mode,
-cpu max(AES-NI emulation), 2 vCPUs, 1024MB RAM - KASAN: Generic KASAN with inline instrumentation
- Page poisoning: enabled (
page_poison=1) - Crypto: AES-NI GCM with forced async decrypt via
cryptdworkqueue - Test: kTLS AES-128-GCM, TLS 1.2, 4096-byte records, 100-byte partial reads
Recommendations / Next Steps
- Upgrade: Apply the fix (commit
32b55c5ff9103b8508c1e04bfa5a08c64e7a925f) or upgrade to Linux 6.6.19+, 6.7.7+, 6.1.82+, or 6.8-rc3+. - Testing: Enable
CONFIG_KASANandCONFIG_PAGE_POISONINGin kernel testing configurations to detect similar use-after-free bugs in the kTLS receive path. - Code review: Audit other completion callbacks in the kTLS code that use pointer comparison (
sgout != sgin) instead of explicit allocation tracking. - Mitigation: If kTLS is used in production with hardware crypto accelerators (which naturally produce async completions), ensure the kernel is patched. The bug only manifests with async decryption, which is the normal case with hardware crypto.
Additional Notes
- Idempotency: The reproduction script is idempotent — it checks for existing build artifacts and reuses them. Running it multiple times produces the same result.
- Async path simulation: The
crypto/simd.cpatch forces AEAD decrypt operations through thecryptdworkqueue, simulating the async behavior that occurs naturally with hardware crypto accelerators or in contexts where SIMD/FPU is unavailable (e.g., softirq context). This does not modify the vulnerable code path intls_sw.c; it only ensures the async completion path is exercised. In production, this async path is triggered by hardware crypto offload or when the crypto operation is deferred. - Page poisoning:
CONFIG_PAGE_POISONINGwithpage_poison=1fills freed pages with a poison pattern (0xAA), making the use-after-free visible through data corruption even without KASAN. This provides an additional layer of detection beyond KASAN's shadow memory tracking. - GCC 15 compatibility: The v6.6.18 kernel requires minor Makefile patches to build with GCC 15, which defaults to C23 where
true/falseare keywords. The patches add-std=gnu11to REALMODE_CFLAGS, boot/compressed, and EFI libstub Makefiles, matching the fix applied in newer kernel versions.
CVE-2024-26582 Reproduction Transcript
The agent's step-by-step process — every tool call, every handoff, the moment the exploit fired.
Full session Replay every step — scrub the timeline or play it back.
cd /data/pruva/project-cache/6cba72b6-b104-4ebf-be7b-01f748e87ccf/linux-src && git log --oneline -3 2>/dev/null; echo "---HEAD---"; git rev-parse HEAD 2>/dev/null; echo "---VERSION---"; head -5 Makefile---HEAD--- ---VERSION--- # SPDX-License-Identifier: GPL-2.0 VERSION = 6 PATCHLEVEL = 18 SUBLEVEL = 18 EXTRAVERSION =
cd /data/pruva/project-cache/6cba72b6-b104-4ebf-be7b-01f748e87ccf/linux-src-7rc2 && git log --oneline -3 2>/dev/null; echo "---HEAD---"; git rev-parse HEAD 2>/dev/null; echo "---VERSION---"; head -5 Makefile---HEAD--- ---VERSION--- # SPDX-License-Identifier: GPL-2.0 VERSION = 7 PATCHLEVEL = 0 SUBLEVEL = 0 EXTRAVERSION = -rc2
Artifacts and Evidence for CVE-2024-26582
Scripts, logs, diffs, and output captured during the reproduction.
How to Fix CVE-2024-26582
FAQ: CVE-2024-26582
How does the CVE-2024-26582 use-after-free get triggered?
tls_decrypt_done() frees the clear_skb pages prematurely, and the subsequent read via process_rx_list() dereferences the already-freed pages, leading to memory corruption, information leaks, or potential further exploitation.Which Linux kernel versions are affected by CVE-2024-26582, and where is it fixed?
32b55c5ff9103b8508c1e04bfa5a08c64e7a925f, which adds a free_sgout flag so tls_decrypt_sg()-allocated pages are only freed if they were newly allocated.How severe is CVE-2024-26582?
How can I reproduce CVE-2024-26582?
References for CVE-2024-26582
Authoritative sources for CVE-2024-26582 — official vulnerability databases and the upstream advisory. Pruva's reproduction verifies the issue firsthand; these are the primary records to corroborate it.