@@ -127,6 +127,14 @@ where
127
127
}
128
128
}
129
129
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
+
130
138
self . inner . remove_copied_flags ( & self . elf_file ) . unwrap ( ) ;
131
139
132
140
Ok ( tls_template)
@@ -496,6 +504,44 @@ where
496
504
497
505
Ok ( ( ) )
498
506
}
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
+ }
499
545
}
500
546
501
547
/// Check that the virtual offset belongs to a load segment.
0 commit comments