diff --git a/context/context.rs b/context/context.rs
index 512c66e9a1ddaee382ad0628f6a855dc1e7a26f0..8c09573648973687b18b3e53a0ec44b67bb2dfa1 100644
--- a/context/context.rs
+++ b/context/context.rs
@@ -22,10 +22,14 @@ pub struct Context {
     pub id: usize,
     /// The ID of the parent context
     pub ppid: usize,
-    /// The user id
-    pub uid: u32,
-    /// The group id
-    pub gid: u32,
+    /// The real user id
+    pub ruid: u32,
+    /// The real group id
+    pub rgid: u32,
+    /// The effective user id
+    pub euid: u32,
+    /// The effective group id
+    pub egid: u32,
     /// Status of context
     pub status: Status,
     /// Context running or not
@@ -62,8 +66,10 @@ impl Context {
         Context {
             id: id,
             ppid: 0,
-            uid: 0,
-            gid: 0,
+            ruid: 0,
+            rgid: 0,
+            euid: 0,
+            egid: 0,
             status: Status::Blocked,
             running: false,
             vfork: false,
diff --git a/scheme/user.rs b/scheme/user.rs
index 542f01e651127402bad5c37813d05c4efe8ecd52..6bc25fd41783d54ebea4841c3dce22fb8af0829c 100644
--- a/scheme/user.rs
+++ b/scheme/user.rs
@@ -38,7 +38,7 @@ impl UserInner {
             let contexts = context::contexts();
             let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
             let context = context_lock.read();
-            (context.id, context.uid, context.gid)
+            (context.id, context.euid, context.egid)
         };
 
         let id = self.next_id.fetch_add(1, Ordering::SeqCst);
diff --git a/syscall/fs.rs b/syscall/fs.rs
index 1c969f6791d47736ba799ed56528f7e468379497..f527c36ced5e424724cb71f9c202b5ad5d563ff4 100644
--- a/syscall/fs.rs
+++ b/syscall/fs.rs
@@ -11,7 +11,7 @@ pub fn file_op(a: usize, fd: usize, c: usize, d: usize) -> Result<usize> {
         let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
         let context = context_lock.read();
         let file = context.get_file(fd).ok_or(Error::new(EBADF))?;
-        (file, context.id, context.uid, context.gid)
+        (file, context.id, context.euid, context.egid)
     };
 
     let scheme = {
@@ -74,7 +74,7 @@ pub fn open(path: &[u8], flags: usize) -> 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.uid, context.gid)
+        (context.canonicalize(path), context.euid, context.egid)
     };
 
     let mut parts = path_canon.splitn(2, |&b| b == b':');
@@ -107,7 +107,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.uid, context.gid)
+        (context.canonicalize(path), context.euid, context.egid)
     };
 
     let mut parts = path_canon.splitn(2, |&b| b == b':');
@@ -129,7 +129,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.uid, context.gid)
+        (context.canonicalize(path), context.euid, context.egid)
     };
 
     let mut parts = path_canon.splitn(2, |&b| b == b':');
@@ -151,7 +151,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.uid, context.gid)
+        (context.canonicalize(path), context.euid, context.egid)
     };
 
     let mut parts = path_canon.splitn(2, |&b| b == b':');
diff --git a/syscall/mod.rs b/syscall/mod.rs
index c0d389ef93b10f92d3c44eebe405c49784d26f87..fc357a6b5781f11839a01f2b128c07b5c27ecda8 100644
--- a/syscall/mod.rs
+++ b/syscall/mod.rs
@@ -55,6 +55,8 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize
                 SYS_GETCWD => getcwd(validate_slice_mut(b as *mut u8, c)?),
                 SYS_GETUID => getuid(),
                 SYS_GETGID => getgid(),
+                SYS_GETEUID => geteuid(),
+                SYS_GETEGID => getegid(),
                 SYS_SETUID => setuid(b as u32),
                 SYS_SETGID => setgid(b as u32),
                 SYS_PHYSALLOC => physalloc(b),
diff --git a/syscall/process.rs b/syscall/process.rs
index 9519ef2bff1aab7c40de05f61196243d9e4190fa..e00d3146e9e47b15bc64c9d8719d1c6553cecf42 100644
--- a/syscall/process.rs
+++ b/syscall/process.rs
@@ -1,7 +1,7 @@
 ///! Process syscalls
 use alloc::arc::Arc;
 use alloc::boxed::Box;
-use collections::Vec;
+use collections::{BTreeMap, Vec};
 use core::mem;
 use core::str;
 use spin::Mutex;
@@ -58,8 +58,10 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
     let ppid;
     let pid;
     {
-        let uid;
-        let gid;
+        let ruid;
+        let rgid;
+        let euid;
+        let egid;
         let arch;
         let vfork;
         let mut kfx_option = None;
@@ -80,8 +82,10 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
             let context = context_lock.read();
 
             ppid = context.id;
-            uid = context.uid;
-            gid = context.gid;
+            ruid = context.ruid;
+            rgid = context.rgid;
+            euid = context.euid;
+            egid = context.egid;
 
             arch = context.arch.clone();
 
@@ -191,7 +195,11 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
             if flags & CLONE_VM == CLONE_VM {
                 env = context.env.clone();
             } else {
-                env = Arc::new(Mutex::new(context.env.lock().clone()));
+                let mut new_env = BTreeMap::new();
+                for item in context.env.lock().iter() {
+                    new_env.insert(item.0.clone(), Arc::new(Mutex::new(item.1.lock().clone())));
+                }
+                env = Arc::new(Mutex::new(new_env));
             }
 
             if flags & CLONE_FILES == CLONE_FILES {
@@ -253,8 +261,10 @@ pub fn clone(flags: usize, stack_base: usize) -> Result<usize> {
             pid = context.id;
 
             context.ppid = ppid;
-            context.uid = uid;
-            context.gid = gid;
+            context.ruid = ruid;
+            context.rgid = rgid;
+            context.euid = euid;
+            context.egid = egid;
 
             context.status = context::Status::Runnable;
 
@@ -436,7 +446,7 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
             let contexts = context::contexts();
             let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
             let context = context_lock.read();
-            (context.uid, context.gid)
+            (context.euid, context.egid)
         };
 
         let file = syscall::open(path, 0)?;
@@ -483,11 +493,11 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
                     context.grants = Arc::new(Mutex::new(Vec::new()));
 
                     if stat.st_mode & syscall::flag::MODE_SETUID == syscall::flag::MODE_SETUID {
-                        context.uid = stat.st_uid;
+                        context.euid = stat.st_uid;
                     }
 
                     if stat.st_mode & syscall::flag::MODE_SETGID == syscall::flag::MODE_SETGID {
-                        context.gid = stat.st_gid;
+                        context.egid = stat.st_gid;
                     }
 
                     // Map and copy new segments
@@ -612,11 +622,25 @@ pub fn exec(path: &[u8], arg_ptrs: &[[usize; 2]]) -> Result<usize> {
     unsafe { usermode(entry, sp); }
 }
 
+pub fn getegid() -> Result<usize> {
+    let contexts = context::contexts();
+    let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
+    let context = context_lock.read();
+    Ok(context.egid as usize)
+}
+
+pub fn geteuid() -> Result<usize> {
+    let contexts = context::contexts();
+    let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
+    let context = context_lock.read();
+    Ok(context.euid as usize)
+}
+
 pub fn getgid() -> Result<usize> {
     let contexts = context::contexts();
     let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
     let context = context_lock.read();
-    Ok(context.gid as usize)
+    Ok(context.rgid as usize)
 }
 
 pub fn getpid() -> Result<usize> {
@@ -630,7 +654,7 @@ pub fn getuid() -> Result<usize> {
     let contexts = context::contexts();
     let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
     let context = context_lock.read();
-    Ok(context.uid as usize)
+    Ok(context.ruid as usize)
 }
 
 pub fn iopl(_level: usize) -> Result<usize> {
@@ -734,10 +758,9 @@ pub fn setgid(gid: u32) -> Result<usize> {
     let contexts = context::contexts();
     let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
     let mut context = context_lock.write();
-    if context.gid == 0 {
-        context.gid = gid;
-        Ok(0)
-    } else if context.gid == gid {
+    if context.egid == 0 {
+        context.rgid = gid;
+        context.egid = gid;
         Ok(0)
     } else {
         Err(Error::new(EPERM))
@@ -748,10 +771,9 @@ pub fn setuid(uid: u32) -> Result<usize> {
     let contexts = context::contexts();
     let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
     let mut context = context_lock.write();
-    if context.uid == 0 {
-        context.uid = uid;
-        Ok(0)
-    } else if context.uid == uid {
+    if context.euid == 0 {
+        context.ruid = uid;
+        context.euid = uid;
         Ok(0)
     } else {
         Err(Error::new(EPERM))