CVE-2021-39815: PowerVR GPU driver pinned-memory unpin use-after-free¶
PowerVR GPU driver'ı, unprivileged bir app'in memory'yi pin'lemesine, sonra unpin edip kernel'in backing page'leri free etmesine izin vermesine, ve ardından o page'leri GPU çağrılarında kullanmaya devam etmesine olanak tanır — özel privilege gerektirmeden kernel memory corruption'a yol açan bir use-after-free.
Mechanism¶
Neden çalışır: unpin, page'i ayakta tutan reference'ı düşürür ama GPU mapping'leri onu hâlâ kullanır
PowerVR (Imagination Technologies) GPU driver'ı, page'lerin GPU tarafından referans edilebilmesi için userspace'in onları pin'lemesine izin verir. Pinning, GPU page'e dokunabilecekken page'in free edilip kernel tarafından reclaim edilmesini engelleyen bir reference alır; unpinning o reference'ı serbest bırakır. Lifetime sözleşmesi şu: GPU'nun hâlâ referans ettiği bir page pin'li kalmalı.
Bug bu sözleşmeyi bozar. Driver, userspace'e pin reference'ını düşüren bir unpin operasyonu sunar — page'i free edilmeye uygun hale getirir — ama hâlâ page'e işaret eden GPU-side mapping'leri veya device reference'larını invalidate etmeden. Yani unprivileged bir app şunu yapabilir:
- Driver üzerinden memory allocate / pin edip, GPU'nun kullanabileceği bir handle alır.
- O memory'yi unpin eder. Bu, backing page'i tutan reference'ı serbest bırakır; kernel'in bakış açısından page artık free edilip alakasız bir amaç için yeniden allocate edilebilir.
- Handle'ı GPU çağrılarında kullanmaya devam eder. GPU (ve driver'ın handle için bayatlamış bookkeeping'i) artık free edilmiş page'i hâlâ okur/yazar.
2–3. adımlar bir use-after-free (CWE-416): physical page free edilip başka bir kernel allocation'a verilmiştir, ama GPU ve driver hâlâ geçerli olan handle üzerinden ona erişmeye devam eder. GPU page'i okuyup yazabildiği için, attacker free edilen page'i reclaim eden hangi kernel object olursa ona read/write kazanır — güçlü bir corruption primitive. Kritik olan, hiç privilege gerekmemesi: bütün dizi, PowerVR device node'una ulaşabilen sıradan bir Android app'ine açık.
Bu, sonraki cve-2022-20122-powervr-gpu-driver-pinned-memory-unpin-free.md pinned-memory bug'ıyla aynı lifetime-confusion ailesinden. Android ID A-232440670 olarak takip edildi ve Android 2022-08-05 security patch level'ında düzeltildi.
Walkthrough¶
Tetikleyici, PowerVR services interface'ine karşı pin / unpin / tekrar-kullan dizisidir. Kavramsal akış (public advisory kısa; tam bridge ioctl id'leri device/DDK'ya özgü):
Pin'le, unpin et, sonra page'i kullanmaya devam et
/* Open the PowerVR services device node (name varies by platform). */
int fd = open("/dev/pvr_sync", O_RDWR); /* or platform pvrsrvkm node */
/* 1. Allocate and pin memory so the GPU can reference it. The driver
returns a handle and holds a pin reference on the backing page(s). */
handle_t h = pvr_alloc_and_pin(fd, size);
Şimdi handle'ı tutarken pin'i düşür, sonra onu dereference eden GPU işini issue etmeye devam et:
/* 2. Unpin: releases the reference that kept the page from being freed.
The driver does NOT tear down the GPU-side mapping/handle. */
pvr_unpin(fd, h);
/* 3. Encourage the kernel to free and reallocate the now-unpinned page
(allocation pressure / targeted spray), so a victim object lands on it. */
spray_kernel_objects();
/* 4. Keep using the same handle in GPU calls -> GPU reads/writes the freed
page, now owned by the victim object: a use-after-free read/write. */
pvr_gpu_submit_using(fd, h);
Zafiyetli bir build'de beklenen sonuç: h üzerinden yapılan GPU erişimleri,
başka bir kernel allocation tarafından reclaim edilmiş free bir page'e iner ve
kontrollü corruption verir. Exploit'ler page'i, corruption'ı escalation veren
(refcount/pointer overwrite) bir object'le reclaim eder, sonra kernel R/W'ye
pivot eder — bkz.
dirty-pagetable-page-table-data-only-attack.md.
Fix'li bir driver'da (Android 2022-08-05+), unpinning ya ilişkili GPU mapping'lerini/handle'ını yıkar ya da hâlâ referans edilen bir page'i serbest bırakmayı reddeder, böylece sonraki GPU çağrıları artık free bir page'e dokunmaz.
Detection¶
Göstergeler
- PowerVR memory'yi pin'leyen, unpin eden ve sonra aynı handle'ı referans eden GPU işini submit etmeye devam eden unprivileged process'ler.
- Yakın zamanda unpin edilmiş page'ler üzerindeki KASAN use-after-free raporları veya PowerVR services modülünden kaynaklanan corruption oops'ları.
- Cihazların 2022-08-05 (veya sonrası) Android patch level'ını taşıdığını doğrula.
Mitigation¶
Fix ve hardening
- Android 2022-08-05 security patch level'ını veya sonrasını uygula
(Android ID A-232440670) — PowerVR DDK /
pvrsrvkm.ko'yu fix'li bir build'e güncelle. - GPU device node'larına erişimi SELinux ile kısıtla, böylece keyfi app'ler pin/unpin yüzeyine erişemesin.
- Defense-in-depth UAF mitigation'ları (slab freelist hardening, testte KASAN, delayed/quarantined free'ler) free edilmiş page'i işe yarar bir victim object'le reclaim etmenin maliyetini artırır.