kernelCTF exp521: CVE-2025-40019 essiv on mitigation-v4-6.12#382
kernelCTF exp521: CVE-2025-40019 essiv on mitigation-v4-6.12#382AshmitSh4rma wants to merge 9 commits into
Conversation
Adds a 1-day submission porting the published CVE-2025-40019 essiv ssize-underflow technique to the mitigation-v4-6.12 target (vanilla v6.12.0 + jannh mitigations). - Flag captured live 2026-05-13 13:33Z (exp521 on the public spreadsheet). - Per-target symbol offsets re-derived from the mit-v4-6.12 vmlinux. - Inline AES-256-ECB + SHA-256 (tinycrypto.h) to drop the OpenSSL runtime dependency.
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
- affected_versions: use '6.0 - 6.12.82' (range form per schema regex) - requirements.attack_surface: empty (only 'userns'|'io_uring' enum allowed, this exploit uses neither) - exploits.mitigation-v4-6.12.uses: empty for same reason Free-text bug-class / primitive descriptions live in docs/exploit.md, not in metadata.json's tag arrays.
|
The
The CVE column on the public spreadsheet for There is no user-facing CVE field on the Google submission form, so I can't populate it from my side. Could a reviewer kick the auto-resolver, or fill the The PR metadata correctly identifies the bug as CVE-2025-40019 via |
cb836aa to
d992fae
Compare
|
@googlebot I have signed the CLA |
The CI workflow's debug rewrite injects -g via 'sed -E s/gcc(\s)/gcc -g\1/g', which requires gcc to be followed by whitespace. With 'CC = gcc' at EOL the sed never matched, so the resulting binary had no DWARF and the workflow's 'file exploit_debug | grep debug_info' check failed. Inlining gcc directly in the recipe matches the convention used by every other kernelctf submission. Also gate 'strip $@' on the target name so the workflow's renamed 'exploit_debug:' target keeps its DWARF; the original 'exploit' target still strips as before, so the release binary is unchanged.
The vuln-verify harness (kernelctf/vuln-verify/run_exploit.sh) invokes
the exploit as '/exp.sh --vuln-trigger', expecting the exploit to fire
just the underlying CVE primitive on a KASAN build so the verifier can
confirm the supplied patch_commit actually closes the bug.
Previously argv[1]='--vuln-trigger' fell through into the existing
'argc>1 → root_payload(argv[1])' path (which exists for core_pattern
re-entry with a PID). strtoull("--vuln-trigger")=0, pidfd_open(0)
failed, /flag was unreadable, exploit exited cleanly — so all five
verify probes reported pwned=False and PR_VERIFY produced UNKNOWN.
The new vuln_trigger() does the minimal essiv_aead_crypt(enc=0) fire
(assoclen=0 + 16-byte IV) and exits, skipping KASLR / spray / fork.
On the unpatched KASAN kernel scatterwalk_map_and_copy walks OOB and
KASAN reports it (kasan.fault=panic ends the VM, log carries 'KASAN:').
On the patched kernel the new bounds check returns EINVAL, exp.sh
falls off the end, init-death panics the VM cleanly — pwned=False.
See rules.md §384 for the harness contract.
reqFilesPerExploit in kernelctf/check-submission.py requires the compiled 'exploit' binary alongside Makefile and exploit.c. Rebuilt from current sources (now containing --vuln-trigger handler).
Rename exploit.c → exploit.cpp, link -lkernelXDK, switch CC to g++, drop
the #ifdef LTS/MIT/COS/MIT4_612 ladder. metadata.json now declares
"uses": ["kernelXDK"].
Symbol resolution:
- TargetDb("target_db.kxdb", target_db) with INCBIN fallback for the
bundled KXDB, identical pattern to the libxdk samples (exp111 etc.).
- AutoDetectTarget() with try/catch + fallback to
GetTarget("kernelctf", "mitigation-v4-6.12") so production targets
whose /proc/version may have drifted still resolve correctly.
- core_pattern and __brk_base aren't in the v0.1 KXDB's curated symbol
set, so we target.AddSymbol() them locally with the per-target offsets
that used to live in the #ifdef ladder. Future targets get one-line
AddSymbol additions.
vuln_trigger() runs BEFORE the libxdk init. The KASAN kernels in
vuln-verify have a /proc/version not in the KXDB; deferring the
TargetDb instantiation keeps the working before:True / after:False
behavior we just got green.
Local verification done with the v0.1 release tarball (-I/-L mirroring
the workflow's install layout):
- release build clean
- ./exploit --vuln-trigger → EC=0 (sendmsg EINVAL on patched host)
- bare ./exploit reaches compute_iv + setup_sacrificial_aead via the
AutoDetect-fail fallback path
- workflow's 6 debug-rewrite seds applied + actual debug build →
file exploit_debug reports 'with debug_info, not stripped'
target_db.kxdb is a Makefile build dependency (wget from
storage.googleapis.com/kernelxdk/db/kernelctf.kxdb), matching the
exp111 convention; not committed.
The 'uses' field is a runtime-kernel-feature enum, not a libxdk/kernelXDK signal. kernelXDK adoption is signaled purely by the .cpp extension and the -lkernelXDK linkage; there is no metadata field for it (rules.md §284–298 doesn't mention one, and the v3 schema's enum confirms). Previous commit (db4dd89) put 'kernelXDK' here and broke structure_check schema validation: '<root>.exploits[mitigation-v4-6.12].uses[0]': 'kernelXDK' is not one of ['userns', 'io_uring'].
Submission for exp521.
mitigation-v4-6.12crypto/essiv.ckernelCTF{v1:mitigation-v4-6.12:1778679222:cd35326a7169f91303f32929a9beeb219df90157}at 2026-05-13T13:33:42Zd96391e7c5aaa72a8d782d1392496ce864bb0695c456f11ca4a688d3e293df33Layout
docs/vulnerability.md— bug root cause + introducing/fixing commitsdocs/exploit.md— full 8-step exploit walkthrough (essiv ssize underflow → chained-SGL crafted reclaim → PTE remap → core_pattern overwrite → root via usermodehelper + pidfd stdio theft)exploit/mitigation-v4-6.12/exploit.c— single-file source (~620 lines)exploit/mitigation-v4-6.12/tinycrypto.h— inline AES-256-ECB + SHA-256 (drops OpenSSL runtime dependency)exploit/mitigation-v4-6.12/Makefile—make exploitbuilds;make runnotesexploit/mitigation-v4-6.12/exploit— the binary that captured the flagoriginal.tar.gz— matches the SHA256 submitted via the Google Formmetadata.json— schema v3Reachability
Triggerable from any unprivileged UID with no caps and no user namespaces. Required configs:
CONFIG_CRYPTO_USER_API_AEAD=y,CONFIG_CRYPTO_ESSIV=y(both=yin the kCTF mitigation-v4 image). Compatible with all of the kCTF mitigation hardening (max_user_namespaces=1,io_uring_disabled=2,unprivileged_bpf_disabled=2).