diff --git a/src/scheme/memory.rs b/src/scheme/memory.rs index 2c443551260ebf2651503bbdaedaf537b45ac269..2636ebf84ef2bb8ddf94f4aed533262e5288fcb1 100644 --- a/src/scheme/memory.rs +++ b/src/scheme/memory.rs @@ -13,25 +13,8 @@ impl MemoryScheme { pub fn new() -> Self { MemoryScheme } -} -impl Scheme for MemoryScheme { - fn open(&self, _path: &str, _flags: usize, _uid: u32, _gid: u32) -> Result<usize> { - Ok(0) - } - fn fstatvfs(&self, _file: usize, stat: &mut StatVfs) -> Result<usize> { - let used = used_frames() as u64; - let free = free_frames() as u64; - - stat.f_bsize = PAGE_SIZE as u32; - stat.f_blocks = used + free; - stat.f_bfree = free; - stat.f_bavail = stat.f_bfree; - - Ok(0) - } - - fn fmap(&self, _id: usize, map: &Map) -> Result<usize> { + pub fn fmap_anonymous(map: &Map) -> Result<usize> { //TODO: Abstract with other grant creation if map.size == 0 { Ok(0) @@ -63,6 +46,27 @@ impl Scheme for MemoryScheme { Ok(region.start_address().data()) } } +} +impl Scheme for MemoryScheme { + fn open(&self, _path: &str, _flags: usize, _uid: u32, _gid: u32) -> Result<usize> { + Ok(0) + } + + fn fstatvfs(&self, _file: usize, stat: &mut StatVfs) -> Result<usize> { + let used = used_frames() as u64; + let free = free_frames() as u64; + + stat.f_bsize = PAGE_SIZE as u32; + stat.f_blocks = used + free; + stat.f_bfree = free; + stat.f_bavail = stat.f_bfree; + + Ok(0) + } + + fn fmap(&self, _id: usize, map: &Map) -> Result<usize> { + Self::fmap_anonymous(map) + } fn fmap_old(&self, id: usize, map: &OldMap) -> Result<usize> { if map.flags.contains(MapFlags::MAP_FIXED) { // not supported for fmap, which lacks the address argument. diff --git a/src/syscall/mod.rs b/src/syscall/mod.rs index 54c66e19a3ca82b0c2a842c0b2ba30ad18abbccd..3955af57029288c75a757512a1095adf7957fc2b 100644 --- a/src/syscall/mod.rs +++ b/src/syscall/mod.rs @@ -25,14 +25,14 @@ pub use self::process::*; pub use self::time::*; pub use self::validate::*; -use self::data::{SigAction, TimeSpec}; +use self::data::{Map, SigAction, TimeSpec}; use self::error::{Error, Result, ENOSYS}; use self::flag::{CloneFlags, MapFlags, PhysmapFlags, WaitFlags}; use self::number::*; use crate::context::ContextId; use crate::interrupt::InterruptStack; -use crate::scheme::{FileHandle, SchemeNamespace}; +use crate::scheme::{FileHandle, SchemeNamespace, memory::MemoryScheme}; /// Debug pub mod debug; @@ -68,7 +68,12 @@ pub fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, bp: u SYS_CLASS_FILE => { let fd = FileHandle::from(b); match a & SYS_ARG { - SYS_ARG_SLICE => file_op_slice(a, fd, validate_slice(c as *const u8, d)?), + SYS_ARG_SLICE => match a { + SYS_FMAP if b == !0 => { + MemoryScheme::fmap_anonymous(unsafe { validate_ref(c as *const Map, d)? }) + }, + _ => file_op_slice(a, fd, validate_slice(c as *const u8, d)?), + } SYS_ARG_MSLICE => file_op_mut_slice(a, fd, validate_slice_mut(c as *mut u8, d)?), _ => match a { SYS_CLOSE => close(fd), diff --git a/src/syscall/validate.rs b/src/syscall/validate.rs index 883f01c3770648af03866fcf1d8840ad658605f1..e6cf7352918d07ea2ff5e438ddf2915ad26bb346 100644 --- a/src/syscall/validate.rs +++ b/src/syscall/validate.rs @@ -31,6 +31,16 @@ fn validate(address: usize, size: usize, writable: bool) -> Result<()> { Ok(()) } +/// Convert a pointer and length to reference, if valid +pub unsafe fn validate_ref<T>(ptr: *const T, size: usize) -> Result<&'static T> { + if size == mem::size_of::<T>() { + validate(ptr as usize, mem::size_of::<T>(), false)?; + Ok(unsafe { &*ptr }) + } else { + Err(Error::new(EINVAL)) + } +} + /// Convert a pointer and length to slice, if valid //TODO: Mark unsafe pub fn validate_slice<T>(ptr: *const T, len: usize) -> Result<&'static [T]> {