Unaligned msg_msg technique¶
Bir System V
msg_msgnesnesininm_tssize alanını ya danextsegment pointer'ını corrupt et — çoğu zaman sadece küçük/kısmi bir overwrite ile — onu bir out-of-bounds read'e ya da userfaultfd ile slab boyunca bir arbitrary read/write'a çevirmek için.
Mechanism¶
Note
msgsnd(), load_msg → alloc_msg aracılığıyla bir struct msg_msg header'ı (ve büyük
mesajlar için zincirlenmiş msg_msgseg segmentleri) kurar ve user verisini copy_from_user()
ile kopyalar. msgrcv(), copy_msg/store_msg aracılığıyla min(bufsz, msg->m_ts) byte'ı
geri kopyalar, sonra (MSG_COPY olmadan) unlink eder, nesneyi free_msg()'ler ve next
segment zincirini yürür. İki primitive bunu izler. m_ts üzerinden OOB read: m_ts size
alanını overwrite etmek (bir UAF write ya da header'a küçük/kısmi bir overflow) raporlanan
uzunluğu şişirir, böylece msgrcv chunk sınırını aşarak kopyalar ve bitişik slab verisini ile
kernel pointer'larını leak'ler. next üzerinden arb read/write: next pointer'ını
overwrite etmek kernel'in saldırganın seçtiği bir adresi msg_msgseg gibi ele almasına yol
açar; böylece sonraki bir msgrcv o hedefi dışarı kopyalar (arbitrary read) ya da bir re-send
onun içine yazar (arbitrary write). "Unaligned/kısmi" yönü şudur: m_ts/next'in tek bir null
byte'ı ya da birkaç low byte'ı zinciri başlatmaya yeter — tam bir pointer overwrite gerekmez.
Walkthrough¶
Doğrulanmış layout (header 0x30 byte; DATALEN_MSG = PAGE_SIZE - sizeof(struct msg_msg) =
0xfd0, DATALEN_SEG = PAGE_SIZE - sizeof(struct msg_msgseg) = 0xff8):
struct msg_msg {
struct list_head m_list; /* prev/next queue linkage */
long m_type;
size_t m_ts; /* message text size */
struct msg_msgseg *next; /* pointer to next segment */
void *security; /* LSM pointer (NULL without SELinux) */
/* data follows */
};
- OOB read (
m_ts):msg_msg'i spray'le ki biri freed/UAF chunk'a düşsün; onunm_ts'ini büyük bir değere corrupt et; sonramsgrcv(qid, buf, large, type, IPC_NOWAIT | MSG_NOERROR)gerçek sınırları aşarak kopyalar ve bitişik slab/kernel pointer'larını leak'ler. Unlink/free etmeden okumak içinMSG_COPYkullan, böylece aynı mesaj tekrar okunabilir. - Kısıt:
next-pointer arbitrary read için hedef bir NULL qword (zincir sonlandırıcı) ile başlamalıdır, aksi halde kernel panic olur. - Arbitrary write (
next+ userfaultfd):load_msg()'dekicopy_from_user()'ın source/dest'i olarak bir userfaultfd region register et; copy'si fault'layan birmsgsnd/msgrcvtetikle, böylece kernel thread'inext'i okumadan önce askıya alınır. Askıdaykennext'i hedefe (örneğincred - 0x8) işaret ettirmek için UAF'yi kullan;UFFDIO_COPYile serbest bırak; devam eden işlem saldırgan byte'larını yazar (örneğincreduid/gid üzerine sıfırlar → root).
Warning
NULL olmayan bir security pointer'ı (SELinux/LSM açık), layout'u değiştirir ve naif
m_ts/next matematiğini bozabilir. Hedef offset'ler (örneğin task_struct.cred)
kernel/config'e özgüdür.
Mitigation¶
CONFIG_SLAB_FREELIST_HARDENED/CONFIG_SLAB_FREELIST_RANDOM, tekniğin dayandığı LIFO free/realloc swap'ini zorlaştırır.CONFIG_HARDENED_USERCOPY, nesne sınırlarını aşan aşırı büyükm_tskopyalarını yakalayabilir.vm.unprivileged_userfaultfd = 0, arbitrary-write adımının merkezindeki unprivileged stall primitive'ini kaldırır.