From 81da1bb1a3eb70e6c4c47f14b49ab419d501d277 Mon Sep 17 00:00:00 2001 From: oddcoder <ahmedsoliman@oddcoder.com> Date: Sat, 13 Jun 2020 19:50:08 +0200 Subject: [PATCH] Fix the avoid accessing errno issue from ld_so for real this time This patch implements access function for both redox and linux and makes sure that neither access errno variable --- src/ld_so/access.rs | 53 +++++++++++++++++++++++++++++++++++++++++++++ src/ld_so/linker.rs | 3 +-- src/ld_so/mod.rs | 10 +++------ 3 files changed, 57 insertions(+), 9 deletions(-) create mode 100644 src/ld_so/access.rs diff --git a/src/ld_so/access.rs b/src/ld_so/access.rs new file mode 100644 index 000000000..624edff86 --- /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 149f26543..ff6d89669 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 b39a5e7e2..baa253e6e 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; -- GitLab