Change how we handle the vmar permission

This commit is contained in:
Ben Pig Chu 2020-09-19 21:36:56 +08:00
parent 31fde3be20
commit 0988aa6b56
3 changed files with 60 additions and 26 deletions

View File

@ -19,6 +19,7 @@ pub mod defs {
const WRITE = 1 << 3;
const EXECUTE = 1 << 4;
const USER = 1 << 5;
const RXW = Self::READ.bits | Self::WRITE.bits | Self::EXECUTE.bits;
}
}
numeric_enum! {

View File

@ -157,7 +157,7 @@ impl VmAddressRegion {
len: usize,
flags: MMUFlags,
) -> ZxResult<VirtAddr> {
self.map_ext(Some(vmar_offset), vmo, vmo_offset, len, flags, false, true)
self.map(Some(vmar_offset), vmo, vmo_offset, len, flags)
}
/// Map the `vmo` into this VMAR.
@ -169,7 +169,16 @@ impl VmAddressRegion {
len: usize,
flags: MMUFlags,
) -> ZxResult<VirtAddr> {
self.map_ext(vmar_offset, vmo, vmo_offset, len, flags, false, true)
self.map_ext(
vmar_offset,
vmo,
vmo_offset,
len,
MMUFlags::RXW,
flags,
false,
true,
)
}
/// Map the `vmo` into this VMAR.
@ -180,6 +189,7 @@ impl VmAddressRegion {
vmo: Arc<VmObject>,
vmo_offset: usize,
len: usize,
permissions: MMUFlags,
flags: MMUFlags,
overwrite: bool,
_map_range: bool,
@ -187,6 +197,9 @@ impl VmAddressRegion {
if !page_aligned(vmo_offset) || !page_aligned(len) || vmo_offset.overflowing_add(len).1 {
return Err(ZxError::INVALID_ARGS);
}
if !permissions.contains(flags & MMUFlags::RXW) {
return Err(ZxError::ACCESS_DENIED);
}
// TODO: allow the mapping extends past the end of vmo
if vmo_offset > vmo.len() || len > vmo.len() - vmo_offset {
return Err(ZxError::INVALID_ARGS);
@ -208,7 +221,15 @@ impl VmAddressRegion {
return Err(ZxError::NO_MEMORY);
}
}
let mapping = VmMapping::new(addr, len, vmo, vmo_offset, flags, self.page_table.clone());
let mapping = VmMapping::new(
addr,
len,
vmo,
vmo_offset,
permissions,
flags,
self.page_table.clone(),
);
let map_range = true;
if map_range {
mapping.map()?;
@ -614,6 +635,9 @@ pub struct VmarInfo {
/// Virtual Memory Mapping
pub struct VmMapping {
/// The permission limitation of the vmar
permissions: MMUFlags,
/// The actual flags used in the mapping
flags: MMUFlags,
vmo: Arc<VmObject>,
page_table: Arc<Mutex<dyn PageTableTrait>>,
@ -643,6 +667,7 @@ impl core::fmt::Debug for VmMapping {
f.debug_struct("VmMapping")
.field("addr", &inner.addr)
.field("size", &inner.size)
.field("permissions", &self.permissions)
.field("flags", &self.flags)
.field("vmo_id", &self.vmo.id())
.field("vmo_offset", &inner.vmo_offset)
@ -656,6 +681,7 @@ impl VmMapping {
size: usize,
vmo: Arc<VmObject>,
vmo_offset: usize,
permissions: MMUFlags,
flags: MMUFlags,
page_table: Arc<Mutex<dyn PageTableTrait>>,
) -> Arc<Self> {
@ -665,6 +691,7 @@ impl VmMapping {
size,
vmo_offset,
}),
permissions,
flags,
page_table,
vmo: vmo.clone(),
@ -769,6 +796,7 @@ impl VmMapping {
new_len2,
self.vmo.clone(),
inner.vmo_offset + (end - inner.addr),
self.permissions,
self.flags,
self.page_table.clone(),
))
@ -786,16 +814,7 @@ impl VmMapping {
}
fn is_valid_mapping_flags(&self, flags: MMUFlags) -> bool {
if !flags.contains(MMUFlags::READ) && self.flags.contains(MMUFlags::READ) {
return false;
}
if !flags.contains(MMUFlags::WRITE) && self.flags.contains(MMUFlags::WRITE) {
return false;
}
if !flags.contains(MMUFlags::EXECUTE) && self.flags.contains(MMUFlags::EXECUTE) {
return false;
}
true
self.permissions.contains(flags & MMUFlags::RXW)
}
fn protect(&self, flags: MMUFlags) {
@ -864,6 +883,7 @@ impl VmMapping {
let new_vmo = self.vmo.create_child(false, 0, self.vmo.len())?;
let mapping = Arc::new(VmMapping {
inner: Mutex::new(self.inner.lock().clone()),
permissions: self.permissions,
flags: self.flags,
page_table,
vmo: new_vmo.clone(),

View File

@ -117,19 +117,17 @@ impl Syscall<'_> {
if !is_specific && vmar_offset != 0 {
return Err(ZxError::INVALID_ARGS);
}
if !vmar_rights.contains(options.to_required_rights()) {
return Err(ZxError::ACCESS_DENIED);
}
let mut permissions = MMUFlags::empty();
permissions.set(MMUFlags::READ, vmo_rights.contains(Rights::READ));
permissions.set(MMUFlags::WRITE, vmo_rights.contains(Rights::WRITE));
permissions.set(MMUFlags::EXECUTE, vmo_rights.contains(Rights::EXECUTE));
let mut mapping_flags = MMUFlags::USER;
mapping_flags.set(
MMUFlags::READ,
vmar_rights.contains(Rights::READ) && vmo_rights.contains(Rights::READ),
);
mapping_flags.set(
MMUFlags::WRITE,
vmar_rights.contains(Rights::WRITE) && vmo_rights.contains(Rights::WRITE),
);
mapping_flags.set(
MMUFlags::EXECUTE,
vmar_rights.contains(Rights::EXECUTE) && vmo_rights.contains(Rights::EXECUTE),
);
mapping_flags.set(MMUFlags::READ, options.contains(VmOptions::PERM_READ));
mapping_flags.set(MMUFlags::WRITE, options.contains(VmOptions::PERM_WRITE));
mapping_flags.set(MMUFlags::EXECUTE, options.contains(VmOptions::PERM_EXECUTE));
info!(
"mmuflags: {:?}, is_specific {:?}",
mapping_flags, is_specific
@ -153,6 +151,7 @@ impl Syscall<'_> {
vmo,
vmo_offset,
len,
permissions,
mapping_flags,
overwrite,
map_range,
@ -183,7 +182,7 @@ impl Syscall<'_> {
len: u64,
) -> ZxResult {
let options = VmOptions::from_bits(options).ok_or(ZxError::INVALID_ARGS)?;
let rights = options.to_rights();
let rights = options.to_required_rights();
info!(
"vmar.protect: handle={:#x}, options={:#x}, addr={:#x}, len={:#x}",
handle_value, options, addr, len
@ -255,6 +254,20 @@ impl VmOptions {
rights
}
fn to_required_rights(self) -> Rights {
let mut rights = Rights::empty();
if self.contains(VmOptions::PERM_READ) {
rights.insert(Rights::READ);
}
if self.contains(VmOptions::PERM_WRITE) {
rights.insert(Rights::WRITE);
}
if self.contains(VmOptions::PERM_EXECUTE) {
rights.insert(Rights::EXECUTE);
}
rights
}
fn to_flags(self) -> VmarFlags {
let mut flags = VmarFlags::empty();
if self.contains(VmOptions::COMPACT) {