diff --git a/src/header/unistd/mod.rs b/src/header/unistd/mod.rs
index 67b8370031e31a13b3eda4d7d2f81b0da01db983..fe5a3cbb62fa2e06c9bf480e5967a4cd309713d5 100644
--- a/src/header/unistd/mod.rs
+++ b/src/header/unistd/mod.rs
@@ -321,9 +321,9 @@ pub extern "C" fn getgid() -> gid_t {
     Sys::getgid()
 }
 
-// #[no_mangle]
-pub extern "C" fn getgroups(gidsetsize: c_int, grouplist: *mut gid_t) -> c_int {
-    unimplemented!();
+#[no_mangle]
+pub unsafe extern "C" fn getgroups(size: c_int, list: *mut gid_t) -> c_int {
+    Sys::getgroups(size, list)
 }
 
 // #[no_mangle]
@@ -620,6 +620,11 @@ pub extern "C" fn setgid(gid: gid_t) -> c_int {
     Sys::setregid(gid, gid)
 }
 
+#[no_mangle]
+pub unsafe extern "C" fn setgroups(size: size_t, list: *const gid_t) -> c_int {
+    Sys::setgroups(size, list)
+}
+
 #[no_mangle]
 pub extern "C" fn setpgid(pid: pid_t, pgid: pid_t) -> c_int {
     Sys::setpgid(pid, pgid)
diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs
index 857cda4544fb22114630c9f445307601153c90b0..0622fc3df963bfa428102ae60122d81e1d5183b4 100644
--- a/src/platform/linux/mod.rs
+++ b/src/platform/linux/mod.rs
@@ -277,6 +277,10 @@ impl Pal for Sys {
         e(unsafe { syscall!(GETGID) }) as gid_t
     }
 
+    unsafe fn getgroups(size: c_int, list: *mut gid_t) -> c_int {
+        e(unsafe { syscall!(GETGROUPS, size, list) })
+    }
+
     fn getpagesize() -> usize {
         4096
     }
@@ -508,6 +512,10 @@ impl Pal for Sys {
         e(unsafe { syscall!(SCHED_YIELD) }) as c_int
     }
 
+    unsafe fn setgroups(size: size_t, list: *const gid_t) -> c_int {
+        e(unsafe { syscall!(SETGROUPS, size, list) })
+    }
+
     fn setpgid(pid: pid_t, pgid: pid_t) -> c_int {
         e(unsafe { syscall!(SETPGID, pid, pgid) }) as c_int
     }
diff --git a/src/platform/pal/mod.rs b/src/platform/pal/mod.rs
index 3d6a690454cb4f0b3a4d3ab71f22bf1b9dabc2ee..e05c9c3ff70a853cea9527380fbb251b05b0a9f5 100644
--- a/src/platform/pal/mod.rs
+++ b/src/platform/pal/mod.rs
@@ -98,6 +98,8 @@ pub trait Pal {
 
     fn getgid() -> gid_t;
 
+    unsafe fn getgroups(size: c_int, list: *mut gid_t) -> c_int;
+
     /* Note that this is distinct from the legacy POSIX function
      * getpagesize(), which returns a c_int. On some Linux platforms,
      * page size may be determined through a syscall ("getpagesize"). */
@@ -184,6 +186,8 @@ pub trait Pal {
 
     fn sched_yield() -> c_int;
 
+    unsafe fn setgroups(size: size_t, list: *const gid_t) -> c_int;
+
     fn setpgid(pid: pid_t, pgid: pid_t) -> c_int;
 
     fn setpriority(which: c_int, who: id_t, prio: c_int) -> c_int;
diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs
index 254f5910bfce879a3d27ce7cb24847998b6759a5..0df6597d881c07806c6351c63e13046549de4378 100644
--- a/src/platform/redox/mod.rs
+++ b/src/platform/redox/mod.rs
@@ -504,6 +504,13 @@ impl Pal for Sys {
         e(syscall::getgid()) as gid_t
     }
 
+    unsafe fn getgroups(size: c_int, list: *mut gid_t) -> c_int {
+        // TODO
+        eprintln!("relibc getgroups({}, {:p}): not implemented", size, list);
+        unsafe { errno = ENOSYS };
+        -1
+    }
+
     fn getpagesize() -> usize {
         PAGE_SIZE
     }
@@ -827,6 +834,13 @@ impl Pal for Sys {
         e(syscall::sched_yield()) as c_int
     }
 
+    unsafe fn setgroups(size: size_t, list: *const gid_t) -> c_int {
+        // TODO
+        eprintln!("relibc setgroups({}, {:p}): not implemented", size, list);
+        unsafe { errno = ENOSYS };
+        -1
+    }
+
     fn setpgid(pid: pid_t, pgid: pid_t) -> c_int {
         e(syscall::setpgid(pid as usize, pgid as usize)) as c_int
     }