
aristotle (au/KDDI Xiaomi XIG04)Local privilege escalation (tmp-root) for the au/KDDI Xiaomi "aristotle" (XIG04) on Android 12, via CVE-2026-43499. It is a device-owner rooting primitive: it roots your own phone (e.g. to re-enable ADB when developer options are unreachable).
This is an aristotle port of the upstream implementation:
https://github.com/x-spy/CVE-2026-43499-popsicle — which targets the Xiaomi
17 / Pro / Ultra (popsicle, Snapdragon, Android 16, kernel 6.12.23). All
credit for the exploit technique goes upstream; this fork only retargets it to a
different device and kernel generation.
Scope: your own XIG04 running
Xiaomi/XIG04_jp_kdi/XIG04:12/SP1A.210812.016/V14.0.3.0.TMFJPKD. Not a general-purpose or remote exploit.
device : aristotle (au/KDDI XIG04), MediaTek, Android 12
kernel : 5.10.136-android12-9-00020-gc9f59ef34367-ab9585114 (VA=39, 4K pages, KASLR)
CVE-2026-43499 is a use-after-free in the Linux kernel Futex-PI path:
remove_waiter() in kernel/locking/rtmutex.c operates on current instead of
waiter::task during proxy-lock rollback from futex_requeue(), leaving a
dangling pi_blocked_on. It is an old, long-lived bug (affected Linux
2.6.39 – 6.18.x), so the 5.10.136 kernel here is in range
(CONFIG_FUTEX_PI=y, CONFIG_RT_MUTEXES=y). The exploit uses a data-only
"direct-root" (swap cred → init_cred, flip SELinux enforcing) and
brute-forces MTE tags to survive the device's hardening
(KASAN_HW_TAGS, MTE, , ).
Upstream targets Snapdragon / Android 16 / kernel 6.12; aristotle is MediaTek / Android 12 / kernel 5.10, so the port re-derives everything device-specific:
rt_mutex_waiter is the old flat 5.10 layout (no nested rt_waiter_node,
no wake_state/ww_ctx). The fake-waiter tables in source/src/{slide,fops}.c
and source/src/util.c are rebuilt from 13 words to 10.xbl_config. KASLR is defeated dynamically (kernel info-leak in
slide.c); the two physical constants upstream took from the Qualcomm XBL are
replaced by a static DRAM base (0x40000000, from the device tree) plus
runtime memstart_addr / kimage_voffset.ARISTOTLE_CVE43499_PORT.md.A measured source/src/target.h for XIG04 is already committed, so you can build
directly. To regenerate it from a boot image, use the aristotle generator (no
--xbl-config; it emits memstart_addr/kimage_voffset RVAs for dynamic use):
python3 gen_aristotle_target.py \
--boot boot.img \
--pselect-shift 0 \
--loggers 0xffffffc012771380 \
--boot-id-data 0xffffffc012886cf8 \
--kernel-phys-load 0x40080000 \
-o source/src/target.h
(The three anchors and the kernel-phys-load are the values baked into the
committed header; see ARISTOTLE_CVE43499_PORT.md for how they were obtained.)
Needs Python 3 and the Android NDK (r29). API=31 is required so the
payload loads on Android 12:
make -C source clean preload API=31
If the NDK isn't auto-detected:
NDK_ROOT=/path/to/android-ndk make -C source clean preload API=31
Final artifact:
source/build/bin/preload.so
adb push source/build/bin/preload.so /data/local/tmp/preload.so
adb shell 'chmod 0644 /data/local/tmp/preload.so'
adb shell 'LD_PRELOAD=/data/local/tmp/preload.so /system/bin/true'
adb shell '/data/local/tmp/su -c id'
On success:
uid=0(root) gid=0(root) groups=0(root) context=u:r:kernel:s0
direct-root-summary root=1 id=1 su=1/... selinux=1->0 uid=0 euid=0 gid=0 egid=0
preload.so embeds and self-installs its own su client + daemon when loaded,
so no separate su binary is needed.
Status: the port is code-complete from static analysis but not yet validated on hardware. Validate the crash trigger first, then root, on your own device. Kernel-specific tuning items (
MM_ORDER,P0_KERNEL_PHYS_LOAD, the flat-waiter behavior) are listed inARISTOTLE_CVE43499_PORT.md.
CFISCS