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]> {