diff --git a/kernel/context/context.rs b/kernel/context/context.rs
index 5e053cabe3f088cec955bba90a656bc5a19116c6..a7d41d488944f81858772649cf9f1b53b6726c42 100644
--- a/kernel/context/context.rs
+++ b/kernel/context/context.rs
@@ -34,10 +34,14 @@ pub struct Context {
     pub ruid: u32,
     /// The real group id
     pub rgid: u32,
+    /// The real namespace id
+    pub rns: SchemeNamespace,
     /// The effective user id
     pub euid: u32,
     /// The effective group id
     pub egid: u32,
+    /// The effective namespace id
+    pub ens: SchemeNamespace,
     /// Status of context
     pub status: Status,
     /// Context running or not
@@ -70,8 +74,6 @@ pub struct Context {
     pub grants: Arc<Mutex<Vec<Grant>>>,
     /// The name of the context
     pub name: Arc<Mutex<Vec<u8>>>,
-    /// The scheme namespace of this context
-    pub scheme_ns: SchemeNamespace,
     /// The current working directory
     pub cwd: Arc<Mutex<Vec<u8>>>,
     /// Kernel events
@@ -89,8 +91,10 @@ impl Context {
             ppid: ContextId::from(0),
             ruid: 0,
             rgid: 0,
+            rns: SchemeNamespace::from(0),
             euid: 0,
             egid: 0,
+            ens: SchemeNamespace::from(0),
             status: Status::Blocked,
             running: false,
             cpu_id: None,
@@ -107,7 +111,6 @@ impl Context {
             tls: None,
             grants: Arc::new(Mutex::new(Vec::new())),
             name: Arc::new(Mutex::new(Vec::new())),
-            scheme_ns: SchemeNamespace::from(0),
             cwd: Arc::new(Mutex::new(Vec::new())),
             events: Arc::new(WaitQueue::new()),
             env: Arc::new(Mutex::new(BTreeMap::new())),
diff --git a/kernel/scheme/mod.rs b/kernel/scheme/mod.rs
index 1c2fbd2a5f2889bc0ab10d11474662be294d0034..abb9e120d8f9d06b72ef8601e5174b1e72cf0f15 100644
--- a/kernel/scheme/mod.rs
+++ b/kernel/scheme/mod.rs
@@ -141,7 +141,7 @@ impl SchemeList {
         self.insert(ns, Box::new(*b"pipe"), |scheme_id| Arc::new(Box::new(PipeScheme::new(scheme_id)))).unwrap();
     }
 
-    pub fn setns(&mut self, from: SchemeNamespace, names: &[&[u8]]) -> Result<SchemeNamespace> {
+    pub fn make_ns(&mut self, from: SchemeNamespace, names: &[&[u8]]) -> Result<SchemeNamespace> {
         // Create an empty namespace
         let to = self.new_ns();
 
diff --git a/kernel/scheme/sys/context.rs b/kernel/scheme/sys/context.rs
index 26e3e2d66182bd7e1d0c7e1b683ddfb0f60d191a..a28820dc2b4f6698e1853c8cd5079b8db1cf86fe 100644
--- a/kernel/scheme/sys/context.rs
+++ b/kernel/scheme/sys/context.rs
@@ -5,17 +5,18 @@ use context;
 use syscall::error::Result;
 
 pub fn resource() -> Result<Vec<u8>> {
-    let mut string = format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{:<6}{}\n",
+    let mut string = format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{}\n",
                              "PID",
                              "PPID",
                              "RUID",
                              "RGID",
+                             "RNS",
                              "EUID",
                              "EGID",
+                             "ENS",
                              "STAT",
                              "CPU",
                              "MEM",
-                             "SNS",
                              "NAME");
     {
         let contexts = context::contexts();
@@ -85,17 +86,18 @@ pub fn resource() -> Result<Vec<u8>> {
             let name_bytes = context.name.lock();
             let name = str::from_utf8(&name_bytes).unwrap_or("");
 
-            string.push_str(&format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{:<6}{}\n",
+            string.push_str(&format!("{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<6}{:<8}{}\n",
                                context.id.into(),
                                context.ppid.into(),
                                context.ruid,
                                context.rgid,
+                               context.rns.into(),
                                context.euid,
                                context.egid,
+                               context.ens.into(),
                                stat_string,
                                cpu_string,
                                memory_string,
-                               context.scheme_ns.into(),
                                name));
         }
     }
diff --git a/kernel/scheme/sys/scheme.rs b/kernel/scheme/sys/scheme.rs
index 04df3d34dbdec1a15dd9a2b404981284de93fb48..b0f0c7d080f449e085bceb6db175bdac06c4866e 100644
--- a/kernel/scheme/sys/scheme.rs
+++ b/kernel/scheme/sys/scheme.rs
@@ -9,7 +9,7 @@ pub fn resource() -> Result<Vec<u8>> {
         let contexts = context::contexts();
         let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
         let context = context_lock.read();
-        context.scheme_ns
+        context.ens
     };
 
     let mut data = Vec::new();
diff --git a/kernel/syscall/fs.rs b/kernel/syscall/fs.rs
index 12d18859c9e9a3579e0949ac3c979ced25d3aa08..30bd291c9f283b12cf209c499d1cef9ae040e71d 100644
--- a/kernel/syscall/fs.rs
+++ b/kernel/syscall/fs.rs
@@ -86,7 +86,7 @@ pub fn open(path: &[u8], flags: usize) -> Result<FileHandle> {
         let contexts = context::contexts();
         let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
         let context = context_lock.read();
-        (context.canonicalize(path), context.euid, context.egid, context.scheme_ns)
+        (context.canonicalize(path), context.euid, context.egid, context.ens)
     };
 
     let mut parts = path_canon.splitn(2, |&b| b == b':');
@@ -150,7 +150,7 @@ pub fn mkdir(path: &[u8], mode: u16) -> Result<usize> {
         let contexts = context::contexts();
         let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
         let context = context_lock.read();
-        (context.canonicalize(path), context.euid, context.egid, context.scheme_ns)
+        (context.canonicalize(path), context.euid, context.egid, context.ens)
     };
 
     let mut parts = path_canon.splitn(2, |&b| b == b':');
@@ -172,7 +172,7 @@ pub fn chmod(path: &[u8], mode: u16) -> Result<usize> {
         let contexts = context::contexts();
         let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
         let context = context_lock.read();
-        (context.canonicalize(path), context.euid, context.egid, context.scheme_ns)
+        (context.canonicalize(path), context.euid, context.egid, context.ens)
     };
 
     let mut parts = path_canon.splitn(2, |&b| b == b':');
@@ -194,7 +194,7 @@ pub fn rmdir(path: &[u8]) -> Result<usize> {
         let contexts = context::contexts();
         let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
         let context = context_lock.read();
-        (context.canonicalize(path), context.euid, context.egid, context.scheme_ns)
+        (context.canonicalize(path), context.euid, context.egid, context.ens)
     };
 
     let mut parts = path_canon.splitn(2, |&b| b == b':');
@@ -216,7 +216,7 @@ pub fn unlink(path: &[u8]) -> Result<usize> {
         let contexts = context::contexts();
         let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
         let context = context_lock.read();
-        (context.canonicalize(path), context.euid, context.egid, context.scheme_ns)
+        (context.canonicalize(path), context.euid, context.egid, context.ens)
     };
 
     let mut parts = path_canon.splitn(2, |&b| b == b':');
diff --git a/kernel/syscall/mod.rs b/kernel/syscall/mod.rs
index c4e30aef1dc5cf3567fb4dcf8ccfa5c45a36e07b..f197f845844a8e978b830d27ba429d259131d901 100644
--- a/kernel/syscall/mod.rs
+++ b/kernel/syscall/mod.rs
@@ -17,7 +17,7 @@ use self::error::{Error, Result, ENOSYS};
 use self::number::*;
 
 use context::ContextId;
-use scheme::FileHandle;
+use scheme::{FileHandle, SchemeNamespace};
 
 /// Driver syscalls
 pub mod driver;
@@ -82,13 +82,16 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize
                 SYS_EXECVE => exec(validate_slice(b as *const u8, c)?, validate_slice(d as *const [usize; 2], e)?),
                 SYS_IOPL => iopl(b, stack),
                 SYS_GETCWD => getcwd(validate_slice_mut(b as *mut u8, c)?),
-                SYS_GETUID => getuid(),
-                SYS_GETGID => getgid(),
-                SYS_GETEUID => geteuid(),
                 SYS_GETEGID => getegid(),
+                SYS_GETENS => getens(),
+                SYS_GETEUID => geteuid(),
+                SYS_GETGID => getgid(),
+                SYS_GETNS => getns(),
+                SYS_GETUID => getuid(),
+                SYS_MKNS => mkns(validate_slice(b as *const [usize; 2], c)?),
                 SYS_SETREUID => setreuid(b as u32, c as u32),
+                SYS_SETRENS => setrens(SchemeNamespace::from(b), SchemeNamespace::from(c)),
                 SYS_SETREGID => setregid(b as u32, c as u32),
-                SYS_SETNS => setns(validate_slice(b as *const [usize; 2], c)?),
                 SYS_PIPE2 => pipe2(validate_slice_mut(b as *mut usize, 2)?, c),
                 SYS_PHYSALLOC => physalloc(b),
                 SYS_PHYSFREE => physfree(b, c),
diff --git a/kernel/syscall/privilege.rs b/kernel/syscall/privilege.rs
index e1abd8a271b92c88a4f0a0ecf7c0daf6e03d09f6..e718196fb17688730f1f568bdf9cb4ab9fc6ed83 100644
--- a/kernel/syscall/privilege.rs
+++ b/kernel/syscall/privilege.rs
@@ -1,7 +1,7 @@
 use collections::Vec;
 
 use context;
-use scheme;
+use scheme::{self, SchemeNamespace};
 use syscall::error::*;
 use syscall::validate::validate_slice;
 
@@ -12,6 +12,13 @@ pub fn getegid() -> Result<usize> {
     Ok(context.egid as usize)
 }
 
+pub fn getens() -> Result<usize> {
+    let contexts = context::contexts();
+    let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
+    let context = context_lock.read();
+    Ok(context.ens.into())
+}
+
 pub fn geteuid() -> Result<usize> {
     let contexts = context::contexts();
     let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
@@ -26,6 +33,13 @@ pub fn getgid() -> Result<usize> {
     Ok(context.rgid as usize)
 }
 
+pub fn getns() -> Result<usize> {
+    let contexts = context::contexts();
+    let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
+    let context = context_lock.read();
+    Ok(context.rns.into())
+}
+
 pub fn getuid() -> Result<usize> {
     let contexts = context::contexts();
     let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
@@ -33,6 +47,27 @@ pub fn getuid() -> Result<usize> {
     Ok(context.ruid as usize)
 }
 
+pub fn mkns(name_ptrs: &[[usize; 2]]) -> Result<usize> {
+    let mut names = Vec::new();
+    for name_ptr in name_ptrs {
+        names.push(validate_slice(name_ptr[0] as *const u8, name_ptr[1])?);
+    }
+
+    let (uid, from) = {
+        let contexts = context::contexts();
+        let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
+        let context = context_lock.read();
+        (context.euid, context.ens)
+    };
+
+    if uid == 0 {
+        let to = scheme::schemes_mut().make_ns(from, &names)?;
+        Ok(to.into())
+    } else {
+        Err(Error::new(EACCES))
+    }
+}
+
 pub fn setregid(rgid: u32, egid: u32) -> Result<usize> {
     let contexts = context::contexts();
     let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
@@ -59,6 +94,32 @@ pub fn setregid(rgid: u32, egid: u32) -> Result<usize> {
     }
 }
 
+pub fn setrens(rns: SchemeNamespace, ens: SchemeNamespace) -> Result<usize> {
+    let contexts = context::contexts();
+    let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
+    let mut context = context_lock.write();
+
+    if (context.euid == 0
+    || rns.into() as isize == -1
+    || rns == context.ens
+    || rns == context.rns)
+    && (context.euid == 0
+    || ens.into() as isize == -1
+    || ens == context.ens
+    || ens == context.rns)
+    {
+        if rns.into() as isize != -1 {
+            context.rns = rns;
+        }
+        if ens.into() as isize != -1 {
+            context.ens = ens;
+        }
+        Ok(0)
+    } else {
+        Err(Error::new(EPERM))
+    }
+}
+
 pub fn setreuid(ruid: u32, euid: u32) -> Result<usize> {
     let contexts = context::contexts();
     let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
@@ -84,28 +145,3 @@ pub fn setreuid(ruid: u32, euid: u32) -> Result<usize> {
         Err(Error::new(EPERM))
     }
 }
-
-pub fn setns(name_ptrs: &[[usize; 2]]) -> Result<usize> {
-    let mut names = Vec::new();
-    for name_ptr in name_ptrs {
-        names.push(validate_slice(name_ptr[0] as *const u8, name_ptr[1])?);
-    }
-
-    let from = {
-        let contexts = context::contexts();
-        let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
-        let context = context_lock.read();
-        context.scheme_ns
-    };
-
-    let to = scheme::schemes_mut().setns(from, &names)?;
-
-    {
-        let contexts = context::contexts();
-        let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
-        let mut context = context_lock.write();
-        context.scheme_ns = to;
-    }
-
-    Ok(0)
-}
diff --git a/kernel/syscall/process.rs b/kernel/syscall/process.rs
index 376334194fca92ea29b3413058983e8a96264c53..9c1c69a571425639f94946c8971b2b9b8f33071f 100644
--- a/kernel/syscall/process.rs
+++ b/kernel/syscall/process.rs
@@ -59,8 +59,10 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
     {
         let ruid;
         let rgid;
+        let rns;
         let euid;
         let egid;
+        let ens;
         let mut cpu_id = None;
         let arch;
         let vfork;
@@ -73,7 +75,6 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
         let mut tls_option = None;
         let grants;
         let name;
-        let scheme_ns;
         let cwd;
         let env;
         let files;
@@ -87,8 +88,10 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
             ppid = context.id;
             ruid = context.ruid;
             rgid = context.rgid;
+            rns = context.rns;
             euid = context.euid;
             egid = context.egid;
+            ens = context.ens;
 
             if flags & CLONE_VM == CLONE_VM {
                 cpu_id = context.cpu_id;
@@ -222,8 +225,6 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
                 name = Arc::new(Mutex::new(context.name.lock().clone()));
             }
 
-            scheme_ns = context.scheme_ns;
-
             if flags & CLONE_FS == CLONE_FS {
                 cwd = context.cwd.clone();
             } else {
@@ -304,8 +305,10 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
             context.ppid = ppid;
             context.ruid = ruid;
             context.rgid = rgid;
+            context.rns = rns;
             context.euid = euid;
             context.egid = egid;
+            context.ens = ens;
 
             context.cpu_id = cpu_id;
 
@@ -434,8 +437,6 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<ContextId> {
 
             context.name = name;
 
-            context.scheme_ns = scheme_ns;
-
             context.cwd = cwd;
 
             context.env = env;
diff --git a/programs/contain/src/main.rs b/programs/contain/src/main.rs
index 8ec63ba21f0e87d1dcb1a9db7835079432b8d626..0a14ecaeea90970cafc506f1f38576f2d40a34ca 100644
--- a/programs/contain/src/main.rs
+++ b/programs/contain/src/main.rs
@@ -13,16 +13,18 @@ pub fn main() {
 
     let command = "sh";
 
+    let mut name_ptrs = Vec::new();
+    for name in names.iter() {
+        name_ptrs.push([name.as_ptr() as usize, name.len()]);
+    }
+
+    let new_ns = syscall::mkns(&name_ptrs).unwrap();
+
     let pid = unsafe { syscall::clone(0).unwrap() };
     if pid == 0 {
-        let mut name_ptrs = Vec::new();
-        for name in names.iter() {
-            name_ptrs.push([name.as_ptr() as usize, name.len()]);
-        }
-
-        syscall::setns(&name_ptrs).unwrap();
+        syscall::setrens(new_ns, new_ns).unwrap();
 
-        println!("Container enter: {}", command);
+        println!("Container {}: enter: {}", new_ns, command);
 
         let err = Command::new(command).exec();
 
@@ -41,6 +43,6 @@ pub fn main() {
             }
         }
 
-        println!("Container exited: {:X}", status);
+        println!("Container {}: exit: {:X}", new_ns, status);
     }
 }
diff --git a/syscall b/syscall
index cc90408d147cc1d23b0e820d5b47522bd7dfc847..2835586ee671b0777ef1a98ced9237269c472941 160000
--- a/syscall
+++ b/syscall
@@ -1 +1 @@
-Subproject commit cc90408d147cc1d23b0e820d5b47522bd7dfc847
+Subproject commit 2835586ee671b0777ef1a98ced9237269c472941