/proc/PID/pagemap physical address leak¶
/proc/PID/pagemapiçindeki page başına 64-bit girişleri okuyarak bir virtual address'i physical frame number'ına çevir ve userspace'e bir virtual→physical oracle ver.
Mechanism¶
Note
/proc/PID/pagemap, virtual page başına bir 64-bit giriş açığa çıkarır. Present bir
page için bit 63 set'lidir ve bit 0–54 page frame number'ı (PFN) tutar. Dosyayı
(vaddr / PAGE_SIZE) * 8 konumunda indekslemek vaddr için girişi verir ve physical
address phys = (PFN << PAGE_SHIFT) | (vaddr & (PAGE_SIZE - 1))'dir. Bu, userspace bir
process'e bir virtual→physical translation oracle'ı sunar — tam olarak physical-memory
saldırılarının (Rowhammer templating, DMA, cache eviction-set kurma) ihtiyaç duyduğu şey.
Giriş bit layout'u (present page):
Bits 0-54 page frame number (PFN) if present
Bit 55 pte is soft-dirty
Bit 56 page exclusively mapped (since 4.2)
Bits 57-60 zero
Bit 61 page is file-page or shared-anon (since 3.5)
Bit 62 page swapped
Bit 63 page present
Swapped page: bit 0–4 = swap type, bit 5–54 = swap offset.
Walkthrough¶
Kendi process'inde bir vaddr virtual address'i için PFN'i çöz:
uint64_t entry, pfn, phys;
int fd = open("/proc/self/pagemap", O_RDONLY);
off_t off = (vaddr / 0x1000) * sizeof(uint64_t);
pread(fd, &entry, sizeof(entry), off);
if (entry & (1ULL << 63)) { /* present */
pfn = entry & ((1ULL << 55) - 1); /* bits 0-54 */
phys = (pfn << 12) | (vaddr & 0xfff);
}
Warning
Kernel >= 4.2'de CAP_SYS_ADMIN olmadan PFN alanı 0 olarak geri okunur — dosya yine
açılır, ama entry & ((1ULL<<55)-1) sıfırdır, dolayısıyla translation başarısız olur.
Bit 63'ü set yapmak için önce page'e dokun (yaz), aksi hâlde present olmaz.
Detection¶
/proc/self/pagemap'i açıp sıfır olmayan PFN'ler okuyan izlenen bir process'in
CAP_SYS_ADMIN taşıdığı anlaşılır; unprivileged context'lerden gelen pagemap okumalarını
denetlemek bir phys-map oracle kurma girişimlerini işaretler.
Mitigation¶
Kernel pagemap dokümantasyonundan:
- Linux 4.0'dan beri yalnızca CAP_SYS_ADMIN'e sahip user'lar PFN edinebilir.
- 4.0 ve 4.1'de unprivileged
open()-EPERMile başarısız olur. - 4.2'den beri dosya açılır ama
CAP_SYS_ADMIN'i olmayan caller'lar için PFN alanı sıfırlanır.
Belirtilen gerekçe: "PFN'ler hakkındaki bilgi Rowhammer'ı exploit etmeye yardımcı olur."