Implement efault detection by fixup

toolchain_update
Jiajie Chen 6 years ago
parent a05fabfde5
commit 92a9674f66

@ -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);
}

@ -14,6 +14,9 @@ SECTIONS {
.text ALIGN(4K):
{
stext = .;
_copy_user_start = .;
*(.text.copy_user)
_copy_user_end = .;
*(.text .text.*)
etext = .;
}

@ -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<u8> {
#[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,
}
}

@ -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<T>(condvars: &[&Condvar], mut action: impl FnMut() -> Optio
Condvar::wait_any(&condvars);
}
}
pub fn check_and_clone_cstr(user: *const u8) -> Result<String, SysError> {
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);
}

@ -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)? };

Loading…
Cancel
Save