* 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
This commit is contained in:
+10
-4
@@ -63,6 +63,8 @@ pub struct ExtraInfo<'a> {
|
||||
pub ns_fd: Option<usize>,
|
||||
/// CWD handle
|
||||
pub cwd_fd: Option<usize>,
|
||||
/// 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<InterpOverride>,
|
||||
) -> Result<FexecResult> {
|
||||
) -> Result<Option<FexecResult>> {
|
||||
// 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<const N: usize>(fd: &FdGuardUpper, usizes: [usize; N]) -> Result<usize> {
|
||||
fd.write(unsafe { plain::as_bytes(&usizes) })
|
||||
|
||||
+17
-9
@@ -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<pid_t> {
|
||||
) -> 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
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user