From 6a5f374a777088eb849fafc947294a4229e36978 Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Wed, 2 Oct 2024 17:59:35 +0200 Subject: [PATCH] Use ELF segment flags when allocating memory --- src/sys/allocator.rs | 4 +++- src/sys/idt.rs | 9 ++++++--- src/sys/process.rs | 40 ++++++++++++++++++++++++++++++++-------- 3 files changed, 41 insertions(+), 12 deletions(-) diff --git a/src/sys/allocator.rs b/src/sys/allocator.rs index 6e6b9cd96..ee017bcbe 100644 --- a/src/sys/allocator.rs +++ b/src/sys/allocator.rs @@ -59,7 +59,7 @@ pub fn init_heap() -> Result<(), MapToError> { } pub fn alloc_pages( - mapper: &mut OffsetPageTable, addr: u64, size: usize + mapper: &mut OffsetPageTable, addr: u64, size: usize, flags: PageTableFlags ) -> Result<(), ()> { let size = size.saturating_sub(1) as u64; let mut frame_allocator = sys::mem::frame_allocator(); @@ -70,9 +70,11 @@ pub fn alloc_pages( Page::range_inclusive(start_page, end_page) }; + /* let flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE | PageTableFlags::USER_ACCESSIBLE; + */ for page in pages { if let Some(frame) = frame_allocator.allocate_frame() { diff --git a/src/sys/idt.rs b/src/sys/idt.rs index e2c895df7..05f3b667e 100644 --- a/src/sys/idt.rs +++ b/src/sys/idt.rs @@ -12,7 +12,7 @@ use x86_64::structures::idt::{ InterruptDescriptorTable, InterruptStackFrame, InterruptStackFrameValue, PageFaultErrorCode, }; -use x86_64::structures::paging::{OffsetPageTable, Translate}; +use x86_64::structures::paging::{OffsetPageTable, PageTableFlags, Translate}; use x86_64::VirtAddr; const PIC1: u16 = 0x21; @@ -136,9 +136,12 @@ extern "x86-interrupt" fn page_fault_handler( let mut mapper = unsafe { OffsetPageTable::new(page_table, VirtAddr::new(phys_mem_offset)) }; + let flags = PageTableFlags::PRESENT + | PageTableFlags::WRITABLE + | PageTableFlags::USER_ACCESSIBLE; // TODO if error_code.contains(PageFaultErrorCode::CAUSED_BY_WRITE) { - if sys::allocator::alloc_pages(&mut mapper, addr, 1).is_err() { + if sys::allocator::alloc_pages(&mut mapper, addr, 1, flags).is_err() { printk!( "{}Error:{} Could not allocate page at {:#X}\n", csi_color, csi_reset, addr @@ -161,7 +164,7 @@ extern "x86-interrupt" fn page_fault_handler( // first. sys::allocator::free_pages(&mut mapper, start, 4096); } - if sys::allocator::alloc_pages(&mut mapper, start, 4096).is_ok() { + if sys::allocator::alloc_pages(&mut mapper, start, 4096, flags).is_ok() { if error_code.contains(PageFaultErrorCode::INSTRUCTION_FETCH) { let code_addr = sys::process::code_addr(); let src = (code_addr + start) as *mut u8; diff --git a/src/sys/process.rs b/src/sys/process.rs index 0ec70dd24..b6a2db844 100644 --- a/src/sys/process.rs +++ b/src/sys/process.rs @@ -15,11 +15,12 @@ use core::sync::atomic::{AtomicU64, AtomicUsize, Ordering}; use lazy_static::lazy_static; use linked_list_allocator::LockedHeap; use object::{Object, ObjectSegment}; +use object::read::SegmentFlags; use spin::RwLock; use x86_64::registers::control::Cr3; use x86_64::structures::idt::InterruptStackFrameValue; use x86_64::structures::paging::{ - FrameAllocator, OffsetPageTable, PageTable, PhysFrame + FrameAllocator, OffsetPageTable, PageTable, PageTableFlags, PhysFrame }; use x86_64::VirtAddr; @@ -372,16 +373,21 @@ impl Process { /* debug!( "{:#X}..{:#X}: {} bytes for a code segment ({:#X}..{:#X}: {} bytes)", - addr, addr + data.len() as u64, data.len(), - segment.address(), segment.address() + segment.size(), segment.size(), + addr, addr + size as u64, size, + segment.address(), segment.address() + data.len() as u64, data.len(), ); */ - load_binary(&mut mapper, addr, size, data)?; + let flags = parse_flags(segment.flags()).unwrap(); + //debug!("{:#?}", flags); + load_binary(&mut mapper, addr, size, data, flags)?; } } } } else if bin[0..4] == BIN_MAGIC { // Flat binary - load_binary(&mut mapper, code_addr, bin.len() - 4, &bin[4..])?; + let flags = PageTableFlags::PRESENT + | PageTableFlags::WRITABLE + | PageTableFlags::USER_ACCESSIBLE; // TODO + load_binary(&mut mapper, code_addr, bin.len() - 4, &bin[4..], flags)?; } else { return Err(()); } @@ -428,7 +434,10 @@ impl Process { // Copy args to user memory let args_addr = self.code_addr + (self.stack_addr - self.code_addr) / 2; - sys::allocator::alloc_pages(&mut mapper, args_addr, 1). + let flags = PageTableFlags::PRESENT + | PageTableFlags::WRITABLE + | PageTableFlags::USER_ACCESSIBLE; // TODO + sys::allocator::alloc_pages(&mut mapper, args_addr, 1, flags). expect("proc args alloc"); let args: &[&str] = unsafe { let ptr = ptr_from_addr(args_ptr as u64) as usize; @@ -491,10 +500,14 @@ impl Process { } fn load_binary( - mapper: &mut OffsetPageTable, addr: u64, size: usize, buf: &[u8] + mapper: &mut OffsetPageTable, + addr: u64, + size: usize, + buf: &[u8], + flags: PageTableFlags, ) -> Result<(), ()> { debug_assert!(size >= buf.len()); - sys::allocator::alloc_pages(mapper, addr, size)?; + sys::allocator::alloc_pages(mapper, addr, size, flags)?; let src = buf.as_ptr(); let dst = addr as *mut u8; unsafe { @@ -505,3 +518,14 @@ fn load_binary( } Ok(()) } + +fn parse_flags(flags: SegmentFlags) -> Option { + match flags { + SegmentFlags::Elf { p_flags } => { + PageTableFlags::from_bits(p_flags as u64) + } + _ => { + None + } + } +}