Skip to content
Snippets Groups Projects
Commit 2b6fae01 authored by Jeremy Soller's avatar Jeremy Soller
Browse files

Validate memory pointers

parent e2ec6fd2
No related branches found
No related tags found
No related merge requests found
...@@ -65,76 +65,84 @@ impl UserInner { ...@@ -65,76 +65,84 @@ impl UserInner {
} }
fn capture_inner(&self, address: usize, size: usize, writable: bool) -> Result<usize> { fn capture_inner(&self, address: usize, size: usize, writable: bool) -> Result<usize> {
let context_lock = self.context.upgrade().ok_or(Error::new(ESRCH))?; if size == 0 {
let context = context_lock.read(); Ok(0)
} else {
let context_lock = self.context.upgrade().ok_or(Error::new(ESRCH))?;
let context = context_lock.read();
let mut grants = context.grants.lock(); let mut grants = context.grants.lock();
let mut new_table = unsafe { InactivePageTable::from_address(context.arch.get_page_table()) }; let mut new_table = unsafe { InactivePageTable::from_address(context.arch.get_page_table()) };
let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(arch::USER_TMP_GRANT_OFFSET))); let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(arch::USER_TMP_GRANT_OFFSET)));
let from_address = (address/4096) * 4096; let from_address = (address/4096) * 4096;
let offset = address - from_address; let offset = address - from_address;
let full_size = ((offset + size + 4095)/4096) * 4096; let full_size = ((offset + size + 4095)/4096) * 4096;
let mut to_address = arch::USER_GRANT_OFFSET; let mut to_address = arch::USER_GRANT_OFFSET;
let mut flags = entry::PRESENT | entry::NO_EXECUTE; let mut flags = entry::PRESENT | entry::NO_EXECUTE;
if writable { if writable {
flags |= entry::WRITABLE; flags |= entry::WRITABLE;
} }
for i in 0 .. grants.len() { for i in 0 .. grants.len() {
let start = grants[i].start_address().get(); let start = grants[i].start_address().get();
if to_address + full_size < start { if to_address + full_size < start {
grants.insert(i, Grant::new( grants.insert(i, Grant::new(
VirtualAddress::new(from_address), VirtualAddress::new(from_address),
VirtualAddress::new(to_address), VirtualAddress::new(to_address),
full_size, full_size,
flags, flags,
&mut new_table, &mut new_table,
&mut temporary_page &mut temporary_page
)); ));
return Ok(to_address + offset); return Ok(to_address + offset);
} else { } else {
let pages = (grants[i].size() + 4095) / 4096; let pages = (grants[i].size() + 4095) / 4096;
let end = start + pages * 4096; let end = start + pages * 4096;
to_address = end; to_address = end;
}
} }
}
grants.push(Grant::new( grants.push(Grant::new(
VirtualAddress::new(from_address), VirtualAddress::new(from_address),
VirtualAddress::new(to_address), VirtualAddress::new(to_address),
full_size, full_size,
flags, flags,
&mut new_table, &mut new_table,
&mut temporary_page &mut temporary_page
)); ));
return Ok(to_address + offset); Ok(to_address + offset)
}
} }
pub fn release(&self, address: usize) -> Result<()> { pub fn release(&self, address: usize) -> Result<()> {
let context_lock = self.context.upgrade().ok_or(Error::new(ESRCH))?; if address == 0 {
let context = context_lock.read(); Ok(())
} else {
let context_lock = self.context.upgrade().ok_or(Error::new(ESRCH))?;
let context = context_lock.read();
let mut grants = context.grants.lock(); let mut grants = context.grants.lock();
let mut new_table = unsafe { InactivePageTable::from_address(context.arch.get_page_table()) }; let mut new_table = unsafe { InactivePageTable::from_address(context.arch.get_page_table()) };
let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(arch::USER_TMP_GRANT_OFFSET))); let mut temporary_page = TemporaryPage::new(Page::containing_address(VirtualAddress::new(arch::USER_TMP_GRANT_OFFSET)));
for i in 0 .. grants.len() { for i in 0 .. grants.len() {
let start = grants[i].start_address().get(); let start = grants[i].start_address().get();
let end = start + grants[i].size(); let end = start + grants[i].size();
if address >= start && address < end { if address >= start && address < end {
grants.remove(i).destroy(&mut new_table, &mut temporary_page); grants.remove(i).destroy(&mut new_table, &mut temporary_page);
return Ok(()); return Ok(());
}
} }
}
Err(Error::new(EFAULT)) Err(Error::new(EFAULT))
}
} }
pub fn read(&self, buf: &mut [u8]) -> Result<usize> { pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
......
use core::slice; use core::{mem, slice};
use arch::paging::{ActivePageTable, Page, VirtualAddress, entry};
use syscall::error::*; use syscall::error::*;
fn validate(address: usize, size: usize, flags: entry::EntryFlags) -> Result<()> {
let active_table = unsafe { ActivePageTable::new() };
let start_page = Page::containing_address(VirtualAddress::new(address));
let end_page = Page::containing_address(VirtualAddress::new(address + size - 1));
for page in Page::range_inclusive(start_page, end_page) {
let page_flags = active_table.translate_page_flags(page).ok_or(Error::new(EFAULT))?;
if ! page_flags.contains(flags) {
return Err(Error::new(EFAULT));
}
}
Ok(())
}
/// Convert a pointer and length to slice, if valid /// Convert a pointer and length to slice, if valid
/// TODO: Check validity
pub fn validate_slice<T>(ptr: *const T, len: usize) -> Result<&'static [T]> { pub fn validate_slice<T>(ptr: *const T, len: usize) -> Result<&'static [T]> {
Ok(unsafe { slice::from_raw_parts(ptr, len) }) if len == 0 {
Ok(&[])
} else {
validate(ptr as usize, len * mem::size_of::<T>(), entry::PRESENT /* TODO | entry::USER_ACCESSIBLE */)?;
Ok(unsafe { slice::from_raw_parts(ptr, len) })
}
} }
/// Convert a pointer and length to slice, if valid /// Convert a pointer and length to slice, if valid
/// TODO: Check validity
pub fn validate_slice_mut<T>(ptr: *mut T, len: usize) -> Result<&'static mut [T]> { pub fn validate_slice_mut<T>(ptr: *mut T, len: usize) -> Result<&'static mut [T]> {
Ok(unsafe { slice::from_raw_parts_mut(ptr, len) }) if len == 0 {
Ok(&mut [])
} else {
validate(ptr as usize, len * mem::size_of::<T>(), entry::PRESENT | entry::WRITABLE /* TODO | entry::USER_ACCESSIBLE */)?;
Ok(unsafe { slice::from_raw_parts_mut(ptr, len) })
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment