Skip to content

PUAF (Physical Use-After-Free) primitive

Physical page'lerin kernel'e geri free edilip, userspace'in hâlâ onları map'leyen dangling read/write PTE'leri tuttuğu bir primitive; o page'lere sonradan reallocate edilen her kernel object üzerinde read/write verir.

Mechanism

PUAF, felix-pb'nin kfd exploit'lerinin (PhysPuppet, Smith, Landa) kalbindeki generic primitive'dir. Klasik bir use-after-free, free edilmiş bir object'e virtual bir pointer dangle ederken, bir PUAF bir page-table entry dangle eder: physical page free list'tedir, ama saldırganın address space'indeki geçerli bir PTE hâlâ ona VM_PROT_READ | VM_PROT_WRITE ile işaret eder.

Note

Bir kernel'in koruduğu invariant şudur: bir physical page yalnızca onu map'leyen her PTE söküldükten sonra yeniden kullanılabilir (pmap_disconnect()). Bir PUAF bug'ı bunu ihlal eder: bir VM/pmap desenkronizasyonu üzerinden (örn. hizalanmamış bir VM entry, bir double map ya da reap'te eksik bir pmap_disconnect()), page PTE'si hayatta kalırken free edilir. Dolayısıyla saldırganın, kernel'in free olduğuna inandığı — ve bir sonraki allocation isteğine teslim edeceği — ham physical memory'yi okuyup yazan kararlı bir user VA'sı olur. Oraya hangi kernel object düşerse hiçbir kernel pointer'ı forge edilmeden saldırgan tarafından okunabilir ve yazılabilir hâle gelir; PUAF'in yalnızca pointer'ları koruyan zone_require() / data-PAC gibi mitigation'ları atlatmasının nedeni budur.

Walkthrough

Bir PUAF exploit'inin iki yarısı vardır: (1) dangling PTE'leri üreten bir bug, (2) onu kernel read/write'a (krkw) çevirmek için generic bir "grab + reallocate + scan + corrupt" pipeline'ı.

// (1) A bug (e.g. PhysPuppet / Landa) leaves N dangling R/W PTEs at puaf_uaddr.
//     The physical pages behind them are now free.

// (2a) grab_free_pages: force the kernel to reallocate the freed pages with
//      a target object. kfd uses krkw_helper_grab_free_pages() driving
//      vm_copy() over purgeable regions until the PUAF pages are reused.

// (2b) spray a recognizable kernel object into the freed pages, e.g.
//      kqueue_workloop_ctl() -> kqworkloop, sem_open() -> psemnode, dup() -> fileproc

Exploit ardından PUAF page'lerini, ektiği bir magic value için dangling PTE'ler üzerinden tarar, hedef object'i bulur ve PAC'lı olmayan bir pointer'ı corrupt eder:

// (3) overwrite a pointer inside the reclaimed object via the dangling PTE:
//       socket method:  inp6_outputopts
//       kqueue method:  kqwl_owner
// (4) a normal syscall that follows that pointer now reads/writes attacker memory,
//     e.g. kread_sem_open() abuses psemnode->pinfo via proc_info() to leak 8 bytes.
Tam kernel R/W'ye bootstrapping

İlk zayıf kread8/kwrite8, daha hızlı, arbitrary-size bir primitive kurmak için kullanılır. Desteklenen build'lerde kfd perfmon tabanlı bir read/write (perf_init() / perf_free()) bootstrap eder; ardından exploit'in temiz arbitrary kernel memory erişimi olur ve credential'ları yamalayıp / unsandbox edebilir.

Warning

PUAF, reallocate edilen page'lerin physical read/write'ını verir — son derece güçlü, ama saldırgan, kernel free edilmiş page'leri inert bir şey için yeniden kullanmadan (ya da bayat bir mapping'de panik etmeden) önce onları yararlı bir object'le reallocate etme race'ini kazanmalıdır. Güvenilirlik grab/spray sıralamasına bağlıdır.

Detection

  • Etkilenen Apple build'lerinde page-fault / pmap anomalileri ve panik'ler.
  • purgeable-memory + spray syscall'larının (kqueue_workloop_ctl, sem_open) hızlı ardışıklıkla yoğun kullanımı karakteristiktir.

Mitigation

  • Altta yatan VM/pmap desenkronizasyon bug'larını düzelt, böylece page'ler asla live PTE'lerle free edilmez.
  • zone_require() ve PAC, PUAF sonrası corruption adımının maliyetini yükseltir; daha yeni Apple silicon'daki PPL/SPTM doğrudan physical-page kurcalamasını kısıtlar.

References