@@ -325,25 +325,6 @@ fn make_p4_writable() {
325325
326326 let mut pt = unsafe { identity_mapped_page_table ( ) } ;
327327
328- let p4_page = {
329- let ( p4_frame, _) = Cr3 :: read_raw ( ) ;
330- let p4_addr = x86_64:: VirtAddr :: new ( p4_frame. start_address ( ) . as_u64 ( ) ) ;
331- Page :: < Size4KiB > :: from_start_address ( p4_addr) . unwrap ( )
332- } ;
333-
334- let TranslateResult :: Mapped { frame, flags, .. } = pt. translate ( p4_page. start_address ( ) ) else {
335- unreachable ! ( )
336- } ;
337-
338- let make_writable = || unsafe {
339- let flags = flags | PageTableEntryFlags :: WRITABLE ;
340- match frame {
341- MappedFrame :: Size1GiB ( _) => pt. set_flags_p3_entry ( p4_page, flags) . unwrap ( ) . ignore ( ) ,
342- MappedFrame :: Size2MiB ( _) => pt. set_flags_p2_entry ( p4_page, flags) . unwrap ( ) . ignore ( ) ,
343- MappedFrame :: Size4KiB ( _) => pt. update_flags ( p4_page, flags) . unwrap ( ) . ignore ( ) ,
344- }
345- } ;
346-
347328 unsafe fn without_protect < F , R > ( f : F ) -> R
348329 where
349330 F : FnOnce ( ) -> R ,
@@ -359,7 +340,55 @@ fn make_p4_writable() {
359340 ret
360341 }
361342
362- unsafe { without_protect ( make_writable) }
343+ let ( p4_frame, _) = Cr3 :: read_raw ( ) ;
344+ unsafe {
345+ without_protect ( || make_page_table_writable ( & mut pt, p4_frame, 4 ) ) ;
346+ } ;
347+ }
348+
349+ unsafe fn make_page_table_writable (
350+ page_table : & mut OffsetPageTable < ' static > ,
351+ pt_frame : PhysFrame ,
352+ level : u8 ,
353+ ) {
354+ let pt_address = page_table. phys_offset ( ) + pt_frame. start_address ( ) . as_u64 ( ) ;
355+ let pt = unsafe { pt_address. as_ptr :: < PageTable > ( ) . as_ref ( ) . unwrap ( ) } ;
356+
357+ // Unmap the page table
358+ let TranslateResult :: Mapped { frame, flags, .. } = page_table. translate ( pt_address) else {
359+ unreachable ! ( )
360+ } ;
361+
362+ if !flags. contains ( PageTableEntryFlags :: WRITABLE ) {
363+ let flags = flags | PageTableEntryFlags :: WRITABLE ;
364+ let page = Page :: < Size4KiB > :: containing_address ( pt_address) ;
365+ unsafe {
366+ match frame {
367+ MappedFrame :: Size1GiB ( _) => {
368+ page_table. set_flags_p3_entry ( page, flags) . unwrap ( ) . ignore ( )
369+ }
370+ MappedFrame :: Size2MiB ( _) => {
371+ page_table. set_flags_p2_entry ( page, flags) . unwrap ( ) . ignore ( )
372+ }
373+ MappedFrame :: Size4KiB ( _) => page_table. update_flags ( page, flags) . unwrap ( ) . ignore ( ) ,
374+ }
375+ }
376+ warn ! ( "Page table {pt_frame:x?}, was mapped from RO memory!" ) ;
377+ }
378+
379+ for entry in pt. iter ( ) {
380+ if entry. is_unused ( ) {
381+ continue ;
382+ }
383+
384+ let is_page_table = level > 1 && !entry. flags ( ) . contains ( PageTableEntryFlags :: HUGE_PAGE ) ;
385+ if is_page_table {
386+ let phys = entry. frame ( ) . unwrap ( ) ;
387+ unsafe {
388+ make_page_table_writable ( page_table, phys, level - 1 ) ;
389+ }
390+ }
391+ }
363392}
364393
365394pub unsafe fn log_page_tables ( ) {
0 commit comments