Repository navigation
Locked-bootloader root on Redmi K70 Pro (manet, kernel 6.1.118): working temp-root via mqsas, and where persistent root got stuck #3905
jiusi1-cpu
started this conversation in
Show and tell
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
TL;DR
A vendor-left injection channel gives working temporary root on the Redmi K70 Pro (locked bootloader). Persistent root is not achieved — this post documents exactly where it got stuck, in case it's useful to others on the same kernel.
manet/ 23117RK66C / SM8650)OS3.0.9.0.WNMCNXM6.1.118-android14-11-gca0ef6d17716-ab13624819, KMIandroid14-6.1,+pgo,+bolt,+ltoro.boot.flash.locked=1,sys.oem_unlock_allowed=0)ksud3.1.0-29-gf0615d3c, injected vialate-load1. Working temporary root (not an exploit — a vendor channel)
The injected process lands as
uid=0(root) gid=1000(system) context=u:r:hypsys_ssi_default:s0.Constraints worth knowing:
ro.boot.selinuxreads backenforcingeven when the fastboot arg was passed — usegetenforce, not the prop.late-loadruns moduleservice.sh, and those scripts commonly flip SELinux back to Enforcing (e.g.if Permissive then setenforce 1). You get one shot.2. Where persistent root got stuck
2.1 HyperOS blocks framework interfaces even as root
In domain
u:r:su:s0, withuid=0andCapEff=000001ffffffffff:Dropping to
su 2000doesn't help — the context is stillu:r:su:s0.⇒ after escalation you cannot use framework APIs at all. Only kernel/sysfs nodes, direct PID kills, and
dumpsys(read) remain useful. Worth knowing if you plan to do post-exploitation setup fromservice.sh.2.2 Some of the sysfs nodes KernelSU-style tuners write are read-only
Resolved from the Joyose cloud config (
/data/data/com.xiaomi.joyose/databases/teg_config.db), Xiaomi writes these itself:policy{0,2,5,7}/walt/target_load_thresh-r--r--r--policy{0,2,5,7}/walt/target_loads-r--r--r--policy{0,2,5,7}/walt/hispeed_freq-r--r--r--policy{0,2,5,7}/walt/pl,rtg_boost_freq-rw-r--r--✅Even as root, writing the 0444 sysfs nodes fails with
Permission denied. Any module that writes those is silently doing nothing. The writable levers here were/proc/sys/walt/sched_fmax_cap,kgsl-3d0/max_gpuclk, and several/sys/module/migt/parameters/*entries.2.3 A locked-bootloader kernel UAF route, and the wall it hit
Explored
CVE-2026-43499(futex PI stack UAF) as a path to persistent root. Feasibility pre-check passed (__arm64_sys_futex → bl do_futex → bl futex_wait_requeue_pi, none LTO-inlined), and stack geometry worked out:CONFIG_RANDOMIZE_KSTACK_OFFSETis compiled in but off by default (static key initial 0), so the geometry is deterministic.Two independent findings that may be useful to others:
Published
rt_mutex_waiteroffsets appear wrong for this build. Measured layout (3 independent disassembly proofs):pi_tree_entrytasklockpriodeadlineKey evidence — one
stpwrites both pointers:Laying data out against
+0x58would silently misalign.Hard threshold that prunes candidates cheaply. With
D= stack depth from syscall entry to the copy site andoff_b= buffer offset in the frame (off_b ≥ 0):Any syscall carrier shallower than that is structurally out, no matter the buffer size. Three carriers passed (
rt_sigreturnfpsimd restore atSP0-0x280, ashmemASHMEM_SET_NAMEioctl atSP0-0x228,sendmsgatSP0-0x1C8).The blocker: 6.1
core_sys_selectuseskvmalloc_nodefor the fd bitmap — heap, not stack — so the pselect-style stack overlay can't reach the freed waiter, and theres_*stack buffers used by theSLIDE_PSELECT_RES_ENCODEroute don't exist in this kernel.The unsolved core: geometry says a buffer can overlap the waiter, but nothing yet shows the kernel will dereference the overwritten slot inside the free/reuse window. That distinction is the whole game, and it's where this stopped.
3. Why post this here
Two reasons:
am/pm/appops/settingsblock inu:r:su:s0is a post-exploitation constraint that module authors on HyperOS/ColorOS builds will run into, and it's not obvious until you hit it.walt/*sysfs discovery means some commonly-copied tuning writes are no-ops. If a module relies on them, that's a silent failure worth checking.Full write-up (device facts, geometry derivation, carrier list, dead ends, open questions):
https://github.com/jiusi1-cpu/manet-persistent-root-research
Includes an English README. Happy to provide kernel disassembly dumps for any of the addresses above. If any of this is already known for 6.1 GKI, feel free to correct me — that's the main reason for posting.
All reactions