Skip to content

Commit 77c9525

Browse files
authored
Merge pull request #269 from Freax13/implement-relro
implement read-only relocations
2 parents b1f442b + ff7cadc commit 77c9525

File tree

1 file changed

+46
-0
lines changed

1 file changed

+46
-0
lines changed

src/binary/load_kernel.rs

+46
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)