
Shizuku-driven CVE-2026-98260 root + KernelSU runtime LKM loader for Xiaomi yingtian / lhasa (kernel 6.18.21)
Chinese translation:
README.zh-CN.md— a translation of this file; if the two disagree, this English file is authoritative.
Local privilege escalation + KernelSU for the Xiaomi yingtian (Pad 9 Pro
Max) and lhasa (Xiaomi 18 Fold) family on HyperOS 4 (Android 17, kernel
6.18.21). The whole chain is delivered as a normal Android app that drives
Shizuku in shell mode, exploits
CVE-2026-98260, and loads the KernelSU-family LKM that matches the installed manager
(KernelSU / KernelSU-Next / SukiSU) — no PC, no unlocked bootloader, no
partition changes.
Research / education / device-repair project. Boot-only (a reboot removes it). Only run on devices you own. Read
docs/SECURITY.mdbefore using it.
Agents / automated contributors: start with AGENTS.md (entry
point: invariants, build/test recipes, traps, hygiene), then
docs/AGENT_HANDOFF.md (verified state, failed
experiments, open work). Run bash scripts/verify.sh before committing; it also
rebuilds the payload/APK when the toolchain environment is set.
中文版: AGENTS.zh-CN.md /
docs/AGENT_HANDOFF.zh-CN.md
| release | v3.2 (release/o3root2-v3.2.apk, 14,239,248 B, sha256 64bbc654…) |
| O1 test build | v3.3.3-o1-test (release/test/o3root2-v3.3.3-o1-test.apk, 14,247,440 B, sha256 62411f72…): v3.2 plus an experimental O1 (XRING) profile (dijun / jinghu / violin) and the hidden root console. Accepts any OS4.0.0.x build on the 6.18.21-android17…-4k kernel series: the analysed build is the verified path, other builds run in relaxed mode with a warning; for testers only, never hardware-validated |
| previous test build | v3.2.1-console (release/beta/o3root2-v3.2.1-console.apk, 14,243,344 B, sha256 9cba365a…): stable v3.2 plus a hidden root console (long-press the version row; three confirmations) |
| O1 devices | Xiaomi O1 SoC dijun / jinghu / violin on OS4.0.0.x: all three ship the same 6.18.21 kernel (sha256 0d9917ca…, g1d099fcb35e0); static analysis says the chain applies, no device test yet |
| custom LKM | optional user-supplied KernelSU-family .ko (basic compatibility check; falls back to the built-in adaptive module; the choice is saved and restored on launch — long-press the row to clear) |
| chain | Shizuku shell → CVE-2026-98260 → uid=0 + full caps → matching KernelSU LKM (KernelSU / KernelSU-Next / SukiSU) → rootd |
| persistence | none (current boot only) |
| tested device | Xiaomi Pad 9 Pro Max yingtian, HyperOS OS4.0.16.0.XBMCNXM |
| second device | lhasa (Xiaomi 18 Fold, OS4.0.26.0.XPNCNXM): the boot kernel is bit-identical to yingtian's (sha256 cde87cd7…), so the same payload applies; not device-tested |
/system/bin/sh -c … through Shizuku's newProcess, so the
payload runs in u:r:shell:s0 (uid=2000).CLOCK_THREAD_CPUTIME_ID + execve/de_thread
race (CVE-2026-98260), reclaims the freed posix_timers_cache order-1 slab
page with a sprayed kmalloc-8k buffer containing a forged RB-tree node, and
uses the second timerqueue_del → rb_erase to write one 8-byte value to an
arbitrary kernel address.enforcing with an 8-byte unaligned write at
selinux_state-7 (this also clears the adjacent notif_lock pending/tail
bytes; initialized/policycap stay intact); stage 1 writes
task_struct.cred to a fake cred page (uid 0, full caps)./proc/kallsyms (fallback: 248-symbol union relink + the
current KASLR slide), with no init patch — because policycap stayed
clean, KernelSU's own setenforce(1) is harmless and the device ends in
Enforcing. Then it is insmoded and a rootd daemon is left behind
(abstract socket @o3p_rootd, peer-uid 0/2000). Upstream KernelSU,
KernelSU-Next and SukiSU LKMs all work (legacy: O3P_CODEPATCH=1 patches the
setenforce immediate). Since v3.1 the app can instead load a .ko you pick
(basic ELF/.modinfo compatibility check, automatic fallback to the built-in
LKM when it is rejected or fails to load). Since v3.1.1 that selection is
persisted (files/custom-ko.ko + custom-ko.meta) and restored on launch;
a stale file that no longer validates is dropped, and a long press on the
module row clears it. Since v3.2 the log box is selectable and has a
复制 action that copies the whole log; it only auto-scrolls while you
are already near the bottom. On a recognised O1 device the test build
asks for a two-step risk confirmation before the payload starts. The test
build additionally hides a root console behind a long press of the
version row: three non-skippable confirmations, then commands run as root
through the rootd socket (requires one payload run in the current boot).
The stable build does not contain the console classes.See docs/ARCHITECTURE.md for offsets, the write
primitive, the KernelSU patch and the porting guide.
shizuku_plus_server must run as uid=2000, u:r:shell:s0.release/o3root2-v3.2.apk (MIUI may need "Install via USB" allowed).★ UIDNOW uid=0,
★ KSU_MODULE LIVE, and the KernelSU manager opens automatically.Testing on an O1 device (dijun / jinghu / violin)? Install
release/test/o3root2-v3.3.3-o1-test.apk
instead and follow docs/TESTING_O1.md. The gate accepts
the three codenames on any 6.18.21-android17…-4k kernel (OS4.0.0.x); the
analysed build g1d099fcb35e0 gets the verified path, other builds log
固件门禁通过(O1 宽松模式:…) and reuse the O1 address with a warning. The
payload logs SELINUX_PROFILE kernel=… base=… src=env|uname, so the report
only needs the exported log.
No manager installed? The button turns into Install KernelSU manager and installs the bundled APK (accept the system prompts).