diff --git a/Cargo.lock b/Cargo.lock
index ca2660b04070783c282fcf1ca54a24a91ca6ca3a..5750edb8c18316ab4d747404d2be29a121d5e08c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -247,6 +247,7 @@ dependencies = [
  "ralloc 1.0.0",
  "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "sc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
+ "spin 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
diff --git a/include/bits/sys/mman.h b/include/bits/sys/mman.h
new file mode 100644
index 0000000000000000000000000000000000000000..e2ece78cc5e054f871289d5ba68ff1596025bb84
--- /dev/null
+++ b/include/bits/sys/mman.h
@@ -0,0 +1,6 @@
+#ifndef _BITS_SYS_MMAN_H
+#define _BITS_SYS_MMAN_H
+
+#define MAP_FAILED ((void *) -1)
+
+#endif
diff --git a/include/limits.h b/include/limits.h
index a8a750bb490bf8124f181bfa892971bafce8c21c..1b2de46fc821197cdcd923a2459afa1ac1b2d76e 100644
--- a/include/limits.h
+++ b/include/limits.h
@@ -1,7 +1,11 @@
 #define MB_LEN_MAX 4 // unicode
 
 #define CHAR_BIT __CHAR_BIT__
-#define CHAR_MAX __CHAR_MAX__
+#ifdef __CHAR_MAX__
+# define CHAR_MAX __CHAR_MAX__
+#else
+# define CHAR_MAX 0xFF
+#endif
 #define CHAR_MIN 0
 #define INT_MAX __INT_MAX__
 #define INT_MIN (-INT_MAX - 1)
diff --git a/include/stddef.h b/include/stddef.h
index 1dc7f60fc1f57381b7323237c472de81c6cc86ed..0ee2d47174902e7223af0fe346ab93bbbc5dd7da 100644
--- a/include/stddef.h
+++ b/include/stddef.h
@@ -10,4 +10,6 @@ typedef int32_t wchar_t;
 
 typedef unsigned long long size_t;
 
+#define offsetof(type, member) __builtin_offsetof(type, member)
+
 #endif /* _STDDEF_H */
diff --git a/src/fcntl/src/linux.rs b/src/fcntl/src/linux.rs
index 98a5f8a2cfc7501941333a8a21e8bd4fece709dc..05948a6da50d482a5f6879dccffd6285c588b48c 100644
--- a/src/fcntl/src/linux.rs
+++ b/src/fcntl/src/linux.rs
@@ -10,3 +10,4 @@ pub const O_APPEND: c_int = 0o2000;
 pub const O_CLOEXEC: c_int = 0o2_000_000;
 pub const O_DIRECTORY: c_int = 0o200_000;
 pub const O_EXCL: c_int = 0o200;
+pub const O_NONBLOCK: c_int = 0o4000;
diff --git a/src/platform/Cargo.toml b/src/platform/Cargo.toml
index 3a1ecfbfdaed7d43bbc4739b008626e1a415ff9e..6c179a9fc615b070bafc783b476cfbaac9cf12f1 100644
--- a/src/platform/Cargo.toml
+++ b/src/platform/Cargo.toml
@@ -13,3 +13,4 @@ sc = "0.2"
 
 [target.'cfg(target_os = "redox")'.dependencies]
 redox_syscall = "0.1"
+spin = "0.4"
diff --git a/src/platform/src/lib.rs b/src/platform/src/lib.rs
index 37964737071a71b3885766b331c080c401eb6d4d..2a634a4eef497a329e36353b13eee6b84be19610 100644
--- a/src/platform/src/lib.rs
+++ b/src/platform/src/lib.rs
@@ -6,13 +6,16 @@
 #[cfg_attr(target_os = "redox", macro_use)]
 extern crate alloc;
 
-#[cfg(all(not(feature = "no_std"), target_os = "linux"))]
+#[cfg(target_os = "linux")]
 #[macro_use]
 extern crate sc;
 
-#[cfg(all(not(feature = "no_std"), target_os = "redox"))]
+#[cfg(target_os = "redox")]
 extern crate syscall;
 
+#[cfg(target_os = "redox")]
+extern crate spin;
+
 pub use allocator::*;
 
 #[cfg(not(feature = "ralloc"))]
@@ -38,7 +41,7 @@ pub mod types;
 
 pub use rawfile::RawFile;
 
-use alloc::Vec;
+use alloc::vec::Vec;
 use core::{fmt, ptr};
 
 use types::*;
diff --git a/src/platform/src/linux/mod.rs b/src/platform/src/linux/mod.rs
index be108e8d62133595fbc52f022256d9820674fbdc..5446a52f1a47344903a3daa0acdc9ad2ebffe316 100644
--- a/src/platform/src/linux/mod.rs
+++ b/src/platform/src/linux/mod.rs
@@ -284,6 +284,21 @@ pub fn mkfifo(path: *const c_char, mode: mode_t) -> c_int {
     e(unsafe { syscall!(MKNODAT, AT_FDCWD, path, mode, 0) }) as c_int
 }
 
+pub unsafe fn mmap(
+    addr: *mut c_void,
+    len: usize,
+    prot: c_int,
+    flags: c_int,
+    fildes: c_int,
+    off: off_t,
+) -> *mut c_void {
+    e(syscall!(MMAP, addr, len, prot, flags, fildes, off)) as *mut c_void
+}
+
+pub unsafe fn munmap(addr: *mut c_void, len: usize) -> c_int {
+    e(syscall!(MUNMAP, addr, len)) as c_int
+}
+
 pub fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int {
     e(unsafe { syscall!(NANOSLEEP, rqtp, rmtp) }) as c_int
 }
diff --git a/src/platform/src/redox/mod.rs b/src/platform/src/redox/mod.rs
index 789e7748300e1cfa15fd2fe49fd9356e6a9fe3c4..6d9afdb3be841f42739938f6b509b01bea05f131 100644
--- a/src/platform/src/redox/mod.rs
+++ b/src/platform/src/redox/mod.rs
@@ -1,9 +1,9 @@
 //! sys/socket implementation, following http://pubs.opengroup.org/onlinepubs/009696699/basedefs/sys/socket.h.html
 
+use alloc::btree_map::BTreeMap;
 use core::fmt::Write;
-use core::mem;
-use core::ptr;
-use core::slice;
+use core::{mem, ptr, slice};
+use spin::{Once, Mutex, MutexGuard};
 use syscall::data::Stat as redox_stat;
 use syscall::data::TimeSpec as redox_timespec;
 use syscall::flag::*;
@@ -13,10 +13,17 @@ use types::*;
 use *;
 
 const EINVAL: c_int = 22;
+const MAP_ANON: c_int = 1;
 
 #[thread_local]
 static mut SIG_HANDLER: Option<extern "C" fn(c_int)> = None;
 
+static ANONYMOUS_MAPS: Once<Mutex<BTreeMap<usize, usize>>> = Once::new();
+
+fn anonymous_maps() -> MutexGuard<'static, BTreeMap<usize, usize>> {
+    ANONYMOUS_MAPS.call_once(|| Mutex::new(BTreeMap::new())).lock()
+}
+
 extern "C" fn sig_handler(sig: usize) {
     if let Some(ref callback) = unsafe { SIG_HANDLER } {
         callback(sig as c_int);
@@ -640,6 +647,43 @@ pub fn mkfifo(path: *const c_char, mode: mode_t) -> c_int {
     }
 }
 
+pub unsafe fn mmap(
+    _addr: *mut c_void,
+    len: usize,
+    _prot: c_int,
+    flags: c_int,
+    fildes: c_int,
+    off: off_t,
+) -> *mut c_void {
+    if flags & MAP_ANON == MAP_ANON {
+        let fd = e(syscall::open("memory:", 0)); // flags don't matter currently
+        if fd == !0 {
+            return !0 as *mut c_void;
+        }
+
+        let addr = e(syscall::fmap(fd, off as usize, len as usize));
+        if addr == !0 {
+            let _ = syscall::close(fd);
+            return !0 as *mut c_void;
+        }
+
+        anonymous_maps().insert(addr as usize, fd);
+        addr as *mut c_void
+    } else {
+        e(syscall::fmap(fildes as usize, off as usize, len as usize)) as *mut c_void
+    }
+}
+
+pub unsafe fn munmap(addr: *mut c_void, _len: usize) -> c_int {
+    if e(syscall::funmap(addr as usize)) == !0 {
+        return !0;
+    }
+    if let Some(fd) = anonymous_maps().remove(&(addr as usize)) {
+        let _ = syscall::close(fd);
+    }
+    0
+}
+
 pub fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> c_int {
     let redox_rqtp = unsafe { redox_timespec::from(&*rqtp) };
     let mut redox_rmtp: redox_timespec;
diff --git a/src/sys_mman/cbindgen.toml b/src/sys_mman/cbindgen.toml
index baaa532574a3feb7241532931e58b8544ba27604..1fecef571c3c4253da90ff9ad31807e0a4b65daa 100644
--- a/src/sys_mman/cbindgen.toml
+++ b/src/sys_mman/cbindgen.toml
@@ -1,5 +1,6 @@
 sys_includes = ["stdint.h", "sys/types.h"]
 include_guard = "_SYS_MMAN_H"
+trailer = "#include <bits/sys/mman.h>"
 language = "C"
 style = "Tag"
 
diff --git a/src/sys_mman/src/lib.rs b/src/sys_mman/src/lib.rs
index 4c47b135aa6be5f7c5a4dc5358edc9c8a66ecd7f..c2151e40368b85b25a09f5ca59a965cb30883fce 100644
--- a/src/sys_mman/src/lib.rs
+++ b/src/sys_mman/src/lib.rs
@@ -24,8 +24,8 @@ pub extern "C" fn mlockall(flags: c_int) -> c_int {
     unimplemented!();
 }
 
-// #[no_mangle]
-pub extern "C" fn mmap(
+#[no_mangle]
+pub unsafe extern "C" fn mmap(
     addr: *mut c_void,
     len: usize,
     prot: c_int,
@@ -33,7 +33,7 @@ pub extern "C" fn mmap(
     fildes: c_int,
     off: off_t,
 ) -> *mut c_void {
-    unimplemented!();
+    platform::mmap(addr, len, prot, flags, fildes, off)
 }
 
 // #[no_mangle]
@@ -56,9 +56,9 @@ pub extern "C" fn munlockall() -> c_int {
     unimplemented!();
 }
 
-// #[no_mangle]
-pub extern "C" fn munmap(addr: *mut c_void, len: usize) -> c_int {
-    unimplemented!();
+#[no_mangle]
+pub unsafe extern "C" fn munmap(addr: *mut c_void, len: usize) -> c_int {
+    platform::munmap(addr, len)
 }
 
 // #[no_mangle]
diff --git a/src/sys_mman/src/linux.rs b/src/sys_mman/src/linux.rs
index 1e00227153c8edb59c915816bea064a940ce7670..0a6933af0d89422ebfe6f868443062947e423889 100644
--- a/src/sys_mman/src/linux.rs
+++ b/src/sys_mman/src/linux.rs
@@ -7,3 +7,5 @@ pub const PROT_NONE: c_int = 0x0;
 
 pub const MAP_SHARED: c_int = 0x1;
 pub const MAP_PRIVATE: c_int = 0x2;
+pub const MAP_ANON: c_int = 0x20;
+pub const MAP_ANONYMOUS: c_int = MAP_ANON;
diff --git a/src/sys_mman/src/redox.rs b/src/sys_mman/src/redox.rs
index 8b137891791fe96927ad78e64b0aad7bded08bdc..1822e15205731bc0efddb89b1117f8bd3aff34ed 100644
--- a/src/sys_mman/src/redox.rs
+++ b/src/sys_mman/src/redox.rs
@@ -1 +1,11 @@
+use platform::types::*;
 
+pub const PROT_READ: c_int = 0;
+pub const PROT_WRITE: c_int = 0;
+pub const PROT_EXEC: c_int = 0;
+pub const PROT_NONE: c_int = 0;
+
+pub const MAP_SHARED: c_int = 0;
+pub const MAP_PRIVATE: c_int = 0;
+pub const MAP_ANON: c_int = 1;
+pub const MAP_ANONYMOUS: c_int = MAP_ANON;