Skip to content

Rooting with root cause: finding a variant of a Project Zero bug (CVE-2022-46395)

Arm Mali GPU driver'ının imported-user-buffer handling'inde bir page use-after-free; CVE-2022-36449'un (Project Zero issue 2327) bir variant'ı olarak bulundu ve untrusted bir app'ten kernel code execution ile root sağlıyor.

Mechanism

Note

User application'lar Mali GPU ile KBASE_IOCTL_MEM_IMPORT kullanarak memory paylaşır; bu, KBASE_MEM_TYPE_IMPORTED_USER_BUF tipinde bir kbase_va_region oluşturur. Backing page'ler user space'in mülkiyetinde kalır ve import sırasında pin'lenmez. Bunlar, kaynağa ihtiyaç duyan bir GPU softjob çalıştığında lazy olarak pin'lenir: kbase_jd_user_buf_map, kbase_jd_user_buf_pin_pages'i çağırır ve bu da user page'ler üzerinde refcount almak için get_user_pages kullanır, böylece job ortasında free edilmezler.

Kırılan invariant şu: driver, imported page'ler üzerinde oluşturduğu CPU/GPU mapping'lerinin page'lerle aynı lifetime'a sahip olduğunu varsayar. CVE-2022-36449'un root-cause analizi, imported memory'nin yönetilme şeklinde bir sapma ortaya çıkardı — imported page'ler üzerindeki vmap tabanlı mapping'ler (kbase_vmap_prot), artı sticky-resource map/unmap path'i, gerçek page lifetime'ından desync olabiliyor. KBASE_IOCTL_STICKY_RESOURCE_MAP / KBASE_IOCTL_STICKY_RESOURCE_UNMAP ioctl'leri, aynı page'leri eşzamanlı olarak map'leyip yazan softjob'a karşı düzgün synchronization olmadan mapping usage count'larını ayarlar. Sonuç olarak, kernel hâlâ onlara canlı bir mapping tutarken backing page'ler free edilebilir: klasik bir page-level use-after-free.

Bu bir variant, yeniden bildirim değil: CVE-2022-36449 patch'lendi, ama aynı sınıftaki imported-memory lifetime karışıklığı komşu bir code path'te hayatta kaldı. Bunu bulmak, sadece patch'i diff'lemekten değil, orijinal bug'ın neden var olduğunu anlamaktan geldi.

Walkthrough

Exploit, page UAF'i bir kernel read/write primitive'ine dönüştürür. Üst düzeyde:

1. Import a user buffer:        KBASE_IOCTL_MEM_IMPORT  -> KBASE_MEM_TYPE_IMPORTED_USER_BUF
2. Make it "sticky":            KBASE_IOCTL_STICKY_RESOURCE_MAP
3. Submit a GPU softjob that pins+vmaps the imported pages
                                (kbase_jd_user_buf_map / kbase_vmap_prot)
4. Race STICKY_RESOURCE_UNMAP against the softjob to drop the pages
   while the kernel mapping is still live  -> page UAF

Mapping oluşturma ile unmapping arasındaki race window çok dar. Write-up, unmap'i window içine güvenilir şekilde oturtmak için interrupt-driven scheduling (timerfd) kullanıyor.

Warning

Açıktan etkilenen davranış yalnızca KBASE_REG_SHARE_BOTH flag'i olmadan oluşturulan imported memory için ortaya çıkar — yani import sırasında pin'lenmeyip bunun yerine job başına lazy olarak pin'lenen page'ler. Variant'ın tetiklediği path tam olarak budur.

Free edilmiş bir page kernel tarafından yeniden kullanıldığında, exploit onu kernel-controlled state olarak reclaim eder. Write-up, gpu_mappings field'ı sıfırlanacak şekilde bir kbase_mem_phy_alloc'ın corrupt edilmesini anlatır; bu da aliased bir region'ın shrink edilmesini sağlar: backing page'ler kaldırılırken alias mapping'ler hayatta kalır ve free edilmiş page'lere UAF erişimi yeniden türetilir. Bu page'ler daha sonra arbitrary read/write kurmak için page table'lar (PGD'ler) ya da vmalloc tabanlı kernel object'leri olarak reclaim edilir; ardından kernel code execution ve root gelir.

Primitive chain (conceptual)
page UAF (imported pages freed under a live mapping)
    -> reclaim freed page as kbase_mem_phy_alloc metadata
    -> zero gpu_mappings  -> shrink aliased region
    -> backing pages removed, alias mappings remain (UAF again, controlled)
    -> reclaim freed pages as PGD / vmalloc kernel objects
    -> arbitrary kernel read/write -> kernel code execution -> root

Detection

  • Telemetry on untrusted_app access to the Mali device node combined with bursts of KBASE_IOCTL_STICKY_RESOURCE_MAP / KBASE_IOCTL_STICKY_RESOURCE_UNMAP around imported user buffers is a reasonable behavioural signal for this bug class.
  • Tight timerfd-driven racing of the unmap path against softjob submission is anomalous for legitimate GPU clients.

Mitigation

  • Update to Arm Mali driver r42p0 (publicly released 27 January 2023), which fixes the imported-memory lifetime handling.
  • On Android, the fix shipped in the May 2023 security update.
  • Reported to Arm 17 November 2022; CVE-2022-46395 assigned 5 December 2022 (CVSS 9.3).
  • Affected: Arm Mali GPU driver r40p0 and earlier (tested on Pixel 6, November 2022 patch level).

References