From 49aba55e1aa07167d2ba91a8556218745a83ed9a Mon Sep 17 00:00:00 2001 From: HackTricks News Bot Date: Wed, 19 Aug 2026 18:58:28 +0000 Subject: [PATCH] Add content from: Ghostlock: CVE-2026-43499 Root Shell on the Samsung Galaxy A... --- src/SUMMARY.md | 1 + ...af-pipe-buffer-workqueue-usermodehelper.md | 106 ++++++++++++++++++ .../android-app-pentesting/README.md | 5 + 3 files changed, 112 insertions(+) create mode 100644 src/binary-exploitation/linux-kernel-exploitation/futex-pi-uaf-pipe-buffer-workqueue-usermodehelper.md diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 1f2516b4232..935118a0e19 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -940,6 +940,7 @@ - [Adreno A7xx Sds Rb Priv Bypass Gpu Smmu Kernel Rw](binary-exploitation/linux-kernel-exploitation/adreno-a7xx-sds-rb-priv-bypass-gpu-smmu-kernel-rw.md) - [Af Unix Msg Oob Uaf Skb Primitives](binary-exploitation/linux-kernel-exploitation/af-unix-msg-oob-uaf-skb-primitives.md) - [Arm64 Static Linear Map Kaslr Bypass](binary-exploitation/linux-kernel-exploitation/arm64-static-linear-map-kaslr-bypass.md) +- [Futex PI UAF to Pipe Physical R/W and Workqueue Execution](binary-exploitation/linux-kernel-exploitation/futex-pi-uaf-pipe-buffer-workqueue-usermodehelper.md) - [Ksmbd Streams Xattr Oob Write Cve 2025 37947](binary-exploitation/linux-kernel-exploitation/ksmbd-streams_xattr-oob-write-cve-2025-37947.md) - [Pixel Bigwave Bigo Job Timeout Uaf Kernel Write](binary-exploitation/linux-kernel-exploitation/pixel-bigwave-bigo-job-timeout-uaf-kernel-write.md) - [Linux kernel exploitation - toctou](binary-exploitation/linux-kernel-exploitation/posix-cpu-timers-toctou-cve-2025-38352.md) diff --git a/src/binary-exploitation/linux-kernel-exploitation/futex-pi-uaf-pipe-buffer-workqueue-usermodehelper.md b/src/binary-exploitation/linux-kernel-exploitation/futex-pi-uaf-pipe-buffer-workqueue-usermodehelper.md new file mode 100644 index 00000000000..08e18a354c9 --- /dev/null +++ b/src/binary-exploitation/linux-kernel-exploitation/futex-pi-uaf-pipe-buffer-workqueue-usermodehelper.md @@ -0,0 +1,106 @@ +# Futex PI UAF to pipe physical R/W and workqueue execution + +{{#include ../../banners/hacktricks-training.md}} + +This page abstracts the **GhostLock** Android chain (CVE-2026-43499): a futex priority-inheritance lifetime bug is converted into a constrained pointer write, CFI-compatible file operations and forged `pipe_buffer` entries provide physical memory R/W, and a forged workqueue item reaches usermode-helper execution when protected credentials cannot be patched.[[1]](#references)[[2]](#references)[[3]](#references) + +## Primitive ladder + +The original chain and the Samsung port use the following progression; offsets, syscall frame depth, reclaim objects, physical base, and usable workqueue are build-specific.[[1]](#references)[[2]](#references) + +```text +futex PI lifetime race -> dangling waiter state +pselect stack reclaim -> fake rt_mutex_waiter +rb-tree erase -> constrained aligned pointer write +boot_id ctl_table anchors -> KASLR slide +CFI-compatible f_op substitution -> constrained virtual R/W +forged pipe_buffer.page -> arbitrary physical R/W +forged work_struct/subprocess_info -> privileged usermode helper +``` + +### Reclaiming the waiter and obtaining a write + +After the futex PI race leaves stale `rt_mutex_waiter` state in the blocked task, reclaim the old kernel-stack frame with a syscall that copies controllable data deeply enough into its stack frame. The Android chain uses `pselect()` and its copied `fd_set` bitmaps; other builds may require a different syscall after measuring the freed frame. Forge the waiter's `tree`/`pi_tree` RB nodes plus safe `task` and `lock` pointers so unlinking the node makes RB-tree erase write one chosen pointer to a constrained aligned address.[[1]](#references) + +Treat this as a **single pointer-sized write per successful race**, not arbitrary R/W. Repeat the race for independent targets and validate every dereferenced fake field because a malformed waiter normally crashes before the useful erase operation.[[1]](#references) + +### KASLR oracle and CFI-compatible file operations + +A useful first target is a readable sysctl's `ctl_table.data`. Repointing the `boot_id` entry can make its normal proc handler disclose a slid kernel pointer. On the Samsung port, accepting a candidate only when the `procname`, `data`, and `proc_handler` anchors all agree on the same slide avoids false positives across a very large arm64 slide range.[[1]](#references)[[2]](#references)[[3]](#references) + +With kCFI enabled, replacing a file operation with an arbitrary function is insufficient: the indirect-call signature must match. The original chain replaces ashmem `read_iter`/`write_iter`-style entries with configfs handlers sharing `ssize_t (struct kiocb *, struct iov_iter *)`, yielding constrained virtual reads and writes without violating the CFI type check.[[1]](#references) + +### Upgrading `pipe_buffer.page` to physical R/W + +Locate or reclaim a pipe ring, then use the constrained write to replace selected `pipe_buffer.page` pointers with `struct page *` values for chosen PFNs. Ordinary pipe reads and writes now transfer bytes to or from those pages; a known vmemmap layout or a discovered physical-to-`struct page` transform makes the primitive addressable across physical memory.[[1]](#references)[[2]](#references) + +Before trusting the channel, verify the target profile against the exact kernel image. The public port uses kallsyms plus embedded BTF to audit `pipe_inode_info`, `pipe_buffer`, `file`, `workqueue_struct`, `pool_workqueue`, `worker_pool`, `work_struct`, and `subprocess_info` layouts instead of copying offsets from another device or firmware.[[2]](#references)[[3]](#references) + +## Workqueue/user-mode-helper endgame + +Hypervisor-backed data protection can silently discard otherwise valid stores to `cred`, task-slab, or SELinux state. In that situation, avoid a credential-patching endgame and instead make an existing worker execute `call_usermodehelper_exec_work`; the helper inherits privileged kernel/init credentials without modifying the protected credential objects.[[2]](#references)[[3]](#references) + +A robust forged-work installation performs these checks before linking anything into a live pool:[[2]](#references)[[3]](#references) + +1. Read the target workqueue pointer and traverse its `pwqs` list (or a validated `dfl_pwq` for an unbound queue) to a `pool_workqueue` and `worker_pool`. +2. Validate pointer ranges and relationships such as `pwq->wq == wq`, then sanity-check `work_color`, `refcnt`, `nr_active`, `max_active`, and the pool work-list links. +3. Place a build-correct `subprocess_info` in kernel-accessible memory. Its embedded `work_struct.func` points to the slid `call_usermodehelper_exec_work`; `path`, `argv`, and `envp` point to stable kernel-accessible strings and arrays. +4. Encode `work_struct.data` with the selected PWQ and color, link `work.entry` into `worker_pool.worklist`, and update the matching PWQ accounting fields consistently. +5. Wake the chosen pool with legitimate work. The demonstrated port creates a `ptmx` allocation/free storm so normal queued work wakes a worker that also consumes the forged entry. + +The helper can execute a small script such as `/system/bin/sh umh.sh`, create a root marker, and launch a restricted command channel. Start the daemon before slow evidence collection or repeated `sync` calls, and persist its exit status and stderr because helper stdout and rate-limited audit output are unreliable debugging channels.[[2]](#references) + +## Runtime object discovery without perf leaks + +When perf-based object leaks are blocked or too slow, start at `init_task.tasks.prev`, subtract the build's `task_struct.tasks` offset, and walk the global list backward until `tgid` matches the exploit process. From `task_struct.files`, follow `files_struct.fdt -> fdtable.fd`, inspect each `struct file`, and find the ashmem/configfs-backed descriptor used for virtual writes.[[2]](#references)[[3]](#references) + +Bound every walk, require canonical/direct-map pointers, validate both list directions where possible, and reject unexpected TGIDs or `f_op` values. A corrupt list node should abort the attempt rather than becoming a second uncontrolled kernel write.[[2]](#references) + +## Cleaning forged pipe slots without a panic + +A forged pipe slot can reference a reserved kernel-image page that never received `get_page()`. Pipe teardown then calls `anon_pipe_buf_release -> __folio_put` on a zero-refcount reserved page; with `panic_on_oops=1`, the resulting bad-page warning resets the device.[[2]](#references) + +Use two independent cleanup layers:[[2]](#references) + +- **Descriptor holder:** an `atexit` handler forks a sleeping child that inherits all exploit FDs. The shared file descriptions never reach zero references, so pipe destruction is deferred until reboot. +- **Ring disarm:** before exit, use the surviving virtual-write descriptor to set `pipe_buffer.ops = NULL` for every forged slot. `free_pipe_info()` skips slots without operations instead of calling a release callback. + +Duplicating a forged slot with `tee()` is not a repair: it only moves the eventual invalid page put to the holder pipe. Keep the descriptor-holder fallback because a partial ring-disarm walk is itself firmware- and corruption-sensitive.[[2]](#references) + +## Path-based privileged-exec restrictions + +Some Android vendor controls kill UID-0 execution from writable paths while allowing trusted system paths. With `CAP_SYS_ADMIN`, a narrowly scoped bypass is to bind-mount the payload over a dormant trusted executable, execute the trusted pathname, and lazily detach the mount after daemonization. The A17 port shadows `/system/bin/lmkd`; this is preferable to overwriting a firmware-specific global DEFEX feature word because it avoids disabling enforcement system-wide.[[2]](#references)[[4]](#references) + +```sh +if mount --bind "$A/g4d" /system/bin/lmkd 2>"$A/g4d.mnt"; then + /system/bin/lmkd >"$A/g4d.out" 2>&1 + rc=$? + umount -l /system/bin/lmkd +else + "$A/g4d" >"$A/g4d.out" 2>&1 + rc=$? +fi +echo "G4D-RC=$rc" >"$A/g4d.rc" +``` + +For a reusable root channel, an abstract Unix socket avoids filesystem socket cleanup, `SO_PEERCRED` can restrict clients to explicitly allowed UIDs, and a fresh PTY per connection preserves interactive shell semantics. This remains per-boot access unless a separate boot-persistent modification is made.[[2]](#references)[[3]](#references) + +## Porting and test checklist + +The public port's workflow is useful beyond this specific bug:[[2]](#references)[[3]](#references) + +- Extract `boot.img` from the exact stock firmware and recover `vmlinux`/`Image` plus symbols and BTF. +- Audit every accessed member and symbol; refuse to run unless the runtime profile matches the expected build. +- Parameterize the physical kernel base instead of inheriting another device's value. +- Boot the real kernel and the same exploit binary in QEMU with an initramfs, applying only patches required for absent platform components. +- Automate success markers and poweroff, and test malformed fake objects, misaligned physical reads, forge-budget exhaustion, and pipe teardown before device deployment. +- Treat the race as probabilistic: preserve a healthy boot after ordinary failures and run bounded, observable retries instead of converting every miss into a reboot. + +## References + +- [1] [Nebula Security — IonStack Part 3: The First Public Android 17 Root](https://nebusec.ai/research/ionstack-part-3/) +- [2] [Mobile Hacking Lab — GhostLock: Root Shell on the Samsung Galaxy A17](https://mobilehackinglab.com/blog/cve-2026-43499-ghostlock-a17-root-shell) +- [3] [Mobile Hacking Lab — `ghostlock-a17` exploit and porting resources](https://github.com/mobilehackinglab/ghostlock-a17) +- [4] [Samsung Knox — Defeat Exploit (DEFEX)](https://docs.samsungknox.com/admin/fundamentals/whitepaper/samsung-knox-mobile-security/system-security/defeat-exploit/) + +{{#include ../../banners/hacktricks-training.md}} diff --git a/src/mobile-pentesting/android-app-pentesting/README.md b/src/mobile-pentesting/android-app-pentesting/README.md index 9cc0231c09e..26f70209cf6 100644 --- a/src/mobile-pentesting/android-app-pentesting/README.md +++ b/src/mobile-pentesting/android-app-pentesting/README.md @@ -31,6 +31,11 @@ Sometimes it is useful to **modify application code** to access **hidden informa - [Play Integrity attestation spoofing (SafetyNet replacement)](play-integrity-attestation-bypass.md)[[1]](#references) - [Android app-level virtualization / app cloning abuse & detection](android-application-level-virtualization.md) - [Shizuku Privileged API (ADB-based non-root privileged access)](shizuku-privileged-api.md) + +{{#ref}} +../../binary-exploitation/linux-kernel-exploitation/futex-pi-uaf-pipe-buffer-workqueue-usermodehelper.md +{{#endref}} + - [Exploiting Insecure In-App Update Mechanisms](insecure-in-app-update-rce.md) - [Abusing Accessibility Services (Android RAT)](accessibility-services-abuse.md) - [Android IME / InputMethodService Abuse (Malicious Keyboards)](inputmethodservice-ime-abuse.md)