@@ -127,6 +127,14 @@ where
127127 }
128128 }
129129
130+ // Mark some memory regions as read-only after relocations have been
131+ // applied.
132+ for program_header in self . elf_file . program_iter ( ) {
133+ if let Type :: GnuRelro = program_header. get_type ( ) ? {
134+ self . inner . handle_relro_segment ( program_header) ;
135+ }
136+ }
137+
130138 self . inner . remove_copied_flags ( & self . elf_file ) . unwrap ( ) ;
131139
132140 Ok ( tls_template)
@@ -496,6 +504,44 @@ where
496504
497505 Ok ( ( ) )
498506 }
507+
508+ /// Mark a region of memory indicated by a GNU_RELRO segment as read-only.
509+ ///
510+ /// This is a security mitigation used to protect memory regions that
511+ /// need to be writable while applying relocations, but should never be
512+ /// written to after relocations have been applied.
513+ fn handle_relro_segment ( & mut self , program_header : ProgramHeader ) {
514+ let start = self . virtual_address_offset + program_header. virtual_addr ( ) ;
515+ let end = start + program_header. mem_size ( ) ;
516+ let start = VirtAddr :: new ( start) ;
517+ let end = VirtAddr :: new ( end) ;
518+ let start_page = Page :: containing_address ( start) ;
519+ let end_page = Page :: containing_address ( end - 1u64 ) ;
520+ for page in Page :: < Size4KiB > :: range_inclusive ( start_page, end_page) {
521+ // Translate the page and get the flags.
522+ let res = self . page_table . translate ( page. start_address ( ) ) ;
523+ let flags = match res {
524+ TranslateResult :: Mapped {
525+ frame : _,
526+ offset : _,
527+ flags,
528+ } => flags,
529+ TranslateResult :: NotMapped | TranslateResult :: InvalidFrameAddress ( _) => {
530+ unreachable ! ( "has the elf file not been mapped correctly?" )
531+ }
532+ } ;
533+
534+ if flags. contains ( Flags :: WRITABLE ) {
535+ // Remove the WRITABLE flag.
536+ unsafe {
537+ self . page_table
538+ . update_flags ( page, flags & !Flags :: WRITABLE )
539+ . unwrap ( )
540+ . ignore ( ) ;
541+ }
542+ }
543+ }
544+ }
499545}
500546
501547/// Check that the virtual offset belongs to a load segment.
0 commit comments