From 8009fcc4f3d9c6f3c1adcee5921ecbf918f416f0 Mon Sep 17 00:00:00 2001 From: Josh Junon Date: Sat, 3 Aug 2024 11:35:39 +0200 Subject: [PATCH] x86_64: fix r/w bit on intermediate page table entries --- oro-arch-x86_64/src/mem/segment.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/oro-arch-x86_64/src/mem/segment.rs b/oro-arch-x86_64/src/mem/segment.rs index aa3223f3..94fb8a94 100644 --- a/oro-arch-x86_64/src/mem/segment.rs +++ b/oro-arch-x86_64/src/mem/segment.rs @@ -82,7 +82,18 @@ impl AddressSegment { translator.to_virtual_addr(entry.address()) } else { let frame_phys_addr = alloc.allocate().ok_or(MapError::OutOfMemory)?; - *entry = self.entry_template.with_address(frame_phys_addr); + + // SAFETY(qix-): We set writable here since if two L4/L3/L2 regions + // SAFETY(qix-): overlap and one is writable, mapping the unwritable + // SAFETY(qix-): first would otherwise cause a fault for any writes + // SAFETY(qix-): to the overlapping region. Since the leaf pages + // SAFETY(qix-): ultimately have their R/W bits set correctly, we set + // SAFETY(qix-): the intermediate pages to writable to avoid this. + *entry = self + .entry_template + .with_address(frame_phys_addr) + .with_writable(); + let frame_virt_addr = translator.to_virtual_addr(frame_phys_addr); crate::asm::invlpg(frame_virt_addr);