Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-97555 — Analysis, POC, and arm64 exploit chain for a Linux cifs.ko DACL heap overflow (CVE-2026-97555), escalating to a uid-0 credential overwrite on the reference build. | Kitploit
Tools/GitHubGitHub/woshigenm/cve-2026-97555
Android SecurityPrivilege EscalationMemory ForensicsVulnerability AnalysisExploitationShellcodePapers & ResearchBinary Exploitation
GitHubwoshigenm/cve-2026-97555

CVE-2026-97555

Analysis, POC, and arm64 exploit chain for a Linux cifs.ko DACL heap overflow (CVE-2026-97555), escalating to a uid-0 credential overwrite on the reference build.

316 days agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share
View Repository

CVE-2026-97555 — cifs DACL owner/group heap overflow

English | 简体中文

Kernel heap overflow in the SMB client DACL rewrite. id_mode_to_cifs_acl() sizes the output security descriptor from the DACL returned by the server, but replace_sids_and_copy_aces() rewrites every ACE with the new owner/group SID (up to 68 bytes). A server that returns a short-SID DACL therefore makes the rewrite outgrow the allocation and write past the kmalloc object.

This repository ships the analysis, a POC that reproduces the cross-object write, and an EXP that turns the overflow into a controlled end-to-end chain (heap leak, page-table reclaim, arbitrary PTE write, self-cred overwrite to uid 0) on the reference build.

Status

ItemValue
CVECVE-2026-97555
ClassHeap buffer overflow (write, CWE-122) in id_mode_to_cifs_acl()
Componentcifs.ko (SMB client)
AffectedLinux cifs.ko without the fix (validated against a 6.12 GKI-based Android kernel)
Patchupstream 0ee150794c75 (stable fb736ab4fb8c)
Reference buildAndroid 16 GKI-based 6.12 kernel, arm64, 4 KiB pages, 64-byte struct page
POCCross-object write reproduced (SET_INFO security descriptor of 696 bytes)
EXPFull chain to a uid-0 shell on the reference build

Scope and safety

  • This is an authorized-research repository. Do not use it against systems you do not own or have explicit permission to test.
  • The harness is privileged by design: it mounts the share, uses tracefs kprobes and reads /proc/kpageflags as root. Obtaining the mount capability is a test fixture, not part of the bug, and is out of scope of this repository.
  • The EXP demonstrates the memory-corruption primitives on a research device. The cred stage deliberately drops to uid 2000 and escalates back by rewriting only the uid/suid/euid/fsuid fields of its own credential; no capability or securebits field is touched. Cleanup is a reboot.
  • The constants in src/exp.c (symbol addresses, vmemmap geometry, BTF offsets) belong to the reference build. Re-derive them for any other build before running; see scripts/derive_offsets.sh.

Root cause

id_mode_to_cifs_acl() computes the allocation from dacl_ptr->size or num_aces * sizeof(struct smb_ace), then replace_sids_and_copy_aces() rebuilds each ACE with the new owner/group SID. When the server's SIDs are short (0-subauth) and the new SID is 68 bytes, the rewritten DACL is longer than the allocation and build_sec_desc() writes past the slab object.

The kernel's dynamic FORTIFY instrumentation checks the inlined ACE-header stores, but the SID copies go through the out-of-line cifs_copy_sid() and are not instrumented. A DACL aligned so that every ACE header stays inside nsecdesclen - 28 reaches the vulnerable copy.

The cross7 server layout (7 ACEs, source sizes 76/76/76/44/44/16/16) makes the allocation exactly 512 bytes; the 7th ACE's 68-byte SID copy starts at offset 492 and crosses the object boundary, and the rewritten descriptor grows to 696 bytes — 184 bytes past the object. The expanded descriptor is still delivered in SET_INFO, so the write is observable from the server side.

Prerequisites

  • arm64 Android device with 4 KiB pages and a 6.12 GKI-based kernel built without fb736ab4fb8c.
  • A root shell for the harness (tracefs kprobes, kpageflags, mount, chown) and a SELinux-permissive window (or an equivalent policy allowance) for the cifs idmap upcall.
  • The share provided by src/poc_smb2_acl.py, mounted with cifsacl/modefromsid through the standard kernel client (scripts/mount_cifs.sh). The mount itself is a privileged fixture; how the tester obtains that privilege is outside this repository.
  • cifs.idmap keys preloaded for the target ids: the reference environment has no /sbin/cifs.idmap upcall helper (src/poc.c and src/exp.c preload them; src/acl_key_preload.c does it standalone).

POC

# host
python3 src/poc_smb2_acl.py            # ACL_LAYOUT=cross7 for the overflow
adb reverse tcp:1468 tcp:1468

# device (root)
sh /data/local/tmp/e2e/mount_cifs.sh 127.0.0.1 share /mnt/cifs
make && make push
/data/local/tmp/poc /mnt/cifs

Expected evidence: the server log prints SET_INFO security: len=696 ... (cross7), i.e. a descriptor longer than the 512-byte allocation, and scripts/trace_acl02.sh shows the id_mode_to_cifs_acl entry/return around the chown.

The POC only triggers the vulnerable path; it does not groom, leak or escalate. The trigger performs an out-of-bounds kernel write: builds whose layout trips the dynamic FORTIFY checks can panic, so run it only on a test device you can reboot.

EXP

The EXP is the full chain, end to end on the reference build:

  1. Leak — a cross7 overflow rewrites a neighbouring key payload's datalen; keyctl_read dumps 64 KiB including a live pipe_buffer array. The leaked anon_pipe_buf_ops pointer gives the KASLR slide and the buffer page P gives the real struct page target.
  2. Trigger — interleaved hit/target pipes share kmalloc-512 slabs; a per-iteration hunt finds an active slab with eight target slots backed by a live hit-pipe array. The freed slots are re-taken by the chown security descriptor in LIFO order, and one hit pipe's buffer[0] is rewritten with page=P, len=0x1234, ops=default_pipe_buf_ops.
  3. Page UAF and PTE reclaim — closing the hit pipe frees P; a fault at base reclaims it as a page-table page, gated by a kretprobe proving __alloc_pages_noprof returned P from __pte_alloc.
  4. Arbitrary PTE write — the observation buffer holds 16 bytes so the merge write starts at P+16 (PTE[2]); its first eight bytes are a self-map descriptor for P itself. Userland then reads and writes the page-table page through base+8 KiB.
  5. Read-only scout — batches of KPF_SLAB pages are mapped through fresh PTEs and scanned for this task's comm; pid/tgid, the linear-map window and cred->uid/euid cross-check the hit, and fresh, never-used VAs re-verify the physical page.
  6. Cred overwrite — the process performs a real setresuid(2000) (the kernel allocates a fresh cred), reads task->cred through the self-map, zeros only uid/suid/euid/fsuid, confirms getuid()==0, disarms the self-map and execves /system/bin/sh. The shell runs as uid 0.
make exp
make push
# on the device, as root:
sh /data/local/tmp/e2e/launch_exp.sh /mnt/cifs 10 1 r1 4000 400 2400 7 0 0 cred
# then read /data/local/tmp/e2e/e2e_status.txt and
# /data/local/tmp/e2e/root_shell.txt

The cred stage is opt-in through the last argument (cred); scout stops after the read-only validation. The EXP keeps its PTEs inside the process and cleanup is a reboot.

Build

Requirements: Android NDK r29 (override with NDK=), GNU make, adb.

make            # POC (arm64, API 24)
make exp        # EXP
make build-all  # both
make check      # push and run the read-only pre-check (poc --check)
make push       # push binaries and helper scripts
make run        # push and run the POC against $(MNT) (default /mnt/cifs; destructive)
make host       # static POC build for qemu-aarch64
make emu        # host build and run
make logs       # dump logcat/dmesg into logs/
make help

Repository layout

Download Tool