Share
## https://sploitus.com/exploit?id=CD36E9D2-A95B-5CDA-8BE6-59EAE6D0B2D1
# CVE-2026-43499 โ€” `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.

## Target

```text
device  : aristotle (au/KDDI XIG04), MediaTek, Android 12
kernel  : 5.10.136-android12-9-00020-gc9f59ef34367-ab9585114  (VA=39, 4K pages, KASLR)
```

## The bug

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`, `CFI`, `SCS`).

## What differs from upstream (popsicle โ†’ aristotle)

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.
- **No `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`.
- **No BTF in this kernel**, so struct offsets are recovered by disassembly and
  injected rather than read from BTF.
- All offsets, RVAs and KASLR anchors were measured for this exact kernel โ€” see
  `ARISTOTLE_CVE43499_PORT.md`.

## Generate the target header

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):

```sh
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.)

## Build

Needs Python 3 and the Android NDK (r29). **`API=31` is required** so the
payload loads on Android 12:

```sh
make -C source clean preload API=31
```

If the NDK isn't auto-detected:

```sh
NDK_ROOT=/path/to/android-ndk make -C source clean preload API=31
```

Final artifact:

```text
source/build/bin/preload.so
```

## Run

```sh
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:

```text
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 in `ARISTOTLE_CVE43499_PORT.md`.