From 92a9674f6640be7563613b3dc6cf7f18ab965818 Mon Sep 17 00:00:00 2001 From: Jiajie Chen Date: Wed, 15 May 2019 22:45:09 +0800 Subject: [PATCH] Implement efault detection by fixup --- kernel/src/arch/x86_64/interrupt/handler.rs | 11 ++++++++ kernel/src/arch/x86_64/linker.ld | 3 +++ kernel/src/memory.rs | 28 +++++++++++++++++++++ kernel/src/syscall/mod.rs | 19 +++++++++++++- kernel/src/syscall/proc.rs | 2 +- 5 files changed, 61 insertions(+), 2 deletions(-) diff --git a/kernel/src/arch/x86_64/interrupt/handler.rs b/kernel/src/arch/x86_64/interrupt/handler.rs index ac36e4c..d6fb976 100644 --- a/kernel/src/arch/x86_64/interrupt/handler.rs +++ b/kernel/src/arch/x86_64/interrupt/handler.rs @@ -147,6 +147,17 @@ fn page_fault(tf: &mut TrapFrame) { if crate::memory::handle_page_fault(addr) { return; } + + extern "C" { + fn _copy_user_start(); + fn _copy_user_end(); + } + if tf.rip >= _copy_user_start as usize && tf.rip < _copy_user_end as usize { + debug!("fixup for addr {:x?}", addr); + tf.rip = crate::memory::read_user_fixup as usize; + return; + } + error!("\nEXCEPTION: Page Fault @ {:#x}, code: {:?}", addr, code); error(tf); } diff --git a/kernel/src/arch/x86_64/linker.ld b/kernel/src/arch/x86_64/linker.ld index a03f48e..1d46248 100644 --- a/kernel/src/arch/x86_64/linker.ld +++ b/kernel/src/arch/x86_64/linker.ld @@ -14,6 +14,9 @@ SECTIONS { .text ALIGN(4K): { stext = .; + _copy_user_start = .; + *(.text.copy_user) + _copy_user_end = .; *(.text .text.*) etext = .; } diff --git a/kernel/src/memory.rs b/kernel/src/memory.rs index 1330cc6..01af298 100644 --- a/kernel/src/memory.rs +++ b/kernel/src/memory.rs @@ -177,3 +177,31 @@ pub fn enlarge_heap(heap: &mut Heap) { } core::mem::forget(page_table); } + +pub fn access_ok(from: usize, len: usize) -> bool { + from < PHYSICAL_MEMORY_OFFSET && (from + len) < PHYSICAL_MEMORY_OFFSET +} + +#[naked] +pub unsafe extern "C" fn read_user_fixup() -> usize { + return 1; +} + +#[no_mangle] +pub fn copy_from_user_u8(addr: *const u8) -> Option { + #[naked] + #[inline(never)] + #[link_section = ".text.copy_user"] + unsafe extern "C" fn read_user_u8(dst: *mut u8, src: *const u8) -> usize { + dst.copy_from_nonoverlapping(src, 1); + 0 + } + if !access_ok(addr as usize, 1) { + return None; + } + let mut dst: u8 = 0; + match unsafe { read_user_u8((&mut dst) as *mut u8, addr) } { + 0 => Some(dst), + _ => None, + } +} diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 896d5d1..10674b3 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -10,7 +10,7 @@ use rcore_memory::VMError; use crate::arch::cpu; use crate::arch::interrupt::TrapFrame; use crate::arch::syscall::*; -use crate::memory::MemorySet; +use crate::memory::{copy_from_user_u8, MemorySet}; use crate::process::*; use crate::sync::{Condvar, MutexGuard, SpinNoIrq}; use crate::thread; @@ -556,3 +556,20 @@ pub fn spin_and_wait(condvars: &[&Condvar], mut action: impl FnMut() -> Optio Condvar::wait_any(&condvars); } } + +pub fn check_and_clone_cstr(user: *const u8) -> Result { + let mut buffer = Vec::new(); + for i in 0.. { + let addr = unsafe { user.add(i) }; + if let Some(data) = copy_from_user_u8(addr) { + if data > 0 { + buffer.push(data); + } else { + break; + } + } else { + return Err(SysError::EFAULT); + } + } + return String::from_utf8(buffer).map_err(|_| SysError::EFAULT); +} diff --git a/kernel/src/syscall/proc.rs b/kernel/src/syscall/proc.rs index 89cb0f4..e3e4039 100644 --- a/kernel/src/syscall/proc.rs +++ b/kernel/src/syscall/proc.rs @@ -153,7 +153,7 @@ impl Syscall<'_> { path, argv, envp ); let mut proc = self.process(); - let path = unsafe { self.vm().check_and_clone_cstr(path)? }; + let path = unsafe { check_and_clone_cstr(path)? }; let args = unsafe { self.vm().check_and_clone_cstr_array(argv)? }; let envs = unsafe { self.vm().check_and_clone_cstr_array(envp)? };