
Незавершённый/WIP — исследовательский POC для CVE-2026-43499 (IonStack/GhostLock) для Samsung SM-T878U / gts7l. Триггер + геометрия проверены, рабочего root пока НЕТ.
[!CAUTION] ЭТОТ ПРОЕКТ НЕ ЗАВЕРШЁН — ОН ПОКА НЕ РАБОТАЕТ. По состоянию на 2026-10-06 рабочего root нет ни на одном устройстве. Не ожидайте, что приведённый ниже быстрый старт сработает. Прочитайте Текущий статус, прежде чем что-либо собирать или запускать.
[!WARNING] СТАТУС: В РАЗРАБОТКЕ — ring 1 не достигнут
- Не достигнуто: постоянный или хотя бы однократный
rootна SM-T878U.- Последний подтверждённый сбой: полезная нагрузка stack-reclaim так и не доходит до пути записи в ядре. За ~470 инструментированных запусков поддельная блокировка ни разу не была замечена как захваченная в
rtmutex.c:585, поэтому запись*(ASHMEM_MISC_FOPS) = fake_fopsникогда не выполняется.- Прежний блокер, теперь устранён: криминалистика сбоев ранее была недоступна для
uid 2000 shell(/proc/kmsg,/proc/last_kmsg,/sys/fs/pstore,dmesg→ всёEACCES). Теперь устойчивое зеркало журналаwrite()+fsync()(IONSTACK_LOG_MIRROR) переживаетCONFIG_PANIC_ON_OOPS=y, поэтому панический запуск всё равно оставляет полный след.- Полную цепочку доказательств см. в
docs/RTMUTEX_WEAPONIZATION.md§15.16–§15.18.
Доказательство концепции повторного получения root на чистом C с хост-ассистированием для Samsung Galaxy Tab S7 (SM-T878U / gts7l) против CVE-2026-43499 (IonStack / GhostLock).
Цепочка времени выполнения использует только нативные компоненты C/ELF. Она не требует
Python, Java, DEX, app_process или JVM на целевой Android-системе. ADB используется
для развёртывания и проверки.
Root не получен. Этот раздел является авторитетным, актуальным
описанием состояния цепочки (последняя редакция 2026-10-06). Всё
ниже измерено на реальном оборудовании (SM-T878U, T878USQS8DXE1, ядро
4.19.113-27114284), а не в теории.
| Этап | Статус | Доказательство |
|---|---|---|
| Идентификация цели + утечка KASLR | работает | [reroot] LEAK_OK kaslr_base=… task=… (побочный канал perf) |
Триггер CVE: FUTEX_CMP_REQUEUE_PI → -EDEADLK | работает | [*] requeue ret=-1 errno=35 — EDEADLK == 35 в Linux |
Ошибочный откат оставляет висячий pi_blocked_on | совпадает с upstream-исправлением | upstream 3bfdc63936dd меняет current->pi_blocked_on → waiter->task->pi_blocked_on |
Раскладка struct rt_mutex_waiter (4.19) | проверено по исходникам | tree_entry@0x00 pi_tree_entry@0x18 task@0x30 lock@0x38 prio@0x40 deadline@0x48 |
Геометрия стека paint == rt_waiter + 0x28 | проверено 4×, вкл. objdump | rt_waiter = do_futex_sp+0xC0; address = ___sys_sendmsg_sp+0xB8 |
| Устойчивая криминалистика сбоев | работает | след IONSTACK_LOG_MIRROR write()+fsync() переживает паническую перезагрузку |
| Тег идентичности frag-страницы на сообщение | работает | reclaim-scan tag=1 sent=8201 range=1..8201 ok=8192 bad=0 dup=0 undecoded=0 absent=9 |
| Сканирование очереди: ядро записало 0 байт в 8192 поставленных в очередь frag-страниц | проверено | 256 МБ побайтово сравнены с полезной нагрузкой, hits=0 |
rt_mutex_adjust_prio_chain достигает пути записи | проверено по дизассемблированию | top_waiter == NULL ⇒ requeue остаётся true ⇒ 664/682/685/716-725 структурно достижимы |
page-dump и 45 наблюдений ring1-page сообщают
first_diff=8000 (pristine), owner_cpu=00000000, case1_gate=0 и
lock_root/lock_leftmost, в точности равные значению полезной нагрузки. Ни разу не наблюдалось, чтобы обход
брал fake_lock->wait_lock в rtmutex.c:585, поэтому
664/682/685/716-725 — единственная ветвь, которая может записать в
*(ASHMEM_MISC_FOPS) — никогда не выполнялась.
Отметим, что _raw_spin_trylock()/_raw_spin_unlock() идут через
внешние хелперы, и в этом вендорском дереве нет переопределения
queued_spin_unlock для arm64, поэтому wait_lock.val == 1 — надёжный
свидетель 585, а owner_cpu != 0 — лишь вторичный.prctl(PR_SET_MM, PR_SET_MM_MAP, …). В этом ядре
# CONFIG_CHECKPOINT_RESTORE is not set, поэтому этот системный вызов
скомпилирован вне ядра.
Он также никогда не использует sendmsg — наше средство, — что, весьма вероятно, и есть корневая
причина (1).ring1-read никогда не выполнялся. Единственное чтение ring 1 из
пространства пользователя (configfs_read_once(fd, data_addr(ASHMEM_MISC_FOPS), …)) находится за
шлюзом сканирования очереди и за значением по умолчанию MARKER в харнессе, которое останавливается на 8 с
раньше на ring1-page. Каждый запуск, дошедший до шлюза, умирал между
page-dump tag=pre-arm и page-dump tag=post-arm.664/682/685 могут завершиться внутри нашей
собственной страницы — IONSTACK_FOPS_WAIT_LOCK_WORD=0 с
IONSTACK_PAINT_WAITER_TASK_MODE=fake-task — и прочитать
page-dump tag=post-arm / ring1-lock585 на предмет wait_lock=00000001.ring1-read: запустить с незаданным IONSTACK_RECLAIM_SCAN_QUEUE и
MARKER='ring1-read|…', чтобы харнесс не останавливался на ring1-page.IONSTACK_RECLAIM_TAG=1 и сравнить
pipe_tag с msg_tag в page-dump. Все frag-страницы — побайтово идентичные
копии полезной нагрузки, поэтому по одному first_diff их не различить.IONSTACK_FOPS_WAIT_LOCK_WORD на корректно поставленной
основе — wlw=0 против wlw=1 при неизменном IONSTACK_RECLAIM_TAG. Более
ранняя корреляция была искажена тем, что две переменные менялись вместе.pselect6 res_in/res_out из порта K40 4.19.fops.c:3157 reason=selinux_write ret=-1 errno=22 EINVAL — всё ещё не решён.