simplify copy_from_user

master
WangRunji 6 years ago
parent 8b07e7d31c
commit 9dec0bbda5

@ -171,8 +171,9 @@ pub fn enlarge_heap(heap: &mut Heap) {
} }
} }
pub fn access_ok(from: usize, len: usize) -> bool { /// Check whether the address range [addr, addr + len) is not in kernel space
from < PHYSICAL_MEMORY_OFFSET && (from + len) < PHYSICAL_MEMORY_OFFSET pub fn access_ok(addr: usize, len: usize) -> bool {
addr < PHYSICAL_MEMORY_OFFSET && (addr + len) < PHYSICAL_MEMORY_OFFSET
} }
#[naked] #[naked]
@ -180,39 +181,19 @@ pub unsafe extern "C" fn read_user_fixup() -> usize {
return 1; return 1;
} }
#[no_mangle] pub fn copy_from_user<T>(addr: *const T) -> Option<T> {
pub fn copy_from_user_u8(addr: *const u8) -> Option<u8> {
#[naked] #[naked]
#[inline(never)] #[inline(never)]
#[link_section = ".text.copy_user"] #[link_section = ".text.copy_user"]
unsafe extern "C" fn read_user_u8(dst: *mut u8, src: *const u8) -> usize { unsafe extern "C" fn read_user<T>(dst: *mut T, src: *const T) -> usize {
dst.copy_from_nonoverlapping(src, 1); dst.copy_from_nonoverlapping(src, 1);
0 0
} }
if !access_ok(addr as usize, size_of::<u8>()) { if !access_ok(addr as usize, size_of::<T>()) {
return None; return None;
} }
let mut dst: u8 = 0; let mut dst: T = unsafe { core::mem::uninitialized() };
match unsafe { read_user_u8((&mut dst) as *mut u8, addr) } { match unsafe { read_user(&mut dst, addr) } {
0 => Some(dst),
_ => None,
}
}
#[no_mangle]
pub fn copy_from_user_usize(addr: *const usize) -> Option<usize> {
#[naked]
#[inline(never)]
#[link_section = ".text.copy_user"]
unsafe extern "C" fn read_user_usize(dst: *mut usize, src: *const usize) -> usize {
dst.copy_from_nonoverlapping(src, 1);
0
}
if !access_ok(addr as usize, size_of::<usize>()) {
return None;
}
let mut dst: usize = 0;
match unsafe { read_user_usize((&mut dst) as *mut usize, addr) } {
0 => Some(dst), 0 => Some(dst),
_ => None, _ => None,
} }

@ -10,7 +10,7 @@ use rcore_memory::VMError;
use crate::arch::cpu; use crate::arch::cpu;
use crate::arch::interrupt::TrapFrame; use crate::arch::interrupt::TrapFrame;
use crate::arch::syscall::*; use crate::arch::syscall::*;
use crate::memory::{copy_from_user_u8, copy_from_user_usize, MemorySet}; use crate::memory::{copy_from_user, MemorySet};
use crate::process::*; use crate::process::*;
use crate::sync::{Condvar, MutexGuard, SpinNoIrq}; use crate::sync::{Condvar, MutexGuard, SpinNoIrq};
use crate::thread; use crate::thread;
@ -561,33 +561,25 @@ pub fn check_and_clone_cstr(user: *const u8) -> Result<String, SysError> {
let mut buffer = Vec::new(); let mut buffer = Vec::new();
for i in 0.. { for i in 0.. {
let addr = unsafe { user.add(i) }; let addr = unsafe { user.add(i) };
if let Some(data) = copy_from_user_u8(addr) { let data = copy_from_user(addr).ok_or(SysError::EFAULT)?;
if data > 0 { if data == 0 {
buffer.push(data); break;
} else {
break;
}
} else {
return Err(SysError::EFAULT);
} }
buffer.push(data);
} }
return String::from_utf8(buffer).map_err(|_| SysError::EFAULT); String::from_utf8(buffer).map_err(|_| SysError::EFAULT)
} }
pub fn check_and_clone_cstr_array(user: *const *const u8) -> Result<Vec<String>, SysError> { pub fn check_and_clone_cstr_array(user: *const *const u8) -> Result<Vec<String>, SysError> {
let mut buffer = Vec::new(); let mut buffer = Vec::new();
for i in 0.. { for i in 0.. {
let addr = unsafe { user.add(i) }; let addr = unsafe { user.add(i) };
if let Some(str_addr) = copy_from_user_usize(addr as *const usize) { let str_ptr = copy_from_user(addr).ok_or(SysError::EFAULT)?;
if str_addr > 0 { if str_ptr.is_null() {
let string = check_and_clone_cstr(str_addr as *const u8)?; break;
buffer.push(string);
} else {
break;
}
} else {
return Err(SysError::EFAULT);
} }
let string = check_and_clone_cstr(str_ptr)?;
buffer.push(string);
} }
return Ok(buffer); Ok(buffer)
} }

Loading…
Cancel
Save