io_uring provided-buffer spray¶
io_uring provided buffer'ları kullanarak küçük bir kmalloc cache'inde çok sayıda kontrollü
io_bufferobject'i allocate et — free edilmiş slot'ları reclaim etmek için kullanışlı bir heap-spray primitive.
Mechanism¶
io_uring, bir uygulamanın kernel'a önceden buffer havuzları vermesine izin verir. Klasik provided buffer'lar IORING_OP_PROVIDE_BUFFERS opcode'uyla eklenir; ring-tabanlı provided buffer'lar ise IORING_REGISTER_PBUF_RING ile register edilir. Klasik provided buffer eklemek, kernel'ın bunları izlemek için struct io_buffer object'leri allocate etmesine yol açar.
Note
Her provided buffer küçük bir io_buffer kernel object'iyle izlenir (&bl->buf_list üzerinden bağlanır). Attacker kaç buffer sağlayacağını ve hangi adres/uzunlukla sağlayacağını seçtiğinden, bu küçük bir cache'te kontrol edilebilir bir allocation'dır (io_buffer'ın kmalloc-32'ye düştüğü dokümante edilmiştir — ancak kesin cache, struct io_buffer'ın boyutuna bağlı olarak kernel sürümüne/config'e göre değişebilir; hedef kernel'da assume etmek yerine doğrulanmalıdır). Bu da onu temiz bir reclaim/spray primitive yapar: bir victim object'i free et, sonra slab'i yeniden doldurmak için buffer sağla ve free edilmiş slot'un üzerine io_buffer'ları bindir.
Warning
Spray'in işe yaraması hedef object'in boyutunun io_buffer cache'iyle eşleşmesine bağlıdır. Diğer boyutlar için ring-tabanlı provided buffer'lar (IORING_REGISTER_PBUF_RING) bunun yerine page-backed ring'ler allocate eder; bu farklı (page-level) bir primitive'dir — bkz. io_uring provided-buffer ring UAF.
Walkthrough¶
Klasik provided buffer'larla kavramsal spray akışı:
- Bir io_uring instance'ı kur (
io_uring_setup). - Bir buffer sayısı, bir uzunluk, bir buffer group id ve bir başlangıç buffer id'si belirten
IORING_OP_PROVIDE_BUFFERSSQE'leri submit et; kernel ilgiliio_bufferobject'lerini allocate eder. - Bunu aynı cache'teki bir victim object'i free ettikten hemen sonra kullan ki allocator free edilmiş slot'u attacker kontrolündeki
io_buffer'lar için yeniden kullansın. - Bir info-leak veya overwrite primitive'iyle eşleştir: örneğin içeriğini attacker'ın kontrol ettiği, dangling bir reference ile örtüşen bir object.
Bu spray birçok io_uring exploit'inde bir yapı taşı olarak görünür ve io_buffer gibi küçük-cache object'lerinin tercih edilen reclaim hedefleri olmasının sebeplerinden biridir.
Detection¶
Unprivileged bir task'tan gelen yüksek hacimli IORING_OP_PROVIDE_BUFFERS submission'ları veya kmalloc-32'de çok sayıda io_buffer allocation'ı gözlemlenebilir. Spray'in exploit etmek için kullanıldığı UAF'ı KASAN yakalar.
Mitigation¶
Unprivileged io_uring'i kısıtlamak (/proc/sys/kernel/io_uring_disabled) spray surface'ini ortadan kaldırır. Slab hardening (CONFIG_SLAB_FREELIST_RANDOM, dedicated/random kmalloc cache'ler) io_buffer'ın seçilmiş bir victim slot'una deterministik örtüşmesini azaltır.