diff --git a/Cargo.lock b/Cargo.lock
index b42e20eddffee31519984ed943290525fb650915..0cc040753313db48d3153fd1c60a73dc9d34047e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -66,7 +66,7 @@ dependencies = [
 
 [[package]]
 name = "redox_syscall"
-version = "0.1.31"
+version = "0.1.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -75,7 +75,7 @@ version = "0.3.2"
 dependencies = [
  "fuse 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
  "spin 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
  "uuid 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -98,7 +98,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
- "redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)",
+ "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -130,7 +130,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"
 "checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
 "checksum rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6475140dfd8655aeb72e1fd4b7a1cc1c202be65d71669476e392fe62532b9edd"
-"checksum redox_syscall 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "8dde11f18c108289bef24469638a04dce49da56084f2d50618b226e47eb04509"
+"checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0"
 "checksum spin 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7e4deb3c2455c73779e6d3eebceae9599fc70957e54c69fe88f93aa48e62f432"
 "checksum thread-scoped 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bcbb6aa301e5d3b0b5ef639c9a9c7e2f1c944f177b460c04dc24c69b1fa2bd99"
 "checksum time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d788d3aa77bc0ef3e9621256885555368b47bd495c13dd2e7413c89f845520"
diff --git a/src/mount/redox/resource.rs b/src/mount/redox/resource.rs
index ebe16067b6077cd1980f23091d9b1ef4b35ad1c4..59b9a25e4eb35b4348df0b1703a4f094e02febd3 100644
--- a/src/mount/redox/resource.rs
+++ b/src/mount/redox/resource.rs
@@ -2,8 +2,8 @@ use std::cmp::{min, max};
 use std::time::{SystemTime, UNIX_EPOCH};
 
 use syscall::data::TimeSpec;
-use syscall::error::{Error, Result, EBADF, EINVAL, EISDIR};
-use syscall::flag::{O_ACCMODE, O_RDONLY, O_WRONLY, O_RDWR, F_GETFL, F_SETFL};
+use syscall::error::{Error, Result, EBADF, EINVAL, EISDIR, EPERM};
+use syscall::flag::{O_ACCMODE, O_RDONLY, O_WRONLY, O_RDWR, F_GETFL, F_SETFL, MODE_PERM};
 use syscall::{Stat, SEEK_SET, SEEK_CUR, SEEK_END};
 
 use disk::Disk;
@@ -14,6 +14,8 @@ pub trait Resource<D: Disk> {
     fn read(&mut self, buf: &mut [u8], fs: &mut FileSystem<D>) -> Result<usize>;
     fn write(&mut self, buf: &[u8], fs: &mut FileSystem<D>) -> Result<usize>;
     fn seek(&mut self, offset: usize, whence: usize, fs: &mut FileSystem<D>) -> Result<usize>;
+    fn fchmod(&mut self, mode: u16, fs: &mut FileSystem<D>) -> Result<usize>;
+    fn fchown(&mut self, uid: u32, gid: u32, fs: &mut FileSystem<D>) -> Result<usize>;
     fn fcntl(&mut self, cmd: usize, arg: usize) -> Result<usize>;
     fn path(&self, buf: &mut [u8]) -> Result<usize>;
     fn stat(&self, _stat: &mut Stat, fs: &mut FileSystem<D>) -> Result<usize>;
@@ -27,15 +29,17 @@ pub struct DirResource {
     block: u64,
     data: Option<Vec<u8>>,
     seek: usize,
+    uid: u32,
 }
 
 impl DirResource {
-    pub fn new(path: String, block: u64, data: Option<Vec<u8>>) -> DirResource {
+    pub fn new(path: String, block: u64, data: Option<Vec<u8>>, uid: u32) -> DirResource {
         DirResource {
             path: path,
             block: block,
             data: data,
             seek: 0,
+            uid: uid,
         }
     }
 }
@@ -46,7 +50,8 @@ impl<D: Disk> Resource<D> for DirResource {
             path: self.path.clone(),
             block: self.block,
             data: self.data.clone(),
-            seek: self.seek
+            seek: self.seek,
+            uid: self.uid
         }))
     }
 
@@ -77,6 +82,40 @@ impl<D: Disk> Resource<D> for DirResource {
         Ok(self.seek)
     }
 
+    fn fchmod(&mut self, mode: u16, fs: &mut FileSystem<D>) -> Result<usize> {
+        let mut node = fs.node(self.block)?;
+
+        if node.1.uid == self.uid || self.uid == 0 {
+            node.1.mode = (node.1.mode & ! MODE_PERM) | (mode & MODE_PERM);
+
+            fs.write_at(node.0, &node.1)?;
+
+            Ok(0)
+        } else {
+            Err(Error::new(EPERM))
+        }
+    }
+
+    fn fchown(&mut self, uid: u32, gid: u32, fs: &mut FileSystem<D>) -> Result<usize> {
+        let mut node = fs.node(self.block)?;
+
+        if node.1.uid == self.uid || self.uid == 0 {
+            if uid as i32 != -1 {
+                node.1.uid = uid;
+            }
+
+            if gid as i32 != -1 {
+                node.1.gid = gid;
+            }
+
+            fs.write_at(node.0, &node.1)?;
+
+            Ok(0)
+        } else {
+            Err(Error::new(EPERM))
+        }
+    }
+
     fn fcntl(&mut self, _cmd: usize, _arg: usize) -> Result<usize> {
         Err(Error::new(EBADF))
     }
@@ -192,6 +231,40 @@ impl<D: Disk> Resource<D> for FileResource {
         Ok(self.seek as usize)
     }
 
+    fn fchmod(&mut self, mode: u16, fs: &mut FileSystem<D>) -> Result<usize> {
+        let mut node = fs.node(self.block)?;
+
+        if node.1.uid == self.uid || self.uid == 0 {
+            node.1.mode = (node.1.mode & ! MODE_PERM) | (mode & MODE_PERM);
+
+            fs.write_at(node.0, &node.1)?;
+
+            Ok(0)
+        } else {
+            Err(Error::new(EPERM))
+        }
+    }
+
+    fn fchown(&mut self, uid: u32, gid: u32, fs: &mut FileSystem<D>) -> Result<usize> {
+        let mut node = fs.node(self.block)?;
+
+        if node.1.uid == self.uid || self.uid == 0 {
+            if uid as i32 != -1 {
+                node.1.uid = uid;
+            }
+
+            if gid as i32 != -1 {
+                node.1.gid = gid;
+            }
+
+            fs.write_at(node.0, &node.1)?;
+
+            Ok(0)
+        } else {
+            Err(Error::new(EPERM))
+        }
+    }
+
     fn fcntl(&mut self, cmd: usize, arg: usize) -> Result<usize> {
         match cmd {
             F_GETFL => Ok(self.flags),
@@ -265,7 +338,7 @@ impl<D: Disk> Resource<D> for FileResource {
                 Ok(0)
             }
         } else {
-            Err(Error::new(EBADF))
+            Err(Error::new(EPERM))
         }
     }
 }
diff --git a/src/mount/redox/scheme.rs b/src/mount/redox/scheme.rs
index 1f4bdb442baa3c76107327ffaff85185b329236b..2407ff29bc7b4fe013b45f044f54ad0262cd7882 100644
--- a/src/mount/redox/scheme.rs
+++ b/src/mount/redox/scheme.rs
@@ -210,12 +210,12 @@ impl<D: Disk> Scheme for FileScheme<D> {
                         }
                     }
 
-                    Box::new(DirResource::new(path.to_string(), node.0, Some(data)))
+                    Box::new(DirResource::new(path.to_string(), node.0, Some(data), uid))
                 } else if flags & O_WRONLY == O_WRONLY {
                     // println!("{:X} & {:X}: EISDIR {}", flags, O_DIRECTORY, path);
                     return Err(Error::new(EISDIR));
                 } else {
-                    Box::new(DirResource::new(path.to_string(), node.0, None))
+                    Box::new(DirResource::new(path.to_string(), node.0, None, uid))
                 }
             } else if node.1.is_symlink() && !(flags & O_STAT == O_STAT && flags  & O_NOFOLLOW == O_NOFOLLOW) && flags & O_SYMLINK != O_SYMLINK {
                 let mut resolve_nodes = Vec::new();
@@ -287,7 +287,7 @@ impl<D: Disk> Scheme for FileScheme<D> {
                         fs.write_at(node.0, &node.1)?;
 
                         if dir {
-                            Box::new(DirResource::new(path.to_string(), node.0, None))
+                            Box::new(DirResource::new(path.to_string(), node.0, None, uid))
                         } else {
                             let seek = if flags & O_APPEND == O_APPEND {
                                 fs.node_len(node.0)?
@@ -466,6 +466,24 @@ impl<D: Disk> Scheme for FileScheme<D> {
         }
     }
 
+    fn fchmod(&self, id: usize, mode: u16) -> Result<usize> {
+        let mut files = self.files.lock();
+        if let Some(file) = files.get_mut(&id) {
+            file.fchmod(mode, &mut self.fs.borrow_mut())
+        } else {
+            Err(Error::new(EBADF))
+        }
+    }
+
+    fn fchown(&self, id: usize, uid: u32, gid: u32) -> Result<usize> {
+        let mut files = self.files.lock();
+        if let Some(file) = files.get_mut(&id) {
+            file.fchown(uid, gid, &mut self.fs.borrow_mut())
+        } else {
+            Err(Error::new(EBADF))
+        }
+    }
+
     fn fcntl(&self, id: usize, cmd: usize, arg: usize) -> Result<usize> {
         let mut files = self.files.lock();
         if let Some(file) = files.get_mut(&id) {