Skip to content

Elastic objects

Allocation size'ı ve in-band length field'ı attacker-controlled olan kernel object'leri; bu yüzden herhangi bir kmalloc cache'ine spray edilebilir ve length'leri bozularak out-of-bounds read'e dönüştürülebilir.

Mechanism

Note

Bir elastic object (Chen, Lin, Xing — ACM CCS 2020, "A Systematic Study of Elastic Objects in Kernel Exploitation"), elastik bir kernel buffer'ının boyutunu kontrol eden bir length field içerir; kernel daha sonra o buffer'ı okurken kaç byte okuyup yazacağına karar vermek için bu length'e güvenir. İki yapısal biçim vardır: buffer object'in içine gömülüdür (sondaki flexible array), ya da object harici bir buffer'a pointer tutar.

İki özellik onları güçlü kılar. (1) Allocation size kullanıcı-kontrollü bir length tarafından sürüldüğü için, aynı object tipi farklı kmalloc-N cache'lerine yönlendirilebilir; böylece keyfi boyuttaki freed bir victim'i eşleştirip reclaim eder — universal heap spray. (2) In-band length field'ını bir OOB write ile bozmak, sonraki bir read'i komşu kernel memory'sinin over-read'ine çevirir: bir function pointer'ı leak etmek KASLR'ı kırar, freed bir slot'u over-read etmek heap cookie'sini sızdırır, ve object bir pointer tutuyorsa over-read arbitrary read'e yaklaşır.

Paper'ın keşif aracı ELOISE (ExploitabLe Object dIScovEry). 40 güvenlik açığı arasında elastic object'ler 27/40'ında KASLR/cookie disclosure'ı ve 8/40'ında arbitrary read'i mümkün kıldı.

Walkthrough

Kanonik elastic object, System V message header'ı struct msg_msg'dir:

struct msg_msg {
    struct list_head m_list;
    long             m_type;
    size_t           m_ts;        /* message text size = elastic LENGTH field */
    struct msg_msgseg *next;      /* pointer to next data segment */
    void            *security;
    /* message data follows inline */
};

msgsnd() -> load_msg() -> alloc_msg(), ilk chunk'ı min(len, DATALEN_MSG) olarak boyutlandırır; DATALEN_MSG = PAGE_SIZE - sizeof(struct msg_msg) = 0xfd0'dır, yani message length'ini seçmek msg_msg'i seçilen bir kmalloc-N'e spray ederek freed bir victim'i reclaim eder. Length-corruption read:

  1. Bir msg_msg'i bir victim'e bitişik/onunla örtüşecek şekilde yerleştir ve kuyruğa al (henüz receive etme).
  2. m_ts'i ayrı bir OOB write / UAF ile daha büyük bir değere boz.
  3. msgrcv() çağır — kernel m_ts byte'ı userland'e geri kopyalar, gerçek buffer'ın ötesine geçerek komşu kernel memory'sini okur (OOB read / info leak).
  4. Corruption ayrıca next'i de set ediyorsa, segment-traversal döngüsü attacker-controlled pointer'ı takip ederek neredeyse-arbitrary bir read yapar.

Warning

Paper'ın kendi işlenmiş örneği xfrm_replay_state_esn'dir (length field'ı bmp_len, recvmsg ile geri okunur); bu, komşu bir object'in f_op'una (ext4_file_operations) over-read yaparak KASLR'ı kırar. msg_msg, paper'ın elastic-object tablosunda listelenir; yukarıdaki m_ts/msgrcv mekanikleri kernel-doğru writeup'lardan alınmıştır.

Mitigation

ELOISE, elastic object'leri bir __GFP_ISOLATE flag'i aracılığıyla özel shadow cache'lere (örn. kmalloc-isolated-N) izole etmeyi önerir; böylece sıradan bir cache'teki bir bug bir elastic object'i victim'inin bitişiğine yerleştiremez (~%0.19 overhead). Genel slab freelist hardening/randomization da deterministik bitişikliği azaltır.

References