Slab grooming¶
Kontrollü alloc/free aracılığıyla SLUB slab ve page-allocator layout'unu deterministik olarak düzenle; böylece bir victim object attacker-kontrollü bir object'e komşu düşer ya da onun slot'unu yeniden kullanır.
Mechanism¶
SLUB belirli bir boyuttaki object'leri slab'lardan (bir veya birden fazla bitişik page) dağıtır. Bir slab içindeki allocation sırası büyük ölçüde deterministiktir (per-CPU freelist'ten LIFO) ve bir cache tükendiğinde SLUB buddy/page allocator'dan taze bir slab ister. Bu kuralları anlayan bir attacker heap'i önceden şekillendirebilir; böylece sonraki allocation tam istenen yere düşer.
Note
Grooming, SLUB ile page allocator arasındaki etkileşimi exploit eder. (1) hedef kmalloc-N cache'ini partial-slab boşluğunu tüketmek için önceden doldurarak, sonra (2) page-allocator freelist'lerini aynı order'daki allocation'larla boşaltarak, attacker taze bir slab'ın bilinen bir page'den carve edilmesini zorlar; bu da sonraki victim/attacker object'lerinin yerleşimini deterministik yapar — overflow'lar için komşuluk ya da UAF reclaim için kesin slot yeniden kullanımı.
Walkthrough¶
Kanonik deterministik dizi (Project Zero'nun CVE-2017-7308 packet-socket exploit'inden; burada packet_sock ≈1920 B kmalloc-2048'e yuvarlanır ve groom için kullanılan AF_PACKET ring-buffer blokları 0x8000 boyutundadır):
- Cache'i doldur: kmalloc-2048'deki partial-slab boşluğunu tüketmek için ~512
packet_sockobject'i allocate et. - Page allocator'ı boşalt: page allocator'ın ilgili freelist'leri boşalsın ve öngörülebilir olsun diye ~1024
0x8000ring-buffer bloğu allocate et. - Kontrollü bloğu yerleştir: exploit'in
0x8000ring-buffer bloğunu allocate et — artık komşu yerleşim garantili. - Victim'leri yerleştir: victim
packet_sockstruct'larını, overflow hedefinin hemen ardına düşecek şekilde allocate et.
// Sketch: exhaust kmalloc-2048, then allocate adjacent 0x8000 blocks via packet rings.
for (i = 0; i < 512; i++) s[i] = socket(AF_PACKET, SOCK_RAW, 0); // packet_sock
for (i = 0; i < 1024; i++) drain_ring_block(0x8000); // drain page alloc
alloc_controlled_ring_block(0x8000); // adjacent block
for (i = 0; i < N; i++) v[i] = socket(AF_PACKET, SOCK_RAW, 0); // victims after target
Beklenen sonuç: victim'e güvenilir biçimde komşu olan (ya da onun tarafından yeniden kullanılan) kontrollü bir allocation; böylece bir OOB write ya da UAF reclaim rastgele bellek yerine seçilen bir hedefi vurur.
Mitigation¶
CONFIG_SLAB_FREELIST_RANDOM slab-içi sırayı bozar; RANDOM_KMALLOC_CACHES / SLAB_BUCKETS allocation site'larını ayırır; page-allocator freelist randomization'ı (CONFIG_SHUFFLE_PAGE_ALLOCATOR) cross-cache komşuluk determinizmini azaltır — hepsi grooming güvenilirliğini düşürür ama ortadan kaldırmaz.