futex requeue Towelroot LPE (CVE-2014-3153)¶
Linux
futex_requeue()priority-inheritance path'indeki bir logic flaw, free edilmiş kernel-stack memory'sine referans veren dangling bir rt_waiter bırakır — geohot tarafından Towelroot Android root'u olarak paketlenmiştir.
Mechanism¶
Kırılan invariant
kernel/futex.c içindeki futex_requeue() (Linux ≤ 3.14.5), source ve
destination futex adreslerinin farklı olduğundan emin olmaz ve
priority-inheritance (PI) requeue kurallarını yanlış handle eder. İki mantıksal
flaw birleşir: bir PI futex değeri userspace'ten 0'a release edilebilir
(sahte biçimde availability sinyali verir) ve bir PI waiter uygunsuz biçimde
self-/double-requeue edilebilir; bu da yalnızca non-PI waiter'ların PI futex'lere
requeue edilmesi kuralını ihlal eder. Sonuç, scope dışına çıkmış kernel-stack
memory'sine referans veren dangling bir rt_waiter node'udur — unprivileged bir
task tarafından erişilebilen bir kernel-memory-corruption primitive'i.
Kavramsal akış (boyutlar/adresler kernel'e göre değişir):
Normal requeue Buggy self-/double-requeue
-------------- --------------------------
syscall frame (kernel stack) syscall frame returns -> popped
+-----------------+ +-----------------+
| rt_waiter |<--- PI futex | (stale data) |<--- PI futex
| (alive, on | waiter list | reused for | waiter list
| active frame) | | other calls | still points
+-----------------+ +-----------------+ here (dangling)
^ ^
in-scope, valid out-of-scope freed stack
= UAF write/read primitive
Walkthrough¶
Public CVE-2014-3153 writeup'larından alınan kavramsal reproduction.
- Sonraki acquisition'ların bloklanması için bir PI futex'i lock'la.
- Non-PI bir futex'ten
FUTEX_WAIT_REQUEUE_PIissue et; böylecert_waiter'ı kernel stack'inde yaşayan bir waiter oluştur. - O waiter'ı
FUTEX_CMP_REQUEUE_PIile PI futex'e requeue et. - Lock availability'sini spoof etmek için PI futex değerini userspace'ten 0'a overwrite et.
- PI waiter'ı self-requeue et ki düzgün cleanup olmadan uyansın ve free edilmiş stack memory'sine giden bozuk / dangling bir list node bıraksın.
- O kernel-stack bölgesini (örn.
sendmmsgile) forge edilmiş waiter yapılarıyla yeniden işgal et,thread_info'yu bulmak için adresleri leak et, access kısıtlamalarını kaldırmak içinaddr_limit'i overwrite et (bkz. addr_limit overwrite), sonra root için process'incredUID/GID'lerini sıfırla.
Detection¶
- Aynı source / destination uaddr'larıyla
FUTEX_CMP_REQUEUE_PI/FUTEX_WAIT_REQUEUE_PIissue eden process'ler (geçersiz durum). - futex syscall'larıyla birlikte kernel-stack grooming için kullanılan olağandışı
sendmmsg/recvmmsgaktivitesi. - Meşru bir setuid path olmadan ani UID/GID geçişinin 0'a olması;
addr_limit/ cred tampering. - Android'de, bir root shell spawn eden third-party app process'i.
- futex op kombinasyonunu unprivileged task'lardan flag'leyen Audit / seccomp logları.
Mitigation¶
- Düzeltilmiş bir kernel'a patch'le (upstream commit
e9c243a5a6de, requeue source ve destination futex'lerinin farklı olduğunu doğrulayan bir check ekler); 3.14.6+ kernel'lar ya da backport'lu olanlar korumalıdır. - Android cihazları Haziran 2014'ten sonra build edilmiş kernel'lara güncelle.
- Untrusted process'ler için tehlikeli futex requeue operasyonlarını kısıtlamak üzere seccomp-bpf kullan.
- SMAP/SMEP ve kernel-stack hardening, stack-reuse primitive'i üzerindeki çıtayı yükseltir.