diff --git a/src/ld_so/access.rs b/src/ld_so/access.rs
new file mode 100644
index 0000000000000000000000000000000000000000..624edff861c777ca44232d25f2b0cc085a57878f
--- /dev/null
+++ b/src/ld_so/access.rs
@@ -0,0 +1,53 @@
+// Wrapper over the access syscall that doesn't touch errno variable,
+// Do not use outside of ld_so
+
+use crate::{c_str::CStr, platform::types::*};
+
+#[cfg(target_os = "redox")]
+use crate::header::unistd::{F_OK, R_OK, W_OK, X_OK};
+
+#[cfg(target_os = "linux")]
+pub unsafe fn access(path: *const c_char, mode: c_int) -> c_int {
+    let path = CStr::from_ptr(path);
+    syscall!(ACCESS, (path).as_ptr(), mode) as c_int
+}
+
+// Wrapper over the systemcall, Do not use outside of ld_so
+#[cfg(target_os = "redox")]
+pub unsafe fn access(path: *const c_char, mode: c_int) -> c_int {
+    let path = CStr::from_ptr(path).to_bytes();
+    let fd = match syscall::open(path, syscall::O_CLOEXEC) {
+        Ok(fd) => fd,
+        _ => return -1,
+    };
+    if mode == F_OK {
+        return 0;
+    }
+    let mut stat = syscall::Stat::default();
+    if syscall::fstat(fd, &mut stat).is_err() {
+        return -1;
+    }
+    let uid = match syscall::getuid() {
+        Ok(uid) => uid,
+        Err(_) => return -1,
+    };
+    let gid = match syscall::getgid() {
+        Ok(gid) => gid,
+        Err(_) => return -1,
+    };
+
+    let perms = if stat.st_uid as usize == uid {
+        stat.st_mode >> (3 * 2 & 0o7)
+    } else if stat.st_gid as usize == gid {
+        stat.st_mode >> (3 * 1 & 0o7)
+    } else {
+        stat.st_mode & 0o7
+    };
+    if (mode & R_OK == R_OK && perms & 0o4 != 0o4)
+        || (mode & W_OK == W_OK && perms & 0o2 != 0o2)
+        || (mode & X_OK == X_OK && perms & 0o1 != 0o1)
+    {
+        return -1;
+    }
+    0
+}
diff --git a/src/ld_so/linker.rs b/src/ld_so/linker.rs
index 149f26543f816fe887439b2b5c30060ee320c5fa..ff6d89669a88cbe2149282d77f1cb261c78b4821 100644
--- a/src/ld_so/linker.rs
+++ b/src/ld_so/linker.rs
@@ -26,12 +26,11 @@ use crate::{
 };
 
 use super::{
-    access,
+    access::access,
     debug::{RTLDDebug, RTLDState, _dl_debug_state, _r_debug},
     tcb::{Master, Tcb},
     PAGE_SIZE,
 };
-
 #[cfg(target_os = "redox")]
 const PATH_SEP: char = ';';
 
diff --git a/src/ld_so/mod.rs b/src/ld_so/mod.rs
index b39a5e7e269e2c8ffb937ffb113046b591d881e6..baa253e6e66899fc8923cb2fda9e722cd1ea2856 100644
--- a/src/ld_so/mod.rs
+++ b/src/ld_so/mod.rs
@@ -1,13 +1,15 @@
 use goblin::elf::program_header::{self, program_header32, program_header64, ProgramHeader};
 
 use self::tcb::{Master, Tcb};
-use crate::{c_str::CStr, platform::types::*, start::Stack};
+use crate::start::Stack;
 pub const PAGE_SIZE: usize = 4096;
 
+mod access;
 pub mod debug;
 pub mod linker;
 pub mod start;
 pub mod tcb;
+
 pub fn static_init(sp: &'static Stack) {
     let mut phdr_opt = None;
     let mut phent_opt = None;
@@ -79,12 +81,6 @@ pub fn static_init(sp: &'static Stack) {
     }
 }
 
-// Wrapper over the systemcall, Do not use outside of ld_so
-pub unsafe fn access(path: *const c_char, mode: c_int) -> c_int {
-    let path = CStr::from_ptr(path);
-    syscall!(ACCESS, (path).as_ptr(), mode) as c_int
-}
-
 #[cfg(target_os = "linux")]
 pub unsafe fn init(sp: &'static Stack) {
     let mut tp = 0usize;