From 119f078216feb866427b5e27f7c229776557aa19 Mon Sep 17 00:00:00 2001 From: R Aadarsh Date: Fri, 15 May 2026 16:11:36 +0530 Subject: [PATCH] * Fix bug that caused pid of the child process to be returned instead of 0 or errorno * Add `same_process` field to not change the address space when `fexec_impl` is called on a different process --- redox-rt/src/proc.rs | 14 ++++++++++---- src/header/spawn/mod.rs | 26 +++++++++++++++++--------- src/platform/redox/exec.rs | 4 +++- src/platform/redox/mod.rs | 32 ++++++++++++++++++++++++++++---- 4 files changed, 58 insertions(+), 18 deletions(-) diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index 2682e2443b..0c067af24d 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -63,6 +63,8 @@ pub struct ExtraInfo<'a> { pub ns_fd: Option, /// CWD handle pub cwd_fd: Option, + /// If the process for which the image is to be loaded the same as the currently running process + pub same_process: bool, } pub fn fexec_impl( @@ -74,7 +76,7 @@ pub fn fexec_impl( envs: &[&[u8]], extrainfo: &ExtraInfo, interp_override: Option, -) -> Result { +) -> Result> { // Here, we do the minimum part of loading an application, which is what the kernel used to do. // We load the executable into memory (albeit at different offsets in this executable), fix // some misalignments, and then switch address space. @@ -235,7 +237,7 @@ pub fn fexec_impl( } if let Some(interpreter_path) = interpreter { - return Ok(FexecResult::Interp { + return Ok(Some(FexecResult::Interp { path: interpreter_path, interp_override: InterpOverride { at_entry: base_addr + header.e_entry as usize, @@ -246,7 +248,7 @@ pub fn fexec_impl( min_mmap_addr, grants_fd: grants_fd.take(), }, - }); + })); } mmap_anon_remote( @@ -495,7 +497,11 @@ pub fn fexec_impl( // Dropping this FD will cause the address space switch. drop(addrspace_selection_fd); - unreachable!(); + if extrainfo.same_process { + unreachable!(); + } else { + Ok(None) + } } fn write_usizes(fd: &FdGuardUpper, usizes: [usize; N]) -> Result { fd.write(unsafe { plain::as_bytes(&usizes) }) diff --git a/src/header/spawn/mod.rs b/src/header/spawn/mod.rs index 2d079f128a..0e66fe9d6a 100644 --- a/src/header/spawn/mod.rs +++ b/src/header/spawn/mod.rs @@ -19,13 +19,14 @@ use crate::{ }; fn spawn( + pid: Option<&mut pid_t>, mut program: &str, file_actions: Option<&posix_spawn_file_actions_t>, spawn_attr: Option<&posix_spawnattr_t>, argv: *const *mut c_char, envp: *const *mut c_char, use_path: bool, -) -> Result { +) -> Result<()> { if use_path { let path_env = unsafe { CStr::from_ptr(getenv("PATH".as_ptr() as *const c_char)) @@ -57,12 +58,17 @@ fn spawn( envp, use_path, ) + .map(|v| { + if let Some(pid) = pid { + *pid = v; + } + }) } } #[unsafe(no_mangle)] pub extern "C" fn posix_spawn( - pid: *const pid_t, + pid: *mut pid_t, program: *const c_char, file_actions: *const posix_spawn_file_actions_t, spawn_attr: *const posix_spawnattr_t, @@ -71,7 +77,8 @@ pub extern "C" fn posix_spawn( ) -> c_int { let program = unsafe { CStr::from_ptr(program).to_str().unwrap() }; - match spawn( + if let Err(e) = spawn( + unsafe { pid.as_mut() }, program, unsafe { file_actions.as_ref() }, unsafe { spawn_attr.as_ref() }, @@ -79,14 +86,14 @@ pub extern "C" fn posix_spawn( envp, false, ) { - Ok(v) => v, - Err(e) => e.0, + return e.0; } + 0 } #[unsafe(no_mangle)] pub extern "C" fn posix_spawnp( - pid: *const pid_t, + pid: *mut pid_t, program: *const c_char, file_actions: *const posix_spawn_file_actions_t, spawn_attr: *const posix_spawnattr_t, @@ -95,7 +102,8 @@ pub extern "C" fn posix_spawnp( ) -> c_int { let program = unsafe { CStr::from_ptr(program).to_str().unwrap() }; - match spawn( + if let Err(e) = spawn( + unsafe { pid.as_mut() }, program, unsafe { file_actions.as_ref() }, unsafe { spawn_attr.as_ref() }, @@ -103,7 +111,7 @@ pub extern "C" fn posix_spawnp( envp, true, ) { - Ok(v) => v, - Err(e) => e.0, + return e.0; } + 0 } diff --git a/src/platform/redox/exec.rs b/src/platform/redox/exec.rs index f269f59234..5235549f90 100644 --- a/src/platform/redox/exec.rs +++ b/src/platform/redox/exec.rs @@ -38,7 +38,8 @@ fn fexec_impl( envs, extrainfo, interp_override, - )?; + )? + .unwrap(); // According to elf(5), PT_INTERP requires that the interpreter path be // null-terminated. Violating this should therefore give the "format error" ENOEXEC. @@ -238,6 +239,7 @@ pub fn execve( cwd_fd: super::path::current_dir() .ok() .map(|fd| fd.as_ref().unwrap().fd.as_raw_fd()), + same_process: true, }; fexec_impl( diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index 549891c9d2..55a0551a56 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -61,7 +61,11 @@ use crate::{ free, sys::timer::{TIMERS, timer_routine, timer_update_wake_time}, }, - sync::rwlock::RwLock, + sync::{ + self, Mutex, + rwlock::RwLock, + sys::timer::{timer_routine, timer_update_wake_time}, + }, }; pub use redox_rt::proc::FdGuard; @@ -1225,6 +1229,7 @@ impl Pal for Sys { cwd_fd: path::current_dir() .ok() .map(|fd| fd.as_ref().unwrap().fd.as_raw_fd()), + same_process: false, }; let mut args = Vec::new(); @@ -1244,7 +1249,10 @@ impl Pal for Sys { envp = unsafe { envp.add(1) }; } - redox_rt::proc::fexec_impl( + if let Some(redox_rt::proc::FexecResult::Interp { + path: interp_path, + interp_override, + }) = redox_rt::proc::fexec_impl( FdGuard::new(executable.fd as usize).to_upper().unwrap(), &child.thr_fd, &proc_fd, @@ -1253,8 +1261,24 @@ impl Pal for Sys { envs.as_slice(), &extra_info, None, - ) - .map_err(|_| syscall::error::Error::new(syscall::error::ENOEXEC))?; + )? { + let interp_path = CStr::from_bytes_with_nul(&interp_path) + .map_err(|_| platform::Errno(syscall::error::ENOEXEC))?; + + let interpreter = File::open(interp_path, fcntl::O_RDONLY | fcntl::O_CLOEXEC) + .map_err(|_| platform::Errno(syscall::error::ENOEXEC))?; + + redox_rt::proc::fexec_impl( + FdGuard::new(interpreter.fd as usize).to_upper().unwrap(), + &child.thr_fd, + &proc_fd, + program.to_bytes(), + args.as_slice(), + envs.as_slice(), + &extra_info, + Some(interp_override), + )?; + } Ok(i32::try_from(child.pid).unwrap()) }