mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-08 21:06:48 +00:00
Fix some performance issue in VmMapping
This commit is contained in:
parent
c875201c3f
commit
e77026c30e
@ -189,10 +189,9 @@ impl VmMapping {
|
|||||||
|
|
||||||
// TODO: the current logic is vulnerable to TOCTTOU attack, since the permission may change after check.
|
// TODO: the current logic is vulnerable to TOCTTOU attack, since the permission may change after check.
|
||||||
let page_idx_range = get_page_idx_range(&(vmo_read_offset..vmo_read_offset + buf.len()));
|
let page_idx_range = get_page_idx_range(&(vmo_read_offset..vmo_read_offset + buf.len()));
|
||||||
|
self.check_page_idx_range(&page_idx_range)?;
|
||||||
let read_perm = VmPerm::R;
|
let read_perm = VmPerm::R;
|
||||||
for page_idx in page_idx_range {
|
self.check_perm(&read_perm)?;
|
||||||
self.check_perm(&page_idx, &read_perm)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.vmo.read_bytes(vmo_read_offset, buf)?;
|
self.vmo.read_bytes(vmo_read_offset, buf)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -202,13 +201,13 @@ impl VmMapping {
|
|||||||
let vmo_write_offset = self.vmo_offset() + offset;
|
let vmo_write_offset = self.vmo_offset() + offset;
|
||||||
|
|
||||||
let page_idx_range = get_page_idx_range(&(vmo_write_offset..vmo_write_offset + buf.len()));
|
let page_idx_range = get_page_idx_range(&(vmo_write_offset..vmo_write_offset + buf.len()));
|
||||||
|
self.check_page_idx_range(&page_idx_range)?;
|
||||||
let write_perm = VmPerm::W;
|
let write_perm = VmPerm::W;
|
||||||
|
self.check_perm(&write_perm)?;
|
||||||
|
|
||||||
let mut page_addr =
|
let mut page_addr =
|
||||||
self.map_to_addr() - self.vmo_offset() + page_idx_range.start * PAGE_SIZE;
|
self.map_to_addr() - self.vmo_offset() + page_idx_range.start * PAGE_SIZE;
|
||||||
for page_idx in page_idx_range {
|
for page_idx in page_idx_range {
|
||||||
self.check_perm(&page_idx, &write_perm)?;
|
|
||||||
|
|
||||||
let parent = self.parent.upgrade().unwrap();
|
let parent = self.parent.upgrade().unwrap();
|
||||||
let vm_space = parent.vm_space();
|
let vm_space = parent.vm_space();
|
||||||
|
|
||||||
@ -255,7 +254,7 @@ impl VmMapping {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let required_perm = if write { VmPerm::W } else { VmPerm::R };
|
let required_perm = if write { VmPerm::W } else { VmPerm::R };
|
||||||
self.check_perm(&page_idx, &required_perm)?;
|
self.check_perm(&required_perm)?;
|
||||||
|
|
||||||
let frame = self.vmo.get_committed_frame(page_idx, write)?;
|
let frame = self.vmo.get_committed_frame(page_idx, write)?;
|
||||||
|
|
||||||
@ -442,8 +441,12 @@ impl VmMapping {
|
|||||||
self.inner.lock().trim_right(vm_space, vaddr)
|
self.inner.lock().trim_right(vm_space, vaddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_perm(&self, page_idx: &usize, perm: &VmPerm) -> Result<()> {
|
fn check_perm(&self, perm: &VmPerm) -> Result<()> {
|
||||||
self.inner.lock().check_perm(page_idx, perm)
|
self.inner.lock().check_perm(perm)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_page_idx_range(&self, page_idx_range: &Range<usize>) -> Result<()> {
|
||||||
|
self.inner.lock().check_page_idx_range(page_idx_range)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -501,7 +504,9 @@ impl VmMappingInner {
|
|||||||
..(range.end - map_to_addr + self.vmo_offset);
|
..(range.end - map_to_addr + self.vmo_offset);
|
||||||
let page_idx_range = get_page_idx_range(&vmo_map_range);
|
let page_idx_range = get_page_idx_range(&vmo_map_range);
|
||||||
for page_idx in page_idx_range {
|
for page_idx in page_idx_range {
|
||||||
self.unmap_one_page(vm_space, page_idx)?;
|
if self.mapped_pages.contains(&page_idx) {
|
||||||
|
self.unmap_one_page(vm_space, page_idx)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if may_destroy && *range == self.range() {
|
if may_destroy && *range == self.range() {
|
||||||
self.is_destroyed = false;
|
self.is_destroyed = false;
|
||||||
@ -590,17 +595,19 @@ impl VmMappingInner {
|
|||||||
self.map_to_addr..self.map_to_addr + self.map_size
|
self.map_to_addr..self.map_to_addr + self.map_size
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_perm(&self, page_idx: &usize, perm: &VmPerm) -> Result<()> {
|
fn check_perm(&self, perm: &VmPerm) -> Result<()> {
|
||||||
// Check if the page is in current VmMapping.
|
|
||||||
if page_idx * PAGE_SIZE < self.vmo_offset
|
|
||||||
|| (page_idx + 1) * PAGE_SIZE > self.vmo_offset + self.map_size
|
|
||||||
{
|
|
||||||
return_errno_with_message!(Errno::EINVAL, "invalid page idx");
|
|
||||||
}
|
|
||||||
if !self.perm.contains(*perm) {
|
if !self.perm.contains(*perm) {
|
||||||
return_errno_with_message!(Errno::EACCES, "perm check fails");
|
return_errno_with_message!(Errno::EACCES, "perm check fails");
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_page_idx_range(&self, page_idx_range: &Range<usize>) -> Result<()> {
|
||||||
|
if page_idx_range.start * PAGE_SIZE < self.vmo_offset
|
||||||
|
|| page_idx_range.end * PAGE_SIZE > self.vmo_offset + self.map_size
|
||||||
|
{
|
||||||
|
return_errno_with_message!(Errno::EINVAL, "invalid page idx");
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user