PartitionAlloc SuperPage metadata overwrite¶
Out-of-line per-SuperPage metadata'ya (slot span'leri ve freelist'leri tanımlayan 32-byte'lık
SlotSpanMetadata/ extent entry'leri) ulaş ve onu boz, böylece allocator'ın kendi bookkeeping'i attacker'a kontrollü bir allocation verir.
Mechanism¶
Note
Bir PartitionAlloc SuperPage'i, ilk ve son partition page'leri erişilemez guard page'ler
olan 2 MiB'lık bir bölgedir; ön guard içindeki bir system page metadata array'ini tutar
— partition page başına bir 32-byte'lık SlotSpanMetadata (ya da SubsequentPageMetadata),
her slot span'in freelist head'ini, free count'unu ve bucket'ını tanımlar. PartitionAlloc bu
metadata'yı tam da lineer bir user-data overflow'unun ona ulaşamaması için out-of-line
(user data ile iç içe değil) ve guard-page-korumalı tutar. Teknik o sınırı non-linear bir
rota ile geçer: metadata'nın konumu herhangi bir slot adresinden deterministik olarak
türetilir (SuperPage base'ini maskele, metadata alanını index'le). Bir slot pointer'ı leak
eden bir attacker bu yüzden metadata adresini hesaplar ve oraya yazabilen bir primitive
(örn. metadata'ya düşen forge edilmiş bir allocation,
partitionalloc-double-free-to-arbitrary-allocation.md
gereğince), allocator'ın güvendiği freelist head'ini üzerine yazar — bookkeeping'i
attacker-seçimli bir allocation'a dönüştürür.
Walkthrough¶
Kavramsal zincir (kamuya açık 0CTF Chromium yazısına göre modellenmiş):
- Bir slot pointer'ı leak et. UAF read üzerinden, in-slot (encoded) bir pointer elde et; SuperPage base'ini ve metadata-area offset'ini geri kazanmak için onu decode et.
- Bir allocation'ı metadata'ya nişanla. Bir freelist-poisoning primitive'i (partitionalloc-freelist-pointer-encoding-bypass.md) kullan, böylece aynı-boyutlu bir allocation metadata array'i ile overlap eden bir chunk döndürür.
- Freelist head'ini yeniden yaz. Hedeflenen
SlotSpanMetadata'nın freelist pointer'ını üzerine yaz (kamuya açık yazı allocator'ın bir "unlink" yaptığını ve attacker-yazılı değeri benimsediğini belirtir); bir sonraki allocation artık attacker-seçimli bir adresten karşılanır. - R/W'ye yükselt. Bir victim nesnesinin üzerine allocate ederek arbitrary-read-primitive.md / arbitrary-write-primitive.md için length/pointer field'larını forge et ve metadata bloğunun içindeki pointer'lardan module base'ini oku.
Warning
Guard page'ler metadata'ya lineer overflow'u durdurur; bu path ise metadata adresini var olan bir allocation primitive'i üzerinden türetir ve yazar, dolayısıyla evade ettiği savunma freelist değerinin kendisi üzerindeki integrity check'leri değil, spatial isolation'dır.
Detection¶
- Metadata system page'ini çevreleyen guard-page fault'ları; faulting adresi bir SuperPage'in ön metadata bölgesine düşen crash'ler.
- Metadata-türevli bir freelist entry'si same-SuperPage ya da metadata-avoidance check'lerini
geçemediğinde
FreelistCorruptionDetected()/IsWellFormed()abort'ları; ASan/*Scanraporları.
Mitigation¶
- Out-of-line, guard-page-sınırlı metadata temel hattıdır; freelist shadow check'lerini ve
metadata-avoidance doğrulamasını (
IsWellFormed) etkin tut, böylece forge edilmiş bir head reddedilir. - BackupRefPtr quarantine (backuprefptr-bypass.md) ve
*Scan, ön koşul olan allocation primitive'ini elde etme maliyetini yükseltir; MTE-tagged build'ler metadata-overlapping reuse'da fault eder. - SuperPage yerleşimi üzerinde ASLR ve module pointer'larını erişilebilir metadata'ya gömmemek, leak değerini azaltır.