Skip to content

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ş):

  1. 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.
    superpage = slot_addr & ~(2MiB-1)
    metadata  = superpage + metadata_area_offset   // derived, not adjacent
    
  2. 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.
  3. 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.
  4. 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/*Scan raporları.

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.

References