fix check user ptr across VMAs

master
WangRunji 6 years ago
parent a25c8132fe
commit 60cdea81d9

@ -3,6 +3,7 @@
use alloc::{boxed::Box, string::String, vec::Vec}; use alloc::{boxed::Box, string::String, vec::Vec};
use core::fmt::{Debug, Error, Formatter}; use core::fmt::{Debug, Error, Formatter};
use core::mem::size_of;
use crate::paging::*; use crate::paging::*;
@ -52,16 +53,27 @@ impl MemoryArea {
pub fn contains(&self, addr: VirtAddr) -> bool { pub fn contains(&self, addr: VirtAddr) -> bool {
addr >= self.start_addr && addr < self.end_addr addr >= self.start_addr && addr < self.end_addr
} }
/// Check the array is within the readable memory /// Check the array is within the readable memory.
fn check_read_array<S>(&self, ptr: *const S, count: usize) -> bool { /// Return the size of space covered in the area.
fn check_read_array<S>(&self, ptr: *const S, count: usize) -> usize {
// page align // page align
ptr as usize >= Page::of_addr(self.start_addr).start_address() let min_bound = (ptr as usize).max(Page::of_addr(self.start_addr).start_address());
&& unsafe { ptr.add(count) as usize } let max_bound = unsafe { ptr.add(count) as usize }
< Page::of_addr(self.end_addr + PAGE_SIZE - 1).start_address() .min(Page::of_addr(self.end_addr + PAGE_SIZE - 1).start_address());
if max_bound >= min_bound {
max_bound - min_bound
} else {
0
}
}
/// Check the array is within the writable memory.
/// Return the size of space covered in the area.
fn check_write_array<S>(&self, ptr: *mut S, count: usize) -> usize {
if self.attr.readonly {
0
} else {
self.check_read_array(ptr, count)
} }
/// Check the array is within the writable memory
fn check_write_array<S>(&self, ptr: *mut S, count: usize) -> bool {
!self.attr.readonly && self.check_read_array(ptr, count)
} }
/// Check the null-end C string is within the readable memory, and is valid. /// Check the null-end C string is within the readable memory, and is valid.
/// If so, clone it to a String. /// If so, clone it to a String.
@ -198,11 +210,14 @@ impl<T: InactivePageTable> MemorySet<T> {
ptr: *const S, ptr: *const S,
count: usize, count: usize,
) -> VMResult<&'static [S]> { ) -> VMResult<&'static [S]> {
self.areas let mut valid_size = 0;
.iter() for area in self.areas.iter() {
.find(|area| area.check_read_array(ptr, count)) valid_size += area.check_read_array(ptr, count);
.map(|_| core::slice::from_raw_parts(ptr, count)) if valid_size == size_of::<S>() * count {
.ok_or(VMError::InvalidPtr) return Ok(core::slice::from_raw_parts(ptr, count));
}
}
Err(VMError::InvalidPtr)
} }
/// Check the array is within the writable memory /// Check the array is within the writable memory
pub unsafe fn check_write_array<S>( pub unsafe fn check_write_array<S>(
@ -210,11 +225,14 @@ impl<T: InactivePageTable> MemorySet<T> {
ptr: *mut S, ptr: *mut S,
count: usize, count: usize,
) -> VMResult<&'static mut [S]> { ) -> VMResult<&'static mut [S]> {
self.areas let mut valid_size = 0;
.iter() for area in self.areas.iter() {
.find(|area| area.check_write_array(ptr, count)) valid_size += area.check_write_array(ptr, count);
.map(|_| core::slice::from_raw_parts_mut(ptr, count)) if valid_size == size_of::<S>() * count {
.ok_or(VMError::InvalidPtr) return Ok(core::slice::from_raw_parts_mut(ptr, count));
}
}
Err(VMError::InvalidPtr)
} }
/// Check the null-end C string pointer array /// Check the null-end C string pointer array
/// Used for getting argv & envp /// Used for getting argv & envp

@ -189,14 +189,14 @@ impl Thread {
let ustack_top = USER_STACK_OFFSET + USER_STACK_SIZE; let ustack_top = USER_STACK_OFFSET + USER_STACK_SIZE;
vm.push( vm.push(
ustack_buttom, ustack_buttom,
ustack_top - PAGE_SIZE, ustack_top - PAGE_SIZE * 4,
MemoryAttr::default().user(), MemoryAttr::default().user(),
Delay::new(GlobalFrameAlloc), Delay::new(GlobalFrameAlloc),
"user_stack_delay", "user_stack_delay",
); );
// We are going to write init info now. So map the last page eagerly. // We are going to write init info now. So map the last 4 pages eagerly.
vm.push( vm.push(
ustack_top - PAGE_SIZE, ustack_top - PAGE_SIZE * 4,
ustack_top, ustack_top,
MemoryAttr::default().user(), MemoryAttr::default().user(),
ByFrame::new(GlobalFrameAlloc), ByFrame::new(GlobalFrameAlloc),

Loading…
Cancel
Save