Skip to content

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.

  1. Sonraki acquisition'ların bloklanması için bir PI futex'i lock'la.
  2. Non-PI bir futex'ten FUTEX_WAIT_REQUEUE_PI issue et; böylece rt_waiter'ı kernel stack'inde yaşayan bir waiter oluştur.
  3. O waiter'ı FUTEX_CMP_REQUEUE_PI ile PI futex'e requeue et.
  4. Lock availability'sini spoof etmek için PI futex değerini userspace'ten 0'a overwrite et.
  5. 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.
  6. O kernel-stack bölgesini (örn. sendmmsg ile) 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çin addr_limit'i overwrite et (bkz. addr_limit overwrite), sonra root için process'in cred UID/GID'lerini sıfırla.

Detection

  • Aynı source / destination uaddr'larıyla FUTEX_CMP_REQUEUE_PI / FUTEX_WAIT_REQUEUE_PI issue eden process'ler (geçersiz durum).
  • futex syscall'larıyla birlikte kernel-stack grooming için kullanılan olağandışı sendmmsg / recvmmsg aktivitesi.
  • 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.

References