Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
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.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2026-43499-S26 — Exploits CVE-2026-43499 on Android GKI 6.12 devices: deterministic arbitrary kernel read/write, KASLR bypass, and full root via LD_PRELOAD payload. | Kitploit
Tools/GitHubGitHub/1ndevelopment/cve-2026-43499-s26
Android SecurityPrivilege EscalationVulnerability AnalysisExploitationPost-ExploitationPayload DevelopmentBinary Exploitation
GitHub1ndevelopment/cve-2026-43499-s26

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-43499-S26

Exploits CVE-2026-43499 on Android GKI 6.12 devices: deterministic arbitrary kernel read/write, KASLR bypass, and full root via LD_PRELOAD payload.

View Repository
711 day agoNot yet reviewed

CVE-2026-43499 — Android GKI 6.12 pselect / configfs kernel exploit

A Linux kernel exploit for the Android GKI 6.12 line (Samsung and Pixel devices) targeting CVE-2026-43499: a buggy remove_waiter() rollback in rt_mutex_start_proxy_lock() that uses current instead of waiter::task, leaving a waiter's pi_blocked_on pointing at its (later-popped) kernel stack rt_mutex_waiter. Combined with a pselect() fd_set stack overwrite and a consumer sched_setattr-driven fake rb_tree walk, it yields a deterministic kernel write primitive and full root.

The exploit runs as an LD_PRELOAD shared library (preload.so) and installs a root su daemon plus wallpaper as post-root artifacts.

Status: active development. Per-target stack-depth offsets (PSELECT_* word shifts) and slide behavior vary by device and are still being verified on-device. The m1q (ZF1) target is the current bring-up focus.

Vulnerable primitive (CVE-2026-43499)

When FUTEX_CMP_REQUEUE_PI requeues a waiter and the requeue's deadlock-detection chain walk returns -EDEADLK, __rt_mutex_start_proxy_lock() rolls back via remove_waiter() (rtmutex.c:1535). The rollback correctly dequeues the waiter from the wait tree but clears the requeue caller's pi_blocked_on instead of waiter->task->pi_blocked_on. The WAITER's pi_blocked_on stays dangling at its stack rt_mutex_waiter, which is popped once the futex times out.

After the timeout, the waiter's kernel stack region is reused: core_sys_select() copies the three fd_sets into that stack buffer (the nfds < 344 stack path on ZF1). A crafted fd_set word array re-materializes a fake rt_mutex_waiter / fake task / fake rt_mutex (with an rb_tree root whose pointers are controlled). A consumer thread then calls sched_setattr_tid(waiter) → rt_mutex_adjust_pi() → rb_erase_cached, which produces an arbitrary address write of a controlled value.

The whole primitive requires the PI chain cycle: the owner holds f_pi_target and also blocks on f_pi_chain (held by the waiter), so the chain walk hits owner → chain → waiter → target → owner and fails with -EDEADLK. Removing the cycle makes the requeue return success with zero kernel effect.

Exploitation chain

  1. Slide (KASLR) — leak the kernel base. Two routes:
    • tracefs sched_blocked_reason (m1q primary): a blocked kworker's saved return PC (stack_trace_save_tsk) is read from the ring buffer and compared against the compiled-in worker_thread offset.
    • boot_id pselect route (fallback, slide-independent): a pselect write plants SLIDE_LOGGERS_0_1 into the boot_id sysctl data via a linear-map alias; the leaked value reconstructs stext.
  2. KernelSnitch — spray mm_struct-sized objects and use a futex-hash collision to locate an mm_struct on the heap, leaking a kernel heap page address used as the fake-object spray base.
  3. Main route — the pselect corruption writes configfs_bin_write_iter into the write_iter slot (+0x30) of the static .data ashmem file_operations. Opening ashmem then yields arbitrary kernel read/write through the configfs binary-fs path.

Stage 3 (pgd-swap bridge, static/build only)

Optional STAGE3=1 phase that forks a bridge child, swaps its mm->pgd to a staged fake page table (3-level: PGD→L1→L2, RX loop leaf + RW stack leaf), and lets the child run a register-only assembly blob that patches its own cred through a 2MB physical scan window — all-RAM phys R/W without the configfs/pipe primitives. Currently wired only into the m1q target and has not been run on-device.

Supported targets

41 targets in src/targets/<codename>-<build>/, each requiring at minimum a target.h (kernel symbol offsets, KIMAGE_TEXT_BASE, direct-map base, struct offsets). Pixel targets (comet, tokay, tegu, caiman, komodo, frankel, mustang, rango, stallion, blazer) override shared sources; Samsung targets (m1q-*) add device-specific logic.

root@kitploit:~
make list-projects   # full list

Kernel struct layouts differ per device — offsets must be verified against the actual kernel binary / kallsyms for each target.

Build

Output: build/<PROJECT>/bin/preload.so (shared lib loaded via LD_PRELOAD).

root@kitploit:~
# Default project
CC=clang make

# Specific device target (default: blazer-CP2A.260605.012)
CC=clang make PROJECT=m1q-BP4A.251205.006

# Without CC=clang: uses NDK if found ($NDK_ROOT / $ANDROID_NDK_HOME /
# $ANDROID_NDK_ROOT), otherwise host clang + Android sysroot
make PROJECT=m1q-BP4A.251205.006

# Show build configuration
make info

# Clean
make clean

The build embeds a PIE su_daemon binary (src/su_daemon.c, built to build/embed/su_daemon_aarch64_pie) and assets/wallpaper.webp into preload.so via src/su_blob.S / src/wallpaper_blob.S.

Run on device

Push the build outputs to /data/local/tmp, then run the exploit under LD_PRELOAD. Run WITHOUT tee on a live bring-up target — tee buffers its own stdio and loses the tail of the log on a kernel panic (exploit stdout is unbuffered, so redirecting straight to a file preserves every line):

root@kitploit:~
adb push build/m1q-BP4A.251205.006/bin/preload.so /data/local/tmp/preload.so
adb push build/embed/su_daemon_aarch64_pie /data/local/tmp/su_daemon_aarch64_pie
adb shell "chmod 755 /data/local/tmp/preload.so /data/local/tmp/su_daemon_aarch64_pie"

adb shell "LD_PRELOAD=/data/local/tmp/preload.so \
  /data/local/tmp/su_daemon_aarch64_pie \
  > /data/local/tmp/output.log 2>&1"

On success the daemon listens on /data/local/tmp/temp_su.sock and su is installed under /apex/com.android.virt/bin.

Runtime configuration (environment variables)

Project layout

root@kitploit:~
exploit/
  Makefile
  assets/                     # wallpaper.webp (embedded post-root artifact)
  src/
    main.c                    # run_exploit() entry point (shared)
    preload.c                 # LD_PRELOAD constructor, su/wallpaper install
    util.c                    # addr translation, page prep, configfs helpers
    pipe.c                    # pipe-based physical read/write
    root.c                    # cred patching / task walk
    slide.c                   # KASLR slide (tracefs + boot_id routes)
    fops.c                    # pselect corruption + fops manipulation
    faketables.c              # stage-3 fake page-table builders (3-level)
    stage3.c                  # pgd-swap bridge child (no-op unless configured)
    stage3_loop.S, stage3_poll.S  # bridge blob + enter trampoline
    su_daemon.c               # root daemon (compiled as separate PIE)
    su_blob.S, wallpaper_blob.S   # embedded binaries
    offset.h                  # pulls per-target target.h via -DTARGET_CONFIG_H
    kernelsnitch/             # mm_struct futex-hash leak library
    targets/<codename>-<build>/    # per-device target.h + optional overrides
poc/poc.c                     # standalone POC (separate from the exploit)

Targets override shared sources through the Makefile pick_src mechanism: if src/targets/<PROJECT>/<file>.c exists it is used instead of the shared src/<file>.c; otherwise the shared version is used.

Notes and gotchas

  • Never remove the PI chain cycle. The write primitive depends on the requeue failing with -EDEADLK (errno 35). A missing cycle shows up as success=1 with zero kernel effect.
  • The waiter must hold the PI chain lock across pselect. Releasing it first lets the owner wake and race the fake rb_tree traversal → panic.
  • m1q: PSELECT_WAITER_WORD_SHIFT must be 0 (ZF1 stack depths verified from ELF). Other targets still default to 1 — verify per device before trusting them.
  • p0_data_alias() uses DIRECT_MAP_BASE (the linear map), which differs from P0_PAGE_OFFSET on ZF1. Data aliases for dereferenced kernel objects must use the linear map.
  • pr_error() is fatal (exit(-1)), unlike the warning/info macros.
  • Slide reconstruction uses SLIDE_LOGGERS_0_1, not SLIDE_NFULNL_LOGGER; the word is a non-randomized linear-map alias, so the boot_id route is slide-independent (use it only at slide=0 — run the tracefs leak first).

Disclaimer

This is exploit code for Android devices and is intended for security research, authorized vulnerability testing, and defense work on hardware you own or have explicit permission to test. Misuse on devices you do not own is illegal. The author is not responsible for bricked devices, bricked kernels, or voided warranties.

Download Tool
  • Pipe physrw — forge pipe buffer pages in the sprayed kernel page for physical read/write: cred patching, SELinux disable, and direct kernel memory manipulation.
  • Root — patch the root child's cred (uid/gid/caps/SELinux SID), then preload.c installs the embedded su daemon (tmpfs-mounted into /apex/com.android.virt/bin, plus adbd-namespace and local variants) and swaps the wallpaper.
  • VariableDefaultPurpose
    PSELECT_ROUTE_SHIFTcompile-timeA/B fd_set word shift for the main route (m1q)
    SLIDE_SHIFTcompile-timeA/B fd_set word shift for the slide route
    PSELECT_ROUTE_DELAY_USEC50000Consumer delay before sched_setattr (must be > 0)
    SLIDE_CONSUME_USEC, SLIDE_ENTER_DELAY_USEC, SLIDE_CONSUMER_CORE—Slide route timing/pinning
    SKIP_SLIDE0Use direct-map fallback (slide = 0)
    SLIDE_ONLY0Run only the KASLR slide and exit
    SLIDE_P0_OFFSET, SLIDE_BOOTID_OFF—Override slide p0-alias / boot_id offsets
    KSNITCH_COLLISIONS4KernelSnitch collision count
    STAGE30Enable the pgd-swap bridge child phase (m1q)
    STAGE3_DRYRUN0Stage/verify tables then abort before the swap
    PAGE_RECLAIM_SENDS, PSELECT_SIMPLE_LAYOUT—Spray/fd-set layout tweaks
    TMP_PAGE_* / TMP_UNAME_*—tmp_page experiment route (m1q)