From 31570e99ab3ed019bd66433de35e99fbeb148e4e Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Wed, 25 Dec 2024 14:35:54 +0100 Subject: [PATCH 01/61] Patch redox_syscall. --- Cargo.lock | 10 +++++----- Cargo.toml | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e485d476b7..83f396cea8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -227,9 +227,9 @@ version = "0.1.0" [[package]] name = "libc" -version = "0.2.171" +version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libm" @@ -377,9 +377,9 @@ version = "0.1.2" [[package]] name = "proc-macro2" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] @@ -458,7 +458,7 @@ dependencies = [ [[package]] name = "redox_syscall" version = "0.5.11" -source = "git+https://gitlab.redox-os.org/redox-os/syscall.git#080f2003cd065bcc9a290230ede06da0a1ea0502" +source = "git+https://gitlab.redox-os.org/4lDO2/syscall.git?branch=nuke_proc#8a80d1f58bc92d8c0eb73a939420fb30fe1e85d0" dependencies = [ "bitflags", ] diff --git a/Cargo.toml b/Cargo.toml index ebe3371f8e..d576ffe53d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -81,4 +81,4 @@ panic = "abort" [patch.crates-io] cc-11 = { git = "https://github.com/tea/cc-rs", branch = "riscv-abi-arch-fix", package = "cc" } -redox_syscall = { git = "https://gitlab.redox-os.org/redox-os/syscall.git" } +redox_syscall = { git = "https://gitlab.redox-os.org/4lDO2/syscall.git", branch = "nuke_proc" } From 422a32690dc9c4696428b0213fb5f897d08cb2b5 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Wed, 25 Dec 2024 14:36:13 +0100 Subject: [PATCH 02/61] Replace removed syscalls with redox-rt stubs. --- redox-rt/Cargo.toml | 4 +++ redox-rt/src/lib.rs | 20 ++++++++++-- redox-rt/src/proc.rs | 11 +++---- redox-rt/src/signal.rs | 6 ++-- redox-rt/src/sys.rs | 52 ++++++++++++++++++++++++++++--- src/platform/redox/exec.rs | 4 +-- src/platform/redox/libredox.rs | 18 +++++------ src/platform/redox/mod.rs | 56 +++++++++++++--------------------- 8 files changed, 110 insertions(+), 61 deletions(-) diff --git a/redox-rt/Cargo.toml b/redox-rt/Cargo.toml index a69851747e..9210ba259a 100644 --- a/redox-rt/Cargo.toml +++ b/redox-rt/Cargo.toml @@ -15,3 +15,7 @@ plain = "0.2" redox_syscall = "0.5.8" generic-rt = { path = "../generic-rt" } + +[features] +proc = [] +default = ["proc"] diff --git a/redox-rt/src/lib.rs b/redox-rt/src/lib.rs index 1d0906a057..7931d978c5 100644 --- a/redox-rt/src/lib.rs +++ b/redox-rt/src/lib.rs @@ -63,7 +63,7 @@ impl RtTcb { unsafe { if (&*self.thr_fd.get()).is_none() { self.thr_fd.get().write(Some(FdGuard::new( - syscall::open("/scheme/thisproc/current/open_via_dup", O_CLOEXEC).unwrap(), + syscall::open("/scheme/thisproc/current", O_CLOEXEC).unwrap(), ))); } (&*self.thr_fd.get()).as_ref().unwrap() @@ -178,17 +178,31 @@ pub unsafe fn initialize_freestanding() { initialize(); } pub unsafe fn initialize() { + #[cfg(feature = "proc")] + // Find the PID attached to this process + let pid = todo!("getpid"); + + #[cfg(not(feature = "proc"))] + // Bootstrap mode, don't associate proc fds with PIDs + let pid = 0; + THIS_PID .get() - .write(Some(syscall::getpid().unwrap().try_into().unwrap()).unwrap()); + .write(Some(pid).unwrap()); } static THIS_PID: SyncUnsafeCell = SyncUnsafeCell::new(0); unsafe fn child_hook_common(new_pid_fd: FdGuard) { + // TODO: just pass PID to child rather than obtaining it via IPC? + #[cfg(feature = "proc")] + let pid = todo!("getpid"); + #[cfg(not(feature = "proc"))] + let pid = 0; + // TODO: Currently pidfd == threadfd, but this will not be the case later. RtTcb::current().thr_fd.get().write(Some(new_pid_fd)); THIS_PID .get() - .write(Some(syscall::getpid().unwrap().try_into().unwrap()).unwrap()); + .write(Some(pid).unwrap()); } diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index a6a4d67e60..abb2fe0a4d 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -74,8 +74,7 @@ where { // 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 execute the SYS_EXEC syscall to replace the program memory - // entirely. + // some misalignments, and then switch address space. let mut header_bytes = [0_u8; size_of::
()]; pread_all(*image_file, 0, &mut header_bytes)?; @@ -695,10 +694,10 @@ pub fn fork_inner(initial_rsp: *mut usize) -> Result { { let cur_pid_fd = FdGuard::new(syscall::open( - "/scheme/thisproc/current/open_via_dup", + "/scheme/thisproc/current", O_CLOEXEC, )?); - (new_pid_fd, new_pid) = new_child_process()?; + (new_pid_fd, new_pid) = new_child_process(*cur_pid_fd)?; copy_str(*cur_pid_fd, *new_pid_fd, "name")?; @@ -823,10 +822,10 @@ pub fn fork_inner(initial_rsp: *mut usize) -> Result { Ok(new_pid) } -pub fn new_child_process() -> Result<(FdGuard, usize)> { +pub fn new_child_process(_cur_pid_fd: usize) -> Result<(FdGuard, usize)> { // Create a new context (fields such as uid/gid will be inherited from the current context). let fd = FdGuard::new(syscall::open( - "/scheme/thisproc/new/open_via_dup", + "/scheme/thisproc/new", O_CLOEXEC, )?); diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index f303383957..f252ba5418 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -152,7 +152,8 @@ unsafe fn inner(stack: &mut SigStack) { panic!("ctl {:x?} signal {}", os.control, stack.sig_num) } SigactionKind::Default => { - syscall::exit(stack.sig_num as usize); + //syscall::exit(stack.sig_num as usize); + todo!("exit"); unreachable!(); } SigactionKind::Handled { handler } => handler, @@ -497,7 +498,8 @@ bitflags::bitflags! { const STORED_FLAGS: u32 = 0xfe00_0000; fn default_handler(sig: c_int) { - syscall::exit(sig as usize); + //syscall::exit(sig as usize); + todo!("exit") } #[derive(Clone, Copy)] diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs index 2f9bd82c30..1fffae6e20 100644 --- a/redox-rt/src/sys.rs +++ b/redox-rt/src/sys.rs @@ -43,7 +43,7 @@ pub fn posix_write(fd: usize, buf: &[u8]) -> Result { } #[inline] pub fn posix_kill(pid: usize, sig: usize) -> Result<()> { - match wrapper(false, || syscall::kill(pid, sig)) { + match wrapper(false, || Ok(todo!("kill"))) { Ok(_) | Err(Error { errno: EINTR }) => Ok(()), Err(error) => Err(error), } @@ -57,7 +57,8 @@ pub fn posix_sigqueue(pid: usize, sig: usize, arg: usize) -> Result<()> { pid: posix_getpid(), }; match wrapper(false, || unsafe { - syscall::syscall3(syscall::SYS_SIGENQUEUE, pid, sig, addr_of!(siginf) as usize) + //syscall::syscall3(syscall::SYS_SIGENQUEUE, pid, sig, addr_of!(siginf) as usize) + Ok(todo!("sigenqueue")) }) { Ok(_) | Err(Error { errno: EINTR }) => Ok(()), Err(error) => Err(error), @@ -70,7 +71,10 @@ pub fn posix_getpid() -> u32 { } #[inline] pub fn posix_killpg(pgrp: usize, sig: usize) -> Result<()> { - match wrapper(false, || syscall::kill(usize::wrapping_neg(pgrp), sig)) { + match wrapper(false, || + //syscall::kill(usize::wrapping_neg(pgrp), sig) + Ok(todo!("killpg")) + ) { Ok(_) | Err(Error { errno: EINTR }) => Ok(()), Err(error) => Err(error), } @@ -103,11 +107,12 @@ pub unsafe fn sys_futex_wake(addr: *mut u32, num: u32) -> Result { } pub fn sys_waitpid(pid: usize, status: &mut usize, flags: usize) -> Result { wrapper(true, || { - syscall::waitpid( + /*syscall::waitpid( pid, status, syscall::WaitFlags::from_bits(flags).expect("waitpid: invalid bit pattern"), - ) + )*/ + todo!("waitpid") }) } pub fn posix_kill_thread(thread_fd: usize, signal: u32) -> Result<()> { @@ -134,3 +139,40 @@ pub fn swap_umask(mask: u32) -> u32 { pub fn get_umask() -> u32 { UMASK.load(Ordering::Acquire) } + +pub fn posix_setresuid(ruid: Option, euid: Option, suid: Option) -> Result<()> { + todo!("posix_setresuid") +} +pub fn posix_setresgid(rgid: Option, egid: Option, sgid: Option) -> Result<()> { + todo!("posix_setresgid") +} +pub fn posix_getruid() -> u32 { + todo!("posix_getruid") +} +pub fn posix_getrgid() -> u32 { + todo!("posix_getrgid") +} +pub fn posix_geteuid() -> u32 { + todo!("posix_geteuid") +} +pub fn posix_getegid() -> u32 { + todo!("posix_getegid") +} +pub fn posix_getppid() -> usize { + todo!("posix_getppid") +} +pub fn posix_exit(status: i32) -> ! { + todo!("posix_exit") +} +pub fn setrens(rns: usize, ens: usize) -> Result<()> { + todo!("setrens") +} +pub fn posix_getpgid(pid: usize) -> Result { + todo!("posix_getpgid") +} +pub fn posix_setpgid(pid: usize, pgid: usize) -> Result<()> { + todo!("posix_setpgid") +} +pub fn posix_getsid(pid: usize) -> Result { + todo!("posix_getsid") +} diff --git a/src/platform/redox/exec.rs b/src/platform/redox/exec.rs index 10e09eccc1..2e7923d83e 100644 --- a/src/platform/redox/exec.rs +++ b/src/platform/redox/exec.rs @@ -119,8 +119,8 @@ pub fn execve( let mut stat = Stat::default(); syscall::fstat(*image_file as usize, &mut stat)?; - let uid = syscall::getuid()?; - let gid = syscall::getuid()?; + let uid = redox_rt::sys::posix_getruid() as usize; + let gid = redox_rt::sys::posix_getrgid() as usize; let mode = if uid == stat.st_uid as usize { (stat.st_mode >> 3 * 2) & 0o7 diff --git a/src/platform/redox/libredox.rs b/src/platform/redox/libredox.rs index 5447db0436..62506a4b08 100644 --- a/src/platform/redox/libredox.rs +++ b/src/platform/redox/libredox.rs @@ -219,36 +219,36 @@ pub unsafe extern "C" fn redox_close_v1(fd: usize) -> RawResult { #[no_mangle] pub unsafe extern "C" fn redox_get_pid_v1() -> RawResult { - Error::mux(syscall::getpid()) + redox_rt::sys::posix_getpid() as _ } #[no_mangle] pub unsafe extern "C" fn redox_get_euid_v1() -> RawResult { - Error::mux(syscall::geteuid()) + redox_rt::sys::posix_geteuid() as _ } #[no_mangle] pub unsafe extern "C" fn redox_get_ruid_v1() -> RawResult { - Error::mux(syscall::getuid()) + redox_rt::sys::posix_getruid() as _ } #[no_mangle] pub unsafe extern "C" fn redox_get_egid_v1() -> RawResult { - Error::mux(syscall::getegid()) + redox_rt::sys::posix_getegid() as _ } #[no_mangle] pub unsafe extern "C" fn redox_get_rgid_v1() -> RawResult { - Error::mux(syscall::getgid()) + redox_rt::sys::posix_getrgid() as _ } #[no_mangle] pub unsafe extern "C" fn redox_setrens_v1(rns: usize, ens: usize) -> RawResult { - Error::mux(syscall::setrens(rns, ens)) + Error::mux(redox_rt::sys::setrens(rns, ens).map(|()| 0)) } #[no_mangle] pub unsafe extern "C" fn redox_waitpid_v1(pid: usize, status: *mut i32, options: u32) -> RawResult { let mut sts = 0_usize; - let res = Error::mux(syscall::waitpid( + let res = Error::mux(redox_rt::sys::sys_waitpid( pid, &mut sts, - WaitFlags::from_bits_truncate(options as usize), + WaitFlags::from_bits_truncate(options as usize).bits(), )); status.write(sts as i32); res @@ -256,7 +256,7 @@ pub unsafe extern "C" fn redox_waitpid_v1(pid: usize, status: *mut i32, options: #[no_mangle] pub unsafe extern "C" fn redox_kill_v1(pid: usize, signal: u32) -> RawResult { - Error::mux(syscall::kill(pid, signal as usize)) + Error::mux(redox_rt::sys::posix_kill(pid, signal as usize).map(|()| 0)) } #[no_mangle] diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index f3cfa0b137..48986b2539 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -50,6 +50,13 @@ fn round_up_to_page_size(val: usize) -> Option { .map(|val| (val - 1) / PAGE_SIZE * PAGE_SIZE) } +fn cvt_uid(id: c_int) -> Result> { + if id == -1 { + return Ok(None); + } + Ok(Some(id.try_into().map_err(|_| Errno(EINVAL))?)) +} + mod clone; mod epoll; mod event; @@ -93,8 +100,8 @@ impl Pal for Sys { syscall::fstat(*fd as usize, &mut stat)?; - let uid = syscall::getuid()?; - let gid = syscall::getgid()?; + let uid = redox_rt::sys::posix_getruid() as usize; + let gid = redox_rt::sys::posix_getrgid() as usize; let perms = if stat.st_uid as usize == uid { stat.st_mode >> (3 * 2 & 0o7) @@ -199,7 +206,7 @@ impl Pal for Sys { } fn exit(status: c_int) -> ! { - let _ = syscall::exit((status as usize) << 8); + let _ = redox_rt::sys::posix_exit(status); loop {} } @@ -401,15 +408,15 @@ impl Pal for Sys { } fn getegid() -> gid_t { - syscall::getegid().unwrap() as gid_t + redox_rt::sys::posix_getegid() as gid_t } fn geteuid() -> uid_t { - syscall::geteuid().unwrap() as uid_t + redox_rt::sys::posix_geteuid() as uid_t } fn getgid() -> gid_t { - syscall::getgid().unwrap() as gid_t + redox_rt::sys::posix_getrgid() as gid_t } unsafe fn getgroups(size: c_int, list: *mut gid_t) -> Result { @@ -423,7 +430,7 @@ impl Pal for Sys { } fn getpgid(pid: pid_t) -> Result { - Ok(syscall::getpgid(pid as usize)? as pid_t) + Ok(redox_rt::sys::posix_getpgid(pid as usize)? as pid_t) } fn getpid() -> pid_t { @@ -431,7 +438,7 @@ impl Pal for Sys { } fn getppid() -> pid_t { - syscall::getppid().unwrap() as pid_t + redox_rt::sys::posix_getppid() as pid_t } fn getpriority(which: c_int, who: id_t) -> Result { @@ -487,17 +494,7 @@ impl Pal for Sys { } fn getsid(pid: pid_t) -> Result { - let mut buf = [0; mem::size_of::()]; - let path = if pid == 0 { - format!("/scheme/thisproc/current/session_id") - } else { - format!("/scheme/proc/{}/session_id", pid) - }; - let path_c = CString::new(path).unwrap(); - let mut file = File::open(CStr::borrow(&path_c), fcntl::O_RDONLY | fcntl::O_CLOEXEC)?; - file.read(&mut buf) - .map_err(|err| Errno(err.raw_os_error().unwrap_or(EIO)))?; - Ok(usize::from_ne_bytes(buf).try_into().unwrap()) + Ok(redox_rt::sys::posix_getsid(pid as usize)? as _) } fn gettid() -> pid_t { @@ -527,7 +524,7 @@ impl Pal for Sys { } fn getuid() -> uid_t { - syscall::getuid().unwrap() as pid_t + redox_rt::sys::posix_getruid() as uid_t } fn lchown(path: CStr, owner: uid_t, group: gid_t) -> Result<()> { @@ -838,8 +835,7 @@ impl Pal for Sys { } fn setpgid(pid: pid_t, pgid: pid_t) -> Result<()> { - syscall::setpgid(pid as usize, pgid as usize)?; - Ok(()) + Ok(redox_rt::sys::posix_setpgid(pid as usize, pgid as usize)?) } fn setpriority(which: c_int, who: id_t, prio: c_int) -> Result<()> { @@ -864,19 +860,11 @@ impl Pal for Sys { } fn setresgid(rgid: gid_t, egid: gid_t, sgid: gid_t) -> Result<()> { - if sgid != -1 { - println!("TODO: suid"); - } - syscall::setregid(rgid as usize, egid as usize)?; - Ok(()) + Ok(redox_rt::sys::posix_setresgid(cvt_uid(rgid)?, cvt_uid(egid)?, cvt_uid(sgid)?)?) } fn setresuid(ruid: uid_t, euid: uid_t, suid: uid_t) -> Result<()> { - if suid != -1 { - println!("TODO: suid"); - } - syscall::setreuid(ruid as usize, euid as usize)?; - Ok(()) + Ok(redox_rt::sys::posix_setresuid(cvt_uid(ruid)?, cvt_uid(euid)?, cvt_uid(suid)?)?) } fn symlink(path1: CStr, path2: CStr) -> Result<()> { @@ -1057,8 +1045,8 @@ impl Pal for Sys { } fn verify() -> bool { - // GETPID on Redox is 20, which is WRITEV on Linux - (unsafe { syscall::syscall5(syscall::number::SYS_GETPID, !0, !0, !0, !0, !0) }).is_ok() + // YIELD on Redox is 20, which is SYS_ARCH_PRCTL on Linux + (unsafe { syscall::syscall5(syscall::number::SYS_YIELD, !0, !0, !0, !0, !0) }).is_ok() } unsafe fn exit_thread(stack_base: *mut (), stack_size: usize) -> ! { From 91e58e856839f7fc11595f1f7a54accb12a990b9 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Thu, 26 Dec 2024 20:06:07 +0100 Subject: [PATCH 03/61] WIP: dynamic and static proc info --- redox-rt/src/lib.rs | 44 ++++++++++++++++++++++++++++---------- redox-rt/src/proc.rs | 38 +++++++++++++++----------------- redox-rt/src/sys.rs | 10 +++++---- src/platform/redox/exec.rs | 2 +- 4 files changed, 57 insertions(+), 37 deletions(-) diff --git a/redox-rt/src/lib.rs b/redox-rt/src/lib.rs index 7931d978c5..672e81fa01 100644 --- a/redox-rt/src/lib.rs +++ b/redox-rt/src/lib.rs @@ -15,6 +15,7 @@ use generic_rt::{ExpectTlsFree, GenericTcb}; use syscall::{Sigcontrol, O_CLOEXEC}; use self::proc::FdGuard; +use self::sync::Mutex; extern crate alloc; @@ -180,29 +181,50 @@ pub unsafe fn initialize_freestanding() { pub unsafe fn initialize() { #[cfg(feature = "proc")] // Find the PID attached to this process - let pid = todo!("getpid"); + let (pid, ppid) = todo!("getpid"); #[cfg(not(feature = "proc"))] // Bootstrap mode, don't associate proc fds with PIDs - let pid = 0; + let (pid, ppid): (u32, u32) = (0, 0); - THIS_PID - .get() - .write(Some(pid).unwrap()); + STATIC_PROC_INFO.get().write(StaticProcInfo { + pid, + ppid, + }); } -static THIS_PID: SyncUnsafeCell = SyncUnsafeCell::new(0); +struct StaticProcInfo { + pid: u32, + ppid: u32, + proc_fd: FdGuard, +} +struct DynamicProcInfo { + pgid: u32, + euid: u32, + ruid: u32, + egid: u32, + rgid: u32, +} + +static STATIC_PROC_INFO: SyncUnsafeCell = SyncUnsafeCell::new(StaticProcInfo { + pid: 0, + ppid: 0, +}); +static DYNAMIC_PROC_INFO: Mutex = Mutex::new(DynamicProcInfo { + pgid: u32::MAX, + euid: u32::MAX, + egid: u32::MAX, + ruid: u32::MAX, + rgid: u32::MAX, +}); unsafe fn child_hook_common(new_pid_fd: FdGuard) { // TODO: just pass PID to child rather than obtaining it via IPC? #[cfg(feature = "proc")] - let pid = todo!("getpid"); + let (pid, ppid): (u32, u32) = todo!("getpid"); #[cfg(not(feature = "proc"))] - let pid = 0; + let (pid, ppid): (u32, u32) = (0, 0); // TODO: Currently pidfd == threadfd, but this will not be the case later. RtTcb::current().thr_fd.get().write(Some(new_pid_fd)); - THIS_PID - .get() - .write(Some(pid).unwrap()); } diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index abb2fe0a4d..ee9e2666b1 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -1,6 +1,6 @@ use core::{fmt::Debug, mem::size_of}; -use crate::{arch::*, auxv_defs::*}; +use crate::{arch::*, auxv_defs::*, DYNAMIC_PROC_INFO, STATIC_PROC_INFO}; use alloc::{boxed::Box, collections::BTreeMap, vec}; @@ -822,33 +822,18 @@ pub fn fork_inner(initial_rsp: *mut usize) -> Result { Ok(new_pid) } -pub fn new_child_process(_cur_pid_fd: usize) -> Result<(FdGuard, usize)> { +pub fn new_child_process(cur_pid_fd: usize) -> Result<(FdGuard, usize)> { // Create a new context (fields such as uid/gid will be inherited from the current context). let fd = FdGuard::new(syscall::open( "/scheme/thisproc/new", O_CLOEXEC, )?); - // Extract pid. - let mut buffer = [0_u8; 64]; - let len = syscall::fpath(*fd, &mut buffer)?; - let buffer = buffer.get(..len).ok_or(Error::new(ENAMETOOLONG))?; + #[cfg(feature = "proc")] + let pid = todo!("child pid"); - let colon_idx = buffer - .iter() - .position(|c| *c == b':') - .ok_or(Error::new(EINVAL))?; - let slash_idx = buffer - .iter() - .skip(colon_idx) - .position(|c| *c == b'/') - .ok_or(Error::new(EINVAL))? - + colon_idx; - let pid_bytes = buffer - .get(colon_idx + 1..slash_idx) - .ok_or(Error::new(EINVAL))?; - let pid_str = core::str::from_utf8(pid_bytes).map_err(|_| Error::new(EINVAL))?; - let pid = pid_str.parse::().map_err(|_| Error::new(EINVAL))?; + #[cfg(not(feature = "proc"))] + let pid = 1; Ok((fd, pid)) } @@ -866,3 +851,14 @@ pub fn copy_str(cur_pid_fd: usize, new_pid_fd: usize, key: &str) -> Result<()> { Ok(()) } + +pub unsafe fn make_init() { + STATIC_PROC_INFO.get().write(crate::StaticProcInfo { pid: 1, ppid: 1 }); + *DYNAMIC_PROC_INFO.lock() = crate::DynamicProcInfo { + pgid: 1, + egid: 0, + euid: 0, + rgid: 0, + ruid: 0, + }; +} diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs index 1fffae6e20..f65f75185f 100644 --- a/redox-rt/src/sys.rs +++ b/redox-rt/src/sys.rs @@ -67,7 +67,12 @@ pub fn posix_sigqueue(pid: usize, sig: usize, arg: usize) -> Result<()> { #[inline] pub fn posix_getpid() -> u32 { // SAFETY: read-only except during program/fork child initialization - unsafe { crate::THIS_PID.get().read() } + unsafe { addr_of!((*crate::STATIC_PROC_INFO.get()).pid).read() } +} +#[inline] +pub fn posix_getppid() -> u32 { + // SAFETY: read-only except during program/fork child initialization + unsafe { addr_of!((*crate::STATIC_PROC_INFO.get()).ppid).read() } } #[inline] pub fn posix_killpg(pgrp: usize, sig: usize) -> Result<()> { @@ -158,9 +163,6 @@ pub fn posix_geteuid() -> u32 { pub fn posix_getegid() -> u32 { todo!("posix_getegid") } -pub fn posix_getppid() -> usize { - todo!("posix_getppid") -} pub fn posix_exit(status: i32) -> ! { todo!("posix_exit") } diff --git a/src/platform/redox/exec.rs b/src/platform/redox/exec.rs index 2e7923d83e..fa5ba40893 100644 --- a/src/platform/redox/exec.rs +++ b/src/platform/redox/exec.rs @@ -262,7 +262,7 @@ pub fn execve( } } - let this_context_fd = FdGuard::new(syscall::open("/scheme/thisproc/current/open_via_dup", 0)?); + let this_context_fd = FdGuard::new(syscall::open("/scheme/thisproc/current", 0)?); // TODO: Convert image_file to FdGuard earlier? let exec_fd_guard = FdGuard::new(image_file.fd as usize); core::mem::forget(image_file); From b85142221446b6d192d552fe74b280ba077f3a99 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Thu, 26 Dec 2024 21:28:48 +0100 Subject: [PATCH 04/61] WIP: use proc manager in non-init fork. --- redox-rt/src/arch/x86_64.rs | 31 +++++---- redox-rt/src/lib.rs | 70 ++++++++++++++----- redox-rt/src/proc.rs | 129 +++++++++++++++++++++++------------- src/platform/auxv_defs.rs | 9 +++ 4 files changed, 164 insertions(+), 75 deletions(-) diff --git a/redox-rt/src/arch/x86_64.rs b/redox-rt/src/arch/x86_64.rs index cf9d69388a..d70f27eb88 100644 --- a/redox-rt/src/arch/x86_64.rs +++ b/redox-rt/src/arch/x86_64.rs @@ -11,8 +11,11 @@ use syscall::{ }; use crate::{ - proc::{fork_inner, FdGuard}, - signal::{get_sigaltstack, inner_c, PosixStackt, RtSigarea, SigStack, PROC_CONTROL_STRUCT}, + proc::{fork_inner, FdGuard, ForkArgs}, + signal::{ + get_sigaltstack, inner_c, PosixStackt, RtSigarea, SigStack, + PROC_CONTROL_STRUCT, + }, Tcb, }; @@ -92,16 +95,16 @@ pub fn copy_env_regs(cur_pid_fd: usize, new_pid_fd: usize) -> Result<()> { Ok(()) } -unsafe extern "sysv64" fn fork_impl(initial_rsp: *mut usize) -> usize { - Error::mux(fork_inner(initial_rsp)) +unsafe extern "sysv64" fn fork_impl(initial_rsp: *mut usize, args: &ForkArgs) -> usize { + Error::mux(fork_inner(initial_rsp, args)) } -unsafe extern "sysv64" fn child_hook(cur_filetable_fd: usize, new_pid_fd: usize) { +unsafe extern "sysv64" fn child_hook(cur_filetable_fd: usize, new_pid_fd: usize, new_thr_fd: usize) { let _ = syscall::close(cur_filetable_fd); - crate::child_hook_common(FdGuard::new(new_pid_fd)); + crate::child_hook_common(FdGuard::new(new_pid_fd), FdGuard::new(new_thr_fd)); } -asmfunction!(__relibc_internal_fork_wrapper -> usize: [" +asmfunction!(__relibc_internal_fork_wrapper (usize) -> usize: [" push rbp mov rbp, rsp @@ -112,15 +115,16 @@ asmfunction!(__relibc_internal_fork_wrapper -> usize: [" push r14 push r15 - sub rsp, 32 + sub rsp, 48 - stmxcsr [rsp+16] - fnstcw [rsp+24] + stmxcsr [rsp+32] + fnstcw [rsp+40] mov rdi, rsp + // rsi: &ForkArgs call {fork_impl} - add rsp, 80 + add rsp, 96 pop rbp ret @@ -129,10 +133,11 @@ asmfunction!(__relibc_internal_fork_wrapper -> usize: [" asmfunction!(__relibc_internal_fork_ret: [" mov rdi, [rsp] mov rsi, [rsp + 8] + mov rdx, [rsp + 16] call {child_hook} - ldmxcsr [rsp + 16] - fldcw [rsp + 24] + ldmxcsr [rsp + 32] + fldcw [rsp + 40] xor rax, rax diff --git a/redox-rt/src/lib.rs b/redox-rt/src/lib.rs index 672e81fa01..68b56afceb 100644 --- a/redox-rt/src/lib.rs +++ b/redox-rt/src/lib.rs @@ -10,18 +10,20 @@ #![forbid(unreachable_patterns)] use core::cell::{SyncUnsafeCell, UnsafeCell}; +use core::mem::size_of; use generic_rt::{ExpectTlsFree, GenericTcb}; use syscall::{Sigcontrol, O_CLOEXEC}; use self::proc::FdGuard; +use self::protocol::ProcMeta; use self::sync::Mutex; extern crate alloc; #[macro_export] macro_rules! asmfunction( - ($name:ident $(-> $ret:ty)? : [$($asmstmt:expr),*$(,)?] <= [$($decl:ident = $(sym $symname:ident)?$(const $constval:expr)?),*$(,)?]$(,)? ) => { + ($name:ident $(($($arg:ty),*))? $(-> $ret:ty)? : [$($asmstmt:expr),*$(,)?] <= [$($decl:ident = $(sym $symname:ident)?$(const $constval:expr)?),*$(,)?]$(,)? ) => { ::core::arch::global_asm!(concat!(" .p2align 4 .section .text.", stringify!($name), ", \"ax\", @progbits @@ -33,7 +35,7 @@ macro_rules! asmfunction( "), $($decl = $(sym $symname)?$(const $constval)?),*); extern "C" { - pub fn $name() $(-> $ret)?; + pub fn $name($($(_: $arg),*)?) $(-> $ret)?; } } ); @@ -45,6 +47,7 @@ pub mod proc; #[path = "../../src/platform/auxv_defs.rs"] pub mod auxv_defs; +pub mod protocol; pub mod signal; pub mod sync; pub mod sys; @@ -135,6 +138,7 @@ pub unsafe fn tcb_activate(_tcb: &RtTcb, tls_end: usize, tls_len: usize) { } /// Initialize redox-rt in situations where relibc is not used +#[cfg(not(feature = "proc"))] pub unsafe fn initialize_freestanding() { // TODO: This code is a hack! Integrate the ld_so TCB code into generic-rt, and then use that // (this function will need pointers to the ELF structs normally passed in auxvs), so the TCB @@ -178,24 +182,48 @@ pub unsafe fn initialize_freestanding() { } initialize(); } -pub unsafe fn initialize() { +#[cfg(feature = "proc")] +pub(crate) fn read_proc_meta(proc: &FdGuard) -> syscall::Result { + let mut bytes = [0_u8; size_of::()]; + let _ = syscall::read(**proc, &mut bytes)?; + Ok(*plain::from_bytes::(&bytes).unwrap()) +} +pub unsafe fn initialize( #[cfg(feature = "proc")] - // Find the PID attached to this process - let (pid, ppid) = todo!("getpid"); + proc_fd: FdGuard, +) { + #[cfg(feature = "proc")] + let metadata = read_proc_meta(&proc_fd).unwrap(); #[cfg(not(feature = "proc"))] // Bootstrap mode, don't associate proc fds with PIDs - let (pid, ppid): (u32, u32) = (0, 0); + let metadata = ProcMeta::default(); STATIC_PROC_INFO.get().write(StaticProcInfo { - pid, - ppid, + pid: metadata.pid, + ppid: metadata.ppid, + + #[cfg(feature = "proc")] + proc_fd, }); + + #[cfg(feature = "proc")] + { + *DYNAMIC_PROC_INFO.lock() = DynamicProcInfo { + pgid: metadata.pgid, + egid: metadata.egid, + euid: metadata.euid, + ruid: metadata.ruid, + rgid: metadata.rgid, + }; + } } -struct StaticProcInfo { +pub(crate) struct StaticProcInfo { pid: u32, ppid: u32, + + #[cfg(feature = "proc")] proc_fd: FdGuard, } struct DynamicProcInfo { @@ -209,6 +237,7 @@ struct DynamicProcInfo { static STATIC_PROC_INFO: SyncUnsafeCell = SyncUnsafeCell::new(StaticProcInfo { pid: 0, ppid: 0, + proc_fd: FdGuard::new(usize::MAX), }); static DYNAMIC_PROC_INFO: Mutex = Mutex::new(DynamicProcInfo { pgid: u32::MAX, @@ -218,13 +247,24 @@ static DYNAMIC_PROC_INFO: Mutex = Mutex::new(DynamicProcInfo { rgid: u32::MAX, }); -unsafe fn child_hook_common(new_pid_fd: FdGuard) { +pub(crate) fn static_proc_info() -> &'static StaticProcInfo { + unsafe { &*STATIC_PROC_INFO.get() } +} + +unsafe fn child_hook_common(new_proc_fd: FdGuard, new_thr_fd: FdGuard) { // TODO: just pass PID to child rather than obtaining it via IPC? #[cfg(feature = "proc")] - let (pid, ppid): (u32, u32) = todo!("getpid"); - #[cfg(not(feature = "proc"))] - let (pid, ppid): (u32, u32) = (0, 0); + let metadata = read_proc_meta(&new_proc_fd).unwrap(); - // TODO: Currently pidfd == threadfd, but this will not be the case later. - RtTcb::current().thr_fd.get().write(Some(new_pid_fd)); + #[cfg(not(feature = "proc"))] + let metadata = ProcMeta::default(); + + STATIC_PROC_INFO.get().write(StaticProcInfo { + pid: metadata.pid, + ppid: metadata.ppid, + proc_fd: new_proc_fd, + }); + + // FIXME + RtTcb::current().thr_fd.get().write(Some(new_thr_fd)); } diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index ee9e2666b1..c46f8d82cc 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -1,6 +1,6 @@ use core::{fmt::Debug, mem::size_of}; -use crate::{arch::*, auxv_defs::*, DYNAMIC_PROC_INFO, STATIC_PROC_INFO}; +use crate::{arch::*, auxv_defs::*, read_proc_meta, static_proc_info, RtTcb, DYNAMIC_PROC_INFO, STATIC_PROC_INFO}; use alloc::{boxed::Box, collections::BTreeMap, vec}; @@ -23,14 +23,14 @@ use syscall::{ PAGE_SIZE, PROT_EXEC, PROT_READ, PROT_WRITE, }; -pub enum FexecResult { +pub enum FexecResult<'a> { Normal { addrspace_handle: FdGuard, }, Interp { path: Box<[u8]>, image_file: FdGuard, - open_via_dup: FdGuard, + thread_fd: &'a FdGuard, interp_override: InterpOverride, }, } @@ -55,9 +55,10 @@ pub struct ExtraInfo<'a> { pub umask: u32, } -pub fn fexec_impl( +pub fn fexec_impl<'a, A, E>( image_file: FdGuard, - open_via_dup: FdGuard, + thread_fd: &'a FdGuard, + proc_fd: &FdGuard, memory_scheme_fd: &FdGuard, path: &[u8], args: A, @@ -65,7 +66,7 @@ pub fn fexec_impl( total_args_envs_size: usize, extrainfo: &ExtraInfo, mut interp_override: Option, -) -> Result +) -> Result> where A: IntoIterator, E: IntoIterator, @@ -81,7 +82,7 @@ where let header = Header::from_bytes(&header_bytes); let grants_fd = { - let current_addrspace_fd = FdGuard::new(syscall::dup(*open_via_dup, b"addrspace")?); + let current_addrspace_fd = FdGuard::new(syscall::dup(**thread_fd, b"addrspace")?); FdGuard::new(syscall::dup(*current_addrspace_fd, b"empty")?) }; @@ -134,7 +135,7 @@ where return Ok(FexecResult::Interp { path: interp.into_boxed_slice(), image_file, - open_via_dup, + thread_fd, interp_override: InterpOverride { at_entry: header.e_entry as usize, at_phnum: phnum, @@ -389,7 +390,7 @@ where push(argc)?; - if let Ok(sighandler_fd) = syscall::dup(*open_via_dup, b"sighandler").map(FdGuard::new) { + if let Ok(sighandler_fd) = syscall::dup(**thread_fd, b"sighandler").map(FdGuard::new) { let _ = syscall::write( *sighandler_fd, &SetSighandlerData { @@ -402,11 +403,11 @@ where } unsafe { - deactivate_tcb(*open_via_dup)?; + deactivate_tcb(**thread_fd)?; } // TODO: Restore old name if exec failed? - if let Ok(name_fd) = syscall::dup(*open_via_dup, b"name").map(FdGuard::new) { + if let Ok(name_fd) = syscall::dup(**thread_fd, b"name").map(FdGuard::new) { let _ = syscall::write(*name_fd, interp_override.as_ref().map_or(path, |o| &o.name)); } if interp_override.is_some() { @@ -416,7 +417,7 @@ where let _ = syscall::write(*mmap_min_fd, &usize::to_ne_bytes(aligned_last_addr)); } - let addrspace_selection_fd = FdGuard::new(syscall::dup(*open_via_dup, b"current-addrspace")?); + let addrspace_selection_fd = FdGuard::new(syscall::dup(**thread_fd, b"current-addrspace")?); let _ = syscall::write( *addrspace_selection_fd, @@ -635,7 +636,7 @@ pub struct FdGuard { taken: bool, } impl FdGuard { - pub fn new(fd: usize) -> Self { + pub const fn new(fd: usize) -> Self { Self { fd, taken: false } } pub fn take(&mut self) -> usize { @@ -679,9 +680,9 @@ pub fn create_set_addr_space_buf( /// Spawns a new context which will not share the same address space as the current one. File /// descriptors from other schemes are reobtained with `dup`, and grants referencing such file /// descriptors are reobtained through `fmap`. Other mappings are kept but duplicated using CoW. -pub fn fork_impl() -> Result { +pub fn fork_impl(args: &ForkArgs<'_>) -> Result { let old_mask = crate::signal::get_sigmask()?; - let pid = unsafe { Error::demux(__relibc_internal_fork_wrapper())? }; + let pid = unsafe { Error::demux(__relibc_internal_fork_wrapper(args as *const ForkArgs as usize))? }; if pid == 0 { crate::signal::set_sigmask(Some(old_mask), None)?; @@ -689,36 +690,45 @@ pub fn fork_impl() -> Result { Ok(pid) } -pub fn fork_inner(initial_rsp: *mut usize) -> Result { - let (cur_filetable_fd, new_pid_fd, new_pid); +pub enum ForkArgs<'a> { + Init { this_thr_fd: &'a FdGuard, auth: &'a FdGuard }, + Managed, +} + +pub fn fork_inner(initial_rsp: *mut usize, args: &ForkArgs) -> Result { + let (cur_filetable_fd, new_proc_fd, new_thr_fd, new_pid); { - let cur_pid_fd = FdGuard::new(syscall::open( - "/scheme/thisproc/current", - O_CLOEXEC, - )?); - (new_pid_fd, new_pid) = new_child_process(*cur_pid_fd)?; + let cur_thr_fd = match args { + ForkArgs::Init { this_thr_fd, .. } => this_thr_fd, + ForkArgs::Managed => RtTcb::current().thread_fd(), + }; + let NewChildProc { proc_fd, thr_fd, pid } = new_child_process(args)?; + new_proc_fd = proc_fd; + new_thr_fd = thr_fd; + new_pid = pid; - copy_str(*cur_pid_fd, *new_pid_fd, "name")?; + copy_str(**cur_thr_fd, *new_thr_fd, "name")?; // Copy existing files into new file table, but do not reuse the same file table (i.e. new // parent FDs will not show up for the child). { - cur_filetable_fd = FdGuard::new(syscall::dup(*cur_pid_fd, b"filetable")?); + cur_filetable_fd = FdGuard::new(syscall::dup(**cur_thr_fd, b"filetable")?); // This must be done before the address space is copied. unsafe { initial_rsp.write(*cur_filetable_fd); - initial_rsp.add(1).write(*new_pid_fd); + initial_rsp.add(1).write(*new_proc_fd); + initial_rsp.add(2).write(*new_thr_fd); } } // CoW-duplicate address space. { let new_addr_space_sel_fd = - FdGuard::new(syscall::dup(*new_pid_fd, b"current-addrspace")?); + FdGuard::new(syscall::dup(*new_thr_fd, b"current-addrspace")?); - let cur_addr_space_fd = FdGuard::new(syscall::dup(*cur_pid_fd, b"addrspace")?); + let cur_addr_space_fd = FdGuard::new(syscall::dup(**cur_thr_fd, b"addrspace")?); let new_addr_space_fd = FdGuard::new(syscall::dup(*cur_addr_space_fd, b"exclusive")?); let mut grant_desc_buf = [GrantDesc::default(); 16]; @@ -794,14 +804,14 @@ pub fn fork_inner(initial_rsp: *mut usize) -> Result { // Do this after the address space is cloned, since the kernel will get a shared // reference to the TCB and whatever pages stores the signal proc control struct. { - let new_sighandler_fd = FdGuard::new(syscall::dup(*new_pid_fd, b"sighandler")?); + let new_sighandler_fd = FdGuard::new(syscall::dup(*new_thr_fd, b"sighandler")?); let _ = syscall::write( *new_sighandler_fd, &crate::signal::current_setsighandler_struct(), )?; } } - copy_env_regs(*cur_pid_fd, *new_pid_fd)?; + copy_env_regs(**cur_thr_fd, *new_thr_fd)?; } // Copy the file table. We do this last to ensure that all previously used file descriptors are // closed. The only exception -- the filetable selection fd and the current filetable fd -- @@ -810,37 +820,57 @@ pub fn fork_inner(initial_rsp: *mut usize) -> Result { // TODO: Use file descriptor forwarding or something similar to avoid copying the file // table in the kernel. let new_filetable_fd = FdGuard::new(syscall::dup(*cur_filetable_fd, b"copy")?); - let new_filetable_sel_fd = FdGuard::new(syscall::dup(*new_pid_fd, b"current-filetable")?); + let new_filetable_sel_fd = FdGuard::new(syscall::dup(*new_thr_fd, b"current-filetable")?); let _ = syscall::write( *new_filetable_sel_fd, &usize::to_ne_bytes(*new_filetable_fd), )?; } - let start_fd = FdGuard::new(syscall::dup(*new_pid_fd, b"start")?); + let start_fd = FdGuard::new(syscall::dup(*new_thr_fd, b"start")?); let _ = syscall::write(*start_fd, &[0])?; Ok(new_pid) } -pub fn new_child_process(cur_pid_fd: usize) -> Result<(FdGuard, usize)> { - // Create a new context (fields such as uid/gid will be inherited from the current context). - let fd = FdGuard::new(syscall::open( - "/scheme/thisproc/new", - O_CLOEXEC, - )?); - +struct NewChildProc { #[cfg(feature = "proc")] - let pid = todo!("child pid"); + proc_fd: FdGuard, - #[cfg(not(feature = "proc"))] - let pid = 1; - - Ok((fd, pid)) + thr_fd: FdGuard, + pid: usize, } -pub fn copy_str(cur_pid_fd: usize, new_pid_fd: usize, key: &str) -> Result<()> { +pub fn new_child_process(args: &ForkArgs<'_>) -> Result { + match args { + ForkArgs::Managed => { + let proc_fd = &static_proc_info().proc_fd; + let child_proc_fd = FdGuard::new(syscall::dup(**proc_fd, b"fork")?); + let only_thread_fd = FdGuard::new(syscall::dup(*child_proc_fd, b"thread-0")?); + let meta = read_proc_meta(&child_proc_fd)?; + Ok(NewChildProc { + proc_fd: child_proc_fd, + thr_fd: only_thread_fd, + pid: meta.pid as usize + }) + } + #[cfg(feature = "proc")] + ForkArgs::Init { .. } => unreachable!(), + + #[cfg(not(feature = "proc"))] + #[cfg(feature = "proc")] + ForkArgs::Init { this_thr_fd, auth } => { + let thr_fd = FdGuard::new(syscall::dup(*auth, b"new-context")?); + Ok(NewChildProc { + thr_fd, + pid: 0, + }) + } + } +} + +pub fn copy_str(cur_pid_fd: usize, new_proc_fd: usize, key: &str) -> Result<()> { let cur_name_fd = FdGuard::new(syscall::dup(cur_pid_fd, key.as_bytes())?); - let new_name_fd = FdGuard::new(syscall::dup(new_pid_fd, key.as_bytes())?); + let new_name_fd = FdGuard::new(syscall::dup(new_proc_fd, key.as_bytes())?); // TODO: Max path size? let mut buf = [0_u8; 256]; @@ -852,8 +882,12 @@ pub fn copy_str(cur_pid_fd: usize, new_pid_fd: usize, key: &str) -> Result<()> { Ok(()) } -pub unsafe fn make_init() { - STATIC_PROC_INFO.get().write(crate::StaticProcInfo { pid: 1, ppid: 1 }); +pub unsafe fn make_init(this_thr_fd: FdGuard) -> (&'static FdGuard, &'static FdGuard) { + let this_thr_fd = &*(*RtTcb::current().thr_fd.get()).insert(this_thr_fd); + let proc_fd = FdGuard::new(syscall::open("/scheme/proc/init", syscall::O_CLOEXEC).expect("failed to create init")); + syscall::sendfd(*proc_fd, **this_thr_fd, 0, 0).expect("failed to assign current thread to init process"); + + STATIC_PROC_INFO.get().write(crate::StaticProcInfo { pid: 1, ppid: 1, proc_fd }); *DYNAMIC_PROC_INFO.lock() = crate::DynamicProcInfo { pgid: 1, egid: 0, @@ -861,4 +895,5 @@ pub unsafe fn make_init() { rgid: 0, ruid: 0, }; + (&(*STATIC_PROC_INFO.get()).proc_fd, this_thr_fd) } diff --git a/src/platform/auxv_defs.rs b/src/platform/auxv_defs.rs index ae9a6d36a1..7b817dc517 100644 --- a/src/platform/auxv_defs.rs +++ b/src/platform/auxv_defs.rs @@ -26,6 +26,9 @@ pub const AT_RANDOM: usize = 25; /* Address of 16 random bytes. */ pub const AT_HWCAP2: usize = 26; /* More machine-dependent hints about*/ pub const AT_EXECFN: usize = 31; /* Filename of executable. */ +// TODO: Downgrade aux vectors to getauxval constants on Redox, and use a regular struct for +// passing important runtime info between exec (or posix_spawn in the future) calls. + #[cfg(target_os = "redox")] // XXX: The name AT_CWD is already used in openat... for a completely different purpose. pub const AT_REDOX_INITIAL_CWD_PTR: usize = 32; @@ -46,5 +49,11 @@ pub const AT_REDOX_INITIAL_DEFAULT_SCHEME_PTR: usize = 38; #[cfg(target_os = "redox")] pub const AT_REDOX_INITIAL_DEFAULT_SCHEME_LEN: usize = 39; +#[cfg(target_os = "redox")] +pub const AT_REDOX_PROC_FD: usize = 39; + +#[cfg(target_os = "redox")] +pub const AT_REDOX_THR_FD: usize = 39; + #[cfg(target_os = "redox")] pub const AT_REDOX_UMASK: usize = 40; From 26399569dea7d2260957c2e7f19d92f4b584a081 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Fri, 27 Dec 2024 13:55:26 +0100 Subject: [PATCH 05/61] Reach init w/proc manager. --- redox-rt/src/arch/x86_64.rs | 17 +++++-- redox-rt/src/lib.rs | 75 ++++++++++++++++++----------- redox-rt/src/proc.rs | 96 ++++++++++++++++++++++++++----------- redox-rt/src/protocol.rs | 13 +++++ redox-rt/src/sys.rs | 4 +- redox-rt/src/thread.rs | 1 + src/platform/mod.rs | 15 ++++-- src/platform/redox/exec.rs | 20 ++++---- src/platform/redox/mod.rs | 14 ++++-- 9 files changed, 176 insertions(+), 79 deletions(-) create mode 100644 redox-rt/src/protocol.rs diff --git a/redox-rt/src/arch/x86_64.rs b/redox-rt/src/arch/x86_64.rs index d70f27eb88..928fff297d 100644 --- a/redox-rt/src/arch/x86_64.rs +++ b/redox-rt/src/arch/x86_64.rs @@ -99,9 +99,20 @@ unsafe extern "sysv64" fn fork_impl(initial_rsp: *mut usize, args: &ForkArgs) -> Error::mux(fork_inner(initial_rsp, args)) } -unsafe extern "sysv64" fn child_hook(cur_filetable_fd: usize, new_pid_fd: usize, new_thr_fd: usize) { +unsafe extern "sysv64" fn child_hook( + cur_filetable_fd: usize, + new_proc_fd: usize, + new_thr_fd: usize, +) { let _ = syscall::close(cur_filetable_fd); - crate::child_hook_common(FdGuard::new(new_pid_fd), FdGuard::new(new_thr_fd)); + crate::child_hook_common(crate::ChildHookCommonArgs { + new_thr_fd: FdGuard::new(new_thr_fd), + new_proc_fd: if new_proc_fd == usize::MAX { + None + } else { + Some(FdGuard::new(new_proc_fd)) + }, + }); } asmfunction!(__relibc_internal_fork_wrapper (usize) -> usize: [" @@ -141,7 +152,7 @@ asmfunction!(__relibc_internal_fork_ret: [" xor rax, rax - add rsp, 32 + add rsp, 48 pop r15 pop r14 pop r13 diff --git a/redox-rt/src/lib.rs b/redox-rt/src/lib.rs index 68b56afceb..02e8d690b4 100644 --- a/redox-rt/src/lib.rs +++ b/redox-rt/src/lib.rs @@ -9,15 +9,15 @@ )] #![forbid(unreachable_patterns)] -use core::cell::{SyncUnsafeCell, UnsafeCell}; -use core::mem::size_of; +use core::{ + cell::{SyncUnsafeCell, UnsafeCell}, + mem::size_of, +}; use generic_rt::{ExpectTlsFree, GenericTcb}; use syscall::{Sigcontrol, O_CLOEXEC}; -use self::proc::FdGuard; -use self::protocol::ProcMeta; -use self::sync::Mutex; +use self::{proc::FdGuard, protocol::ProcMeta, sync::Mutex}; extern crate alloc; @@ -64,14 +64,7 @@ impl RtTcb { unsafe { &Tcb::current().unwrap().os_specific } } pub fn thread_fd(&self) -> &FdGuard { - unsafe { - if (&*self.thr_fd.get()).is_none() { - self.thr_fd.get().write(Some(FdGuard::new( - syscall::open("/scheme/thisproc/current", O_CLOEXEC).unwrap(), - ))); - } - (&*self.thr_fd.get()).as_ref().unwrap() - } + unsafe { (&*self.thr_fd.get()).as_ref().unwrap() } } } @@ -139,7 +132,7 @@ pub unsafe fn tcb_activate(_tcb: &RtTcb, tls_end: usize, tls_len: usize) { /// Initialize redox-rt in situations where relibc is not used #[cfg(not(feature = "proc"))] -pub unsafe fn initialize_freestanding() { +pub unsafe fn initialize_freestanding(this_thr_fd: FdGuard) -> &'static FdGuard { // TODO: This code is a hack! Integrate the ld_so TCB code into generic-rt, and then use that // (this function will need pointers to the ELF structs normally passed in auxvs), so the TCB // is initialized properly. @@ -162,8 +155,9 @@ pub unsafe fn initialize_freestanding() { page.tcb_ptr = page; page.tcb_len = syscall::PAGE_SIZE; page.tls_end = (page as *mut Tcb).cast(); + // Make sure to use ptr::write to prevent dropping the existing FdGuard - core::ptr::write(page.os_specific.thr_fd.get(), None); + page.os_specific.thr_fd.get().write(Some(this_thr_fd)); #[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))] unsafe { @@ -181,19 +175,23 @@ pub unsafe fn initialize_freestanding() { core::arch::asm!("mv tp, {}", in(reg) (abi_ptr + 8)); } initialize(); + + (*page.os_specific.thr_fd.get()).as_ref().unwrap() } -#[cfg(feature = "proc")] pub(crate) fn read_proc_meta(proc: &FdGuard) -> syscall::Result { let mut bytes = [0_u8; size_of::()]; let _ = syscall::read(**proc, &mut bytes)?; Ok(*plain::from_bytes::(&bytes).unwrap()) } pub unsafe fn initialize( - #[cfg(feature = "proc")] - proc_fd: FdGuard, + #[cfg(feature = "proc")] proc_fd: FdGuard, + #[cfg(feature = "proc")] thr_fd: FdGuard, ) { #[cfg(feature = "proc")] - let metadata = read_proc_meta(&proc_fd).unwrap(); + let metadata = { + RtTcb::current().thr_fd.get().write(Some(thr_fd)); + read_proc_meta(&proc_fd).unwrap() + }; #[cfg(not(feature = "proc"))] // Bootstrap mode, don't associate proc fds with PIDs @@ -204,7 +202,10 @@ pub unsafe fn initialize( ppid: metadata.ppid, #[cfg(feature = "proc")] - proc_fd, + proc_fd: Some(proc_fd), + + #[cfg(not(feature = "proc"))] + proc_fd: None, }); #[cfg(feature = "proc")] @@ -222,9 +223,7 @@ pub unsafe fn initialize( pub(crate) struct StaticProcInfo { pid: u32, ppid: u32, - - #[cfg(feature = "proc")] - proc_fd: FdGuard, + proc_fd: Option, } struct DynamicProcInfo { pgid: u32, @@ -237,7 +236,7 @@ struct DynamicProcInfo { static STATIC_PROC_INFO: SyncUnsafeCell = SyncUnsafeCell::new(StaticProcInfo { pid: 0, ppid: 0, - proc_fd: FdGuard::new(usize::MAX), + proc_fd: None, }); static DYNAMIC_PROC_INFO: Mutex = Mutex::new(DynamicProcInfo { pgid: u32::MAX, @@ -247,14 +246,33 @@ static DYNAMIC_PROC_INFO: Mutex = Mutex::new(DynamicProcInfo { rgid: u32::MAX, }); +#[inline] pub(crate) fn static_proc_info() -> &'static StaticProcInfo { unsafe { &*STATIC_PROC_INFO.get() } } +#[inline] +#[cfg(feature = "proc")] +pub fn current_proc_fd() -> &'static FdGuard { + static_proc_info() + .proc_fd + .as_ref() + .expect("must be present with proc feature") +} -unsafe fn child_hook_common(new_proc_fd: FdGuard, new_thr_fd: FdGuard) { +struct ChildHookCommonArgs { + new_thr_fd: FdGuard, + new_proc_fd: Option, +} + +unsafe fn child_hook_common(args: ChildHookCommonArgs) { // TODO: just pass PID to child rather than obtaining it via IPC? #[cfg(feature = "proc")] - let metadata = read_proc_meta(&new_proc_fd).unwrap(); + let metadata = read_proc_meta( + args.new_proc_fd + .as_ref() + .expect("must be present with proc feature"), + ) + .unwrap(); #[cfg(not(feature = "proc"))] let metadata = ProcMeta::default(); @@ -262,9 +280,8 @@ unsafe fn child_hook_common(new_proc_fd: FdGuard, new_thr_fd: FdGuard) { STATIC_PROC_INFO.get().write(StaticProcInfo { pid: metadata.pid, ppid: metadata.ppid, - proc_fd: new_proc_fd, + proc_fd: args.new_proc_fd, }); - // FIXME - RtTcb::current().thr_fd.get().write(Some(new_thr_fd)); + RtTcb::current().thr_fd.get().write(Some(args.new_thr_fd)); } diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index c46f8d82cc..0cf57f1b67 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -1,6 +1,9 @@ use core::{fmt::Debug, mem::size_of}; -use crate::{arch::*, auxv_defs::*, read_proc_meta, static_proc_info, RtTcb, DYNAMIC_PROC_INFO, STATIC_PROC_INFO}; +use crate::{ + arch::*, auxv_defs::*, read_proc_meta, static_proc_info, RtTcb, DYNAMIC_PROC_INFO, + STATIC_PROC_INFO, +}; use alloc::{boxed::Box, collections::BTreeMap, vec}; @@ -19,18 +22,17 @@ use goblin::elf64::{ use syscall::{ error::*, flag::{MapFlags, SEEK_SET}, - GrantDesc, GrantFlags, Map, SetSighandlerData, MAP_FIXED_NOREPLACE, MAP_SHARED, O_CLOEXEC, - PAGE_SIZE, PROT_EXEC, PROT_READ, PROT_WRITE, + GrantDesc, GrantFlags, Map, ProcSchemeAttrs, SetSighandlerData, MAP_FIXED_NOREPLACE, + MAP_SHARED, O_CLOEXEC, PAGE_SIZE, PROT_EXEC, PROT_READ, PROT_WRITE, }; -pub enum FexecResult<'a> { +pub enum FexecResult { Normal { addrspace_handle: FdGuard, }, Interp { path: Box<[u8]>, image_file: FdGuard, - thread_fd: &'a FdGuard, interp_override: InterpOverride, }, } @@ -55,9 +57,9 @@ pub struct ExtraInfo<'a> { pub umask: u32, } -pub fn fexec_impl<'a, A, E>( +pub fn fexec_impl( image_file: FdGuard, - thread_fd: &'a FdGuard, + thread_fd: &FdGuard, proc_fd: &FdGuard, memory_scheme_fd: &FdGuard, path: &[u8], @@ -66,7 +68,7 @@ pub fn fexec_impl<'a, A, E>( total_args_envs_size: usize, extrainfo: &ExtraInfo, mut interp_override: Option, -) -> Result> +) -> Result where A: IntoIterator, E: IntoIterator, @@ -135,7 +137,6 @@ where return Ok(FexecResult::Interp { path: interp.into_boxed_slice(), image_file, - thread_fd, interp_override: InterpOverride { at_entry: header.e_entry as usize, at_phnum: phnum, @@ -682,7 +683,11 @@ pub fn create_set_addr_space_buf( /// descriptors are reobtained through `fmap`. Other mappings are kept but duplicated using CoW. pub fn fork_impl(args: &ForkArgs<'_>) -> Result { let old_mask = crate::signal::get_sigmask()?; - let pid = unsafe { Error::demux(__relibc_internal_fork_wrapper(args as *const ForkArgs as usize))? }; + let pid = unsafe { + Error::demux(__relibc_internal_fork_wrapper( + args as *const ForkArgs as usize, + ))? + }; if pid == 0 { crate::signal::set_sigmask(Some(old_mask), None)?; @@ -691,7 +696,10 @@ pub fn fork_impl(args: &ForkArgs<'_>) -> Result { } pub enum ForkArgs<'a> { - Init { this_thr_fd: &'a FdGuard, auth: &'a FdGuard }, + Init { + this_thr_fd: &'a FdGuard, + auth: &'a FdGuard, + }, Managed, } @@ -703,7 +711,11 @@ pub fn fork_inner(initial_rsp: *mut usize, args: &ForkArgs) -> Result { ForkArgs::Init { this_thr_fd, .. } => this_thr_fd, ForkArgs::Managed => RtTcb::current().thread_fd(), }; - let NewChildProc { proc_fd, thr_fd, pid } = new_child_process(args)?; + let NewChildProc { + proc_fd, + thr_fd, + pid, + } = new_child_process(args)?; new_proc_fd = proc_fd; new_thr_fd = thr_fd; new_pid = pid; @@ -718,7 +730,9 @@ pub fn fork_inner(initial_rsp: *mut usize, args: &ForkArgs) -> Result { // This must be done before the address space is copied. unsafe { initial_rsp.write(*cur_filetable_fd); - initial_rsp.add(1).write(*new_proc_fd); + initial_rsp + .add(1) + .write(new_proc_fd.as_ref().map_or(usize::MAX, |p| **p)); initial_rsp.add(2).write(*new_thr_fd); } } @@ -833,36 +847,49 @@ pub fn fork_inner(initial_rsp: *mut usize, args: &ForkArgs) -> Result { } struct NewChildProc { - #[cfg(feature = "proc")] - proc_fd: FdGuard, + proc_fd: Option, thr_fd: FdGuard, pid: usize, } pub fn new_child_process(args: &ForkArgs<'_>) -> Result { - match args { + match *args { ForkArgs::Managed => { - let proc_fd = &static_proc_info().proc_fd; - let child_proc_fd = FdGuard::new(syscall::dup(**proc_fd, b"fork")?); + let this_proc_fd = crate::static_proc_info() + .proc_fd + .as_ref() + .expect("cannot use ForkArgs::Managed without an existing proc info"); + let child_proc_fd = FdGuard::new(syscall::dup(**this_proc_fd, b"fork")?); let only_thread_fd = FdGuard::new(syscall::dup(*child_proc_fd, b"thread-0")?); let meta = read_proc_meta(&child_proc_fd)?; Ok(NewChildProc { - proc_fd: child_proc_fd, + proc_fd: Some(child_proc_fd), thr_fd: only_thread_fd, - pid: meta.pid as usize + pid: meta.pid as usize, }) } #[cfg(feature = "proc")] ForkArgs::Init { .. } => unreachable!(), #[cfg(not(feature = "proc"))] - #[cfg(feature = "proc")] ForkArgs::Init { this_thr_fd, auth } => { - let thr_fd = FdGuard::new(syscall::dup(*auth, b"new-context")?); + let thr_fd = FdGuard::new(syscall::dup(**auth, b"new-context")?); + let buf = ProcSchemeAttrs { + pid: 0, + euid: 0, + egid: 0, + ens: 1, + }; + let attr_fd = FdGuard::new(syscall::dup( + *thr_fd, + alloc::format!("attrs-{}", **auth).as_bytes(), + )?); + let _ = syscall::write(*attr_fd, &buf)?; Ok(NewChildProc { thr_fd, - pid: 0, + pid: 1, // dummy fd to distinguish child from parent + proc_fd: None, }) } } @@ -882,12 +909,23 @@ pub fn copy_str(cur_pid_fd: usize, new_proc_fd: usize, key: &str) -> Result<()> Ok(()) } -pub unsafe fn make_init(this_thr_fd: FdGuard) -> (&'static FdGuard, &'static FdGuard) { - let this_thr_fd = &*(*RtTcb::current().thr_fd.get()).insert(this_thr_fd); - let proc_fd = FdGuard::new(syscall::open("/scheme/proc/init", syscall::O_CLOEXEC).expect("failed to create init")); - syscall::sendfd(*proc_fd, **this_thr_fd, 0, 0).expect("failed to assign current thread to init process"); +pub unsafe fn make_init() -> &'static FdGuard { + let proc_fd = FdGuard::new( + syscall::open("/scheme/proc/init", syscall::O_CLOEXEC).expect("failed to create init"), + ); + syscall::sendfd( + *proc_fd, + syscall::dup(**RtTcb::current().thread_fd(), &[]).unwrap(), + 0, + 0, + ) + .expect("failed to assign current thread to init process"); - STATIC_PROC_INFO.get().write(crate::StaticProcInfo { pid: 1, ppid: 1, proc_fd }); + STATIC_PROC_INFO.get().write(crate::StaticProcInfo { + pid: 1, + ppid: 1, + proc_fd: Some(proc_fd), + }); *DYNAMIC_PROC_INFO.lock() = crate::DynamicProcInfo { pgid: 1, egid: 0, @@ -895,5 +933,5 @@ pub unsafe fn make_init(this_thr_fd: FdGuard) -> (&'static FdGuard, &'static FdG rgid: 0, ruid: 0, }; - (&(*STATIC_PROC_INFO.get()).proc_fd, this_thr_fd) + (*STATIC_PROC_INFO.get()).proc_fd.as_ref().unwrap() } diff --git a/redox-rt/src/protocol.rs b/redox-rt/src/protocol.rs new file mode 100644 index 0000000000..74ba35fc49 --- /dev/null +++ b/redox-rt/src/protocol.rs @@ -0,0 +1,13 @@ +#[derive(Clone, Copy, Debug, Default)] +pub struct ProcMeta { + pub pid: u32, + pub pgid: u32, + pub ppid: u32, + pub euid: u32, + pub ruid: u32, + pub egid: u32, + pub rgid: u32, + pub ens: u32, + pub rns: u32, +} +unsafe impl plain::Plain for ProcMeta {} diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs index f65f75185f..13978efd82 100644 --- a/redox-rt/src/sys.rs +++ b/redox-rt/src/sys.rs @@ -78,8 +78,8 @@ pub fn posix_getppid() -> u32 { pub fn posix_killpg(pgrp: usize, sig: usize) -> Result<()> { match wrapper(false, || //syscall::kill(usize::wrapping_neg(pgrp), sig) - Ok(todo!("killpg")) - ) { + Ok(todo!("killpg"))) + { Ok(_) | Err(Error { errno: EINTR }) => Ok(()), Err(error) => Err(error), } diff --git a/redox-rt/src/thread.rs b/redox-rt/src/thread.rs index 1791732a22..84e8978875 100644 --- a/redox-rt/src/thread.rs +++ b/redox-rt/src/thread.rs @@ -6,6 +6,7 @@ use crate::{arch::*, proc::*, signal::tmp_disable_signals, RtTcb}; /// Spawns a new context sharing the same address space as the current one (i.e. a new thread). pub unsafe fn rlct_clone_impl(stack: *mut usize) -> Result { + // FIXME let cur_thr_fd = RtTcb::current().thread_fd(); let new_thr_fd = FdGuard::new(syscall::open( "/scheme/thisproc/new-thread/open_via_dup", diff --git a/src/platform/mod.rs b/src/platform/mod.rs index 74b2519291..b1d08dd2e6 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -306,13 +306,18 @@ pub fn get_auxv(auxvs: &[[usize; 2]], key: usize) -> Option { #[cfg(target_os = "redox")] // SAFETY: Must only be called when only one thread exists. pub unsafe fn init(auxvs: Box<[[usize; 2]]>) { - redox_rt::initialize(); - + use self::auxv_defs::*; + use crate::header::sys_stat::S_ISVTX; + use redox_rt::proc::FdGuard; use syscall::MODE_PERM; - use crate::header::sys_stat::S_ISVTX; - - use self::auxv_defs::*; + let (Some(thr_fd), Some(proc_fd)) = ( + get_auxv(&auxvs, AT_REDOX_THR_FD), + get_auxv(&auxvs, AT_REDOX_PROC_FD), + ) else { + panic!("Missing proc and thread fd!"); + }; + redox_rt::initialize(FdGuard::new(proc_fd), FdGuard::new(thr_fd)); if let (Some(cwd_ptr), Some(cwd_len)) = ( get_auxv(&auxvs, AT_REDOX_INITIAL_CWD_PTR), diff --git a/src/platform/redox/exec.rs b/src/platform/redox/exec.rs index fa5ba40893..be047a25bf 100644 --- a/src/platform/redox/exec.rs +++ b/src/platform/redox/exec.rs @@ -14,12 +14,14 @@ use crate::{ }, }; -use redox_rt::proc::{ExtraInfo, FdGuard, FexecResult, InterpOverride}; +use redox_rt::{ + proc::{ExtraInfo, FdGuard, FexecResult, InterpOverride}, + RtTcb, +}; use syscall::{data::Stat, error::*, flag::*}; fn fexec_impl( exec_file: FdGuard, - open_via_dup: FdGuard, path: &[u8], args: &[&[u8]], envs: &[&[u8]], @@ -31,7 +33,8 @@ fn fexec_impl( let addrspace_selection_fd = match redox_rt::proc::fexec_impl( exec_file, - open_via_dup, + &RtTcb::current().thread_fd(), + redox_rt::current_proc_fd(), &memory, path, args.iter().rev(), @@ -43,12 +46,10 @@ fn fexec_impl( FexecResult::Normal { addrspace_handle } => addrspace_handle, FexecResult::Interp { image_file, - open_via_dup, path, interp_override: new_interp_override, } => { drop(image_file); - drop(open_via_dup); drop(memory); // According to elf(5), PT_INTERP requires that the interpreter path be @@ -262,7 +263,8 @@ pub fn execve( } } - let this_context_fd = FdGuard::new(syscall::open("/scheme/thisproc/current", 0)?); + let this_thr_fd = RtTcb::current().thread_fd(); + // TODO: Convert image_file to FdGuard earlier? let exec_fd_guard = FdGuard::new(image_file.fd as usize); core::mem::forget(image_file); @@ -272,7 +274,10 @@ pub fn execve( let escalate_fd = FdGuard::new(syscall::open("/scheme/escalate", O_WRONLY)?); // First, send the context handle of this process to escalated. - send_fd_guard(*escalate_fd, this_context_fd)?; + send_fd_guard( + *escalate_fd, + FdGuard::new(syscall::dup(**this_thr_fd, &[])?), + )?; // Then, send the file descriptor containing the file descriptor to be executed. send_fd_guard(*escalate_fd, exec_fd_guard)?; @@ -317,7 +322,6 @@ pub fn execve( }; fexec_impl( exec_fd_guard, - this_context_fd, arg0, &args, &envs, diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index 48986b2539..7afdcafb04 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -272,7 +272,7 @@ impl Pal for Sys { // TODO: Find way to avoid lock. let _guard = CLONE_LOCK.write(); - Ok(clone::fork_impl()? as pid_t) + Ok(clone::fork_impl(&redox_rt::proc::ForkArgs::Managed)? as pid_t) } unsafe fn fstat(fildes: c_int, buf: *mut stat) -> Result<()> { @@ -860,11 +860,19 @@ impl Pal for Sys { } fn setresgid(rgid: gid_t, egid: gid_t, sgid: gid_t) -> Result<()> { - Ok(redox_rt::sys::posix_setresgid(cvt_uid(rgid)?, cvt_uid(egid)?, cvt_uid(sgid)?)?) + Ok(redox_rt::sys::posix_setresgid( + cvt_uid(rgid)?, + cvt_uid(egid)?, + cvt_uid(sgid)?, + )?) } fn setresuid(ruid: uid_t, euid: uid_t, suid: uid_t) -> Result<()> { - Ok(redox_rt::sys::posix_setresuid(cvt_uid(ruid)?, cvt_uid(euid)?, cvt_uid(suid)?)?) + Ok(redox_rt::sys::posix_setresuid( + cvt_uid(ruid)?, + cvt_uid(euid)?, + cvt_uid(suid)?, + )?) } fn symlink(path1: CStr, path2: CStr) -> Result<()> { From ad5efd0f110cf35ffeaa76e867bb71a7f19d18f8 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Fri, 27 Dec 2024 16:32:19 +0100 Subject: [PATCH 06/61] Reach init fork --- redox-rt/src/arch/x86_64.rs | 6 ++--- redox-rt/src/lib.rs | 10 ++------- redox-rt/src/proc.rs | 11 +++++++++- src/ld_so/linker.rs | 5 ++++- src/ld_so/mod.rs | 35 +++++++++++++++++------------ src/ld_so/tcb.rs | 18 ++++++++++++--- src/platform/auxv_defs.rs | 12 +++++----- src/platform/mod.rs | 44 +++++++++++++++++++++++++------------ src/platform/redox/exec.rs | 2 ++ src/pthread/mod.rs | 15 +++++-------- src/start.rs | 13 ++++++++++- 11 files changed, 111 insertions(+), 60 deletions(-) diff --git a/redox-rt/src/arch/x86_64.rs b/redox-rt/src/arch/x86_64.rs index 928fff297d..86a9892568 100644 --- a/redox-rt/src/arch/x86_64.rs +++ b/redox-rt/src/arch/x86_64.rs @@ -95,7 +95,7 @@ pub fn copy_env_regs(cur_pid_fd: usize, new_pid_fd: usize) -> Result<()> { Ok(()) } -unsafe extern "sysv64" fn fork_impl(initial_rsp: *mut usize, args: &ForkArgs) -> usize { +unsafe extern "sysv64" fn fork_impl(args: &ForkArgs, initial_rsp: *mut usize) -> usize { Error::mux(fork_inner(initial_rsp, args)) } @@ -131,8 +131,8 @@ asmfunction!(__relibc_internal_fork_wrapper (usize) -> usize: [" stmxcsr [rsp+32] fnstcw [rsp+40] - mov rdi, rsp - // rsi: &ForkArgs + // rdi: &ForkArgs + mov rsi, rsp call {fork_impl} add rsp, 96 diff --git a/redox-rt/src/lib.rs b/redox-rt/src/lib.rs index 02e8d690b4..3ee2ec1d1b 100644 --- a/redox-rt/src/lib.rs +++ b/redox-rt/src/lib.rs @@ -183,15 +183,9 @@ pub(crate) fn read_proc_meta(proc: &FdGuard) -> syscall::Result { let _ = syscall::read(**proc, &mut bytes)?; Ok(*plain::from_bytes::(&bytes).unwrap()) } -pub unsafe fn initialize( - #[cfg(feature = "proc")] proc_fd: FdGuard, - #[cfg(feature = "proc")] thr_fd: FdGuard, -) { +pub unsafe fn initialize(#[cfg(feature = "proc")] proc_fd: FdGuard) { #[cfg(feature = "proc")] - let metadata = { - RtTcb::current().thr_fd.get().write(Some(thr_fd)); - read_proc_meta(&proc_fd).unwrap() - }; + let metadata = read_proc_meta(&proc_fd).unwrap(); #[cfg(not(feature = "proc"))] // Bootstrap mode, don't associate proc fds with PIDs diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index 0cf57f1b67..84a50d6fae 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -55,6 +55,10 @@ pub struct ExtraInfo<'a> { pub sigprocmask: u64, /// File mode creation mask (POSIX) pub umask: u32, + /// Thread handle + pub thr_fd: usize, + /// Process handle + pub proc_fd: usize, } pub fn fexec_impl( @@ -373,7 +377,12 @@ where push(AT_REDOX_INHERITED_SIGPROCMASK)?; push(extrainfo.umask as usize)?; - push(AT_REDOX_UMASK); + push(AT_REDOX_UMASK)?; + + push(extrainfo.thr_fd as usize)?; + push(AT_REDOX_THR_FD)?; + push(extrainfo.proc_fd as usize)?; + push(AT_REDOX_PROC_FD)?; push(0)?; diff --git a/src/ld_so/linker.rs b/src/ld_so/linker.rs index bf1df86639..a1a429090d 100644 --- a/src/ld_so/linker.rs +++ b/src/ld_so/linker.rs @@ -692,7 +692,10 @@ impl Linker { tcb.append_masters(tcb_masters); // Copy the master data into the static TLS block. tcb.copy_masters().map_err(|_| DlError::Malformed)?; - tcb.activate(); + tcb.activate( + #[cfg(target_os = "redox")] + todo!(), + ); #[cfg(target_os = "redox")] { diff --git a/src/ld_so/mod.rs b/src/ld_so/mod.rs index eb3bb8c369..d3d726df5d 100644 --- a/src/ld_so/mod.rs +++ b/src/ld_so/mod.rs @@ -41,7 +41,10 @@ static mut STATIC_TCB_MASTER: Master = Master { }; #[inline(never)] -pub fn static_init(sp: &'static Stack) { +pub fn static_init( + sp: &'static Stack, + #[cfg(target_os = "redox")] thr_fd: redox_rt::proc::FdGuard, +) { const SIZEOF_PHDR64: usize = mem::size_of::>(); const SIZEOF_PHDR32: usize = mem::size_of::>(); @@ -120,7 +123,10 @@ pub fn static_init(sp: &'static Stack) { tcb.masters_len = mem::size_of::(); tcb.copy_masters() .expect_notls("failed to copy TLS master data"); - tcb.activate(); + tcb.activate( + #[cfg(target_os = "redox")] + thr_fd, + ); } //TODO: Warning on multiple TLS sections? @@ -130,7 +136,10 @@ pub fn static_init(sp: &'static Stack) { } #[cfg(any(target_os = "linux", target_os = "redox"))] -pub unsafe fn init(sp: &'static Stack) { +pub unsafe fn init( + sp: &'static Stack, + #[cfg(target_os = "redox")] thr_fd: redox_rt::proc::FdGuard, +) { let tp: usize; #[cfg(target_os = "linux")] @@ -151,11 +160,8 @@ pub unsafe fn init(sp: &'static Stack) { { let mut env = syscall::EnvRegisters::default(); - let file = syscall::open( - "/scheme/thisproc/current/regs/env", - syscall::O_CLOEXEC | syscall::O_RDONLY, - ) - .expect_notls("failed to open handle for process registers"); + let file = syscall::dup(*thr_fd, b"regs/env") + .expect_notls("failed to open handle for process registers"); let _ = syscall::read(file, &mut env).expect_notls("failed to read gsbase"); @@ -167,11 +173,8 @@ pub unsafe fn init(sp: &'static Stack) { { let mut env = syscall::EnvRegisters::default(); - let file = syscall::open( - "/scheme/thisproc/current/regs/env", - syscall::O_CLOEXEC | syscall::O_RDONLY, - ) - .expect_notls("failed to open handle for process registers"); + let file = syscall::dup(*thr_fd, b"regs/env") + .expect_notls("failed to open handle for process registers"); let _ = syscall::read(file, &mut env).expect_notls("failed to read fsbase"); @@ -188,7 +191,11 @@ pub unsafe fn init(sp: &'static Stack) { } if tp == 0 { - static_init(sp); + static_init( + sp, + #[cfg(target_os = "redox")] + thr_fd, + ); } } diff --git a/src/ld_so/tcb.rs b/src/ld_so/tcb.rs index 66fa39fb61..1191b7c1b3 100644 --- a/src/ld_so/tcb.rs +++ b/src/ld_so/tcb.rs @@ -202,8 +202,14 @@ impl Tcb { } /// Activate TLS - pub unsafe fn activate(&mut self) { - Self::os_arch_activate(&self.os_specific, self.tls_end as usize, self.tls_len); + pub unsafe fn activate(&mut self, #[cfg(target_os = "redox")] thr_fd: redox_rt::proc::FdGuard) { + Self::os_arch_activate( + &self.os_specific, + self.tls_end as usize, + self.tls_len, + #[cfg(target_os = "redox")] + thr_fd, + ); } pub fn setup_dtv(&mut self, n: usize) { @@ -327,7 +333,13 @@ impl Tcb { } #[cfg(target_os = "redox")] - unsafe fn os_arch_activate(os: &OsSpecific, tls_end: usize, tls_len: usize) { + unsafe fn os_arch_activate( + os: &OsSpecific, + tls_end: usize, + tls_len: usize, + thr_fd: redox_rt::proc::FdGuard, + ) { + os.thr_fd.get().write(Some(thr_fd)); redox_rt::tcb_activate(os, tls_end, tls_len) } } diff --git a/src/platform/auxv_defs.rs b/src/platform/auxv_defs.rs index 7b817dc517..5f6dad136b 100644 --- a/src/platform/auxv_defs.rs +++ b/src/platform/auxv_defs.rs @@ -49,11 +49,11 @@ pub const AT_REDOX_INITIAL_DEFAULT_SCHEME_PTR: usize = 38; #[cfg(target_os = "redox")] pub const AT_REDOX_INITIAL_DEFAULT_SCHEME_LEN: usize = 39; -#[cfg(target_os = "redox")] -pub const AT_REDOX_PROC_FD: usize = 39; - -#[cfg(target_os = "redox")] -pub const AT_REDOX_THR_FD: usize = 39; - #[cfg(target_os = "redox")] pub const AT_REDOX_UMASK: usize = 40; + +#[cfg(target_os = "redox")] +pub const AT_REDOX_PROC_FD: usize = 41; + +#[cfg(target_os = "redox")] +pub const AT_REDOX_THR_FD: usize = 42; diff --git a/src/platform/mod.rs b/src/platform/mod.rs index b1d08dd2e6..016f4eec36 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -280,21 +280,40 @@ impl Write for CountingWriter { // get_auxv. #[cold] -pub unsafe fn get_auxvs(mut ptr: *const usize) -> Box<[[usize; 2]]> { - //traverse the stack and collect argument environment variables - let mut auxvs = Vec::new(); +unsafe fn auxv_iter<'a>(ptr: *const usize) -> impl Iterator + 'a { + struct St(*const usize); + impl Iterator for St { + type Item = [usize; 2]; - while *ptr != self::auxv_defs::AT_NULL { - let kind = ptr.read(); - ptr = ptr.add(1); - let value = ptr.read(); - ptr = ptr.add(1); - auxvs.push([kind, value]); + fn next(&mut self) -> Option { + unsafe { + if self.0.read() == self::auxv_defs::AT_NULL { + return None; + } + let kind = self.0.read(); + let value = self.0.add(1).read(); + self.0 = self.0.add(2); + + Some([kind, value]) + } + } } + St(ptr) +} + +#[cold] +pub unsafe fn get_auxvs(ptr: *const usize) -> Box<[[usize; 2]]> { + //traverse the stack and collect argument environment variables + let mut auxvs = auxv_iter(ptr).collect::>(); auxvs.sort_unstable_by_key(|[kind, _]| *kind); auxvs.into_boxed_slice() } +// TODO: Find an auxv replacement for Redox's execv protocol +#[cold] +pub unsafe fn get_auxv_raw(ptr: *const usize, requested_kind: usize) -> Option { + auxv_iter(ptr).find_map(|[kind, value]| Some(value).filter(|_| kind == requested_kind)) +} pub fn get_auxv(auxvs: &[[usize; 2]], key: usize) -> Option { auxvs .binary_search_by_key(&key, |[entry_key, _]| *entry_key) @@ -311,13 +330,10 @@ pub unsafe fn init(auxvs: Box<[[usize; 2]]>) { use redox_rt::proc::FdGuard; use syscall::MODE_PERM; - let (Some(thr_fd), Some(proc_fd)) = ( - get_auxv(&auxvs, AT_REDOX_THR_FD), - get_auxv(&auxvs, AT_REDOX_PROC_FD), - ) else { + let Some(proc_fd) = get_auxv(&auxvs, AT_REDOX_PROC_FD) else { panic!("Missing proc and thread fd!"); }; - redox_rt::initialize(FdGuard::new(proc_fd), FdGuard::new(thr_fd)); + redox_rt::initialize(FdGuard::new(proc_fd)); if let (Some(cwd_ptr), Some(cwd_len)) = ( get_auxv(&auxvs, AT_REDOX_INITIAL_CWD_PTR), diff --git a/src/platform/redox/exec.rs b/src/platform/redox/exec.rs index be047a25bf..4d8cc1a97e 100644 --- a/src/platform/redox/exec.rs +++ b/src/platform/redox/exec.rs @@ -319,6 +319,8 @@ pub fn execve( sigignmask: 0, sigprocmask, umask: redox_rt::sys::get_umask(), + thr_fd: **RtTcb::current().thread_fd(), + proc_fd: **redox_rt::current_proc_fd(), }; fexec_impl( exec_fd_guard, diff --git a/src/pthread/mod.rs b/src/pthread/mod.rs index d7b97fe1de..b41a19d5cc 100644 --- a/src/pthread/mod.rs +++ b/src/pthread/mod.rs @@ -210,19 +210,16 @@ unsafe extern "C" fn new_thread_shim( mutex1: *const Mutex>, mutex2: *const Mutex, ) -> ! { + let tid = (*(&*mutex1).lock()).assume_init(); + if let Some(tcb) = tcb.as_mut() { - tcb.activate(); + tcb.activate( + #[cfg(target_os = "redox")] + redox_rt::proc::FdGuard::new(tid.thread_fd), + ); } let procmask = (&*mutex2).as_ptr().read(); - let tid = (*(&*mutex1).lock()).assume_init(); - - #[cfg(target_os = "redox")] - (*tcb) - .os_specific - .thr_fd - .get() - .write(Some(redox_rt::proc::FdGuard::new(tid.thread_fd))); if let Some(tcb) = tcb.as_mut() { tcb.copy_masters().unwrap(); diff --git a/src/start.rs b/src/start.rs index 3d56738632..faca8b65ec 100644 --- a/src/start.rs +++ b/src/start.rs @@ -2,6 +2,7 @@ use alloc::{boxed::Box, vec::Vec}; use core::{intrinsics, ptr}; +use generic_rt::ExpectTlsFree; use crate::{ header::{libgen, stdio, stdlib}, @@ -141,8 +142,18 @@ pub unsafe extern "C" fn relibc_start(sp: &'static Stack) -> ! { // Ensure correct host system before executing more system calls relibc_verify_host(); + #[cfg(target_os = "redox")] + let thr_fd = redox_rt::proc::FdGuard::new( + crate::platform::get_auxv_raw(sp.auxv().cast(), redox_rt::auxv_defs::AT_REDOX_THR_FD) + .expect_notls("no thread fd present"), + ); + // Initialize TLS, if necessary - ld_so::init(sp); + ld_so::init( + sp, + #[cfg(target_os = "redox")] + thr_fd, + ); // Set up the right allocator... // if any memory rust based memory allocation happen before this step .. we are doomed. From 1cd450a9ae50afa044aa584037a7fe1869e4767a Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Fri, 27 Dec 2024 16:41:15 +0100 Subject: [PATCH 07/61] Implement get{r,e}{u,g}id. --- redox-rt/src/sys.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs index 13978efd82..ef06097190 100644 --- a/redox-rt/src/sys.rs +++ b/redox-rt/src/sys.rs @@ -8,7 +8,10 @@ use syscall::{ RtSigInfo, TimeSpec, }; -use crate::{arch::manually_enter_trampoline, proc::FdGuard, signal::tmp_disable_signals, Tcb}; +use crate::{ + arch::manually_enter_trampoline, proc::FdGuard, signal::tmp_disable_signals, Tcb, + DYNAMIC_PROC_INFO, +}; #[inline] fn wrapper(restart: bool, mut f: impl FnMut() -> Result) -> Result { @@ -152,16 +155,16 @@ pub fn posix_setresgid(rgid: Option, egid: Option, sgid: Option) todo!("posix_setresgid") } pub fn posix_getruid() -> u32 { - todo!("posix_getruid") + DYNAMIC_PROC_INFO.lock().ruid } pub fn posix_getrgid() -> u32 { - todo!("posix_getrgid") + DYNAMIC_PROC_INFO.lock().rgid } pub fn posix_geteuid() -> u32 { - todo!("posix_geteuid") + DYNAMIC_PROC_INFO.lock().euid } pub fn posix_getegid() -> u32 { - todo!("posix_getegid") + DYNAMIC_PROC_INFO.lock().egid } pub fn posix_exit(status: i32) -> ! { todo!("posix_exit") From bd68da3df91553b093a2770c491581f3be7bb1c4 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Fri, 27 Dec 2024 16:46:03 +0100 Subject: [PATCH 08/61] Fix relibc exec thisproc usage. --- src/platform/redox/exec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/redox/exec.rs b/src/platform/redox/exec.rs index 4d8cc1a97e..660a67332e 100644 --- a/src/platform/redox/exec.rs +++ b/src/platform/redox/exec.rs @@ -244,7 +244,7 @@ pub fn execve( // threads, it could still be allowed by keeping certain file descriptors and instead // set the active file table. let files_fd = - File::new(syscall::open("/scheme/thisproc/current/filetable", O_RDONLY)? as c_int); + File::new(syscall::dup(**RtTcb::current().thread_fd(), b"filetable")? as c_int); for line in BufReader::new(files_fd).lines() { let line = match line { Ok(l) => l, From 0c1835a5452a2b65c322df0b3eea7ece9926f435 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Fri, 27 Dec 2024 18:20:08 +0100 Subject: [PATCH 09/61] Implement waitpid using new SYS_CALL. --- redox-rt/src/protocol.rs | 15 +++++++++++++++ redox-rt/src/sys.rs | 24 ++++++++++++++---------- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/redox-rt/src/protocol.rs b/redox-rt/src/protocol.rs index 74ba35fc49..05672aa3b8 100644 --- a/redox-rt/src/protocol.rs +++ b/redox-rt/src/protocol.rs @@ -11,3 +11,18 @@ pub struct ProcMeta { pub rns: u32, } unsafe impl plain::Plain for ProcMeta {} + +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[repr(usize)] +pub enum ProcCall { + Waitpid = 0, +} + +impl ProcCall { + pub fn try_from_raw(raw: usize) -> Option { + Some(match raw { + 0 => Self::Waitpid, + _ => return None, + }) + } +} diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs index ef06097190..e2355f04de 100644 --- a/redox-rt/src/sys.rs +++ b/redox-rt/src/sys.rs @@ -1,16 +1,17 @@ use core::{ + mem::size_of, ptr::addr_of, sync::atomic::{AtomicU32, Ordering}, }; use syscall::{ error::{Error, Result, EINTR}, - RtSigInfo, TimeSpec, + CallFlags, RtSigInfo, TimeSpec, }; use crate::{ - arch::manually_enter_trampoline, proc::FdGuard, signal::tmp_disable_signals, Tcb, - DYNAMIC_PROC_INFO, + arch::manually_enter_trampoline, proc::FdGuard, protocol::ProcCall, + signal::tmp_disable_signals, Tcb, DYNAMIC_PROC_INFO, }; #[inline] @@ -114,13 +115,16 @@ pub unsafe fn sys_futex_wake(addr: *mut u32, num: u32) -> Result { .map(|awoken| awoken as u32) } pub fn sys_waitpid(pid: usize, status: &mut usize, flags: usize) -> Result { - wrapper(true, || { - /*syscall::waitpid( - pid, - status, - syscall::WaitFlags::from_bits(flags).expect("waitpid: invalid bit pattern"), - )*/ - todo!("waitpid") + wrapper(true, || unsafe { + let metadata = [ProcCall::Waitpid as usize, pid, flags]; + syscall::syscall5( + syscall::SYS_CALL, + **crate::current_proc_fd(), + status as *mut usize as usize, + size_of::(), + metadata.len() | CallFlags::empty().bits(), + metadata.as_ptr() as usize, + ) }) } pub fn posix_kill_thread(thread_fd: usize, signal: u32) -> Result<()> { From 4138b681177bb0dc3771d0852b415782e9cfc7d7 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Fri, 27 Dec 2024 21:22:01 +0100 Subject: [PATCH 10/61] Implement setrens and waitpid using procmgr. --- redox-rt/src/lib.rs | 3 +-- redox-rt/src/protocol.rs | 2 ++ redox-rt/src/sys.rs | 29 +++++++++++++++++++++-------- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/redox-rt/src/lib.rs b/redox-rt/src/lib.rs index 3ee2ec1d1b..63eb549487 100644 --- a/redox-rt/src/lib.rs +++ b/redox-rt/src/lib.rs @@ -245,12 +245,11 @@ pub(crate) fn static_proc_info() -> &'static StaticProcInfo { unsafe { &*STATIC_PROC_INFO.get() } } #[inline] -#[cfg(feature = "proc")] pub fn current_proc_fd() -> &'static FdGuard { static_proc_info() .proc_fd .as_ref() - .expect("must be present with proc feature") + .expect("proc fd must be present") } struct ChildHookCommonArgs { diff --git a/redox-rt/src/protocol.rs b/redox-rt/src/protocol.rs index 05672aa3b8..20ac56a8ec 100644 --- a/redox-rt/src/protocol.rs +++ b/redox-rt/src/protocol.rs @@ -16,12 +16,14 @@ unsafe impl plain::Plain for ProcMeta {} #[repr(usize)] pub enum ProcCall { Waitpid = 0, + Setrens = 1, } impl ProcCall { pub fn try_from_raw(raw: usize) -> Option { Some(match raw { 0 => Self::Waitpid, + 1 => Self::Setrens, _ => return None, }) } diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs index e2355f04de..61d87bf980 100644 --- a/redox-rt/src/sys.rs +++ b/redox-rt/src/sys.rs @@ -114,17 +114,25 @@ pub unsafe fn sys_futex_wake(addr: *mut u32, num: u32) -> Result { ) .map(|awoken| awoken as u32) } -pub fn sys_waitpid(pid: usize, status: &mut usize, flags: usize) -> Result { - wrapper(true, || unsafe { - let metadata = [ProcCall::Waitpid as usize, pid, flags]; +fn proc_call(payload: &mut [u8], flags: CallFlags, metadata: &[usize]) -> Result { + unsafe { syscall::syscall5( syscall::SYS_CALL, **crate::current_proc_fd(), - status as *mut usize as usize, - size_of::(), - metadata.len() | CallFlags::empty().bits(), + payload.as_mut_ptr() as usize, + payload.len(), + metadata.len() | flags.bits(), metadata.as_ptr() as usize, ) + } +} +pub fn sys_waitpid(pid: usize, status: &mut usize, flags: usize) -> Result { + wrapper(true, || { + proc_call( + unsafe { plain::as_mut_bytes(status) }, + CallFlags::empty(), + &[ProcCall::Waitpid as usize, pid, flags], + ) }) } pub fn posix_kill_thread(thread_fd: usize, signal: u32) -> Result<()> { @@ -171,10 +179,15 @@ pub fn posix_getegid() -> u32 { DYNAMIC_PROC_INFO.lock().egid } pub fn posix_exit(status: i32) -> ! { - todo!("posix_exit") + todo!() } pub fn setrens(rns: usize, ens: usize) -> Result<()> { - todo!("setrens") + proc_call( + &mut [], + CallFlags::empty(), + &[ProcCall::Setrens as usize, rns, ens], + )?; + Ok(()) } pub fn posix_getpgid(pid: usize) -> Result { todo!("posix_getpgid") From 9566a00ad1884d7bd8e50c29e336a81d142591c3 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sun, 19 Jan 2025 14:56:17 +0100 Subject: [PATCH 11/61] WIP: waitpid and exit IPC calls. --- redox-rt/src/lib.rs | 17 +++++++---- redox-rt/src/protocol.rs | 54 ++++++++++++++++++++++++++++++++++ redox-rt/src/sys.rs | 46 +++++++++++++++++++++++++---- src/platform/redox/libredox.rs | 11 ++++--- src/platform/redox/mod.rs | 30 +++++++++++-------- 5 files changed, 131 insertions(+), 27 deletions(-) diff --git a/redox-rt/src/lib.rs b/redox-rt/src/lib.rs index 63eb549487..985ca1db8d 100644 --- a/redox-rt/src/lib.rs +++ b/redox-rt/src/lib.rs @@ -270,11 +270,16 @@ unsafe fn child_hook_common(args: ChildHookCommonArgs) { #[cfg(not(feature = "proc"))] let metadata = ProcMeta::default(); - STATIC_PROC_INFO.get().write(StaticProcInfo { - pid: metadata.pid, - ppid: metadata.ppid, - proc_fd: args.new_proc_fd, - }); + let old_proc_fd = STATIC_PROC_INFO + .get() + .replace(StaticProcInfo { + pid: metadata.pid, + ppid: metadata.ppid, + proc_fd: args.new_proc_fd, + }) + .proc_fd; + drop(old_proc_fd); - RtTcb::current().thr_fd.get().write(Some(args.new_thr_fd)); + let old_thr_fd = RtTcb::current().thr_fd.get().replace(Some(args.new_thr_fd)); + drop(old_thr_fd); } diff --git a/redox-rt/src/protocol.rs b/redox-rt/src/protocol.rs index 20ac56a8ec..e636679021 100644 --- a/redox-rt/src/protocol.rs +++ b/redox-rt/src/protocol.rs @@ -1,3 +1,5 @@ +use bitflags::bitflags; + #[derive(Clone, Copy, Debug, Default)] pub struct ProcMeta { pub pid: u32, @@ -17,6 +19,8 @@ unsafe impl plain::Plain for ProcMeta {} pub enum ProcCall { Waitpid = 0, Setrens = 1, + Exit = 2, + Waitpgid = 3, } impl ProcCall { @@ -24,7 +28,57 @@ impl ProcCall { Some(match raw { 0 => Self::Waitpid, 1 => Self::Setrens, + 2 => Self::Exit, + 3 => Self::Waitpgid, _ => return None, }) } } + +bitflags! { + #[derive(Clone, Copy, Debug, Default, Eq, Ord, Hash, PartialEq, PartialOrd)] + pub struct WaitFlags: usize { + const WNOHANG = 0x01; + const WUNTRACED = 0x02; + const WCONTINUED = 0x08; + } +} +/// True if status indicates the child is stopped. +pub fn wifstopped(status: usize) -> bool { + (status & 0xff) == 0x7f +} + +/// If wifstopped(status), the signal that stopped the child. +pub fn wstopsig(status: usize) -> usize { + (status >> 8) & 0xff +} + +/// True if status indicates the child continued after a stop. +pub fn wifcontinued(status: usize) -> bool { + status == 0xffff +} + +/// True if STATUS indicates termination by a signal. +pub fn wifsignaled(status: usize) -> bool { + ((status & 0x7f) + 1) as i8 >= 2 +} + +/// If wifsignaled(status), the terminating signal. +pub fn wtermsig(status: usize) -> usize { + status & 0x7f +} + +/// True if status indicates normal termination. +pub fn wifexited(status: usize) -> bool { + wtermsig(status) == 0 +} + +/// If wifexited(status), the exit status. +pub fn wexitstatus(status: usize) -> usize { + (status >> 8) & 0xff +} + +/// True if status indicates a core dump was created. +pub fn wcoredump(status: usize) -> bool { + (status & 0x80) != 0 +} diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs index 61d87bf980..86645d061b 100644 --- a/redox-rt/src/sys.rs +++ b/redox-rt/src/sys.rs @@ -10,8 +10,11 @@ use syscall::{ }; use crate::{ - arch::manually_enter_trampoline, proc::FdGuard, protocol::ProcCall, - signal::tmp_disable_signals, Tcb, DYNAMIC_PROC_INFO, + arch::manually_enter_trampoline, + proc::FdGuard, + protocol::{ProcCall, WaitFlags}, + signal::tmp_disable_signals, + Tcb, DYNAMIC_PROC_INFO, }; #[inline] @@ -126,12 +129,39 @@ fn proc_call(payload: &mut [u8], flags: CallFlags, metadata: &[usize]) -> Result ) } } -pub fn sys_waitpid(pid: usize, status: &mut usize, flags: usize) -> Result { + +#[derive(Clone, Copy, Debug)] +pub enum WaitpidTarget { + AnyChild, + AnyGroupMember, + SingleProc { pid: usize }, + ProcGroup { pgid: usize }, +} +impl WaitpidTarget { + pub fn from_posix_arg(raw: isize) -> Self { + match raw { + 0 => Self::AnyGroupMember, + -1 => Self::AnyChild, + 1.. => Self::SingleProc { pid: raw as usize }, + ..-1 => Self::ProcGroup { + pgid: -raw as usize, + }, + } + } +} + +pub fn sys_waitpid(target: WaitpidTarget, status: &mut usize, flags: WaitFlags) -> Result { + let (call, pid) = match target { + WaitpidTarget::AnyChild => (ProcCall::Waitpid, 0), + WaitpidTarget::SingleProc { pid } => (ProcCall::Waitpid, pid), + WaitpidTarget::AnyGroupMember => (ProcCall::Waitpgid, 0), + WaitpidTarget::ProcGroup { pgid } => (ProcCall::Waitpgid, pgid), + }; wrapper(true, || { proc_call( unsafe { plain::as_mut_bytes(status) }, CallFlags::empty(), - &[ProcCall::Waitpid as usize, pid, flags], + &[call as usize, pid, flags.bits() as usize], ) }) } @@ -179,7 +209,13 @@ pub fn posix_getegid() -> u32 { DYNAMIC_PROC_INFO.lock().egid } pub fn posix_exit(status: i32) -> ! { - todo!() + proc_call( + &mut [], + CallFlags::empty(), + &[ProcCall::Exit as usize, status as usize], + ) + .expect("failed to call proc mgr with Exit"); + unreachable!() } pub fn setrens(rns: usize, ens: usize) -> Result<()> { proc_call( diff --git a/src/platform/redox/libredox.rs b/src/platform/redox/libredox.rs index 62506a4b08..d3f8fbc4fc 100644 --- a/src/platform/redox/libredox.rs +++ b/src/platform/redox/libredox.rs @@ -1,7 +1,10 @@ use core::{slice, str}; -use redox_rt::sys::{posix_read, posix_write}; -use syscall::{Error, Result, WaitFlags, EMFILE}; +use redox_rt::{ + protocol::WaitFlags, + sys::{posix_read, posix_write, WaitpidTarget}, +}; +use syscall::{Error, Result, EMFILE}; use crate::{ header::{ @@ -246,9 +249,9 @@ pub unsafe extern "C" fn redox_setrens_v1(rns: usize, ens: usize) -> RawResult { pub unsafe extern "C" fn redox_waitpid_v1(pid: usize, status: *mut i32, options: u32) -> RawResult { let mut sts = 0_usize; let res = Error::mux(redox_rt::sys::sys_waitpid( - pid, + WaitpidTarget::from_posix_arg(pid as isize), &mut sts, - WaitFlags::from_bits_truncate(options as usize).bits(), + WaitFlags::from_bits_truncate(options as usize), )); status.write(sts as i32); res diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index 7afdcafb04..05882754bf 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -3,7 +3,11 @@ use core::{ mem::{self, size_of}, ptr, slice, str, }; -use redox_rt::RtTcb; +use redox_rt::{ + protocol::{wifstopped, wstopsig, WaitFlags}, + sys::WaitpidTarget, + RtTcb, +}; use syscall::{ self, data::{Map, Stat as redox_stat, StatVfs as redox_statvfs, TimeSpec as redox_timespec}, @@ -977,14 +981,16 @@ impl Pal for Sys { } unsafe fn waitpid(mut pid: pid_t, stat_loc: *mut c_int, options: c_int) -> Result { - if pid == !0 { - pid = 0; - } let mut res = None; let mut status = 0; + let options = usize::try_from(options) + .ok() + .and_then(WaitFlags::from_bits) + .ok_or(Errno(EINVAL))?; + let inner = |status: &mut usize, flags| { - redox_rt::sys::sys_waitpid(pid as usize, status, flags as usize) + redox_rt::sys::sys_waitpid(WaitpidTarget::from_posix_arg(pid as isize), status, flags) }; // First, allow ptrace to handle waitpid @@ -992,19 +998,19 @@ impl Pal for Sys { let state = ptrace::init_state(); let mut sessions = state.sessions.lock(); if let Ok(session) = ptrace::get_session(&mut sessions, pid) { - if options & sys_wait::WNOHANG != sys_wait::WNOHANG { + if !options.contains(WaitFlags::WNOHANG) { let mut _event = PtraceEvent::default(); let _ = (&mut &session.tracer).read(&mut _event); res = Some(inner( &mut status, - options | sys_wait::WNOHANG | sys_wait::WUNTRACED, + options | WaitFlags::WNOHANG | WaitFlags::WUNTRACED, )); if res == Some(Ok(0)) { // WNOHANG, just pretend ptrace SIGSTOP:ped this status = (syscall::SIGSTOP << 8) | 0x7f; - assert!(syscall::wifstopped(status)); - assert_eq!(syscall::wstopsig(status), syscall::SIGSTOP); + assert!(wifstopped(status)); + assert_eq!(wstopsig(status), syscall::SIGSTOP); res = Some(Ok(pid as usize)); } } @@ -1015,11 +1021,11 @@ impl Pal for Sys { // it if (and only if) a ptrace traceme was activated during // the wait. let res = res.unwrap_or_else(|| loop { - let res = inner(&mut status, options | sys_wait::WUNTRACED); + let res = inner(&mut status, options | WaitFlags::WUNTRACED); // TODO: Also handle special PIDs here - if !syscall::wifstopped(status) - || options & sys_wait::WUNTRACED != 0 + if !wifstopped(status) + || options.contains(WaitFlags::WUNTRACED) || ptrace::is_traceme(pid) { break res; From 779c1e60c5e74ff30fbfbd1e7331dc0e17e9c50c Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sun, 16 Feb 2025 19:13:09 +0100 Subject: [PATCH 12/61] Add todo!() to fix compilation. --- src/ld_so/start.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ld_so/start.rs b/src/ld_so/start.rs index 5f40a6ef4e..4c09f52f34 100644 --- a/src/ld_so/start.rs +++ b/src/ld_so/start.rs @@ -151,7 +151,7 @@ pub extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: usize) -> // Setup TCB for ourselves. unsafe { let tcb = Tcb::new(0).expect_notls("ld.so: failed to allocate bootstrap TCB"); - tcb.activate(); + tcb.activate(todo!()); #[cfg(target_os = "redox")] redox_rt::signal::setup_sighandler(&tcb.os_specific); From 48df8f5bba4903b76cc3a653a88e20ea2e761df5 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Fri, 7 Mar 2025 23:51:45 +0100 Subject: [PATCH 13/61] Add unstable interface for getting current thread fd. --- redox-rt/src/thread.rs | 15 ++++++++------- src/platform/redox/libredox.rs | 6 ++++++ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/redox-rt/src/thread.rs b/redox-rt/src/thread.rs index 84e8978875..5d0c258e7d 100644 --- a/redox-rt/src/thread.rs +++ b/redox-rt/src/thread.rs @@ -1,17 +1,18 @@ use core::mem::size_of; -use syscall::{Result, O_CLOEXEC}; +use syscall::{Error, Result, ESRCH, O_CLOEXEC}; -use crate::{arch::*, proc::*, signal::tmp_disable_signals, RtTcb}; +use crate::{arch::*, proc::*, signal::tmp_disable_signals, static_proc_info, RtTcb}; /// Spawns a new context sharing the same address space as the current one (i.e. a new thread). pub unsafe fn rlct_clone_impl(stack: *mut usize) -> Result { - // FIXME + let cur_proc_fd = static_proc_info() + .proc_fd + .as_ref() + .ok_or(Error::new(ESRCH))?; + let cur_thr_fd = RtTcb::current().thread_fd(); - let new_thr_fd = FdGuard::new(syscall::open( - "/scheme/thisproc/new-thread/open_via_dup", - O_CLOEXEC, - )?); + let new_thr_fd = FdGuard::new(syscall::dup(**cur_proc_fd, b"new-thread")?); copy_str(**cur_thr_fd, *new_thr_fd, "name")?; diff --git a/src/platform/redox/libredox.rs b/src/platform/redox/libredox.rs index d3f8fbc4fc..2324e38afd 100644 --- a/src/platform/redox/libredox.rs +++ b/src/platform/redox/libredox.rs @@ -363,3 +363,9 @@ pub unsafe extern "C" fn redox_mkns_v1( syscall::mkns(core::slice::from_raw_parts(names.cast(), num_names)) })()) } + +// ABI-UNSTABLE +#[no_mangle] +pub unsafe extern "C" fn redox_cur_thrfd_v0() -> usize { + **redox_rt::RtTcb::current().thread_fd() +} From f4a64cfbc39605a3fe395430faaffd2b585dc171 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sat, 29 Mar 2025 12:32:38 +0100 Subject: [PATCH 14/61] Add setresguid. --- redox-rt/src/protocol.rs | 1 + redox-rt/src/sys.rs | 55 +++++++++++++++++++++++++++++++++++---- src/platform/redox/mod.rs | 10 +++++-- 3 files changed, 59 insertions(+), 7 deletions(-) diff --git a/redox-rt/src/protocol.rs b/redox-rt/src/protocol.rs index e636679021..7ea959b702 100644 --- a/redox-rt/src/protocol.rs +++ b/redox-rt/src/protocol.rs @@ -21,6 +21,7 @@ pub enum ProcCall { Setrens = 1, Exit = 2, Waitpgid = 3, + SetResugid = 4, } impl ProcCall { diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs index 86645d061b..8ac95c9288 100644 --- a/redox-rt/src/sys.rs +++ b/redox-rt/src/sys.rs @@ -190,22 +190,67 @@ pub fn get_umask() -> u32 { UMASK.load(Ordering::Acquire) } -pub fn posix_setresuid(ruid: Option, euid: Option, suid: Option) -> Result<()> { - todo!("posix_setresuid") -} -pub fn posix_setresgid(rgid: Option, egid: Option, sgid: Option) -> Result<()> { - todo!("posix_setresgid") +pub fn posix_setresugid( + ruid: Option, + euid: Option, + suid: Option, + rgid: Option, + egid: Option, + sgid: Option, +) -> Result<()> { + // TODO: not sure how "tmp" an IPC call is? + let _sig_guard = tmp_disable_signals(); + let mut guard = DYNAMIC_PROC_INFO.lock(); + + let mut buf = [0_u8; size_of::() * 6]; + plain::slice_from_mut_bytes(&mut buf) + .unwrap() + .copy_from_slice(&[ + ruid.unwrap_or(u32::MAX), + euid.unwrap_or(u32::MAX), + suid.unwrap_or(u32::MAX), + rgid.unwrap_or(u32::MAX), + egid.unwrap_or(u32::MAX), + sgid.unwrap_or(u32::MAX), + ]); + + proc_call( + &mut buf, + CallFlags::empty(), + &[ProcCall::SetResugid as usize], + )?; + + if let Some(ruid) = ruid { + guard.ruid = ruid; + } + if let Some(euid) = euid { + guard.euid = euid; + } + // TODO: suid? + if let Some(rgid) = rgid { + guard.rgid = rgid; + } + if let Some(egid) = egid { + guard.egid = egid; + } + // TODO: sgid? + + Ok(()) } pub fn posix_getruid() -> u32 { + let _guard = tmp_disable_signals(); DYNAMIC_PROC_INFO.lock().ruid } pub fn posix_getrgid() -> u32 { + let _guard = tmp_disable_signals(); DYNAMIC_PROC_INFO.lock().rgid } pub fn posix_geteuid() -> u32 { + let _guard = tmp_disable_signals(); DYNAMIC_PROC_INFO.lock().euid } pub fn posix_getegid() -> u32 { + let _guard = tmp_disable_signals(); DYNAMIC_PROC_INFO.lock().egid } pub fn posix_exit(status: i32) -> ! { diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index 05882754bf..50faa29ce4 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -864,7 +864,10 @@ impl Pal for Sys { } fn setresgid(rgid: gid_t, egid: gid_t, sgid: gid_t) -> Result<()> { - Ok(redox_rt::sys::posix_setresgid( + Ok(redox_rt::sys::posix_setresugid( + None, + None, + None, cvt_uid(rgid)?, cvt_uid(egid)?, cvt_uid(sgid)?, @@ -872,10 +875,13 @@ impl Pal for Sys { } fn setresuid(ruid: uid_t, euid: uid_t, suid: uid_t) -> Result<()> { - Ok(redox_rt::sys::posix_setresuid( + Ok(redox_rt::sys::posix_setresugid( cvt_uid(ruid)?, cvt_uid(euid)?, cvt_uid(suid)?, + None, + None, + None, )?) } From 88848c25fe83172faf4bcefeafc2a1fcf12cdf9d Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sun, 30 Mar 2025 01:13:18 +0100 Subject: [PATCH 15/61] Add (backend todo) proc calls for kill+sigq. --- redox-rt/src/protocol.rs | 36 ++++++++++++++++++++ redox-rt/src/sys.rs | 61 ++++++++++++++++++++++------------ src/platform/redox/libredox.rs | 4 +-- src/platform/redox/mod.rs | 22 +++++------- src/platform/redox/signal.rs | 9 +++-- 5 files changed, 93 insertions(+), 39 deletions(-) diff --git a/redox-rt/src/protocol.rs b/redox-rt/src/protocol.rs index 7ea959b702..69b21ad3f0 100644 --- a/redox-rt/src/protocol.rs +++ b/redox-rt/src/protocol.rs @@ -22,6 +22,11 @@ pub enum ProcCall { Exit = 2, Waitpgid = 3, SetResugid = 4, + Setpgid = 5, + Getsid = 6, + Setsid = 7, + Kill = 8, + Sigq = 9, } impl ProcCall { @@ -31,6 +36,12 @@ impl ProcCall { 1 => Self::Setrens, 2 => Self::Exit, 3 => Self::Waitpgid, + 4 => Self::SetResugid, + 5 => Self::Setpgid, + 6 => Self::Getsid, + 7 => Self::Setsid, + 8 => Self::Kill, + 9 => Self::Sigq, _ => return None, }) } @@ -83,3 +94,28 @@ pub fn wexitstatus(status: usize) -> usize { pub fn wcoredump(status: usize) -> bool { (status & 0x80) != 0 } +#[derive(Clone, Copy, Debug)] +pub enum KillTarget { + SingleProc(usize), + ProcGroup(usize), + All, +} +impl KillTarget { + pub fn raw(self) -> usize { + match self { + Self::SingleProc(p) => p, + Self::ProcGroup(g) => usize::wrapping_neg(g), + Self::All => usize::wrapping_neg(1), + } + } + pub fn from_raw(raw: usize) -> Self { + let raw = raw as isize; + if raw == -1 { + Self::All + } else if raw < 0 { + Self::ProcGroup(raw as usize) + } else { + Self::SingleProc(raw as usize) + } + } +} diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs index 8ac95c9288..fe6fb7cfee 100644 --- a/redox-rt/src/sys.rs +++ b/redox-rt/src/sys.rs @@ -6,13 +6,13 @@ use core::{ use syscall::{ error::{Error, Result, EINTR}, - CallFlags, RtSigInfo, TimeSpec, + CallFlags, RtSigInfo, TimeSpec, EINVAL, }; use crate::{ arch::manually_enter_trampoline, proc::FdGuard, - protocol::{ProcCall, WaitFlags}, + protocol::{KillTarget, ProcCall, WaitFlags}, signal::tmp_disable_signals, Tcb, DYNAMIC_PROC_INFO, }; @@ -49,23 +49,32 @@ pub fn posix_write(fd: usize, buf: &[u8]) -> Result { wrapper(true, || syscall::write(fd, buf)) } #[inline] -pub fn posix_kill(pid: usize, sig: usize) -> Result<()> { - match wrapper(false, || Ok(todo!("kill"))) { +pub fn posix_kill(target: KillTarget, sig: usize) -> Result<()> { + match wrapper(false, || { + proc_call( + &mut [], + CallFlags::empty(), + &[ProcCall::Kill as usize, target.raw(), sig], + ) + }) { Ok(_) | Err(Error { errno: EINTR }) => Ok(()), Err(error) => Err(error), } } #[inline] pub fn posix_sigqueue(pid: usize, sig: usize, arg: usize) -> Result<()> { - let siginf = RtSigInfo { + let mut siginf = RtSigInfo { arg, code: -1, // TODO: SI_QUEUE constant uid: 0, // TODO pid: posix_getpid(), }; - match wrapper(false, || unsafe { - //syscall::syscall3(syscall::SYS_SIGENQUEUE, pid, sig, addr_of!(siginf) as usize) - Ok(todo!("sigenqueue")) + match wrapper(false, || { + proc_call( + &mut siginf, + CallFlags::empty(), + &[ProcCall::Sigq as usize, pid, sig], + ) }) { Ok(_) | Err(Error { errno: EINTR }) => Ok(()), Err(error) => Err(error), @@ -82,16 +91,6 @@ pub fn posix_getppid() -> u32 { unsafe { addr_of!((*crate::STATIC_PROC_INFO.get()).ppid).read() } } #[inline] -pub fn posix_killpg(pgrp: usize, sig: usize) -> Result<()> { - match wrapper(false, || - //syscall::kill(usize::wrapping_neg(pgrp), sig) - Ok(todo!("killpg"))) - { - Ok(_) | Err(Error { errno: EINTR }) => Ok(()), - Err(error) => Err(error), - } -} -#[inline] pub unsafe fn sys_futex_wait(addr: *mut u32, val: u32, deadline: Option<&TimeSpec>) -> Result<()> { wrapper(true, || { syscall::syscall5( @@ -271,11 +270,31 @@ pub fn setrens(rns: usize, ens: usize) -> Result<()> { Ok(()) } pub fn posix_getpgid(pid: usize) -> Result { - todo!("posix_getpgid") + proc_call( + &mut [], + CallFlags::empty(), + &[ProcCall::Setpgid as usize, pid, usize::wrapping_neg(1)], + ) } pub fn posix_setpgid(pid: usize, pgid: usize) -> Result<()> { - todo!("posix_setpgid") + if pgid == usize::wrapping_neg(1) { + return Err(Error::new(EINVAL)); + } + proc_call( + &mut [], + CallFlags::empty(), + &[ProcCall::Setpgid as usize, pid, pgid], + )?; + Ok(()) } pub fn posix_getsid(pid: usize) -> Result { - todo!("posix_getsid") + proc_call( + &mut [], + CallFlags::empty(), + &[ProcCall::Getsid as usize, pid], + ) +} +pub fn posix_setsid() -> Result<()> { + proc_call(&mut [], CallFlags::empty(), &[ProcCall::Setsid as usize])?; + Ok(()) } diff --git a/src/platform/redox/libredox.rs b/src/platform/redox/libredox.rs index 2324e38afd..5ac31de675 100644 --- a/src/platform/redox/libredox.rs +++ b/src/platform/redox/libredox.rs @@ -1,7 +1,7 @@ use core::{slice, str}; use redox_rt::{ - protocol::WaitFlags, + protocol::{KillTarget, WaitFlags}, sys::{posix_read, posix_write, WaitpidTarget}, }; use syscall::{Error, Result, EMFILE}; @@ -259,7 +259,7 @@ pub unsafe extern "C" fn redox_waitpid_v1(pid: usize, status: *mut i32, options: #[no_mangle] pub unsafe extern "C" fn redox_kill_v1(pid: usize, signal: u32) -> RawResult { - Error::mux(redox_rt::sys::posix_kill(pid, signal as usize).map(|()| 0)) + Error::mux(redox_rt::sys::posix_kill(KillTarget::from_raw(pid), signal as usize).map(|()| 0)) } #[no_mangle] diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index 50faa29ce4..c2fee23574 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -839,7 +839,8 @@ impl Pal for Sys { } fn setpgid(pid: pid_t, pgid: pid_t) -> Result<()> { - Ok(redox_rt::sys::posix_setpgid(pid as usize, pgid as usize)?) + redox_rt::sys::posix_setpgid(pid as usize, pgid as usize)?; + Ok(()) } fn setpriority(which: c_int, who: id_t, prio: c_int) -> Result<()> { @@ -852,37 +853,32 @@ impl Pal for Sys { } fn setsid() -> Result<()> { - let session_id = Self::getpid(); - assert!(session_id >= 0); - let mut file = File::open( - c"/scheme/thisproc/current/session_id".into(), - fcntl::O_WRONLY | fcntl::O_CLOEXEC, - )?; - file.write(&usize::to_ne_bytes(session_id.try_into().unwrap())) - .map_err(|err| Errno(err.raw_os_error().unwrap_or(EIO)))?; + redox_rt::sys::posix_setsid()?; Ok(()) } fn setresgid(rgid: gid_t, egid: gid_t, sgid: gid_t) -> Result<()> { - Ok(redox_rt::sys::posix_setresugid( + redox_rt::sys::posix_setresugid( None, None, None, cvt_uid(rgid)?, cvt_uid(egid)?, cvt_uid(sgid)?, - )?) + )?; + Ok(()) } fn setresuid(ruid: uid_t, euid: uid_t, suid: uid_t) -> Result<()> { - Ok(redox_rt::sys::posix_setresugid( + redox_rt::sys::posix_setresugid( cvt_uid(ruid)?, cvt_uid(euid)?, cvt_uid(suid)?, None, None, None, - )?) + )?; + Ok(()) } fn symlink(path1: CStr, path2: CStr) -> Result<()> { diff --git a/src/platform/redox/signal.rs b/src/platform/redox/signal.rs index e4a16c9443..5cee8745e2 100644 --- a/src/platform/redox/signal.rs +++ b/src/platform/redox/signal.rs @@ -18,6 +18,7 @@ use crate::{ use core::mem::{self, offset_of}; use redox_rt::{ proc::FdGuard, + protocol::KillTarget, signal::{ PosixStackt, SigStack, Sigaction, SigactionFlags, SigactionKind, Sigaltstack, SignalHandler, }, @@ -65,7 +66,7 @@ impl PalSignal for Sys { } fn kill(pid: pid_t, sig: c_int) -> Result<()> { - redox_rt::sys::posix_kill(pid as usize, sig as usize)?; + redox_rt::sys::posix_kill(KillTarget::from_raw(pid as usize), sig as usize)?; Ok(()) } fn sigqueue(pid: pid_t, sig: c_int, val: sigval) -> Result<()> { @@ -77,8 +78,10 @@ impl PalSignal for Sys { } fn killpg(pgrp: pid_t, sig: c_int) -> Result<()> { - redox_rt::sys::posix_killpg(pgrp as usize, sig as usize)?; - Ok(()) + if pgrp == 1 { + return Err(Errno(EINVAL)); + } + Self::kill(-pgrp, sig) } fn raise(sig: c_int) -> Result<()> { From 747d11062b02320278618c77029a4ef62f54b51e Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sun, 30 Mar 2025 13:57:11 +0200 Subject: [PATCH 16/61] Rename KillTarget -> ProcKillTarget. --- redox-rt/src/protocol.rs | 4 ++-- redox-rt/src/sys.rs | 4 ++-- src/platform/redox/libredox.rs | 6 ++++-- src/platform/redox/signal.rs | 4 ++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/redox-rt/src/protocol.rs b/redox-rt/src/protocol.rs index 69b21ad3f0..be41985586 100644 --- a/redox-rt/src/protocol.rs +++ b/redox-rt/src/protocol.rs @@ -95,12 +95,12 @@ pub fn wcoredump(status: usize) -> bool { (status & 0x80) != 0 } #[derive(Clone, Copy, Debug)] -pub enum KillTarget { +pub enum ProcKillTarget { SingleProc(usize), ProcGroup(usize), All, } -impl KillTarget { +impl ProcKillTarget { pub fn raw(self) -> usize { match self { Self::SingleProc(p) => p, diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs index fe6fb7cfee..9d8565468e 100644 --- a/redox-rt/src/sys.rs +++ b/redox-rt/src/sys.rs @@ -12,7 +12,7 @@ use syscall::{ use crate::{ arch::manually_enter_trampoline, proc::FdGuard, - protocol::{KillTarget, ProcCall, WaitFlags}, + protocol::{ProcCall, ProcKillTarget, WaitFlags}, signal::tmp_disable_signals, Tcb, DYNAMIC_PROC_INFO, }; @@ -49,7 +49,7 @@ pub fn posix_write(fd: usize, buf: &[u8]) -> Result { wrapper(true, || syscall::write(fd, buf)) } #[inline] -pub fn posix_kill(target: KillTarget, sig: usize) -> Result<()> { +pub fn posix_kill(target: ProcKillTarget, sig: usize) -> Result<()> { match wrapper(false, || { proc_call( &mut [], diff --git a/src/platform/redox/libredox.rs b/src/platform/redox/libredox.rs index 5ac31de675..29efa7caf8 100644 --- a/src/platform/redox/libredox.rs +++ b/src/platform/redox/libredox.rs @@ -1,7 +1,7 @@ use core::{slice, str}; use redox_rt::{ - protocol::{KillTarget, WaitFlags}, + protocol::{ProcKillTarget, WaitFlags}, sys::{posix_read, posix_write, WaitpidTarget}, }; use syscall::{Error, Result, EMFILE}; @@ -259,7 +259,9 @@ pub unsafe extern "C" fn redox_waitpid_v1(pid: usize, status: *mut i32, options: #[no_mangle] pub unsafe extern "C" fn redox_kill_v1(pid: usize, signal: u32) -> RawResult { - Error::mux(redox_rt::sys::posix_kill(KillTarget::from_raw(pid), signal as usize).map(|()| 0)) + Error::mux( + redox_rt::sys::posix_kill(ProcKillTarget::from_raw(pid), signal as usize).map(|()| 0), + ) } #[no_mangle] diff --git a/src/platform/redox/signal.rs b/src/platform/redox/signal.rs index 5cee8745e2..dac99ef3b7 100644 --- a/src/platform/redox/signal.rs +++ b/src/platform/redox/signal.rs @@ -18,7 +18,7 @@ use crate::{ use core::mem::{self, offset_of}; use redox_rt::{ proc::FdGuard, - protocol::KillTarget, + protocol::ProcKillTarget, signal::{ PosixStackt, SigStack, Sigaction, SigactionFlags, SigactionKind, Sigaltstack, SignalHandler, }, @@ -66,7 +66,7 @@ impl PalSignal for Sys { } fn kill(pid: pid_t, sig: c_int) -> Result<()> { - redox_rt::sys::posix_kill(KillTarget::from_raw(pid as usize), sig as usize)?; + redox_rt::sys::posix_kill(ProcKillTarget::from_raw(pid as usize), sig as usize)?; Ok(()) } fn sigqueue(pid: pid_t, sig: c_int, val: sigval) -> Result<()> { From 9999bb6068225d636741ce8828a78002f6524969 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Mon, 31 Mar 2025 11:41:07 +0200 Subject: [PATCH 17/61] Add ThisGroup selector for kill. --- redox-rt/src/protocol.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/redox-rt/src/protocol.rs b/redox-rt/src/protocol.rs index be41985586..25b9323bd8 100644 --- a/redox-rt/src/protocol.rs +++ b/redox-rt/src/protocol.rs @@ -96,6 +96,7 @@ pub fn wcoredump(status: usize) -> bool { } #[derive(Clone, Copy, Debug)] pub enum ProcKillTarget { + ThisGroup, SingleProc(usize), ProcGroup(usize), All, @@ -103,6 +104,7 @@ pub enum ProcKillTarget { impl ProcKillTarget { pub fn raw(self) -> usize { match self { + Self::ThisGroup => 0, Self::SingleProc(p) => p, Self::ProcGroup(g) => usize::wrapping_neg(g), Self::All => usize::wrapping_neg(1), @@ -110,7 +112,9 @@ impl ProcKillTarget { } pub fn from_raw(raw: usize) -> Self { let raw = raw as isize; - if raw == -1 { + if raw == 0 { + Self::ThisGroup + } else if raw == -1 { Self::All } else if raw < 0 { Self::ProcGroup(raw as usize) From 8bd510ff5906c711e9a162f4f26b0ba95fad269d Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Mon, 31 Mar 2025 12:55:43 +0200 Subject: [PATCH 18/61] Simplify [res][ug]id getters and setters. --- redox-rt/src/lib.rs | 16 +++++-- redox-rt/src/proc.rs | 8 ++-- redox-rt/src/protocol.rs | 7 ++- redox-rt/src/sys.rs | 84 +++++++++++++++++++--------------- src/platform/redox/exec.rs | 8 ++-- src/platform/redox/libredox.rs | 8 ++-- src/platform/redox/mod.rs | 49 ++++++++++---------- 7 files changed, 101 insertions(+), 79 deletions(-) diff --git a/redox-rt/src/lib.rs b/redox-rt/src/lib.rs index 985ca1db8d..43cfb811cf 100644 --- a/redox-rt/src/lib.rs +++ b/redox-rt/src/lib.rs @@ -206,25 +206,29 @@ pub unsafe fn initialize(#[cfg(feature = "proc")] proc_fd: FdGuard) { { *DYNAMIC_PROC_INFO.lock() = DynamicProcInfo { pgid: metadata.pgid, - egid: metadata.egid, - euid: metadata.euid, ruid: metadata.ruid, + euid: metadata.euid, + suid: metadata.suid, + egid: metadata.egid, rgid: metadata.rgid, + sgid: metadata.sgid, }; } } pub(crate) struct StaticProcInfo { pid: u32, - ppid: u32, + ppid: u32, // TODO: dynamic proc_fd: Option, } struct DynamicProcInfo { pgid: u32, euid: u32, + suid: u32, ruid: u32, egid: u32, rgid: u32, + sgid: u32, } static STATIC_PROC_INFO: SyncUnsafeCell = SyncUnsafeCell::new(StaticProcInfo { @@ -234,10 +238,12 @@ static STATIC_PROC_INFO: SyncUnsafeCell = SyncUnsafeCell::new(St }); static DYNAMIC_PROC_INFO: Mutex = Mutex::new(DynamicProcInfo { pgid: u32::MAX, - euid: u32::MAX, - egid: u32::MAX, ruid: u32::MAX, + euid: u32::MAX, + suid: u32::MAX, rgid: u32::MAX, + egid: u32::MAX, + sgid: u32::MAX, }); #[inline] diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index 84a50d6fae..78aa939dde 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -937,10 +937,12 @@ pub unsafe fn make_init() -> &'static FdGuard { }); *DYNAMIC_PROC_INFO.lock() = crate::DynamicProcInfo { pgid: 1, - egid: 0, - euid: 0, - rgid: 0, ruid: 0, + euid: 0, + suid: 0, + rgid: 0, + egid: 0, + sgid: 0, }; (*STATIC_PROC_INFO.get()).proc_fd.as_ref().unwrap() } diff --git a/redox-rt/src/protocol.rs b/redox-rt/src/protocol.rs index 25b9323bd8..6161efe411 100644 --- a/redox-rt/src/protocol.rs +++ b/redox-rt/src/protocol.rs @@ -1,14 +1,17 @@ use bitflags::bitflags; #[derive(Clone, Copy, Debug, Default)] +#[repr(C)] pub struct ProcMeta { pub pid: u32, pub pgid: u32, pub ppid: u32, - pub euid: u32, pub ruid: u32, - pub egid: u32, + pub euid: u32, + pub suid: u32, pub rgid: u32, + pub egid: u32, + pub sgid: u32, pub ens: u32, pub rns: u32, } diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs index 9d8565468e..8f299c0379 100644 --- a/redox-rt/src/sys.rs +++ b/redox-rt/src/sys.rs @@ -14,7 +14,7 @@ use crate::{ proc::FdGuard, protocol::{ProcCall, ProcKillTarget, WaitFlags}, signal::tmp_disable_signals, - Tcb, DYNAMIC_PROC_INFO, + DynamicProcInfo, Tcb, DYNAMIC_PROC_INFO, }; #[inline] @@ -189,14 +189,18 @@ pub fn get_umask() -> u32 { UMASK.load(Ordering::Acquire) } -pub fn posix_setresugid( - ruid: Option, - euid: Option, - suid: Option, - rgid: Option, - egid: Option, - sgid: Option, -) -> Result<()> { +/// Real/Effective/Set-User/Group ID +pub struct Resugid { + pub ruid: T, + pub euid: T, + pub suid: T, + pub rgid: T, + pub egid: T, + pub sgid: T, +} + +/// Sets [res][ug]id, fields that are None will be unchanged. +pub fn posix_setresugid(ids: &Resugid>) -> Result<()> { // TODO: not sure how "tmp" an IPC call is? let _sig_guard = tmp_disable_signals(); let mut guard = DYNAMIC_PROC_INFO.lock(); @@ -205,12 +209,12 @@ pub fn posix_setresugid( plain::slice_from_mut_bytes(&mut buf) .unwrap() .copy_from_slice(&[ - ruid.unwrap_or(u32::MAX), - euid.unwrap_or(u32::MAX), - suid.unwrap_or(u32::MAX), - rgid.unwrap_or(u32::MAX), - egid.unwrap_or(u32::MAX), - sgid.unwrap_or(u32::MAX), + ids.ruid.unwrap_or(u32::MAX), + ids.euid.unwrap_or(u32::MAX), + ids.suid.unwrap_or(u32::MAX), + ids.rgid.unwrap_or(u32::MAX), + ids.egid.unwrap_or(u32::MAX), + ids.sgid.unwrap_or(u32::MAX), ]); proc_call( @@ -219,38 +223,46 @@ pub fn posix_setresugid( &[ProcCall::SetResugid as usize], )?; - if let Some(ruid) = ruid { + if let Some(ruid) = ids.ruid { guard.ruid = ruid; } - if let Some(euid) = euid { + if let Some(euid) = ids.euid { guard.euid = euid; } - // TODO: suid? - if let Some(rgid) = rgid { + if let Some(suid) = ids.suid { + guard.suid = suid; + } + if let Some(rgid) = ids.rgid { guard.rgid = rgid; } - if let Some(egid) = egid { + if let Some(egid) = ids.egid { guard.egid = egid; } - // TODO: sgid? + if let Some(sgid) = ids.sgid { + guard.sgid = sgid; + } Ok(()) } -pub fn posix_getruid() -> u32 { - let _guard = tmp_disable_signals(); - DYNAMIC_PROC_INFO.lock().ruid -} -pub fn posix_getrgid() -> u32 { - let _guard = tmp_disable_signals(); - DYNAMIC_PROC_INFO.lock().rgid -} -pub fn posix_geteuid() -> u32 { - let _guard = tmp_disable_signals(); - DYNAMIC_PROC_INFO.lock().euid -} -pub fn posix_getegid() -> u32 { - let _guard = tmp_disable_signals(); - DYNAMIC_PROC_INFO.lock().egid +pub fn posix_getresugid() -> Resugid { + let _sig_guard = tmp_disable_signals(); + let DynamicProcInfo { + ruid, + euid, + suid, + rgid, + egid, + sgid, + .. + } = *DYNAMIC_PROC_INFO.lock(); + Resugid { + ruid, + euid, + suid, + rgid, + egid, + sgid, + } } pub fn posix_exit(status: i32) -> ! { proc_call( diff --git a/src/platform/redox/exec.rs b/src/platform/redox/exec.rs index 660a67332e..c7f9aed4b9 100644 --- a/src/platform/redox/exec.rs +++ b/src/platform/redox/exec.rs @@ -16,6 +16,7 @@ use crate::{ use redox_rt::{ proc::{ExtraInfo, FdGuard, FexecResult, InterpOverride}, + sys::Resugid, RtTcb, }; use syscall::{data::Stat, error::*, flag::*}; @@ -120,12 +121,11 @@ pub fn execve( let mut stat = Stat::default(); syscall::fstat(*image_file as usize, &mut stat)?; - let uid = redox_rt::sys::posix_getruid() as usize; - let gid = redox_rt::sys::posix_getrgid() as usize; + let Resugid { ruid, rgid, .. } = redox_rt::sys::posix_getresugid(); - let mode = if uid == stat.st_uid as usize { + let mode = if ruid == stat.st_uid { (stat.st_mode >> 3 * 2) & 0o7 - } else if gid == stat.st_gid as usize { + } else if rgid == stat.st_gid { (stat.st_mode >> 3 * 1) & 0o7 } else { stat.st_mode & 0o7 diff --git a/src/platform/redox/libredox.rs b/src/platform/redox/libredox.rs index 29efa7caf8..5e5bcad345 100644 --- a/src/platform/redox/libredox.rs +++ b/src/platform/redox/libredox.rs @@ -227,19 +227,19 @@ pub unsafe extern "C" fn redox_get_pid_v1() -> RawResult { #[no_mangle] pub unsafe extern "C" fn redox_get_euid_v1() -> RawResult { - redox_rt::sys::posix_geteuid() as _ + redox_rt::sys::posix_getresugid().euid as _ } #[no_mangle] pub unsafe extern "C" fn redox_get_ruid_v1() -> RawResult { - redox_rt::sys::posix_getruid() as _ + redox_rt::sys::posix_getresugid().ruid as _ } #[no_mangle] pub unsafe extern "C" fn redox_get_egid_v1() -> RawResult { - redox_rt::sys::posix_getegid() as _ + redox_rt::sys::posix_getresugid().egid as _ } #[no_mangle] pub unsafe extern "C" fn redox_get_rgid_v1() -> RawResult { - redox_rt::sys::posix_getrgid() as _ + redox_rt::sys::posix_getresugid().rgid as _ } #[no_mangle] pub unsafe extern "C" fn redox_setrens_v1(rns: usize, ens: usize) -> RawResult { diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index c2fee23574..07612a5d42 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -5,7 +5,7 @@ use core::{ }; use redox_rt::{ protocol::{wifstopped, wstopsig, WaitFlags}, - sys::WaitpidTarget, + sys::{Resugid, WaitpidTarget}, RtTcb, }; use syscall::{ @@ -104,12 +104,11 @@ impl Pal for Sys { syscall::fstat(*fd as usize, &mut stat)?; - let uid = redox_rt::sys::posix_getruid() as usize; - let gid = redox_rt::sys::posix_getrgid() as usize; + let Resugid { ruid, rgid, .. } = redox_rt::sys::posix_getresugid(); - let perms = if stat.st_uid as usize == uid { + let perms = if stat.st_uid == ruid { stat.st_mode >> (3 * 2 & 0o7) - } else if stat.st_gid as usize == gid { + } else if stat.st_gid == rgid { stat.st_mode >> (3 * 1 & 0o7) } else { stat.st_mode & 0o7 @@ -412,15 +411,15 @@ impl Pal for Sys { } fn getegid() -> gid_t { - redox_rt::sys::posix_getegid() as gid_t + redox_rt::sys::posix_getresugid().egid as gid_t } fn geteuid() -> uid_t { - redox_rt::sys::posix_geteuid() as uid_t + redox_rt::sys::posix_getresugid().euid as uid_t } fn getgid() -> gid_t { - redox_rt::sys::posix_getrgid() as gid_t + redox_rt::sys::posix_getresugid().rgid as gid_t } unsafe fn getgroups(size: c_int, list: *mut gid_t) -> Result { @@ -528,7 +527,7 @@ impl Pal for Sys { } fn getuid() -> uid_t { - redox_rt::sys::posix_getruid() as uid_t + redox_rt::sys::posix_getresugid().ruid as uid_t } fn lchown(path: CStr, owner: uid_t, group: gid_t) -> Result<()> { @@ -858,26 +857,26 @@ impl Pal for Sys { } fn setresgid(rgid: gid_t, egid: gid_t, sgid: gid_t) -> Result<()> { - redox_rt::sys::posix_setresugid( - None, - None, - None, - cvt_uid(rgid)?, - cvt_uid(egid)?, - cvt_uid(sgid)?, - )?; + redox_rt::sys::posix_setresugid(&Resugid { + ruid: None, + euid: None, + suid: None, + rgid: cvt_uid(rgid)?, + egid: cvt_uid(egid)?, + sgid: cvt_uid(sgid)?, + })?; Ok(()) } fn setresuid(ruid: uid_t, euid: uid_t, suid: uid_t) -> Result<()> { - redox_rt::sys::posix_setresugid( - cvt_uid(ruid)?, - cvt_uid(euid)?, - cvt_uid(suid)?, - None, - None, - None, - )?; + redox_rt::sys::posix_setresugid(&Resugid { + ruid: cvt_uid(ruid)?, + euid: cvt_uid(euid)?, + suid: cvt_uid(suid)?, + rgid: None, + egid: None, + sgid: None, + })?; Ok(()) } From a4dc232a3330ef7822bdba06f271b6edcc4847d7 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Mon, 31 Mar 2025 13:12:02 +0200 Subject: [PATCH 19/61] Impl getres[ug]id C function. --- src/header/unistd/mod.rs | 22 ++++++++++++++-------- src/platform/linux/mod.rs | 31 +++++++++++++++++++++++++++++++ src/platform/pal/mod.rs | 12 ++++++++++++ src/platform/redox/mod.rs | 39 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 96 insertions(+), 8 deletions(-) diff --git a/src/header/unistd/mod.rs b/src/header/unistd/mod.rs index d0140d3977..bcd682035e 100644 --- a/src/header/unistd/mod.rs +++ b/src/header/unistd/mod.rs @@ -569,15 +569,21 @@ pub extern "C" fn getppid() -> pid_t { } /// See . -// #[no_mangle] -pub extern "C" fn getresgid(rgid: *mut gid_t, egid: *mut gid_t, sgid: *mut gid_t) -> c_int { - unimplemented!(); +#[no_mangle] +pub unsafe extern "C" fn getresgid(rgid: *mut gid_t, egid: *mut gid_t, sgid: *mut gid_t) -> c_int { + // TODO: Out write-only wrapper? + Sys::getresgid(rgid.as_mut(), egid.as_mut(), sgid.as_mut()) + .map(|()| 0) + .or_minus_one_errno() } /// See . -// #[no_mangle] -pub extern "C" fn getresuid(ruid: *mut uid_t, euid: *mut uid_t, suid: *mut uid_t) -> c_int { - unimplemented!(); +#[no_mangle] +pub unsafe extern "C" fn getresuid(ruid: *mut uid_t, euid: *mut uid_t, suid: *mut uid_t) -> c_int { + // TODO: Out write-only wrapper? + Sys::getresuid(ruid.as_mut(), euid.as_mut(), suid.as_mut()) + .map(|()| 0) + .or_minus_one_errno() } /// See . @@ -812,13 +818,13 @@ pub unsafe extern "C" fn set_default_scheme(scheme: *const c_char) -> c_int { /// See . // #[no_mangle] pub extern "C" fn setegid(gid: gid_t) -> c_int { - unimplemented!(); + Sys::setresgid(-1, gid, -1).map(|()| 0).or_minus_one_errno() } /// See . // #[no_mangle] pub extern "C" fn seteuid(uid: uid_t) -> c_int { - unimplemented!(); + Sys::setresuid(-1, uid, -1).map(|()| 0).or_minus_one_errno() } /// See . diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index 86ae1af3b7..b624a7da3a 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -328,6 +328,37 @@ impl Pal for Sys { e_raw(syscall!(GETRLIMIT, resource, rlim)).map(|_| ()) } + fn getresgid( + rgid: Option<&mut gid_t>, + egid: Option<&mut gid_t>, + sgid: Option<&mut gid_t>, + ) -> Result<()> { + unsafe { + e_raw(syscall!( + GETRESGID, + rgid.map_or(0, |r| r as *const _ as usize), + egid.map_or(0, |r| r as *const _ as usize), + sgid.map_or(0, |r| r as *const _ as usize) + )) + .map(|_| ()) + } + } + fn getresuid( + ruid: Option<&mut uid_t>, + euid: Option<&mut uid_t>, + suid: Option<&mut uid_t>, + ) -> Result<()> { + unsafe { + e_raw(syscall!( + GETRESUID, + ruid.map_or(0, |r| r as *const _ as usize), + euid.map_or(0, |r| r as *const _ as usize), + suid.map_or(0, |r| r as *const _ as usize) + )) + .map(|_| ()) + } + } + unsafe fn setrlimit(resource: c_int, rlimit: *const rlimit) -> Result<()> { e_raw(syscall!(SETRLIMIT, resource, rlimit)).map(|_| ()) } diff --git a/src/platform/pal/mod.rs b/src/platform/pal/mod.rs index 6c55a98955..fd5de3e2d8 100644 --- a/src/platform/pal/mod.rs +++ b/src/platform/pal/mod.rs @@ -131,6 +131,18 @@ pub trait Pal { fn getrandom(buf: &mut [u8], flags: c_uint) -> Result; + fn getresgid( + rgid: Option<&mut gid_t>, + egid: Option<&mut gid_t>, + sgid: Option<&mut gid_t>, + ) -> Result<()>; + + fn getresuid( + ruid: Option<&mut uid_t>, + euid: Option<&mut uid_t>, + suid: Option<&mut uid_t>, + ) -> Result<()>; + unsafe fn getrlimit(resource: c_int, rlim: *mut rlimit) -> Result<()>; unsafe fn setrlimit(resource: c_int, rlim: *const rlimit) -> Result<()>; diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index 07612a5d42..6b869367c9 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -468,6 +468,45 @@ impl Pal for Sys { Ok(syscall::read(*fd, buf)?) } + fn getresgid( + rgid_out: Option<&mut gid_t>, + egid_out: Option<&mut gid_t>, + sgid_out: Option<&mut gid_t>, + ) -> Result<()> { + let Resugid { + rgid, egid, sgid, .. + } = redox_rt::sys::posix_getresugid(); + if let Some(rgid_out) = rgid_out { + *rgid_out = rgid as _; + } + if let Some(egid_out) = egid_out { + *egid_out = egid as _; + } + if let Some(sgid_out) = sgid_out { + *sgid_out = sgid as _; + } + Ok(()) + } + fn getresuid( + ruid_out: Option<&mut uid_t>, + euid_out: Option<&mut uid_t>, + suid_out: Option<&mut uid_t>, + ) -> Result<()> { + let Resugid { + ruid, euid, suid, .. + } = redox_rt::sys::posix_getresugid(); + if let Some(ruid_out) = ruid_out { + *ruid_out = ruid as _; + } + if let Some(euid_out) = euid_out { + *euid_out = euid as _; + } + if let Some(suid_out) = suid_out { + *suid_out = suid as _; + } + Ok(()) + } + unsafe fn getrlimit(resource: c_int, rlim: *mut rlimit) -> Result<()> { //TODO eprintln!( From 59090a83f4f5d1112361a8cfc054a5d21612e8f7 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Mon, 31 Mar 2025 15:17:11 +0200 Subject: [PATCH 20/61] Fix thread+proc fd init in ld.so --- src/ld_so/linker.rs | 9 ++++++--- src/ld_so/mod.rs | 4 ++++ src/ld_so/start.rs | 27 +++++++++++++++++++++------ 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/ld_so/linker.rs b/src/ld_so/linker.rs index a1a429090d..ca55590d4f 100644 --- a/src/ld_so/linker.rs +++ b/src/ld_so/linker.rs @@ -612,10 +612,13 @@ impl Linker { unsafe { if !dlopened { #[cfg(target_os = "redox")] - let (tcb, old_tcb) = { + let (tcb, old_tcb, thr_fd) = { use redox_rt::signal::tmp_disable_signals; let old_tcb = Tcb::current().expect("failed to get bootstrap TCB"); + let thr_fd = (&mut *old_tcb.os_specific.thr_fd.get()) + .take() + .expect("no thread FD present"); let new_tcb = Tcb::new(self.tls_size)?; // This actually allocates TCB, TLS and ABI page. // Stash @@ -653,7 +656,7 @@ impl Linker { new_tcb.generic.tcb_len = new_tcb_len; drop(_guard); - (new_tcb, old_tcb as *mut Tcb as *mut c_void) + (new_tcb, old_tcb as *mut Tcb as *mut c_void, thr_fd) }; #[cfg(not(target_os = "redox"))] @@ -694,7 +697,7 @@ impl Linker { tcb.copy_masters().map_err(|_| DlError::Malformed)?; tcb.activate( #[cfg(target_os = "redox")] - todo!(), + thr_fd, ); #[cfg(target_os = "redox")] diff --git a/src/ld_so/mod.rs b/src/ld_so/mod.rs index d3d726df5d..425d04d859 100644 --- a/src/ld_so/mod.rs +++ b/src/ld_so/mod.rs @@ -196,6 +196,10 @@ pub unsafe fn init( #[cfg(target_os = "redox")] thr_fd, ); + } else { + // The thread fd must already be present in the already existing TCB. Don't close it. + #[cfg(target_os = "redox")] + core::mem::forget(thr_fd); } } diff --git a/src/ld_so/start.rs b/src/ld_so/start.rs index 4c09f52f34..390a77c09a 100644 --- a/src/ld_so/start.rs +++ b/src/ld_so/start.rs @@ -145,16 +145,31 @@ fn resolve_path_name( None } -// TODO: Make unsafe #[no_mangle] -pub extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: usize) -> usize { +pub unsafe extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: usize) -> usize { // Setup TCB for ourselves. unsafe { - let tcb = Tcb::new(0).expect_notls("ld.so: failed to allocate bootstrap TCB"); - tcb.activate(todo!()); - #[cfg(target_os = "redox")] - redox_rt::signal::setup_sighandler(&tcb.os_specific); + let thr_fd = + crate::platform::get_auxv_raw(sp.auxv().cast(), redox_rt::auxv_defs::AT_REDOX_THR_FD) + .expect_notls("no thread fd present"); + + let tcb = Tcb::new(0).expect_notls("ld.so: failed to allocate bootstrap TCB"); + tcb.activate( + #[cfg(target_os = "redox")] + redox_rt::proc::FdGuard::new(thr_fd), + ); + #[cfg(target_os = "redox")] + { + let proc_fd = crate::platform::get_auxv_raw( + sp.auxv().cast(), + redox_rt::auxv_defs::AT_REDOX_PROC_FD, + ) + .expect_notls("no proc fd present"); + + redox_rt::initialize(redox_rt::proc::FdGuard::new(proc_fd)); + redox_rt::signal::setup_sighandler(&tcb.os_specific); + } } // We get the arguments, the environment, and the auxilary vector From 98c8beae3dda93fbde33c369c54fe55f52353ee0 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Mon, 31 Mar 2025 16:24:47 +0200 Subject: [PATCH 21/61] Sync sig pages using proc and thread calls. --- redox-rt/src/protocol.rs | 19 +++++++++++++++++++ redox-rt/src/signal.rs | 11 +++++++++-- redox-rt/src/sys.rs | 16 +++++++++------- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/redox-rt/src/protocol.rs b/redox-rt/src/protocol.rs index 6161efe411..90032a5bd4 100644 --- a/redox-rt/src/protocol.rs +++ b/redox-rt/src/protocol.rs @@ -30,6 +30,16 @@ pub enum ProcCall { Setsid = 7, Kill = 8, Sigq = 9, + + // TODO: replace with sendfd equivalent syscall for sending memory + SyncSigPctl = 10, +} +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[repr(usize)] +pub enum ThreadCall { + // TODO: replace with sendfd equivalent syscall for sending memory, or force userspace to + // obtain its TCB memory from this server + SyncSigTctl = 0, } impl ProcCall { @@ -45,6 +55,15 @@ impl ProcCall { 7 => Self::Setsid, 8 => Self::Kill, 9 => Self::Sigq, + 10 => Self::SyncSigPctl, + _ => return None, + }) + } +} +impl ThreadCall { + pub fn try_from_raw(raw: usize) -> Option { + Some(match raw { + 0 => Self::SyncSigTctl, _ => return None, }) } diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index f252ba5418..c7ac63dccd 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -1,12 +1,12 @@ use core::{ffi::c_int, mem::MaybeUninit, ptr::NonNull, sync::atomic::Ordering}; use syscall::{ - data::AtomicU64, Error, RawAction, Result, RtSigInfo, SenderInfo, SetSighandlerData, + data::AtomicU64, CallFlags, Error, RawAction, Result, RtSigInfo, SenderInfo, SetSighandlerData, SigProcControl, Sigcontrol, SigcontrolFlags, TimeSpec, EAGAIN, EINTR, EINVAL, ENOMEM, EPERM, SIGCHLD, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGWINCH, }; -use crate::{arch::*, proc::FdGuard, sync::Mutex, RtTcb, Tcb}; +use crate::{arch::*, proc::FdGuard, protocol::{ProcCall, ThreadCall}, sync::Mutex, sys::{proc_call, thread_call}, RtTcb, Tcb}; #[cfg(target_arch = "x86_64")] static CPUID_EAX1_ECX: core::sync::atomic::AtomicU32 = core::sync::atomic::AtomicU32::new(0); @@ -576,6 +576,13 @@ pub fn setup_sighandler(tcb: &RtTcb) { syscall::dup(**tcb.thread_fd(), b"sighandler").expect("failed to open sighandler fd"), ); let _ = syscall::write(*fd, &data).expect("failed to write to sighandler fd"); + thread_call(&mut [], CallFlags::empty(), &[ + ThreadCall::SyncSigTctl as usize, + ]); + // TODO: Only run for first thread + proc_call(&mut [], CallFlags::empty(), &[ + ProcCall::SyncSigPctl as usize, + ]); // TODO: Inherited set of ignored signals set_sigmask(Some(0), None); diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs index 8f299c0379..5d9bb146eb 100644 --- a/redox-rt/src/sys.rs +++ b/redox-rt/src/sys.rs @@ -10,11 +10,7 @@ use syscall::{ }; use crate::{ - arch::manually_enter_trampoline, - proc::FdGuard, - protocol::{ProcCall, ProcKillTarget, WaitFlags}, - signal::tmp_disable_signals, - DynamicProcInfo, Tcb, DYNAMIC_PROC_INFO, + arch::manually_enter_trampoline, proc::FdGuard, protocol::{ProcCall, ProcKillTarget, WaitFlags}, signal::tmp_disable_signals, DynamicProcInfo, RtTcb, Tcb, DYNAMIC_PROC_INFO }; #[inline] @@ -116,11 +112,11 @@ pub unsafe fn sys_futex_wake(addr: *mut u32, num: u32) -> Result { ) .map(|awoken| awoken as u32) } -fn proc_call(payload: &mut [u8], flags: CallFlags, metadata: &[usize]) -> Result { +pub fn sys_call(fd: usize, payload: &mut [u8], flags: CallFlags, metadata: &[usize]) -> Result { unsafe { syscall::syscall5( syscall::SYS_CALL, - **crate::current_proc_fd(), + fd, payload.as_mut_ptr() as usize, payload.len(), metadata.len() | flags.bits(), @@ -128,6 +124,12 @@ fn proc_call(payload: &mut [u8], flags: CallFlags, metadata: &[usize]) -> Result ) } } +pub fn proc_call(payload: &mut [u8], flags: CallFlags, metadata: &[usize]) -> Result { + sys_call(**crate::current_proc_fd(), payload, flags, metadata) +} +pub fn thread_call(payload: &mut [u8], flags: CallFlags, metadata: &[usize]) -> Result { + sys_call(**RtTcb::current().thread_fd(), payload, flags, metadata) +} #[derive(Clone, Copy, Debug)] pub enum WaitpidTarget { From ac7e0755f131d123357ce79ce3dec80e965ebf74 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Mon, 31 Mar 2025 16:48:54 +0200 Subject: [PATCH 22/61] Fix SyncSigPctl invocation. --- redox-rt/src/arch/x86_64.rs | 5 +---- redox-rt/src/signal.rs | 16 ++++++++-------- redox-rt/src/sys.rs | 13 +++++++++++-- src/platform/mod.rs | 7 +++++++ 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/redox-rt/src/arch/x86_64.rs b/redox-rt/src/arch/x86_64.rs index 86a9892568..fa2f9e372a 100644 --- a/redox-rt/src/arch/x86_64.rs +++ b/redox-rt/src/arch/x86_64.rs @@ -12,10 +12,7 @@ use syscall::{ use crate::{ proc::{fork_inner, FdGuard, ForkArgs}, - signal::{ - get_sigaltstack, inner_c, PosixStackt, RtSigarea, SigStack, - PROC_CONTROL_STRUCT, - }, + signal::{get_sigaltstack, inner_c, PosixStackt, RtSigarea, SigStack, PROC_CONTROL_STRUCT}, Tcb, }; diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index c7ac63dccd..da332ef753 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -6,7 +6,9 @@ use syscall::{ SIGCHLD, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGWINCH, }; -use crate::{arch::*, proc::FdGuard, protocol::{ProcCall, ThreadCall}, sync::Mutex, sys::{proc_call, thread_call}, RtTcb, Tcb}; +use crate::{ + arch::*, proc::FdGuard, protocol::ThreadCall, sync::Mutex, sys::thread_call, RtTcb, Tcb, +}; #[cfg(target_arch = "x86_64")] static CPUID_EAX1_ECX: core::sync::atomic::AtomicU32 = core::sync::atomic::AtomicU32::new(0); @@ -576,13 +578,11 @@ pub fn setup_sighandler(tcb: &RtTcb) { syscall::dup(**tcb.thread_fd(), b"sighandler").expect("failed to open sighandler fd"), ); let _ = syscall::write(*fd, &data).expect("failed to write to sighandler fd"); - thread_call(&mut [], CallFlags::empty(), &[ - ThreadCall::SyncSigTctl as usize, - ]); - // TODO: Only run for first thread - proc_call(&mut [], CallFlags::empty(), &[ - ProcCall::SyncSigPctl as usize, - ]); + thread_call( + &mut [], + CallFlags::empty(), + &[ThreadCall::SyncSigTctl as usize], + ); // TODO: Inherited set of ignored signals set_sigmask(Some(0), None); diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs index 5d9bb146eb..85d37932cd 100644 --- a/redox-rt/src/sys.rs +++ b/redox-rt/src/sys.rs @@ -10,7 +10,11 @@ use syscall::{ }; use crate::{ - arch::manually_enter_trampoline, proc::FdGuard, protocol::{ProcCall, ProcKillTarget, WaitFlags}, signal::tmp_disable_signals, DynamicProcInfo, RtTcb, Tcb, DYNAMIC_PROC_INFO + arch::manually_enter_trampoline, + proc::FdGuard, + protocol::{ProcCall, ProcKillTarget, WaitFlags}, + signal::tmp_disable_signals, + DynamicProcInfo, RtTcb, Tcb, DYNAMIC_PROC_INFO, }; #[inline] @@ -112,7 +116,12 @@ pub unsafe fn sys_futex_wake(addr: *mut u32, num: u32) -> Result { ) .map(|awoken| awoken as u32) } -pub fn sys_call(fd: usize, payload: &mut [u8], flags: CallFlags, metadata: &[usize]) -> Result { +pub fn sys_call( + fd: usize, + payload: &mut [u8], + flags: CallFlags, + metadata: &[usize], +) -> Result { unsafe { syscall::syscall5( syscall::SYS_CALL, diff --git a/src/platform/mod.rs b/src/platform/mod.rs index 016f4eec36..55139c1972 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -335,6 +335,13 @@ pub unsafe fn init(auxvs: Box<[[usize; 2]]>) { }; redox_rt::initialize(FdGuard::new(proc_fd)); + // TODO: Is it safe to assume setup_sighandler has been called at this point? + redox_rt::sys::proc_call( + &mut [], + syscall::CallFlags::empty(), + &[redox_rt::protocol::ProcCall::SyncSigPctl as usize], + ); + if let (Some(cwd_ptr), Some(cwd_len)) = ( get_auxv(&auxvs, AT_REDOX_INITIAL_CWD_PTR), get_auxv(&auxvs, AT_REDOX_INITIAL_CWD_LEN), From b30ccb61fe39281a61b2742c4831019562fa4f34 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Tue, 1 Apr 2025 14:07:50 +0200 Subject: [PATCH 23/61] Enforce procmgr errors, fix attrs path. --- redox-rt/src/proc.rs | 2 +- redox-rt/src/signal.rs | 3 ++- src/platform/mod.rs | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index 78aa939dde..216f282e5b 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -892,7 +892,7 @@ pub fn new_child_process(args: &ForkArgs<'_>) -> Result { }; let attr_fd = FdGuard::new(syscall::dup( *thr_fd, - alloc::format!("attrs-{}", **auth).as_bytes(), + alloc::format!("auth-{}-attrs", **auth).as_bytes(), )?); let _ = syscall::write(*attr_fd, &buf)?; Ok(NewChildProc { diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index da332ef753..e30504aef2 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -582,7 +582,8 @@ pub fn setup_sighandler(tcb: &RtTcb) { &mut [], CallFlags::empty(), &[ThreadCall::SyncSigTctl as usize], - ); + ) + .expect("failed to sync signal tctl"); // TODO: Inherited set of ignored signals set_sigmask(Some(0), None); diff --git a/src/platform/mod.rs b/src/platform/mod.rs index 55139c1972..d5d4a69b40 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -340,7 +340,8 @@ pub unsafe fn init(auxvs: Box<[[usize; 2]]>) { &mut [], syscall::CallFlags::empty(), &[redox_rt::protocol::ProcCall::SyncSigPctl as usize], - ); + ) + .expect("failed to sync signal pctl"); if let (Some(cwd_ptr), Some(cwd_len)) = ( get_auxv(&auxvs, AT_REDOX_INITIAL_CWD_PTR), From 93e88b0ce8db2d818d4e4f218671b17beaa1f108 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Thu, 3 Apr 2025 11:30:16 +0200 Subject: [PATCH 24/61] Reacquire thread fd as procmgr-owned in make_init. --- redox-rt/src/proc.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index 216f282e5b..a58c9bf064 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -918,7 +918,7 @@ pub fn copy_str(cur_pid_fd: usize, new_proc_fd: usize, key: &str) -> Result<()> Ok(()) } -pub unsafe fn make_init() -> &'static FdGuard { +pub unsafe fn make_init() -> [&'static FdGuard; 2] { let proc_fd = FdGuard::new( syscall::open("/scheme/proc/init", syscall::O_CLOEXEC).expect("failed to create init"), ); @@ -930,6 +930,12 @@ pub unsafe fn make_init() -> &'static FdGuard { ) .expect("failed to assign current thread to init process"); + let managed_thr_fd = FdGuard::new( + syscall::dup(*proc_fd, b"thread-0").expect("failed to get managed thread for init"), + ); + + let managed_thr_fd = (*RtTcb::current().thr_fd.get()).insert(managed_thr_fd); + STATIC_PROC_INFO.get().write(crate::StaticProcInfo { pid: 1, ppid: 1, @@ -944,5 +950,8 @@ pub unsafe fn make_init() -> &'static FdGuard { egid: 0, sgid: 0, }; - (*STATIC_PROC_INFO.get()).proc_fd.as_ref().unwrap() + [ + (*STATIC_PROC_INFO.get()).proc_fd.as_ref().unwrap(), + managed_thr_fd, + ] } From dc2988968e493eda0f876a7e76569e268726d480 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Fri, 4 Apr 2025 14:56:42 +0200 Subject: [PATCH 25/61] Use SignalThread call and fix fork sighandler sync with procmgr. --- redox-rt/src/proc.rs | 25 +++++++++++++++--- redox-rt/src/protocol.rs | 2 ++ redox-rt/src/signal.rs | 4 +-- redox-rt/src/sys.rs | 56 ++++++++++++++++++++++++++++------------ src/platform/mod.rs | 2 +- 5 files changed, 66 insertions(+), 23 deletions(-) diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index a58c9bf064..fc4e753d84 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -1,8 +1,12 @@ use core::{fmt::Debug, mem::size_of}; use crate::{ - arch::*, auxv_defs::*, read_proc_meta, static_proc_info, RtTcb, DYNAMIC_PROC_INFO, - STATIC_PROC_INFO, + arch::*, + auxv_defs::*, + protocol::{ProcCall, ThreadCall}, + read_proc_meta, static_proc_info, + sys::{proc_call, thread_call}, + RtTcb, DYNAMIC_PROC_INFO, STATIC_PROC_INFO, }; use alloc::{boxed::Box, collections::BTreeMap, vec}; @@ -22,7 +26,7 @@ use goblin::elf64::{ use syscall::{ error::*, flag::{MapFlags, SEEK_SET}, - GrantDesc, GrantFlags, Map, ProcSchemeAttrs, SetSighandlerData, MAP_FIXED_NOREPLACE, + CallFlags, GrantDesc, GrantFlags, Map, ProcSchemeAttrs, SetSighandlerData, MAP_FIXED_NOREPLACE, MAP_SHARED, O_CLOEXEC, PAGE_SIZE, PROT_EXEC, PROT_READ, PROT_WRITE, }; @@ -410,6 +414,7 @@ where proc_control_addr: 0, }, ); + // TODO: sync with procmgr } unsafe { @@ -833,6 +838,20 @@ pub fn fork_inner(initial_rsp: *mut usize, args: &ForkArgs) -> Result { &crate::signal::current_setsighandler_struct(), )?; } + if let Some(ref proc_fd) = new_proc_fd { + proc_call( + **proc_fd, + &mut [], + CallFlags::empty(), + &[ProcCall::SyncSigPctl as usize], + )?; + } + thread_call( + *new_thr_fd, + &mut [], + CallFlags::empty(), + &[ThreadCall::SyncSigTctl as usize], + )?; } copy_env_regs(**cur_thr_fd, *new_thr_fd)?; } diff --git a/redox-rt/src/protocol.rs b/redox-rt/src/protocol.rs index 90032a5bd4..eb6023324a 100644 --- a/redox-rt/src/protocol.rs +++ b/redox-rt/src/protocol.rs @@ -40,6 +40,7 @@ pub enum ThreadCall { // TODO: replace with sendfd equivalent syscall for sending memory, or force userspace to // obtain its TCB memory from this server SyncSigTctl = 0, + SignalThread = 1, } impl ProcCall { @@ -64,6 +65,7 @@ impl ThreadCall { pub fn try_from_raw(raw: usize) -> Option { Some(match raw { 0 => Self::SyncSigTctl, + 1 => Self::SignalThread, _ => return None, }) } diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index e30504aef2..c0e29b5c23 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -7,7 +7,7 @@ use syscall::{ }; use crate::{ - arch::*, proc::FdGuard, protocol::ThreadCall, sync::Mutex, sys::thread_call, RtTcb, Tcb, + arch::*, proc::FdGuard, protocol::ThreadCall, sync::Mutex, sys::this_thread_call, RtTcb, Tcb, }; #[cfg(target_arch = "x86_64")] @@ -578,7 +578,7 @@ pub fn setup_sighandler(tcb: &RtTcb) { syscall::dup(**tcb.thread_fd(), b"sighandler").expect("failed to open sighandler fd"), ); let _ = syscall::write(*fd, &data).expect("failed to write to sighandler fd"); - thread_call( + this_thread_call( &mut [], CallFlags::empty(), &[ThreadCall::SyncSigTctl as usize], diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs index 85d37932cd..e7794cf36e 100644 --- a/redox-rt/src/sys.rs +++ b/redox-rt/src/sys.rs @@ -12,7 +12,7 @@ use syscall::{ use crate::{ arch::manually_enter_trampoline, proc::FdGuard, - protocol::{ProcCall, ProcKillTarget, WaitFlags}, + protocol::{ProcCall, ProcKillTarget, ThreadCall, WaitFlags}, signal::tmp_disable_signals, DynamicProcInfo, RtTcb, Tcb, DYNAMIC_PROC_INFO, }; @@ -51,7 +51,7 @@ pub fn posix_write(fd: usize, buf: &[u8]) -> Result { #[inline] pub fn posix_kill(target: ProcKillTarget, sig: usize) -> Result<()> { match wrapper(false, || { - proc_call( + this_proc_call( &mut [], CallFlags::empty(), &[ProcCall::Kill as usize, target.raw(), sig], @@ -70,7 +70,7 @@ pub fn posix_sigqueue(pid: usize, sig: usize, arg: usize) -> Result<()> { pid: posix_getpid(), }; match wrapper(false, || { - proc_call( + this_proc_call( &mut siginf, CallFlags::empty(), &[ProcCall::Sigq as usize, pid, sig], @@ -133,11 +133,27 @@ pub fn sys_call( ) } } -pub fn proc_call(payload: &mut [u8], flags: CallFlags, metadata: &[usize]) -> Result { - sys_call(**crate::current_proc_fd(), payload, flags, metadata) +pub fn this_proc_call(payload: &mut [u8], flags: CallFlags, metadata: &[usize]) -> Result { + proc_call(**crate::current_proc_fd(), payload, flags, metadata) } -pub fn thread_call(payload: &mut [u8], flags: CallFlags, metadata: &[usize]) -> Result { - sys_call(**RtTcb::current().thread_fd(), payload, flags, metadata) +pub fn proc_call( + proc_fd: usize, + payload: &mut [u8], + flags: CallFlags, + metadata: &[usize], +) -> Result { + sys_call(proc_fd, payload, flags, metadata) +} +pub fn thread_call( + thread_fd: usize, + payload: &mut [u8], + flags: CallFlags, + metadata: &[usize], +) -> Result { + sys_call(thread_fd, payload, flags, metadata) +} +pub fn this_thread_call(payload: &mut [u8], flags: CallFlags, metadata: &[usize]) -> Result { + thread_call(**RtTcb::current().thread_fd(), payload, flags, metadata) } #[derive(Clone, Copy, Debug)] @@ -168,7 +184,7 @@ pub fn sys_waitpid(target: WaitpidTarget, status: &mut usize, flags: WaitFlags) WaitpidTarget::ProcGroup { pgid } => (ProcCall::Waitpgid, pgid), }; wrapper(true, || { - proc_call( + this_proc_call( unsafe { plain::as_mut_bytes(status) }, CallFlags::empty(), &[call as usize, pid, flags.bits() as usize], @@ -176,8 +192,14 @@ pub fn sys_waitpid(target: WaitpidTarget, status: &mut usize, flags: WaitFlags) }) } pub fn posix_kill_thread(thread_fd: usize, signal: u32) -> Result<()> { - let killfd = FdGuard::new(syscall::dup(thread_fd, b"signal")?); - match wrapper(false, || syscall::write(*killfd, &signal.to_ne_bytes())) { + match wrapper(false, || { + thread_call( + thread_fd, + &mut [], + CallFlags::empty(), + &[ThreadCall::SignalThread as usize, signal as usize], + ) + }) { Ok(_) | Err(Error { errno: EINTR }) => Ok(()), Err(error) => Err(error), } @@ -228,7 +250,7 @@ pub fn posix_setresugid(ids: &Resugid>) -> Result<()> { ids.sgid.unwrap_or(u32::MAX), ]); - proc_call( + this_proc_call( &mut buf, CallFlags::empty(), &[ProcCall::SetResugid as usize], @@ -276,7 +298,7 @@ pub fn posix_getresugid() -> Resugid { } } pub fn posix_exit(status: i32) -> ! { - proc_call( + this_proc_call( &mut [], CallFlags::empty(), &[ProcCall::Exit as usize, status as usize], @@ -285,7 +307,7 @@ pub fn posix_exit(status: i32) -> ! { unreachable!() } pub fn setrens(rns: usize, ens: usize) -> Result<()> { - proc_call( + this_proc_call( &mut [], CallFlags::empty(), &[ProcCall::Setrens as usize, rns, ens], @@ -293,7 +315,7 @@ pub fn setrens(rns: usize, ens: usize) -> Result<()> { Ok(()) } pub fn posix_getpgid(pid: usize) -> Result { - proc_call( + this_proc_call( &mut [], CallFlags::empty(), &[ProcCall::Setpgid as usize, pid, usize::wrapping_neg(1)], @@ -303,7 +325,7 @@ pub fn posix_setpgid(pid: usize, pgid: usize) -> Result<()> { if pgid == usize::wrapping_neg(1) { return Err(Error::new(EINVAL)); } - proc_call( + this_proc_call( &mut [], CallFlags::empty(), &[ProcCall::Setpgid as usize, pid, pgid], @@ -311,13 +333,13 @@ pub fn posix_setpgid(pid: usize, pgid: usize) -> Result<()> { Ok(()) } pub fn posix_getsid(pid: usize) -> Result { - proc_call( + this_proc_call( &mut [], CallFlags::empty(), &[ProcCall::Getsid as usize, pid], ) } pub fn posix_setsid() -> Result<()> { - proc_call(&mut [], CallFlags::empty(), &[ProcCall::Setsid as usize])?; + this_proc_call(&mut [], CallFlags::empty(), &[ProcCall::Setsid as usize])?; Ok(()) } diff --git a/src/platform/mod.rs b/src/platform/mod.rs index d5d4a69b40..611d32ba4b 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -336,7 +336,7 @@ pub unsafe fn init(auxvs: Box<[[usize; 2]]>) { redox_rt::initialize(FdGuard::new(proc_fd)); // TODO: Is it safe to assume setup_sighandler has been called at this point? - redox_rt::sys::proc_call( + redox_rt::sys::this_proc_call( &mut [], syscall::CallFlags::empty(), &[redox_rt::protocol::ProcCall::SyncSigPctl as usize], From cc6fadb8bb800ad47bc3f2e21b9b4d9cc70fd473 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Mon, 7 Apr 2025 17:38:34 +0200 Subject: [PATCH 26/61] Only SyncSigTctl if there exists a proc fd. --- redox-rt/src/proc.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index fc4e753d84..173d6b0aed 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -845,13 +845,13 @@ pub fn fork_inner(initial_rsp: *mut usize, args: &ForkArgs) -> Result { CallFlags::empty(), &[ProcCall::SyncSigPctl as usize], )?; + thread_call( + *new_thr_fd, + &mut [], + CallFlags::empty(), + &[ThreadCall::SyncSigTctl as usize], + )?; } - thread_call( - *new_thr_fd, - &mut [], - CallFlags::empty(), - &[ThreadCall::SyncSigTctl as usize], - )?; } copy_env_regs(**cur_thr_fd, *new_thr_fd)?; } From 9e769fcb57b4b023cf51fa27c851ce7da21405de Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Thu, 10 Apr 2025 15:33:36 +0200 Subject: [PATCH 27/61] Add pthread_exit test. This caught a bug in the kernel where it would return Ok(24) when passing zero extra-munmap length. --- tests/Makefile | 1 + tests/pthread/exit.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 tests/pthread/exit.c diff --git a/tests/Makefile b/tests/Makefile index 948215e198..acc7d5de3b 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -204,6 +204,7 @@ NAMES=\ unistd/sysconf \ pthread/main \ pthread/cleanup \ + pthread/exit \ pthread/extjoin \ pthread/once \ pthread/customstack \ diff --git a/tests/pthread/exit.c b/tests/pthread/exit.c new file mode 100644 index 0000000000..35fc31cf21 --- /dev/null +++ b/tests/pthread/exit.c @@ -0,0 +1,31 @@ +#include +#include +#include + +#include + +#include "common.h" + +void *routine(void *arg) { + assert(arg == NULL); + + sleep(1); + + puts("Thread "); + + return NULL; +} + +int main(void) { + int status; + pthread_t thread; + + if ((status = pthread_create(&thread, NULL, routine, NULL)) != 0) { + return fail(status, "failed to create thread"); + } + if ((status = pthread_detach(thread)) != 0) { + return fail(status, "failed to detach thread"); + } + + pthread_exit(NULL); +} From a8ee9e72eeb3545058c25dd4ecf355aecf4489c4 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Thu, 10 Apr 2025 15:34:33 +0200 Subject: [PATCH 28/61] Fix possible TCB.thread_fd() use-after-free. --- redox-rt/src/thread.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/redox-rt/src/thread.rs b/redox-rt/src/thread.rs index 5d0c258e7d..953fce5e62 100644 --- a/redox-rt/src/thread.rs +++ b/redox-rt/src/thread.rs @@ -56,16 +56,16 @@ pub unsafe fn exit_this_thread(stack_base: *mut (), stack_size: usize) -> ! { let _guard = tmp_disable_signals(); let tcb = RtTcb::current(); - let thread_fd = tcb.thread_fd(); + // TODO: modify interface so it writes directly to the thread fd? + let status_fd = syscall::dup(**tcb.thread_fd(), b"status").unwrap(); let _ = syscall::funmap(tcb as *const RtTcb as usize, syscall::PAGE_SIZE); - // TODO: modify interface so it writes directly to the thread fd? - let status_fd = syscall::dup(**thread_fd, b"status").unwrap(); let mut buf = [0; size_of::() * 3]; plain::slice_from_mut_bytes(&mut buf) .unwrap() .copy_from_slice(&[usize::MAX, stack_base as usize, stack_size]); + // TODO: SYS_CALL w/CONSUME syscall::write(status_fd, &buf).unwrap(); unreachable!() } From 2fb247266baf66c022030aaecd61fb9a8e7bd8c8 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Thu, 10 Apr 2025 15:35:59 +0200 Subject: [PATCH 29/61] Fix typo in pthread_exit test. --- tests/pthread/exit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/pthread/exit.c b/tests/pthread/exit.c index 35fc31cf21..ce276b4239 100644 --- a/tests/pthread/exit.c +++ b/tests/pthread/exit.c @@ -11,7 +11,7 @@ void *routine(void *arg) { sleep(1); - puts("Thread "); + puts("Thread succeeded"); return NULL; } From c99e9c7db3a49212a6fb6ea599d3d71b231bad8b Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Thu, 10 Apr 2025 15:58:31 +0200 Subject: [PATCH 30/61] Add waitpid test back. --- tests/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Makefile b/tests/Makefile index acc7d5de3b..64ad5dfcb3 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -125,10 +125,10 @@ EXPECT_NAMES=\ unistd/getopt_long \ unistd/pipe \ unistd/rmdir \ + waitpid \ # unistd/sleep \ unistd/swab \ unistd/write \ - waitpid \ wchar/fgetwc \ wchar/fwide \ wchar/mbrtowc \ From 134914c580210c3a1db0c6e628dba04420d0652a Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Fri, 11 Apr 2025 15:13:50 +0200 Subject: [PATCH 31/61] Expand waitpid test. --- tests/Makefile | 2 +- tests/waitpid.c | 29 ++++++++++++++++++++++------- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index 64ad5dfcb3..1dd1f31e94 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -217,9 +217,9 @@ NAMES=\ grp/getgrgid_r \ grp/getgrnam_r \ grp/gr_iter \ + sigqueue # resource/getrusage # time/times -# sigqueue # Tests run with `expect` (require a .c file and an .exp file # that takes the produced binary as the first argument) diff --git a/tests/waitpid.c b/tests/waitpid.c index ec4c6dedc6..09a8ffc537 100644 --- a/tests/waitpid.c +++ b/tests/waitpid.c @@ -1,21 +1,36 @@ +#include #include #include #include #include "test_helpers.h" -int main(void) { +void for_code(int code) { pid_t pid = fork(); ERROR_IF(fork, pid, == -1); + // Testing successful exit if (pid == 0) { // child sleep(1); - exit(EXIT_SUCCESS); - } else { - // parent - int stat_loc; - pid_t wid = waitpid(pid, &stat_loc, 0); - ERROR_IF(waitpid, wid, == -1); + _Exit(code); } + printf("Testing waitpid of child %d for code %d\n", pid, code); + // parent + int status; + pid_t wid = waitpid(pid, &status, 0); + ERROR_IF(waitpid, wid, == -1); + + assert(WIFEXITED(status)); + assert(WEXITSTATUS(status) == code); + + puts("Success"); +} + +int main(void) { + for_code(EXIT_SUCCESS); + for_code(EXIT_FAILURE); + for_code(42); + for_code(255); + // TODO: Also add coverage for e.g. WIFSTOPPED, WSTOPSIG, WTERMSIG, etc } From 3a8d63d2b8707ea9f82765a17282b1d4b4fdeaa7 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Fri, 11 Apr 2025 16:10:25 +0200 Subject: [PATCH 32/61] Handle self-kill for posix_kill{,_thread}. --- redox-rt/src/sys.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs index e7794cf36e..97f35dd3ea 100644 --- a/redox-rt/src/sys.rs +++ b/redox-rt/src/sys.rs @@ -6,26 +6,26 @@ use core::{ use syscall::{ error::{Error, Result, EINTR}, - CallFlags, RtSigInfo, TimeSpec, EINVAL, + CallFlags, RtSigInfo, TimeSpec, EINVAL, ERESTART, }; use crate::{ arch::manually_enter_trampoline, - proc::FdGuard, protocol::{ProcCall, ProcKillTarget, ThreadCall, WaitFlags}, signal::tmp_disable_signals, DynamicProcInfo, RtTcb, Tcb, DYNAMIC_PROC_INFO, }; #[inline] -fn wrapper(restart: bool, mut f: impl FnMut() -> Result) -> Result { +fn wrapper(restart: bool, erestart: bool, mut f: impl FnMut() -> Result) -> Result { loop { let _guard = tmp_disable_signals(); let rt_sigarea = unsafe { &Tcb::current().unwrap().os_specific }; let res = f(); + let code = if erestart { ERESTART } else { EINTR }; if let Err(err) = res - && err == Error::new(EINTR) + && err == Error::new(code) { unsafe { manually_enter_trampoline(); @@ -42,22 +42,22 @@ fn wrapper(restart: bool, mut f: impl FnMut() -> Result) -> Result { // TODO: uninitialized memory? #[inline] pub fn posix_read(fd: usize, buf: &mut [u8]) -> Result { - wrapper(true, || syscall::read(fd, buf)) + wrapper(true, false, || syscall::read(fd, buf)) } #[inline] pub fn posix_write(fd: usize, buf: &[u8]) -> Result { - wrapper(true, || syscall::write(fd, buf)) + wrapper(true, false, || syscall::write(fd, buf)) } #[inline] pub fn posix_kill(target: ProcKillTarget, sig: usize) -> Result<()> { - match wrapper(false, || { + match wrapper(false, true, || { this_proc_call( &mut [], CallFlags::empty(), &[ProcCall::Kill as usize, target.raw(), sig], ) }) { - Ok(_) | Err(Error { errno: EINTR }) => Ok(()), + Ok(_) | Err(Error { errno: ERESTART }) => Ok(()), Err(error) => Err(error), } } @@ -69,7 +69,7 @@ pub fn posix_sigqueue(pid: usize, sig: usize, arg: usize) -> Result<()> { uid: 0, // TODO pid: posix_getpid(), }; - match wrapper(false, || { + match wrapper(false, false, || { this_proc_call( &mut siginf, CallFlags::empty(), @@ -92,7 +92,7 @@ pub fn posix_getppid() -> u32 { } #[inline] pub unsafe fn sys_futex_wait(addr: *mut u32, val: u32, deadline: Option<&TimeSpec>) -> Result<()> { - wrapper(true, || { + wrapper(true, false, || { syscall::syscall5( syscall::SYS_FUTEX, addr as usize, @@ -183,7 +183,7 @@ pub fn sys_waitpid(target: WaitpidTarget, status: &mut usize, flags: WaitFlags) WaitpidTarget::AnyGroupMember => (ProcCall::Waitpgid, 0), WaitpidTarget::ProcGroup { pgid } => (ProcCall::Waitpgid, pgid), }; - wrapper(true, || { + wrapper(true, false, || { this_proc_call( unsafe { plain::as_mut_bytes(status) }, CallFlags::empty(), @@ -192,7 +192,7 @@ pub fn sys_waitpid(target: WaitpidTarget, status: &mut usize, flags: WaitFlags) }) } pub fn posix_kill_thread(thread_fd: usize, signal: u32) -> Result<()> { - match wrapper(false, || { + match wrapper(false, true, || { thread_call( thread_fd, &mut [], @@ -200,7 +200,7 @@ pub fn posix_kill_thread(thread_fd: usize, signal: u32) -> Result<()> { &[ThreadCall::SignalThread as usize, signal as usize], ) }) { - Ok(_) | Err(Error { errno: EINTR }) => Ok(()), + Ok(_) | Err(Error { errno: ERESTART }) => Ok(()), Err(error) => Err(error), } } From 6e947a9b2f4ebeee098a68c6adccc086c4e87a41 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sat, 12 Apr 2025 17:59:51 +0200 Subject: [PATCH 33/61] Simplify FdGuard. --- redox-rt/src/proc.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index 173d6b0aed..af8117bf7a 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -646,32 +646,35 @@ impl Drop for MmapGuard { } } +#[repr(transparent)] pub struct FdGuard { fd: usize, - taken: bool, } impl FdGuard { + #[inline] pub const fn new(fd: usize) -> Self { - Self { fd, taken: false } + Self { fd } } - pub fn take(&mut self) -> usize { - self.taken = true; - self.fd + #[inline] + pub fn take(self) -> usize { + let fd = self.fd; + core::mem::forget(self); + fd } } impl core::ops::Deref for FdGuard { type Target = usize; + #[inline] fn deref(&self) -> &Self::Target { &self.fd } } impl Drop for FdGuard { + #[inline] fn drop(&mut self) { - if !self.taken { - let _ = syscall::close(self.fd); - } + let _ = syscall::close(self.fd); } } impl Debug for FdGuard { From 6d72048b1312cb0d3fbbe61931bf085a742124c2 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sun, 13 Apr 2025 12:43:36 +0200 Subject: [PATCH 34/61] Store proc_fd in MaybeUninit with external discriminant. --- redox-rt/src/lib.rs | 29 ++++++++++++++++++----------- redox-rt/src/proc.rs | 20 +++++++++++++------- redox-rt/src/thread.rs | 9 ++++----- 3 files changed, 35 insertions(+), 23 deletions(-) diff --git a/redox-rt/src/lib.rs b/redox-rt/src/lib.rs index 43cfb811cf..f14ccbf4be 100644 --- a/redox-rt/src/lib.rs +++ b/redox-rt/src/lib.rs @@ -11,11 +11,11 @@ use core::{ cell::{SyncUnsafeCell, UnsafeCell}, - mem::size_of, + mem::{size_of, MaybeUninit}, }; use generic_rt::{ExpectTlsFree, GenericTcb}; -use syscall::{Sigcontrol, O_CLOEXEC}; +use syscall::Sigcontrol; use self::{proc::FdGuard, protocol::ProcMeta, sync::Mutex}; @@ -196,10 +196,12 @@ pub unsafe fn initialize(#[cfg(feature = "proc")] proc_fd: FdGuard) { ppid: metadata.ppid, #[cfg(feature = "proc")] - proc_fd: Some(proc_fd), + proc_fd: MaybeUninit::new(proc_fd), #[cfg(not(feature = "proc"))] - proc_fd: None, + proc_fd: MaybeUninit::uninit(), + + has_proc_fd: cfg!(feature = "proc"), }); #[cfg(feature = "proc")] @@ -216,10 +218,12 @@ pub unsafe fn initialize(#[cfg(feature = "proc")] proc_fd: FdGuard) { } } +#[repr(C)] // TODO: is this required? pub(crate) struct StaticProcInfo { pid: u32, ppid: u32, // TODO: dynamic - proc_fd: Option, + proc_fd: MaybeUninit, + has_proc_fd: bool, } struct DynamicProcInfo { pgid: u32, @@ -234,7 +238,8 @@ struct DynamicProcInfo { static STATIC_PROC_INFO: SyncUnsafeCell = SyncUnsafeCell::new(StaticProcInfo { pid: 0, ppid: 0, - proc_fd: None, + proc_fd: MaybeUninit::uninit(), + has_proc_fd: false, }); static DYNAMIC_PROC_INFO: Mutex = Mutex::new(DynamicProcInfo { pgid: u32::MAX, @@ -252,10 +257,9 @@ pub(crate) fn static_proc_info() -> &'static StaticProcInfo { } #[inline] pub fn current_proc_fd() -> &'static FdGuard { - static_proc_info() - .proc_fd - .as_ref() - .expect("proc fd must be present") + let info = static_proc_info(); + assert!(info.has_proc_fd); + unsafe { info.proc_fd.assume_init_ref() } } struct ChildHookCommonArgs { @@ -281,7 +285,10 @@ unsafe fn child_hook_common(args: ChildHookCommonArgs) { .replace(StaticProcInfo { pid: metadata.pid, ppid: metadata.ppid, - proc_fd: args.new_proc_fd, + has_proc_fd: args.new_proc_fd.is_some(), + proc_fd: args + .new_proc_fd + .map_or_else(MaybeUninit::uninit, MaybeUninit::new), }) .proc_fd; drop(old_proc_fd); diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index af8117bf7a..c4bde603f4 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -1,4 +1,7 @@ -use core::{fmt::Debug, mem::size_of}; +use core::{ + fmt::Debug, + mem::{size_of, MaybeUninit}, +}; use crate::{ arch::*, @@ -887,10 +890,12 @@ struct NewChildProc { pub fn new_child_process(args: &ForkArgs<'_>) -> Result { match *args { ForkArgs::Managed => { - let this_proc_fd = crate::static_proc_info() - .proc_fd - .as_ref() - .expect("cannot use ForkArgs::Managed without an existing proc info"); + let proc_info = crate::static_proc_info(); + assert!( + proc_info.has_proc_fd, + "cannot use ForkArgs::Managed without an existing proc info" + ); + let this_proc_fd = unsafe { proc_info.proc_fd.assume_init_ref() }; let child_proc_fd = FdGuard::new(syscall::dup(**this_proc_fd, b"fork")?); let only_thread_fd = FdGuard::new(syscall::dup(*child_proc_fd, b"thread-0")?); let meta = read_proc_meta(&child_proc_fd)?; @@ -961,7 +966,8 @@ pub unsafe fn make_init() -> [&'static FdGuard; 2] { STATIC_PROC_INFO.get().write(crate::StaticProcInfo { pid: 1, ppid: 1, - proc_fd: Some(proc_fd), + proc_fd: MaybeUninit::new(proc_fd), + has_proc_fd: true, }); *DYNAMIC_PROC_INFO.lock() = crate::DynamicProcInfo { pgid: 1, @@ -973,7 +979,7 @@ pub unsafe fn make_init() -> [&'static FdGuard; 2] { sgid: 0, }; [ - (*STATIC_PROC_INFO.get()).proc_fd.as_ref().unwrap(), + (*STATIC_PROC_INFO.get()).proc_fd.assume_init_ref(), managed_thr_fd, ] } diff --git a/redox-rt/src/thread.rs b/redox-rt/src/thread.rs index 953fce5e62..b1bc7e5652 100644 --- a/redox-rt/src/thread.rs +++ b/redox-rt/src/thread.rs @@ -1,15 +1,14 @@ use core::mem::size_of; -use syscall::{Error, Result, ESRCH, O_CLOEXEC}; +use syscall::Result; use crate::{arch::*, proc::*, signal::tmp_disable_signals, static_proc_info, RtTcb}; /// Spawns a new context sharing the same address space as the current one (i.e. a new thread). pub unsafe fn rlct_clone_impl(stack: *mut usize) -> Result { - let cur_proc_fd = static_proc_info() - .proc_fd - .as_ref() - .ok_or(Error::new(ESRCH))?; + let proc_info = static_proc_info(); + assert!(proc_info.has_proc_fd); + let cur_proc_fd = proc_info.proc_fd.assume_init_ref(); let cur_thr_fd = RtTcb::current().thread_fd(); let new_thr_fd = FdGuard::new(syscall::dup(**cur_proc_fd, b"new-thread")?); From f813f5a2223b7dcb010c84119d50460df578971e Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sun, 13 Apr 2025 20:55:35 +0200 Subject: [PATCH 35/61] Fix sigtimedwait realtime signals, almost handler too. --- redox-rt/src/arch/x86_64.rs | 45 ++++++++++++++++++++++++++++--------- redox-rt/src/lib.rs | 12 +++++----- redox-rt/src/proc.rs | 10 ++++++++- redox-rt/src/protocol.rs | 11 +++++++++ redox-rt/src/signal.rs | 33 ++++++++++++++++++--------- redox-rt/src/sys.rs | 8 +++---- 6 files changed, 87 insertions(+), 32 deletions(-) diff --git a/redox-rt/src/arch/x86_64.rs b/redox-rt/src/arch/x86_64.rs index fa2f9e372a..ca4c59423e 100644 --- a/redox-rt/src/arch/x86_64.rs +++ b/redox-rt/src/arch/x86_64.rs @@ -7,11 +7,11 @@ use core::{ use syscall::{ data::{SigProcControl, Sigcontrol}, error::*, - RtSigInfo, }; use crate::{ proc::{fork_inner, FdGuard, ForkArgs}, + protocol::{ProcCall, RtSigInfo}, signal::{get_sigaltstack, inner_c, PosixStackt, RtSigarea, SigStack, PROC_CONTROL_STRUCT}, Tcb, }; @@ -29,6 +29,9 @@ pub struct SigArea { pub tmp_rdx: usize, pub tmp_rdi: usize, pub tmp_rsi: usize, + pub tmp_r8: usize, + pub tmp_r10: usize, + pub tmp_r12: usize, pub tmp_rt_inf: RtSigInfo, pub tmp_id_inf: u64, @@ -37,6 +40,7 @@ pub struct SigArea { pub disable_signals_depth: u64, pub last_sig_was_restart: bool, pub last_sigstack: Option>, + pub proc_fd: usize, // TODO: use global variable instead, fix linker errors } #[repr(C, align(16))] @@ -188,6 +192,9 @@ asmfunction!(__relibc_internal_sigentry: [" mov fs:[{tcb_sa_off} + {sa_tmp_rdx}], rdx mov fs:[{tcb_sa_off} + {sa_tmp_rdi}], rdi mov fs:[{tcb_sa_off} + {sa_tmp_rsi}], rsi + mov fs:[{tcb_sa_off} + {sa_tmp_r12}], r8 + mov fs:[{tcb_sa_off} + {sa_tmp_r12}], r10 + mov fs:[{tcb_sa_off} + {sa_tmp_r12}], r12 // First, select signal, always pick first available bit 1: @@ -225,14 +232,24 @@ asmfunction!(__relibc_internal_sigentry: [" jc 2f // if so, continue as usual // otherwise, try (competitively) dequeueing realtime signal - mov esi, eax - mov eax, {SYS_SIGDEQUEUE} - mov rdi, fs:[0] - add rdi, {tcb_sa_off} + {sa_tmp_rt_inf} // out pointer of dequeued realtime sig + + // SYS_CALL(fd, payload_base, payload_len, metadata_base, metadata_len | (flags << 8)) + // rax rdi rsi rdx r10 r8 + + mov r12d, eax + mov rsi, fs:[0] + mov rdi, [rsi+{tcb_sa_off}+{sa_proc_fd}] + add rsi, {tcb_sa_off} + {sa_tmp_rt_inf} // out pointer of dequeued realtime sig + mov rdx, {RTINF_SIZE} + mov [rsi], eax + lea r10, [rip + {proc_call_sigdeq}] + mov r8, 1 + mov eax, {SYS_CALL} syscall + ud2 test eax, eax jnz 1b // assumes error can only be EAGAIN - lea eax, [esi + 32] + lea eax, [r12d + 32] jmp 9f 2: mov edx, eax @@ -285,13 +302,13 @@ asmfunction!(__relibc_internal_sigentry: [" push fs:[{tcb_sa_off} + {sa_tmp_rdx}] push rcx push fs:[{tcb_sa_off} + {sa_tmp_rax}] - push r8 + push fs:[{tcb_sa_off} + {sa_tmp_r8}] push r9 - push r10 + push fs:[{tcb_sa_off} + {sa_tmp_r10}] push r11 push rbx push rbp - push r12 + push fs:[{tcb_sa_off} + {sa_tmp_r12}] push r13 push r14 push r15 @@ -418,10 +435,14 @@ __relibc_internal_sigentry_crit_third: sa_tmp_rdx = const offset_of!(SigArea, tmp_rdx), sa_tmp_rdi = const offset_of!(SigArea, tmp_rdi), sa_tmp_rsi = const offset_of!(SigArea, tmp_rsi), + sa_tmp_r8 = const offset_of!(SigArea, tmp_r8), + sa_tmp_r10 = const offset_of!(SigArea, tmp_r10), + sa_tmp_r12 = const offset_of!(SigArea, tmp_r12), sa_tmp_rt_inf = const offset_of!(SigArea, tmp_rt_inf), sa_tmp_id_inf = const offset_of!(SigArea, tmp_id_inf), sa_altstack_top = const offset_of!(SigArea, altstack_top), sa_altstack_bottom = const offset_of!(SigArea, altstack_bottom), + sa_proc_fd = const offset_of!(SigArea, proc_fd), sc_saved_rflags = const offset_of!(Sigcontrol, saved_archdep_reg), sc_saved_rip = const offset_of!(Sigcontrol, saved_ip), sc_word = const offset_of!(Sigcontrol, word), @@ -437,7 +458,9 @@ __relibc_internal_sigentry_crit_third: REDZONE_SIZE = const 128, STACK_ALIGN = const 16, SA_ONSTACK_BIT = const 58, // (1 << 58) >> 32 = 0x0400_0000 - SYS_SIGDEQUEUE = const syscall::SYS_SIGDEQUEUE, + SYS_CALL = const syscall::SYS_CALL, + proc_call_sigdeq = sym PROC_CALL_SIGDEQ, + RTINF_SIZE = const size_of::(), ]); extern "C" { @@ -503,3 +526,5 @@ pub fn current_sp() -> usize { } sp } + +static PROC_CALL_SIGDEQ: u64 = ProcCall::Sigdeq as u64; diff --git a/redox-rt/src/lib.rs b/redox-rt/src/lib.rs index f14ccbf4be..314c96e661 100644 --- a/redox-rt/src/lib.rs +++ b/redox-rt/src/lib.rs @@ -17,7 +17,11 @@ use core::{ use generic_rt::{ExpectTlsFree, GenericTcb}; use syscall::Sigcontrol; -use self::{proc::FdGuard, protocol::ProcMeta, sync::Mutex}; +use self::{ + proc::{FdGuard, STATIC_PROC_INFO}, + protocol::ProcMeta, + sync::Mutex, +}; extern crate alloc; @@ -235,12 +239,6 @@ struct DynamicProcInfo { sgid: u32, } -static STATIC_PROC_INFO: SyncUnsafeCell = SyncUnsafeCell::new(StaticProcInfo { - pid: 0, - ppid: 0, - proc_fd: MaybeUninit::uninit(), - has_proc_fd: false, -}); static DYNAMIC_PROC_INFO: Mutex = Mutex::new(DynamicProcInfo { pgid: u32::MAX, ruid: u32::MAX, diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index c4bde603f4..169d8113c7 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -1,4 +1,5 @@ use core::{ + cell::SyncUnsafeCell, fmt::Debug, mem::{size_of, MaybeUninit}, }; @@ -9,7 +10,7 @@ use crate::{ protocol::{ProcCall, ThreadCall}, read_proc_meta, static_proc_info, sys::{proc_call, thread_call}, - RtTcb, DYNAMIC_PROC_INFO, STATIC_PROC_INFO, + RtTcb, StaticProcInfo, DYNAMIC_PROC_INFO, }; use alloc::{boxed::Box, collections::BTreeMap, vec}; @@ -983,3 +984,10 @@ pub unsafe fn make_init() -> [&'static FdGuard; 2] { managed_thr_fd, ] } +pub(crate) static STATIC_PROC_INFO: SyncUnsafeCell = + SyncUnsafeCell::new(StaticProcInfo { + pid: 0, + ppid: 0, + proc_fd: MaybeUninit::zeroed(), + has_proc_fd: false, + }); diff --git a/redox-rt/src/protocol.rs b/redox-rt/src/protocol.rs index eb6023324a..3eb0779123 100644 --- a/redox-rt/src/protocol.rs +++ b/redox-rt/src/protocol.rs @@ -33,6 +33,7 @@ pub enum ProcCall { // TODO: replace with sendfd equivalent syscall for sending memory SyncSigPctl = 10, + Sigdeq = 11, } #[derive(Clone, Copy, Debug, Eq, PartialEq)] #[repr(usize)] @@ -57,6 +58,7 @@ impl ProcCall { 8 => Self::Kill, 9 => Self::Sigq, 10 => Self::SyncSigPctl, + 11 => Self::Sigdeq, _ => return None, }) } @@ -147,3 +149,12 @@ impl ProcKillTarget { } } } +#[derive(Copy, Clone, Debug, Default, PartialEq)] +#[repr(C)] +pub struct RtSigInfo { + pub arg: usize, + pub code: i32, + pub uid: u32, + pub pid: u32, // TODO: usize? +} +unsafe impl plain::Plain for RtSigInfo {} diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index c0e29b5c23..73aebd612d 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -1,13 +1,19 @@ -use core::{ffi::c_int, mem::MaybeUninit, ptr::NonNull, sync::atomic::Ordering}; +use core::{ffi::c_int, ptr::NonNull, sync::atomic::Ordering}; use syscall::{ - data::AtomicU64, CallFlags, Error, RawAction, Result, RtSigInfo, SenderInfo, SetSighandlerData, + data::AtomicU64, CallFlags, Error, RawAction, Result, SenderInfo, SetSighandlerData, SigProcControl, Sigcontrol, SigcontrolFlags, TimeSpec, EAGAIN, EINTR, EINVAL, ENOMEM, EPERM, SIGCHLD, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGWINCH, }; use crate::{ - arch::*, proc::FdGuard, protocol::ThreadCall, sync::Mutex, sys::this_thread_call, RtTcb, Tcb, + arch::*, + proc::FdGuard, + protocol::{ProcCall, RtSigInfo, ThreadCall}, + static_proc_info, + sync::Mutex, + sys::{proc_call, this_thread_call}, + RtTcb, Tcb, }; #[cfg(target_arch = "x86_64")] @@ -558,6 +564,11 @@ pub fn setup_sighandler(tcb: &RtTcb) { // equivalent to not using any altstack at all (the default). arch.altstack_top = usize::MAX; arch.altstack_bottom = 0; + /*#[cfg(target_arch = "x86_64")] + unsafe { + assert!(static_proc_info().has_proc_fd); + arch.proc_fd = **static_proc_info().proc_fd.assume_init_ref(); + }*/ // TODO #[cfg(any(target_arch = "x86", target_arch = "aarch64", target_arch = "riscv64"))] { @@ -774,15 +785,17 @@ fn try_claim_single(sig_idx: u32, thread_control: Option<&Sigcontrol>) -> Option if sig_group == 1 && thread_control.is_none() { // Queued (realtime) signal - let mut ret = MaybeUninit::::uninit(); - let rt_inf = unsafe { - syscall::syscall2( - syscall::SYS_SIGDEQUEUE, - ret.as_mut_ptr() as usize, - sig_idx as usize - 32, + let rt_inf: RtSigInfo = unsafe { + let mut buf = [0_u8; size_of::()]; + buf[..4].copy_from_slice(&(sig_idx - 32).to_ne_bytes()); + proc_call( + **static_proc_info().proc_fd.assume_init_ref(), + &mut buf, + CallFlags::empty(), + &[ProcCall::Sigdeq as usize], ) .ok()?; - ret.assume_init() + core::mem::transmute(buf) }; Some(SiginfoAbi { si_signo: sig_idx as i32 + 1, diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs index 97f35dd3ea..4404c91f9f 100644 --- a/redox-rt/src/sys.rs +++ b/redox-rt/src/sys.rs @@ -6,12 +6,12 @@ use core::{ use syscall::{ error::{Error, Result, EINTR}, - CallFlags, RtSigInfo, TimeSpec, EINVAL, ERESTART, + CallFlags, TimeSpec, EINVAL, ERESTART, }; use crate::{ arch::manually_enter_trampoline, - protocol::{ProcCall, ProcKillTarget, ThreadCall, WaitFlags}, + protocol::{ProcCall, ProcKillTarget, RtSigInfo, ThreadCall, WaitFlags}, signal::tmp_disable_signals, DynamicProcInfo, RtTcb, Tcb, DYNAMIC_PROC_INFO, }; @@ -69,9 +69,9 @@ pub fn posix_sigqueue(pid: usize, sig: usize, arg: usize) -> Result<()> { uid: 0, // TODO pid: posix_getpid(), }; - match wrapper(false, false, || { + match wrapper(false, true, || { this_proc_call( - &mut siginf, + unsafe { plain::as_mut_bytes(&mut siginf) }, CallFlags::empty(), &[ProcCall::Sigq as usize, pid, sig], ) From c77354490608a8f26586b2be6a42710fb6f61000 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sun, 13 Apr 2025 21:21:28 +0200 Subject: [PATCH 36/61] Fix sigentry for realtime sigs, fixing sigqueue test. --- redox-rt/src/arch/x86_64.rs | 16 ++++++++-------- redox-rt/src/lib.rs | 9 +++++++++ redox-rt/src/signal.rs | 6 ------ 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/redox-rt/src/arch/x86_64.rs b/redox-rt/src/arch/x86_64.rs index ca4c59423e..8a85bcfaf9 100644 --- a/redox-rt/src/arch/x86_64.rs +++ b/redox-rt/src/arch/x86_64.rs @@ -1,4 +1,5 @@ use core::{ + cell::SyncUnsafeCell, mem::offset_of, ptr::NonNull, sync::atomic::{AtomicU8, Ordering}, @@ -40,7 +41,6 @@ pub struct SigArea { pub disable_signals_depth: u64, pub last_sig_was_restart: bool, pub last_sigstack: Option>, - pub proc_fd: usize, // TODO: use global variable instead, fix linker errors } #[repr(C, align(16))] @@ -233,20 +233,19 @@ asmfunction!(__relibc_internal_sigentry: [" // otherwise, try (competitively) dequeueing realtime signal - // SYS_CALL(fd, payload_base, payload_len, metadata_base, metadata_len | (flags << 8)) - // rax rdi rsi rdx r10 r8 + // SYS_CALL(fd, payload_base, payload_len, metadata_len, metadata_base | (flags << 8)) + // rax rdi rsi rdx r10 r8 mov r12d, eax mov rsi, fs:[0] - mov rdi, [rsi+{tcb_sa_off}+{sa_proc_fd}] + mov rdi, [rip+{proc_fd}] add rsi, {tcb_sa_off} + {sa_tmp_rt_inf} // out pointer of dequeued realtime sig mov rdx, {RTINF_SIZE} mov [rsi], eax - lea r10, [rip + {proc_call_sigdeq}] - mov r8, 1 + lea r8, [rip + {proc_call_sigdeq}] + mov r10, 1 mov eax, {SYS_CALL} syscall - ud2 test eax, eax jnz 1b // assumes error can only be EAGAIN lea eax, [r12d + 32] @@ -442,7 +441,6 @@ __relibc_internal_sigentry_crit_third: sa_tmp_id_inf = const offset_of!(SigArea, tmp_id_inf), sa_altstack_top = const offset_of!(SigArea, altstack_top), sa_altstack_bottom = const offset_of!(SigArea, altstack_bottom), - sa_proc_fd = const offset_of!(SigArea, proc_fd), sc_saved_rflags = const offset_of!(Sigcontrol, saved_archdep_reg), sc_saved_rip = const offset_of!(Sigcontrol, saved_ip), sc_word = const offset_of!(Sigcontrol, word), @@ -461,6 +459,7 @@ __relibc_internal_sigentry_crit_third: SYS_CALL = const syscall::SYS_CALL, proc_call_sigdeq = sym PROC_CALL_SIGDEQ, RTINF_SIZE = const size_of::(), + proc_fd = sym PROC_FD, ]); extern "C" { @@ -528,3 +527,4 @@ pub fn current_sp() -> usize { } static PROC_CALL_SIGDEQ: u64 = ProcCall::Sigdeq as u64; +pub(crate) static PROC_FD: SyncUnsafeCell = SyncUnsafeCell::new(usize::MAX); diff --git a/redox-rt/src/lib.rs b/redox-rt/src/lib.rs index 314c96e661..3b63c5543d 100644 --- a/redox-rt/src/lib.rs +++ b/redox-rt/src/lib.rs @@ -195,6 +195,11 @@ pub unsafe fn initialize(#[cfg(feature = "proc")] proc_fd: FdGuard) { // Bootstrap mode, don't associate proc fds with PIDs let metadata = ProcMeta::default(); + #[cfg(feature = "proc")] + { + crate::arch::PROC_FD.get().write(*proc_fd); + } + STATIC_PROC_INFO.get().write(StaticProcInfo { pid: metadata.pid, ppid: metadata.ppid, @@ -278,6 +283,10 @@ unsafe fn child_hook_common(args: ChildHookCommonArgs) { #[cfg(not(feature = "proc"))] let metadata = ProcMeta::default(); + if let Some(proc_fd) = &args.new_proc_fd { + crate::arch::PROC_FD.get().write(**proc_fd); + } + let old_proc_fd = STATIC_PROC_INFO .get() .replace(StaticProcInfo { diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index 73aebd612d..9b480a6556 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -564,12 +564,6 @@ pub fn setup_sighandler(tcb: &RtTcb) { // equivalent to not using any altstack at all (the default). arch.altstack_top = usize::MAX; arch.altstack_bottom = 0; - /*#[cfg(target_arch = "x86_64")] - unsafe { - assert!(static_proc_info().has_proc_fd); - arch.proc_fd = **static_proc_info().proc_fd.assume_init_ref(); - }*/ - // TODO #[cfg(any(target_arch = "x86", target_arch = "aarch64", target_arch = "riscv64"))] { arch.pctl = core::ptr::addr_of!(PROC_CONTROL_STRUCT) as usize; From 0213ac2d15f71bd5c188406f0e82e1763a55f393 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Mon, 14 Apr 2025 20:17:27 +0200 Subject: [PATCH 37/61] Probably fix aarch. Bootloader is currently panicking so a bit hard to test. --- redox-rt/src/arch/aarch64.rs | 50 +++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/redox-rt/src/arch/aarch64.rs b/redox-rt/src/arch/aarch64.rs index 0e4dbbc76a..28096ebde9 100644 --- a/redox-rt/src/arch/aarch64.rs +++ b/redox-rt/src/arch/aarch64.rs @@ -1,9 +1,10 @@ -use core::{mem::offset_of, ptr::NonNull}; +use core::{cell::SyncUnsafeCell, mem::offset_of, ptr::NonNull}; use syscall::{data::*, error::*}; use crate::{ - proc::{fork_inner, FdGuard}, + proc::{fork_inner, FdGuard, ForkArgs}, + protocol::{ProcCall, RtSigInfo}, signal::{inner_c, PosixStackt, RtSigarea, SigStack, PROC_CONTROL_STRUCT}, RtTcb, Tcb, }; @@ -20,6 +21,7 @@ pub struct SigArea { pub tmp_x1_x2: [usize; 2], pub tmp_x3_x4: [usize; 2], pub tmp_x5_x6: [usize; 2], + pub tmp_x7_x8: [usize; 2], pub tmp_sp: usize, pub onstack: u64, pub disable_signals_depth: u64, @@ -97,8 +99,8 @@ pub fn copy_env_regs(cur_pid_fd: usize, new_pid_fd: usize) -> Result<()> { Ok(()) } -unsafe extern "C" fn fork_impl(initial_rsp: *mut usize) -> usize { - Error::mux(fork_inner(initial_rsp)) +unsafe extern "C" fn fork_impl(args: &ForkArgs, initial_rsp: *mut usize) -> usize { + Error::mux(fork_inner(initial_rsp, args)) } unsafe extern "C" fn child_hook(cur_filetable_fd: usize, new_pid_fd: usize) { @@ -110,7 +112,7 @@ unsafe extern "C" fn child_hook(cur_filetable_fd: usize, new_pid_fd: usize) { .write(Some(FdGuard::new(new_pid_fd))); } -asmfunction!(__relibc_internal_fork_wrapper -> usize: [" +asmfunction!(__relibc_internal_fork_wrapper (usize) -> usize: [" stp x29, x30, [sp, #-16]! stp x27, x28, [sp, #-16]! stp x25, x26, [sp, #-16]! @@ -122,7 +124,8 @@ asmfunction!(__relibc_internal_fork_wrapper -> usize: [" //TODO: store floating point regs - mov x0, sp + // x0: &ForkArgs + mov x1, sp bl {fork_impl} add sp, sp, #32 @@ -167,6 +170,7 @@ asmfunction!(__relibc_internal_sigentry: [" stp x1, x2, [x0, #{tcb_sa_off} + {sa_tmp_x1_x2}] stp x3, x4, [x0, #{tcb_sa_off} + {sa_tmp_x3_x4}] stp x5, x6, [x0, #{tcb_sa_off} + {sa_tmp_x5_x6}] + stp x7, x8, [x0, #{tcb_sa_off} + {sa_tmp_x7_x8}] mov x1, sp str x1, [x0, #{tcb_sa_off} + {sa_tmp_sp}] @@ -240,14 +244,21 @@ asmfunction!(__relibc_internal_sigentry: [" lsr x3, x1, x2 tbnz x3, #0, 5f - mov x5, x0 - mov x4, x8 - mov x8, #{SYS_SIGDEQUEUE} - mov x0, x1 - add x1, x0, #{tcb_sa_off} + {sa_tmp_rt_inf} + // SYS_CALL(fd, payload_base, payload_len, metadata_len, metadata_base | (flags << 8)) + // x8 x0 x1 x2 x3 x4 + + mov x5, x0 // save TCB pointer + ldr x8, ={SYS_CALL} + adrp x0, {proc_fd} + ldr x0, [x0, #:lo12:{proc_fd}] + add x1, x5, #{tcb_sa_off} + {sa_tmp_rt_inf} + str x2, [x1] + mov x2, #{RTINF_SIZE} + adrp x3, {proc_call} + add x3, x3, :lo12:{proc_call} + mov x4, #1 svc 0 - mov x0, x5 - mov x8, x4 + mov x0, x5 // restore TCB pointer cbnz x0, 1b b 2f @@ -328,8 +339,9 @@ asmfunction!(__relibc_internal_sigentry: [" stp x4, x3, [sp, #-16]! ldp x5, x6, [x0, #{tcb_sa_off} + {sa_tmp_x5_x6}] stp x6, x5, [sp, #-16]! - + ldp x7, x8, [x0, #{tcb_sa_off} + {sa_tmp_x7_x8}] stp x8, x7, [sp, #-16]! + stp x10, x9, [sp, #-16]! stp x12, x11, [sp, #-16]! stp x14, x13, [sp, #-16]! @@ -400,6 +412,7 @@ asmfunction!(__relibc_internal_sigentry: [" sa_tmp_x1_x2 = const offset_of!(SigArea, tmp_x1_x2), sa_tmp_x3_x4 = const offset_of!(SigArea, tmp_x3_x4), sa_tmp_x5_x6 = const offset_of!(SigArea, tmp_x5_x6), + sa_tmp_x7_x8 = const offset_of!(SigArea, tmp_x7_x8), sa_tmp_sp = const offset_of!(SigArea, tmp_sp), sa_tmp_rt_inf = const offset_of!(SigArea, tmp_rt_inf), sa_tmp_id_inf = const offset_of!(SigArea, tmp_id_inf), @@ -409,12 +422,17 @@ asmfunction!(__relibc_internal_sigentry: [" sc_sender_infos = const offset_of!(Sigcontrol, sender_infos), sc_word = const offset_of!(Sigcontrol, word), sc_flags = const offset_of!(Sigcontrol, control_flags), + proc_fd = sym PROC_FD, inner = sym inner_c, + proc_call = sym PROC_CALL, SA_ONSTACK_BIT = const 58, // (1 << 58) >> 32 = 0x0400_0000 - SYS_SIGDEQUEUE = const syscall::SYS_SIGDEQUEUE, + + SYS_CALL = const syscall::SYS_CALL, + STACK_ALIGN = const 16, REDZONE_SIZE = const 128, + RTINF_SIZE = const size_of::(), ]); asmfunction!(__relibc_internal_rlct_clone_ret: [" @@ -460,3 +478,5 @@ pub unsafe fn arch_pre(stack: &mut SigStack, os: &mut SigArea) -> PosixStackt { flags: 0, // TODO } } +pub(crate) static PROC_FD: SyncUnsafeCell = SyncUnsafeCell::new(usize::MAX); +static PROC_CALL: &[usize] = &[ProcCall::Sigdeq as usize]; From 2fbbdcc1c9f84027f8779928ac5f39083727e25c Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Mon, 14 Apr 2025 23:25:47 +0200 Subject: [PATCH 38/61] Aarch64 fix, make i686 compile. --- redox-rt/src/arch/aarch64.rs | 8 ++-- redox-rt/src/arch/i686.rs | 72 ++++++++++++++++++++++++++---------- redox-rt/src/arch/x86_64.rs | 4 +- redox-rt/src/proc.rs | 10 +++-- 4 files changed, 66 insertions(+), 28 deletions(-) diff --git a/redox-rt/src/arch/aarch64.rs b/redox-rt/src/arch/aarch64.rs index 28096ebde9..60ec437c88 100644 --- a/redox-rt/src/arch/aarch64.rs +++ b/redox-rt/src/arch/aarch64.rs @@ -254,9 +254,9 @@ asmfunction!(__relibc_internal_sigentry: [" add x1, x5, #{tcb_sa_off} + {sa_tmp_rt_inf} str x2, [x1] mov x2, #{RTINF_SIZE} - adrp x3, {proc_call} - add x3, x3, :lo12:{proc_call} - mov x4, #1 + adrp x4, {proc_call} + add x4, x4, :lo12:{proc_call} + mov x3, #1 svc 0 mov x0, x5 // restore TCB pointer cbnz x0, 1b @@ -479,4 +479,4 @@ pub unsafe fn arch_pre(stack: &mut SigStack, os: &mut SigArea) -> PosixStackt { } } pub(crate) static PROC_FD: SyncUnsafeCell = SyncUnsafeCell::new(usize::MAX); -static PROC_CALL: &[usize] = &[ProcCall::Sigdeq as usize]; +static PROC_CALL: [usize; 1] = [ProcCall::Sigdeq as usize]; diff --git a/redox-rt/src/arch/i686.rs b/redox-rt/src/arch/i686.rs index 71319f50d5..2e2db3ab07 100644 --- a/redox-rt/src/arch/i686.rs +++ b/redox-rt/src/arch/i686.rs @@ -1,9 +1,10 @@ -use core::{mem::offset_of, ptr::NonNull, sync::atomic::Ordering}; +use core::{cell::SyncUnsafeCell, mem::offset_of, ptr::NonNull, sync::atomic::Ordering}; use syscall::*; use crate::{ - proc::{fork_inner, FdGuard}, + proc::{fork_inner, FdGuard, ForkArgs}, + protocol::{ProcCall, RtSigInfo}, signal::{inner_fastcall, PosixStackt, RtSigarea, SigStack, PROC_CONTROL_STRUCT}, RtTcb, }; @@ -20,8 +21,11 @@ pub struct SigArea { pub tmp_eip: usize, pub tmp_esp: usize, pub tmp_eax: usize, + pub tmp_ebx: usize, pub tmp_ecx: usize, pub tmp_edx: usize, + pub tmp_edi: usize, + pub tmp_esi: usize, pub tmp_rt_inf: RtSigInfo, pub tmp_id_inf: u64, pub tmp_mm0: u64, @@ -79,16 +83,30 @@ pub fn copy_env_regs(cur_pid_fd: usize, new_pid_fd: usize) -> Result<()> { Ok(()) } -unsafe extern "cdecl" fn fork_impl(initial_rsp: *mut usize) -> usize { - Error::mux(fork_inner(initial_rsp)) +unsafe extern "fastcall" fn fork_impl(args: &ForkArgs, initial_rsp: *mut usize) -> usize { + Error::mux(fork_inner(initial_rsp, args)) } -unsafe extern "cdecl" fn child_hook(cur_filetable_fd: usize, new_pid_fd: usize) { +// TODO: duplicate code with x86_64 +unsafe extern "cdecl" fn child_hook( + cur_filetable_fd: usize, + new_proc_fd: usize, + new_thr_fd: usize, +) { let _ = syscall::close(cur_filetable_fd); - crate::child_hook_common(FdGuard::new(new_pid_fd)); + crate::child_hook_common(crate::ChildHookCommonArgs { + new_thr_fd: FdGuard::new(new_thr_fd), + new_proc_fd: if new_proc_fd == usize::MAX { + None + } else { + Some(FdGuard::new(new_proc_fd)) + }, + }); } -asmfunction!(__relibc_internal_fork_wrapper -> usize: [" +asmfunction!(__relibc_internal_fork_wrapper (usize) -> usize: [" + mov ecx, [esp+4] + push ebp mov ebp, esp @@ -103,9 +121,9 @@ asmfunction!(__relibc_internal_fork_wrapper -> usize: [" //TODO stmxcsr [esp+16] fnstcw [esp+24] - push esp + mov edx, esp call {fork_impl} - pop esp + jmp 2f "] <= [fork_impl = sym fork_impl]); @@ -137,6 +155,9 @@ asmfunction!(__relibc_internal_sigentry: [" mov gs:[{tcb_sa_off} + {sa_tmp_eax}], eax mov gs:[{tcb_sa_off} + {sa_tmp_edx}], edx mov gs:[{tcb_sa_off} + {sa_tmp_ecx}], ecx + mov gs:[{tcb_sa_off} + {sa_tmp_ebx}], ebx + mov gs:[{tcb_sa_off} + {sa_tmp_edi}], edi + mov gs:[{tcb_sa_off} + {sa_tmp_esi}], esi 1: // Read standard signal word - first for this thread mov edx, gs:[{tcb_sc_off} + {sc_word} + 4] @@ -176,13 +197,18 @@ asmfunction!(__relibc_internal_sigentry: [" bt edx, eax jc 8f - mov edx, ebx - lea ecx, [eax+32] - mov eax, {SYS_SIGDEQUEUE} - mov edx, gs:[0] - add edx, {tcb_sa_off} + {sa_tmp_rt_inf} + // SYS_CALL(fd, payload_base, payload_len, metadata_len, metadata_base) + // eax ebx ecx edx esi edi + + mov ebx, [{proc_fd}] + mov ecx, gs:[0] + add ecx, {tcb_sa_off} + {sa_tmp_rt_inf} + lea edx, [eax+32] + mov [ecx], edx + mov esi, 1 + mov edi, {proc_call} + mov eax, {SYS_CALL} int 0x80 - mov ebx, edx test eax, eax jnz 1b @@ -228,9 +254,9 @@ asmfunction!(__relibc_internal_sigentry: [" push dword ptr gs:[{tcb_sa_off} + {sa_tmp_edx}] push dword ptr gs:[{tcb_sa_off} + {sa_tmp_ecx}] push dword ptr gs:[{tcb_sa_off} + {sa_tmp_eax}] - push ebx - push edi - push esi + push dword ptr gs:[{tcb_sa_off} + {sa_tmp_ebx}] + push dword ptr gs:[{tcb_sa_off} + {sa_tmp_edi}] + push dword ptr gs:[{tcb_sa_off} + {sa_tmp_esi}] push ebp sub esp, 2 * 4 + 29 * 16 @@ -286,8 +312,11 @@ __relibc_internal_sigentry_crit_third: sa_tmp_eip = const offset_of!(SigArea, tmp_eip), sa_tmp_esp = const offset_of!(SigArea, tmp_esp), sa_tmp_eax = const offset_of!(SigArea, tmp_eax), + sa_tmp_ebx = const offset_of!(SigArea, tmp_ebx), sa_tmp_ecx = const offset_of!(SigArea, tmp_ecx), sa_tmp_edx = const offset_of!(SigArea, tmp_edx), + sa_tmp_edi = const offset_of!(SigArea, tmp_edi), + sa_tmp_esi = const offset_of!(SigArea, tmp_esi), sa_tmp_mm0 = const offset_of!(SigArea, tmp_mm0), sa_tmp_rt_inf = const offset_of!(SigArea, tmp_rt_inf), sa_tmp_id_inf = const offset_of!(SigArea, tmp_id_inf), @@ -305,8 +334,10 @@ __relibc_internal_sigentry_crit_third: pctl_sender_infos = const offset_of!(SigProcControl, sender_infos), pctl_pending = const offset_of!(SigProcControl, pending), pctl = sym PROC_CONTROL_STRUCT, + proc_fd = sym PROC_FD, + proc_call = sym PROC_CALL, STACK_ALIGN = const 16, - SYS_SIGDEQUEUE = const syscall::SYS_SIGDEQUEUE, + SYS_CALL = const syscall::SYS_CALL, ]); asmfunction!(__relibc_internal_rlct_clone_ret -> usize: [" @@ -377,3 +408,6 @@ pub fn current_sp() -> usize { } sp } + +pub static PROC_FD: SyncUnsafeCell = SyncUnsafeCell::new(usize::MAX); +static PROC_CALL: [usize; 1] = [ProcCall::Sigdeq as usize]; diff --git a/redox-rt/src/arch/x86_64.rs b/redox-rt/src/arch/x86_64.rs index 8a85bcfaf9..3a9f1b0166 100644 --- a/redox-rt/src/arch/x86_64.rs +++ b/redox-rt/src/arch/x86_64.rs @@ -233,8 +233,8 @@ asmfunction!(__relibc_internal_sigentry: [" // otherwise, try (competitively) dequeueing realtime signal - // SYS_CALL(fd, payload_base, payload_len, metadata_len, metadata_base | (flags << 8)) - // rax rdi rsi rdx r10 r8 + // SYS_CALL(fd, payload_base, payload_len, metadata_len | (flags << 8), metadata_base) + // rax rdi rsi rdx r10 r8 mov r12d, eax mov rsi, fs:[0] diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index 169d8113c7..561aacc703 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -121,7 +121,7 @@ where |o| core::mem::take(&mut o.tree), ); - pread_all(*image_file as usize, header.e_phoff.into(), phs).map_err(|_| Error::new(EIO))?; + pread_all(*image_file as usize, u64::from(header.e_phoff), phs).map_err(|_| Error::new(EIO))?; for ph_idx in 0..phnum { let ph_bytes = &phs[ph_idx * phentsize..(ph_idx + 1) * phentsize]; @@ -144,7 +144,11 @@ where // PT_INTERP must come before any PT_LOAD, so we don't have to iterate twice. PT_INTERP => { let mut interp = vec![0_u8; segment.p_filesz as usize]; - pread_all(*image_file as usize, segment.p_offset.into(), &mut interp)?; + pread_all( + *image_file as usize, + u64::from(segment.p_offset), + &mut interp, + )?; return Ok(FexecResult::Interp { path: interp.into_boxed_slice(), @@ -193,7 +197,7 @@ where }; pread_all( *image_file, - segment.p_offset.into(), + u64::from(segment.p_offset), &mut dst_memory[voff..voff + filesz], )?; } From 05481b36a6aa4efd680d484bd0a58cf8c637841f Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Mon, 14 Apr 2025 23:42:02 +0200 Subject: [PATCH 39/61] Fix IPC size on i686. --- redox-rt/src/arch/i686.rs | 2 +- redox-rt/src/proc.rs | 4 ++-- redox-rt/src/signal.rs | 4 ++-- redox-rt/src/sys.rs | 36 ++++++++++++++++-------------------- src/platform/mod.rs | 2 +- 5 files changed, 22 insertions(+), 26 deletions(-) diff --git a/redox-rt/src/arch/i686.rs b/redox-rt/src/arch/i686.rs index 2e2db3ab07..90eb2dc823 100644 --- a/redox-rt/src/arch/i686.rs +++ b/redox-rt/src/arch/i686.rs @@ -410,4 +410,4 @@ pub fn current_sp() -> usize { } pub static PROC_FD: SyncUnsafeCell = SyncUnsafeCell::new(usize::MAX); -static PROC_CALL: [usize; 1] = [ProcCall::Sigdeq as usize]; +static PROC_CALL: u64 = ProcCall::Sigdeq as u64; diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index 561aacc703..031b2a02cb 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -854,13 +854,13 @@ pub fn fork_inner(initial_rsp: *mut usize, args: &ForkArgs) -> Result { **proc_fd, &mut [], CallFlags::empty(), - &[ProcCall::SyncSigPctl as usize], + &[ProcCall::SyncSigPctl as u64], )?; thread_call( *new_thr_fd, &mut [], CallFlags::empty(), - &[ThreadCall::SyncSigTctl as usize], + &[ThreadCall::SyncSigTctl as u64], )?; } } diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index 9b480a6556..682b89d7d2 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -586,7 +586,7 @@ pub fn setup_sighandler(tcb: &RtTcb) { this_thread_call( &mut [], CallFlags::empty(), - &[ThreadCall::SyncSigTctl as usize], + &[ThreadCall::SyncSigTctl as u64], ) .expect("failed to sync signal tctl"); @@ -786,7 +786,7 @@ fn try_claim_single(sig_idx: u32, thread_control: Option<&Sigcontrol>) -> Option **static_proc_info().proc_fd.assume_init_ref(), &mut buf, CallFlags::empty(), - &[ProcCall::Sigdeq as usize], + &[ProcCall::Sigdeq as u64], ) .ok()?; core::mem::transmute(buf) diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs index 4404c91f9f..2fcc30c969 100644 --- a/redox-rt/src/sys.rs +++ b/redox-rt/src/sys.rs @@ -54,7 +54,7 @@ pub fn posix_kill(target: ProcKillTarget, sig: usize) -> Result<()> { this_proc_call( &mut [], CallFlags::empty(), - &[ProcCall::Kill as usize, target.raw(), sig], + &[ProcCall::Kill as u64, target.raw() as u64, sig as u64], ) }) { Ok(_) | Err(Error { errno: ERESTART }) => Ok(()), @@ -73,7 +73,7 @@ pub fn posix_sigqueue(pid: usize, sig: usize, arg: usize) -> Result<()> { this_proc_call( unsafe { plain::as_mut_bytes(&mut siginf) }, CallFlags::empty(), - &[ProcCall::Sigq as usize, pid, sig], + &[ProcCall::Sigq as u64, pid as u64, sig as u64], ) }) { Ok(_) | Err(Error { errno: EINTR }) => Ok(()), @@ -120,7 +120,7 @@ pub fn sys_call( fd: usize, payload: &mut [u8], flags: CallFlags, - metadata: &[usize], + metadata: &[u64], ) -> Result { unsafe { syscall::syscall5( @@ -133,14 +133,14 @@ pub fn sys_call( ) } } -pub fn this_proc_call(payload: &mut [u8], flags: CallFlags, metadata: &[usize]) -> Result { +pub fn this_proc_call(payload: &mut [u8], flags: CallFlags, metadata: &[u64]) -> Result { proc_call(**crate::current_proc_fd(), payload, flags, metadata) } pub fn proc_call( proc_fd: usize, payload: &mut [u8], flags: CallFlags, - metadata: &[usize], + metadata: &[u64], ) -> Result { sys_call(proc_fd, payload, flags, metadata) } @@ -148,11 +148,11 @@ pub fn thread_call( thread_fd: usize, payload: &mut [u8], flags: CallFlags, - metadata: &[usize], + metadata: &[u64], ) -> Result { sys_call(thread_fd, payload, flags, metadata) } -pub fn this_thread_call(payload: &mut [u8], flags: CallFlags, metadata: &[usize]) -> Result { +pub fn this_thread_call(payload: &mut [u8], flags: CallFlags, metadata: &[u64]) -> Result { thread_call(**RtTcb::current().thread_fd(), payload, flags, metadata) } @@ -187,7 +187,7 @@ pub fn sys_waitpid(target: WaitpidTarget, status: &mut usize, flags: WaitFlags) this_proc_call( unsafe { plain::as_mut_bytes(status) }, CallFlags::empty(), - &[call as usize, pid, flags.bits() as usize], + &[call as u64, pid as u64, flags.bits() as u64], ) }) } @@ -197,7 +197,7 @@ pub fn posix_kill_thread(thread_fd: usize, signal: u32) -> Result<()> { thread_fd, &mut [], CallFlags::empty(), - &[ThreadCall::SignalThread as usize, signal as usize], + &[ThreadCall::SignalThread as u64, signal.into()], ) }) { Ok(_) | Err(Error { errno: ERESTART }) => Ok(()), @@ -250,11 +250,7 @@ pub fn posix_setresugid(ids: &Resugid>) -> Result<()> { ids.sgid.unwrap_or(u32::MAX), ]); - this_proc_call( - &mut buf, - CallFlags::empty(), - &[ProcCall::SetResugid as usize], - )?; + this_proc_call(&mut buf, CallFlags::empty(), &[ProcCall::SetResugid as u64])?; if let Some(ruid) = ids.ruid { guard.ruid = ruid; @@ -301,7 +297,7 @@ pub fn posix_exit(status: i32) -> ! { this_proc_call( &mut [], CallFlags::empty(), - &[ProcCall::Exit as usize, status as usize], + &[ProcCall::Exit as u64, status as u64], ) .expect("failed to call proc mgr with Exit"); unreachable!() @@ -310,7 +306,7 @@ pub fn setrens(rns: usize, ens: usize) -> Result<()> { this_proc_call( &mut [], CallFlags::empty(), - &[ProcCall::Setrens as usize, rns, ens], + &[ProcCall::Setrens as u64, rns as u64, ens as u64], )?; Ok(()) } @@ -318,7 +314,7 @@ pub fn posix_getpgid(pid: usize) -> Result { this_proc_call( &mut [], CallFlags::empty(), - &[ProcCall::Setpgid as usize, pid, usize::wrapping_neg(1)], + &[ProcCall::Setpgid as u64, pid as u64, u64::wrapping_neg(1)], ) } pub fn posix_setpgid(pid: usize, pgid: usize) -> Result<()> { @@ -328,7 +324,7 @@ pub fn posix_setpgid(pid: usize, pgid: usize) -> Result<()> { this_proc_call( &mut [], CallFlags::empty(), - &[ProcCall::Setpgid as usize, pid, pgid], + &[ProcCall::Setpgid as u64, pid as u64, pgid as u64], )?; Ok(()) } @@ -336,10 +332,10 @@ pub fn posix_getsid(pid: usize) -> Result { this_proc_call( &mut [], CallFlags::empty(), - &[ProcCall::Getsid as usize, pid], + &[ProcCall::Getsid as u64, pid as u64], ) } pub fn posix_setsid() -> Result<()> { - this_proc_call(&mut [], CallFlags::empty(), &[ProcCall::Setsid as usize])?; + this_proc_call(&mut [], CallFlags::empty(), &[ProcCall::Setsid as u64])?; Ok(()) } diff --git a/src/platform/mod.rs b/src/platform/mod.rs index 611d32ba4b..588c526951 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -339,7 +339,7 @@ pub unsafe fn init(auxvs: Box<[[usize; 2]]>) { redox_rt::sys::this_proc_call( &mut [], syscall::CallFlags::empty(), - &[redox_rt::protocol::ProcCall::SyncSigPctl as usize], + &[redox_rt::protocol::ProcCall::SyncSigPctl as u64], ) .expect("failed to sync signal pctl"); From 26c92af7ba6bc2023566384cb72cffe2a8108814 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Tue, 15 Apr 2025 00:12:57 +0200 Subject: [PATCH 40/61] Fix SigSet length. --- src/header/signal/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/header/signal/mod.rs b/src/header/signal/mod.rs index 77189fc98b..9f00dbc1ae 100644 --- a/src/header/signal/mod.rs +++ b/src/header/signal/mod.rs @@ -23,7 +23,7 @@ pub mod sys; #[path = "redox.rs"] pub mod sys; -type SigSet = BitSet<[c_ulong; 1]>; +type SigSet = BitSet<[u64; 1]>; pub(crate) const SIG_DFL: usize = 0; pub(crate) const SIG_IGN: usize = 1; From fb8e3cd751e67c977db8e48f9e82df8cd3706a3b Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Tue, 15 Apr 2025 12:16:51 +0200 Subject: [PATCH 41/61] Fix sigqueue on i686. --- redox-rt/src/arch/i686.rs | 27 ++++++++++++++++----------- redox-rt/src/signal.rs | 2 +- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/redox-rt/src/arch/i686.rs b/redox-rt/src/arch/i686.rs index 90eb2dc823..b089a607bb 100644 --- a/redox-rt/src/arch/i686.rs +++ b/redox-rt/src/arch/i686.rs @@ -27,9 +27,9 @@ pub struct SigArea { pub tmp_edi: usize, pub tmp_esi: usize, pub tmp_rt_inf: RtSigInfo, + pub tmp_signo: usize, pub tmp_id_inf: u64, pub tmp_mm0: u64, - pub pctl: usize, // TODO: reference pctl directly pub disable_signals_depth: u64, pub last_sig_was_restart: bool, pub last_sigstack: Option>, @@ -166,9 +166,8 @@ asmfunction!(__relibc_internal_sigentry: [" bsf eax, eax jnz 9f - mov ecx, gs:[{tcb_sa_off} + {sa_pctl}] - // Read standard signal word - for the process + lea ecx, [{pctl}] mov eax, [ecx + {pctl_pending}] and eax, edx bsf eax, eax @@ -190,12 +189,12 @@ asmfunction!(__relibc_internal_sigentry: [" mov eax, gs:[{tcb_sc_off} + {sc_word} + 8] or eax, edx and eax, gs:[{tcb_sc_off} + {sc_word} + 12] - jz 7f // spurious signal bsf eax, eax + jz 7f // spurious signal - // If thread was specifically targeted, send the signal to it first. + // If thread rather than process was specifically targeted, send the signal to it first. bt edx, eax - jc 8f + jnc 8f // SYS_CALL(fd, payload_base, payload_len, metadata_len, metadata_base) // eax ebx ecx edx esi edi @@ -203,16 +202,18 @@ asmfunction!(__relibc_internal_sigentry: [" mov ebx, [{proc_fd}] mov ecx, gs:[0] add ecx, {tcb_sa_off} + {sa_tmp_rt_inf} - lea edx, [eax+32] - mov [ecx], edx + mov [ecx], eax + mov gs:[{tcb_sa_off} + {sa_tmp_signo}], eax + mov edx, {RTINF_SIZE} mov esi, 1 - mov edi, {proc_call} + lea edi, [{proc_call}] mov eax, {SYS_CALL} int 0x80 test eax, eax jnz 1b - mov eax, ecx + mov eax, gs:[{tcb_sa_off} + {sa_tmp_signo}] + add eax, 32 jmp 2f 8: add eax, 32 @@ -300,8 +301,11 @@ __relibc_internal_sigentry_crit_second: mov gs:[{tcb_sa_off} + {sa_tmp_eip}], eax mov eax, gs:[{tcb_sa_off} + {sa_tmp_eax}] + mov ebx, gs:[{tcb_sa_off} + {sa_tmp_ebx}] mov ecx, gs:[{tcb_sa_off} + {sa_tmp_ecx}] mov edx, gs:[{tcb_sa_off} + {sa_tmp_edx}] + mov edi, gs:[{tcb_sa_off} + {sa_tmp_edi}] + mov esi, gs:[{tcb_sa_off} + {sa_tmp_esi}] and dword ptr gs:[{tcb_sc_off} + {sc_control}], ~1 .globl __relibc_internal_sigentry_crit_third @@ -320,9 +324,9 @@ __relibc_internal_sigentry_crit_third: sa_tmp_mm0 = const offset_of!(SigArea, tmp_mm0), sa_tmp_rt_inf = const offset_of!(SigArea, tmp_rt_inf), sa_tmp_id_inf = const offset_of!(SigArea, tmp_id_inf), + sa_tmp_signo = const offset_of!(SigArea, tmp_signo), sa_altstack_top = const offset_of!(SigArea, altstack_top), sa_altstack_bottom = const offset_of!(SigArea, altstack_bottom), - sa_pctl = const offset_of!(SigArea, pctl), sc_control = const offset_of!(Sigcontrol, control_flags), sc_saved_eflags = const offset_of!(Sigcontrol, saved_archdep_reg), sc_saved_eip = const offset_of!(Sigcontrol, saved_ip), @@ -338,6 +342,7 @@ __relibc_internal_sigentry_crit_third: proc_call = sym PROC_CALL, STACK_ALIGN = const 16, SYS_CALL = const syscall::SYS_CALL, + RTINF_SIZE = const size_of::(), ]); asmfunction!(__relibc_internal_rlct_clone_ret -> usize: [" diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index 682b89d7d2..16f5de3e53 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -564,7 +564,7 @@ pub fn setup_sighandler(tcb: &RtTcb) { // equivalent to not using any altstack at all (the default). arch.altstack_top = usize::MAX; arch.altstack_bottom = 0; - #[cfg(any(target_arch = "x86", target_arch = "aarch64", target_arch = "riscv64"))] + #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] { arch.pctl = core::ptr::addr_of!(PROC_CONTROL_STRUCT) as usize; } From 1c6b3ad78b09bd07c0d004948d0340a628e46e64 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Tue, 15 Apr 2025 12:48:16 +0200 Subject: [PATCH 42/61] Fix aarch64 child_hook. --- redox-rt/src/arch/aarch64.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/redox-rt/src/arch/aarch64.rs b/redox-rt/src/arch/aarch64.rs index 60ec437c88..093d1c91be 100644 --- a/redox-rt/src/arch/aarch64.rs +++ b/redox-rt/src/arch/aarch64.rs @@ -103,13 +103,16 @@ unsafe extern "C" fn fork_impl(args: &ForkArgs, initial_rsp: *mut usize) -> usiz Error::mux(fork_inner(initial_rsp, args)) } -unsafe extern "C" fn child_hook(cur_filetable_fd: usize, new_pid_fd: usize) { +unsafe extern "C" fn child_hook(cur_filetable_fd: usize, new_proc_fd: usize, new_thr_fd: usize) { let _ = syscall::close(cur_filetable_fd); - // TODO: Currently pidfd == threadfd, but this will not be the case later. - RtTcb::current() - .thr_fd - .get() - .write(Some(FdGuard::new(new_pid_fd))); + crate::child_hook_common(crate::ChildHookCommonArgs { + new_thr_fd: FdGuard::new(new_thr_fd), + new_proc_fd: if new_proc_fd == usize::MAX { + None + } else { + Some(FdGuard::new(new_proc_fd)) + }, + }); } asmfunction!(__relibc_internal_fork_wrapper (usize) -> usize: [" @@ -139,14 +142,14 @@ asmfunction!(__relibc_internal_fork_wrapper (usize) -> usize: [" "] <= [fork_impl = sym fork_impl]); asmfunction!(__relibc_internal_fork_ret: [" - ldp x0, x1, [sp] + ldp x0, x1, [sp], #16 + ldp x2, x3, [sp], #16 bl {child_hook} //TODO: load floating point regs mov x0, xzr - add sp, sp, #32 ldp x19, x20, [sp], #16 ldp x21, x22, [sp], #16 ldp x23, x24, [sp], #16 From e86dc155c678983451e501799c5b0584ab140711 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Wed, 16 Apr 2025 11:21:59 +0200 Subject: [PATCH 43/61] Add reference to NLnet project. --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 68bff0533e..27ee65dfbf 100644 --- a/README.md +++ b/README.md @@ -175,3 +175,10 @@ Before starting to contribute, read [this](CONTRIBUTING.md) document. - i686 (Intel/AMD) - x86_64 (Intel/AMD) - Aarch64 (ARM64) + +## Funding - _Unix-style Signals and Process Management_ + +This project is funded through [NGI Zero Core](https://nlnet.nl/core), a fund established by [NLnet](https://nlnet.nl) with financial support from the European Commission's [Next Generation Internet](https://ngi.eu) program. Learn more at the [NLnet project page](https://nlnet.nl/project/RedoxOS-Signals). + +[NLnet foundation logo](https://nlnet.nl) +[NGI Zero Logo](https://nlnet.nl/core) From d0335b30de4de4775e70e54e047714187e645374 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Wed, 16 Apr 2025 14:39:12 +0200 Subject: [PATCH 44/61] Use redox_rt::protocol for sig numbers. --- redox-rt/src/protocol.rs | 32 ++++++++++++++++++++++++++++++++ redox-rt/src/signal.rs | 3 +-- src/platform/redox/clone.rs | 2 +- src/platform/redox/mod.rs | 4 ++-- 4 files changed, 36 insertions(+), 5 deletions(-) diff --git a/redox-rt/src/protocol.rs b/redox-rt/src/protocol.rs index 3eb0779123..1d5feeefdf 100644 --- a/redox-rt/src/protocol.rs +++ b/redox-rt/src/protocol.rs @@ -158,3 +158,35 @@ pub struct RtSigInfo { pub pid: u32, // TODO: usize? } unsafe impl plain::Plain for RtSigInfo {} + +pub const SIGHUP: usize = 1; +pub const SIGINT: usize = 2; +pub const SIGQUIT: usize = 3; +pub const SIGILL: usize = 4; +pub const SIGTRAP: usize = 5; +pub const SIGABRT: usize = 6; +pub const SIGBUS: usize = 7; +pub const SIGFPE: usize = 8; +pub const SIGKILL: usize = 9; +pub const SIGUSR1: usize = 10; +pub const SIGSEGV: usize = 11; +pub const SIGUSR2: usize = 12; +pub const SIGPIPE: usize = 13; +pub const SIGALRM: usize = 14; +pub const SIGTERM: usize = 15; +pub const SIGSTKFLT: usize = 16; +pub const SIGCHLD: usize = syscall::SIGCHLD; +pub const SIGCONT: usize = 18; +pub const SIGSTOP: usize = 19; +pub const SIGTSTP: usize = syscall::SIGTSTP; +pub const SIGTTIN: usize = syscall::SIGTTIN; +pub const SIGTTOU: usize = syscall::SIGTTOU; +pub const SIGURG: usize = 23; +pub const SIGXCPU: usize = 24; +pub const SIGXFSZ: usize = 25; +pub const SIGVTALRM: usize = 26; +pub const SIGPROF: usize = 27; +pub const SIGWINCH: usize = 28; +pub const SIGIO: usize = 29; +pub const SIGPWR: usize = 30; +pub const SIGSYS: usize = 31; diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index 16f5de3e53..ca0c35ba0f 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -3,13 +3,12 @@ use core::{ffi::c_int, ptr::NonNull, sync::atomic::Ordering}; use syscall::{ data::AtomicU64, CallFlags, Error, RawAction, Result, SenderInfo, SetSighandlerData, SigProcControl, Sigcontrol, SigcontrolFlags, TimeSpec, EAGAIN, EINTR, EINVAL, ENOMEM, EPERM, - SIGCHLD, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGWINCH, }; use crate::{ arch::*, proc::FdGuard, - protocol::{ProcCall, RtSigInfo, ThreadCall}, + protocol::{ProcCall, RtSigInfo, ThreadCall, SIGCHLD, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGWINCH}, static_proc_info, sync::Mutex, sys::{proc_call, this_thread_call}, diff --git a/src/platform/redox/clone.rs b/src/platform/redox/clone.rs index 3c78230fa7..e382089394 100644 --- a/src/platform/redox/clone.rs +++ b/src/platform/redox/clone.rs @@ -4,7 +4,7 @@ use syscall::{ data::Map, error::Result, flag::{MapFlags, O_CLOEXEC}, - SetSighandlerData, SIGCONT, + SetSighandlerData, }; use redox_rt::{proc::FdGuard, signal::sighandler_function}; diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index 6b869367c9..3dec9da52d 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -1048,9 +1048,9 @@ impl Pal for Sys { )); if res == Some(Ok(0)) { // WNOHANG, just pretend ptrace SIGSTOP:ped this - status = (syscall::SIGSTOP << 8) | 0x7f; + status = (redox_rt::protocol::SIGSTOP << 8) | 0x7f; assert!(wifstopped(status)); - assert_eq!(wstopsig(status), syscall::SIGSTOP); + assert_eq!(wstopsig(status), redox_rt::protocol::SIGSTOP); res = Some(Ok(pid as usize)); } } From d559450d690c52ea83447097f1ea759e63896779 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Wed, 16 Apr 2025 15:22:56 +0200 Subject: [PATCH 45/61] Use abort() rather than unreachable! when exit fails. --- redox-rt/src/arch/aarch64.rs | 1 + redox-rt/src/lib.rs | 1 + redox-rt/src/proc.rs | 4 +++- redox-rt/src/sys.rs | 3 ++- 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/redox-rt/src/arch/aarch64.rs b/redox-rt/src/arch/aarch64.rs index 093d1c91be..ddc795883b 100644 --- a/redox-rt/src/arch/aarch64.rs +++ b/redox-rt/src/arch/aarch64.rs @@ -104,6 +104,7 @@ unsafe extern "C" fn fork_impl(args: &ForkArgs, initial_rsp: *mut usize) -> usiz } unsafe extern "C" fn child_hook(cur_filetable_fd: usize, new_proc_fd: usize, new_thr_fd: usize) { + //let _ = syscall::write(1, alloc::format!("A{cur_filetable_fd}B{new_proc_fd}C{new_thr_fd}\n").as_bytes()); let _ = syscall::close(cur_filetable_fd); crate::child_hook_common(crate::ChildHookCommonArgs { new_thr_fd: FdGuard::new(new_thr_fd), diff --git a/redox-rt/src/lib.rs b/redox-rt/src/lib.rs index 3b63c5543d..28c427fb72 100644 --- a/redox-rt/src/lib.rs +++ b/redox-rt/src/lib.rs @@ -2,6 +2,7 @@ #![feature( asm_const, array_chunks, + core_intrinsics, int_roundings, let_chains, slice_ptr_get, diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index 031b2a02cb..eaad61c383 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -754,10 +754,12 @@ pub fn fork_inner(initial_rsp: *mut usize, args: &ForkArgs) -> Result { // This must be done before the address space is copied. unsafe { + let proc_fd = new_proc_fd.as_ref().map_or(usize::MAX, |p| **p); + //let _ = syscall::write(1, alloc::format!("P{}Q{}R{}\n", *cur_filetable_fd, proc_fd, *new_thr_fd).as_bytes()); initial_rsp.write(*cur_filetable_fd); initial_rsp .add(1) - .write(new_proc_fd.as_ref().map_or(usize::MAX, |p| **p)); + .write(proc_fd); initial_rsp.add(2).write(*new_thr_fd); } } diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs index 2fcc30c969..9ae42a51f2 100644 --- a/redox-rt/src/sys.rs +++ b/redox-rt/src/sys.rs @@ -300,7 +300,8 @@ pub fn posix_exit(status: i32) -> ! { &[ProcCall::Exit as u64, status as u64], ) .expect("failed to call proc mgr with Exit"); - unreachable!() + let _ = syscall::write(1, b"redox-rt: ProcCall::Exit FAILED, abort()ing!\n"); + core::intrinsics::abort(); } pub fn setrens(rns: usize, ens: usize) -> Result<()> { this_proc_call( From 403beeb9f671c82ae521944a20e9d33fd91b0bd5 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Wed, 16 Apr 2025 16:59:42 +0200 Subject: [PATCH 46/61] Fix sigqueue test for aarch64. --- redox-rt/src/arch/aarch64.rs | 29 ++++++++++++++++------------- redox-rt/src/proc.rs | 4 +--- redox-rt/src/signal.rs | 5 ++++- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/redox-rt/src/arch/aarch64.rs b/redox-rt/src/arch/aarch64.rs index ddc795883b..ade355d156 100644 --- a/redox-rt/src/arch/aarch64.rs +++ b/redox-rt/src/arch/aarch64.rs @@ -227,44 +227,47 @@ asmfunction!(__relibc_internal_sigentry: [" clrex // Load the pending set again. TODO: optimize this? + // Process pending - realtime add x1, x6, #{pctl_pending} ldaxr x2, [x1] lsr x2, x2, #32 + // Thread pending - realtime and allowset add x5, x0, #{tcb_sc_off} + {sc_word} + 8 ldar x1, [x5] - orr x2, x1, x2 - and x2, x2, x2, lsr #32 - cbz x2, 7f + orr x2, x1, x2 // combine proc and thread pending + and x2, x2, x2, lsr #32 // AND pending with allowset + cbz x2, 7f // spurious signal if realtime is clear - rbit x3, x2 - clz x3, x3 - mov x4, #31 - sub x2, x4, x3 + rbit x2, x2 + clz x2, x2 // x2 now contains sig_idx - 32 // If realtime signal was directed at thread, handle it as an idempotent signal. - lsr x3, x1, x2 - tbnz x3, #0, 5f + lsr x3, x1, x2 // x3 := x1 >> x2; x1 is thread pending + tbnz x3, #0, 5f // jump if bit is nonzero // SYS_CALL(fd, payload_base, payload_len, metadata_len, metadata_base | (flags << 8)) // x8 x0 x1 x2 x3 x4 mov x5, x0 // save TCB pointer + mov x6, x2 ldr x8, ={SYS_CALL} adrp x0, {proc_fd} ldr x0, [x0, #:lo12:{proc_fd}] add x1, x5, #{tcb_sa_off} + {sa_tmp_rt_inf} - str x2, [x1] + str x6, [x1] mov x2, #{RTINF_SIZE} adrp x4, {proc_call} add x4, x4, :lo12:{proc_call} mov x3, #1 svc 0 + mov x3, x0 mov x0, x5 // restore TCB pointer - cbnz x0, 1b - + mov x2, x6 // restore signal number - 32 + add x1, x2, #32 // signal number + cbnz x3, 1b b 2f 5: // A realtime signal was sent to this thread, try clearing its bit. @@ -314,7 +317,7 @@ asmfunction!(__relibc_internal_sigentry: [" str x2, [x0, #{tcb_sa_off} + {sa_tmp_id_inf}] 2: ldr x3, [x0, #{tcb_sa_off} + {sa_pctl}] - add x2, x2, {pctl_actions} + add x3, x3, {pctl_actions} add x2, x3, w1, uxtb #4 // actions_base + sig_idx * sizeof Action // TODO: NOT ATOMIC (tearing allowed between regs)! ldxp x2, x3, [x2] diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index eaad61c383..cde74d1de8 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -757,9 +757,7 @@ pub fn fork_inner(initial_rsp: *mut usize, args: &ForkArgs) -> Result { let proc_fd = new_proc_fd.as_ref().map_or(usize::MAX, |p| **p); //let _ = syscall::write(1, alloc::format!("P{}Q{}R{}\n", *cur_filetable_fd, proc_fd, *new_thr_fd).as_bytes()); initial_rsp.write(*cur_filetable_fd); - initial_rsp - .add(1) - .write(proc_fd); + initial_rsp.add(1).write(proc_fd); initial_rsp.add(2).write(*new_thr_fd); } } diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index ca0c35ba0f..2518b5b61e 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -8,7 +8,10 @@ use syscall::{ use crate::{ arch::*, proc::FdGuard, - protocol::{ProcCall, RtSigInfo, ThreadCall, SIGCHLD, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGWINCH}, + protocol::{ + ProcCall, RtSigInfo, ThreadCall, SIGCHLD, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, + SIGURG, SIGWINCH, + }, static_proc_info, sync::Mutex, sys::{proc_call, this_thread_call}, From a293b02992aa76ef420bf5a00305e015167b4bc7 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Wed, 16 Apr 2025 18:58:14 +0200 Subject: [PATCH 47/61] Fix aarch64 signal test. --- redox-rt/src/arch/aarch64.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/redox-rt/src/arch/aarch64.rs b/redox-rt/src/arch/aarch64.rs index ade355d156..35a0a79dd8 100644 --- a/redox-rt/src/arch/aarch64.rs +++ b/redox-rt/src/arch/aarch64.rs @@ -296,7 +296,7 @@ asmfunction!(__relibc_internal_sigentry: [" b 2f 3: // A standard signal was sent to this thread, try clearing its bit. - clz x1, x1 + clz w1, w1 mov x2, #31 sub x1, x2, x1 From 008304373695565d09bdb18698276ac5d24535c6 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Wed, 16 Apr 2025 22:59:36 +0200 Subject: [PATCH 48/61] Write and fix waitpid_multiple test. --- redox-rt/src/arch/aarch64.rs | 2 +- redox-rt/src/proc.rs | 2 +- tests/Makefile | 1 + tests/waitpid_multiple.c | 58 ++++++++++++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 tests/waitpid_multiple.c diff --git a/redox-rt/src/arch/aarch64.rs b/redox-rt/src/arch/aarch64.rs index 35a0a79dd8..de30ce4732 100644 --- a/redox-rt/src/arch/aarch64.rs +++ b/redox-rt/src/arch/aarch64.rs @@ -104,7 +104,7 @@ unsafe extern "C" fn fork_impl(args: &ForkArgs, initial_rsp: *mut usize) -> usiz } unsafe extern "C" fn child_hook(cur_filetable_fd: usize, new_proc_fd: usize, new_thr_fd: usize) { - //let _ = syscall::write(1, alloc::format!("A{cur_filetable_fd}B{new_proc_fd}C{new_thr_fd}\n").as_bytes()); + //let _ = syscall::write(1, alloc::format!("CUR{cur_filetable_fd}PROC{new_proc_fd}THR{new_thr_fd}\n").as_bytes()); let _ = syscall::close(cur_filetable_fd); crate::child_hook_common(crate::ChildHookCommonArgs { new_thr_fd: FdGuard::new(new_thr_fd), diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index cde74d1de8..cc6e713292 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -755,7 +755,7 @@ pub fn fork_inner(initial_rsp: *mut usize, args: &ForkArgs) -> Result { // This must be done before the address space is copied. unsafe { let proc_fd = new_proc_fd.as_ref().map_or(usize::MAX, |p| **p); - //let _ = syscall::write(1, alloc::format!("P{}Q{}R{}\n", *cur_filetable_fd, proc_fd, *new_thr_fd).as_bytes()); + //let _ = syscall::write(1, alloc::format!("FDTBL{}PROC{}THR{}\n", *cur_filetable_fd, proc_fd, *new_thr_fd).as_bytes()); initial_rsp.write(*cur_filetable_fd); initial_rsp.add(1).write(proc_fd); initial_rsp.add(2).write(*new_thr_fd); diff --git a/tests/Makefile b/tests/Makefile index 1dd1f31e94..60ffd85624 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -126,6 +126,7 @@ EXPECT_NAMES=\ unistd/pipe \ unistd/rmdir \ waitpid \ + waitpid_multiple \ # unistd/sleep \ unistd/swab \ unistd/write \ diff --git a/tests/waitpid_multiple.c b/tests/waitpid_multiple.c new file mode 100644 index 0000000000..b872ed1fb5 --- /dev/null +++ b/tests/waitpid_multiple.c @@ -0,0 +1,58 @@ +#include +#include +#include +#include + +#include "test_helpers.h" + +int main(void) { + // Spawn two children, one with same pgid and one with pgid set to its own + // pid, so that the one with different pgid completes first. Then test + // waitpid both for 'any child' and for 'any child with same pgid'. + + pid_t pid_samepgid = fork(); + ERROR_IF(fork, pid_samepgid, == -1); + + if (pid_samepgid == 0) { + // child + sleep(2); + _Exit(2); + } + pid_t pid_diffpgids[2]; + for (int i = 0; i < 2; i++) { + pid_diffpgids[i] = fork(); + ERROR_IF(fork, pid_diffpgids[i], == -1); + + if (pid_diffpgids[i] == 0) { + int ret = setpgid(0, 0); + ERROR_IF(setpgid, ret, == -1); + + // child + sleep(1); + _Exit(i); + } + } + int status; + pid_t wid; + + // First, check that the first different-pgid proc is recognized. + wid = waitpid(-1, &status, 0); + ERROR_IF(waitpid, wid, == -1); + assert(wid == pid_diffpgids[0]); + assert(WIFEXITED(status)); + assert(WEXITSTATUS(status) == 0); + + // Then, check that the longest-waiting proc with the same pgid is properly matched. + wid = waitpid(0, &status, 0); + ERROR_IF(waitpid, wid, == -1); + assert(wid == pid_samepgid); + assert(WIFEXITED(status)); + assert(WEXITSTATUS(status) == 2); + + // Finally, the last same-pgid must have completed. + wid = waitpid(-1, &status, WNOHANG); + ERROR_IF(waitpid, wid, == -1); + assert(wid == pid_diffpgids[1]); + assert(WIFEXITED(status)); + assert(WEXITSTATUS(status) == 1); +} From 37b60b67e0b141cb5c291bab20bbaf783a0f6c98 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Wed, 16 Apr 2025 23:44:36 +0200 Subject: [PATCH 49/61] Add and fix test for kill&waitpid. --- include/bits/sys/wait.h | 2 +- redox-rt/src/signal.rs | 23 ++++++++++------------- tests/Makefile | 1 + 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/include/bits/sys/wait.h b/include/bits/sys/wait.h index 7af6a82bbe..c76dbcab95 100644 --- a/include/bits/sys/wait.h +++ b/include/bits/sys/wait.h @@ -2,7 +2,7 @@ #define _BITS_SYS_WAIT_H #define WEXITSTATUS(s) (((s) >> 8) & 0xff) -#define WTERMSIG(s) (((s) & 0x7f) != 0) +#define WTERMSIG(s) ((s) & 0x7f) #define WSTOPSIG(s) WEXITSTATUS(s) #define WCOREDUMP(s) (((s) & 0x80) != 0) #define WIFEXITED(s) (((s) & 0x7f) == 0) diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index 2518b5b61e..14a39c316f 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -6,16 +6,10 @@ use syscall::{ }; use crate::{ - arch::*, - proc::FdGuard, - protocol::{ + arch::*, current_proc_fd, proc::FdGuard, protocol::{ ProcCall, RtSigInfo, ThreadCall, SIGCHLD, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGWINCH, - }, - static_proc_info, - sync::Mutex, - sys::{proc_call, this_thread_call}, - RtTcb, Tcb, + }, static_proc_info, sync::Mutex, sys::{proc_call, this_thread_call}, RtTcb, Tcb }; #[cfg(target_arch = "x86_64")] @@ -162,9 +156,13 @@ unsafe fn inner(stack: &mut SigStack) { panic!("ctl {:x?} signal {}", os.control, stack.sig_num) } SigactionKind::Default => { - //syscall::exit(stack.sig_num as usize); - todo!("exit"); - unreachable!(); + let sig = (stack.sig_num & 0x3f) as u8; + + let _ = proc_call(**current_proc_fd(), &mut [], CallFlags::empty(), &[ + ProcCall::Exit as u64, + u64::from(sig) << 8, + ]); + core::intrinsics::abort() } SigactionKind::Handled { handler } => handler, }; @@ -508,8 +506,7 @@ bitflags::bitflags! { const STORED_FLAGS: u32 = 0xfe00_0000; fn default_handler(sig: c_int) { - //syscall::exit(sig as usize); - todo!("exit") + unreachable!(); } #[derive(Clone, Copy)] diff --git a/tests/Makefile b/tests/Makefile index 60ffd85624..38412a55ce 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -127,6 +127,7 @@ EXPECT_NAMES=\ unistd/rmdir \ waitpid \ waitpid_multiple \ + kill-waitpid \ # unistd/sleep \ unistd/swab \ unistd/write \ From c25b4c67e1391e5efdb20ee54f966b4b9853e59b Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Thu, 17 Apr 2025 01:04:09 +0200 Subject: [PATCH 50/61] Add kill-waitpid test. --- tests/kill-waitpid.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 tests/kill-waitpid.c diff --git a/tests/kill-waitpid.c b/tests/kill-waitpid.c new file mode 100644 index 0000000000..000029127c --- /dev/null +++ b/tests/kill-waitpid.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "test_helpers.h" + +int main(void) { + int err; + + int fds[2]; + err = pipe(fds); + ERROR_IF(pipe, err, == -1); + + int child = fork(); + ERROR_IF(fork, child, == -1); + + if (child == 0) { + // block forever + char buf[1]; + read(fds[0], buf, 1); + } + + err = kill(child, SIGTERM); + ERROR_IF(kill, err, == -1); + + int status; + err = waitpid(child, &status, 0); + ERROR_IF(waitpid, err, == -1); + printf("STATUS %d\n", status); + assert(WIFSIGNALED(status)); + assert(WTERMSIG(status) == SIGTERM); +} From 5dfc76dda80c48831749be4d69b8346d17e3e33d Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Thu, 17 Apr 2025 01:04:34 +0200 Subject: [PATCH 51/61] Fix signal handlers after EINTR nanosleep. --- redox-rt/src/signal.rs | 21 +++++++++++++++------ redox-rt/src/sys.rs | 4 ++++ src/platform/redox/mod.rs | 2 +- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index 14a39c316f..779c70a9f1 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -6,10 +6,17 @@ use syscall::{ }; use crate::{ - arch::*, current_proc_fd, proc::FdGuard, protocol::{ + arch::*, + current_proc_fd, + proc::FdGuard, + protocol::{ ProcCall, RtSigInfo, ThreadCall, SIGCHLD, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGWINCH, - }, static_proc_info, sync::Mutex, sys::{proc_call, this_thread_call}, RtTcb, Tcb + }, + static_proc_info, + sync::Mutex, + sys::{proc_call, this_thread_call}, + RtTcb, Tcb, }; #[cfg(target_arch = "x86_64")] @@ -158,10 +165,12 @@ unsafe fn inner(stack: &mut SigStack) { SigactionKind::Default => { let sig = (stack.sig_num & 0x3f) as u8; - let _ = proc_call(**current_proc_fd(), &mut [], CallFlags::empty(), &[ - ProcCall::Exit as u64, - u64::from(sig) << 8, - ]); + let _ = proc_call( + **current_proc_fd(), + &mut [], + CallFlags::empty(), + &[ProcCall::Exit as u64, u64::from(sig) << 8], + ); core::intrinsics::abort() } SigactionKind::Handled { handler } => handler, diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs index 9ae42a51f2..d0a69da489 100644 --- a/redox-rt/src/sys.rs +++ b/redox-rt/src/sys.rs @@ -340,3 +340,7 @@ pub fn posix_setsid() -> Result<()> { this_proc_call(&mut [], CallFlags::empty(), &[ProcCall::Setsid as u64])?; Ok(()) } +pub fn posix_nanosleep(rqtp: &TimeSpec, rmtp: &mut TimeSpec) -> Result<()> { + wrapper(false, false, || syscall::nanosleep(rqtp, rmtp))?; + Ok(()) +} diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index 3dec9da52d..3c9b273b97 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -742,7 +742,7 @@ impl Pal for Sys { } else { redox_rmtp = unsafe { redox_timespec::from(&*rmtp) }; } - match syscall::nanosleep(&redox_rqtp, &mut redox_rmtp) { + match redox_rt::sys::posix_nanosleep(&redox_rqtp, &mut redox_rmtp) { Ok(_) => Ok(()), Err(Error { errno: EINTR }) => { unsafe { From 8f2d9ef1dbef157ecf0d08db8e258f3f0c02a687 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Thu, 17 Apr 2025 11:39:52 +0200 Subject: [PATCH 52/61] Ensure allowset bits for SIGSTOP and SIGKILL are always set. --- redox-rt/src/signal.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index 779c70a9f1..175a973e21 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -288,7 +288,10 @@ fn get_allowset_raw(words: &[AtomicU64; 2]) -> u64 { (words[0].load(Ordering::Relaxed) >> 32) | ((words[1].load(Ordering::Relaxed) >> 32) << 32) } /// Sets mask from old to new, returning what was pending at the time. -fn set_allowset_raw(words: &[AtomicU64; 2], old: u64, new: u64) -> u64 { +fn set_allowset_raw(words: &[AtomicU64; 2], old: u64, new_raw: u64) -> u64 { + // TODO: should these bits always be set, or never be set? + let new = new_raw | ALLOWSET_ALWAYS; + // This assumes *only this thread* can change the allowset. If this rule is broken, the use of // fetch_add will corrupt the words entirely. fetch_add is very efficient on x86, being // generated as LOCK XADD which is the fastest RMW instruction AFAIK. @@ -303,6 +306,7 @@ fn set_allowset_raw(words: &[AtomicU64; 2], old: u64, new: u64) -> u64 { prev_w0 | (prev_w1 << 32) } +const ALLOWSET_ALWAYS: u64 = sig_bit(SIGSTOP as u32) | sig_bit(SIGKILL as u32); fn modify_sigmask(old: Option<&mut u64>, op: Option u64>) -> Result<()> { let _guard = tmp_disable_signals(); let ctl = current_sigctl(); From a1937f438ca6ea0ff4edc7ea78000a50b2fd1de5 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Thu, 17 Apr 2025 12:03:59 +0200 Subject: [PATCH 53/61] Allow read-only sigaction for SIG{KILL,STOP}. --- redox-rt/src/signal.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index 175a973e21..ae8af97fc1 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -397,8 +397,23 @@ fn convert_old(action: &RawAction) -> Sigaction { } pub fn sigaction(signal: u8, new: Option<&Sigaction>, old: Option<&mut Sigaction>) -> Result<()> { - if matches!(usize::from(signal), 0 | 32 | SIGKILL | SIGSTOP | 65..) { + if matches!(usize::from(signal), 0 | 32 | 65..) { return Err(Error::new(EINVAL)); + + } + if matches!(usize::from(signal), SIGKILL | SIGSTOP) { + if new.is_some() { + return Err(Error::new(EINVAL)); + } + if let Some(old) = old { + // TODO: Is this the correct value to set it to? + *old = Sigaction { + kind: SigactionKind::Default, + mask: 0, + flags: SigactionFlags::empty(), + }; + } + return Ok(()); } let _sigguard = tmp_disable_signals(); From 35357b2f14d85538a8308c91124f511159863ae1 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Thu, 17 Apr 2025 12:45:40 +0200 Subject: [PATCH 54/61] Clear pending when act becomes Ign (no multi-thread). --- redox-rt/src/signal.rs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index ae8af97fc1..35ba4c3863 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -160,7 +160,7 @@ unsafe fn inner(stack: &mut SigStack) { let handler = match sigaction.kind { SigactionKind::Ignore => { - panic!("ctl {:x?} signal {}", os.control, stack.sig_num) + panic!("ctl {:#x?} signal {}", os.control, stack.sig_num) } SigactionKind::Default => { let sig = (stack.sig_num & 0x3f) as u8; @@ -397,9 +397,14 @@ fn convert_old(action: &RawAction) -> Sigaction { } pub fn sigaction(signal: u8, new: Option<&Sigaction>, old: Option<&mut Sigaction>) -> Result<()> { + // TODO: Now that the goal of keeping logic out of the IPC backend, no longer holds when + // procmgr has taken over signal handling from the kernel, it would probably make sense to make + // parts of this function an IPC call, for synchronization purposes. Apart from SA_RESETHAND + // logic which may need to be fast, regular sigaction is typically in the 'configuration' + // category, allowed to be slower. + if matches!(usize::from(signal), 0 | 32 | 65..) { return Err(Error::new(EINVAL)); - } if matches!(usize::from(signal), SIGKILL | SIGSTOP) { if new.is_some() { @@ -435,8 +440,16 @@ pub fn sigaction(signal: u8, new: Option<&Sigaction>, old: Option<&mut Sigaction let (mask, flags, handler) = match (usize::from(signal), new.kind) { (_, SigactionKind::Ignore) | (SIGURG | SIGWINCH, SigactionKind::Default) => { - // TODO: POSIX specifies that pending signals shall be discarded if set to SIG_IGN by - // sigaction. + let sig_group = (signal - 1) / 32; + let sig_idx = (signal - 1) % 32; + + // TODO: relibc and the procmgr has access to all threads, redox_rt doesn't currently. + // Do this for all threads! + ctl.word[usize::from(sig_group)].fetch_and(!(1 << sig_idx), Ordering::Relaxed); + PROC_CONTROL_STRUCT + .pending + .fetch_and(!sig_bit(signal.into()), Ordering::Relaxed); + // TODO: handle tmp_disable_signals ( MASK_DONTCARE, From e6c06a7cf7ca2881fb747b463abf0516d4ed85c1 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Thu, 17 Apr 2025 15:47:14 +0200 Subject: [PATCH 55/61] Fix signals for spawned threads, and async signal waiting. --- redox-rt/src/signal.rs | 14 +++++++++++--- src/header/signal/mod.rs | 4 +++- src/ld_so/start.rs | 2 +- src/pthread/mod.rs | 13 +++++++++---- src/start.rs | 2 +- 5 files changed, 25 insertions(+), 10 deletions(-) diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index 35ba4c3863..5810398232 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -579,8 +579,8 @@ const fn sig_bit(sig: u32) -> u64 { 1 << (sig - 1) } -pub fn setup_sighandler(tcb: &RtTcb) { - { +pub fn setup_sighandler(tcb: &RtTcb, first_thread: bool) { + if first_thread { let _guard = SIGACTIONS_LOCK.lock(); for (sig_idx, action) in PROC_CONTROL_STRUCT.actions.iter().enumerate() { let sig = sig_idx + 1; @@ -739,17 +739,25 @@ pub fn await_signal_async(inner_allowset: u64) -> Result { }, &mut TimeSpec::default(), ); - set_allowset_raw(&control.word, inner_allowset, old_allowset); if res == Err(Error::new(EINTR)) { unsafe { manually_enter_trampoline(); } } + // POSIX says it shall restore the mask to what it was prior to the call, which is interpreted + // as allowing any changes to sigprocmask inside the signal handler, to be discarded. + set_allowset_raw(&control.word, inner_allowset, old_allowset); res?; unreachable!() } +/*#[no_mangle] +pub extern "C" fn __redox_rt_debug_sigctl() { + let tcb = &RtTcb::current().control; + let _ = syscall::write(1, alloc::format!("SIGCTL: {tcb:#x?}\n").as_bytes()); +}*/ + // TODO: deadline-based API pub fn await_signal_sync(inner_allowset: u64, timeout: Option<&TimeSpec>) -> Result { let _guard = tmp_disable_signals(); diff --git a/src/header/signal/mod.rs b/src/header/signal/mod.rs index 9f00dbc1ae..925a584475 100644 --- a/src/header/signal/mod.rs +++ b/src/header/signal/mod.rs @@ -309,7 +309,9 @@ pub unsafe extern "C" fn sigpause(sig: c_int) -> c_int { let mut pset = mem::MaybeUninit::::uninit(); sigprocmask(0, ptr::null_mut(), pset.as_mut_ptr()); let mut set = pset.assume_init(); - sigdelset(&mut set, sig); + if sigdelset(&mut set, sig) == -1 { + return -1; + } sigsuspend(&set) } diff --git a/src/ld_so/start.rs b/src/ld_so/start.rs index 390a77c09a..26e1a0f3a3 100644 --- a/src/ld_so/start.rs +++ b/src/ld_so/start.rs @@ -168,7 +168,7 @@ pub unsafe extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: us .expect_notls("no proc fd present"); redox_rt::initialize(redox_rt::proc::FdGuard::new(proc_fd)); - redox_rt::signal::setup_sighandler(&tcb.os_specific); + redox_rt::signal::setup_sighandler(&tcb.os_specific, true); } } diff --git a/src/pthread/mod.rs b/src/pthread/mod.rs index b41a19d5cc..bdf70af6ba 100644 --- a/src/pthread/mod.rs +++ b/src/pthread/mod.rs @@ -213,10 +213,15 @@ unsafe extern "C" fn new_thread_shim( let tid = (*(&*mutex1).lock()).assume_init(); if let Some(tcb) = tcb.as_mut() { - tcb.activate( - #[cfg(target_os = "redox")] - redox_rt::proc::FdGuard::new(tid.thread_fd), - ); + #[cfg(not(target_os = "redox"))] + { + tcb.activate(); + } + #[cfg(target_os = "redox")] + { + tcb.activate(redox_rt::proc::FdGuard::new(tid.thread_fd)); + redox_rt::signal::setup_sighandler(&tcb.os_specific, false); + } } let procmask = (&*mutex2).as_ptr().read(); diff --git a/src/start.rs b/src/start.rs index faca8b65ec..279dcbe317 100644 --- a/src/start.rs +++ b/src/start.rs @@ -171,7 +171,7 @@ pub unsafe extern "C" fn relibc_start(sp: &'static Stack) -> ! { tcb.linker_ptr = Box::into_raw(Box::new(Mutex::new(linker))); } #[cfg(target_os = "redox")] - redox_rt::signal::setup_sighandler(&tcb.os_specific); + redox_rt::signal::setup_sighandler(&tcb.os_specific, true); } // Set up argc and argv From aa034fccc86c3f42cbfe7351561c7e4a8537f32f Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Fri, 18 Apr 2025 12:04:28 +0200 Subject: [PATCH 56/61] Compile on riscv64gc. --- redox-rt/src/arch/riscv64.rs | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/redox-rt/src/arch/riscv64.rs b/redox-rt/src/arch/riscv64.rs index 3faa17118e..0743594917 100644 --- a/redox-rt/src/arch/riscv64.rs +++ b/redox-rt/src/arch/riscv64.rs @@ -1,5 +1,8 @@ +use core::cell::SyncUnsafeCell; + use crate::{ - proc::{fork_inner, FdGuard}, + proc::{fork_inner, FdGuard, ForkArgs}, + protocol::{ProcCall, RtSigInfo}, signal::{get_sigaltstack, inner_c, PosixStackt, RtSigarea, SigStack}, RtTcb, Tcb, }; @@ -70,16 +73,23 @@ pub fn copy_env_regs(cur_pid_fd: usize, new_pid_fd: usize) -> Result<()> { Ok(()) } -unsafe extern "C" fn fork_impl(initial_rsp: *mut usize) -> usize { - Error::mux(fork_inner(initial_rsp)) +unsafe extern "C" fn fork_impl(args: &ForkArgs, initial_rsp: *mut usize) -> usize { + Error::mux(fork_inner(initial_rsp, args)) } -unsafe extern "C" fn child_hook(cur_filetable_fd: usize, new_pid_fd: usize) { +unsafe extern "C" fn child_hook(cur_filetable_fd: usize, new_proc_fd: usize, new_thr_fd: usize) { let _ = syscall::close(cur_filetable_fd); - crate::child_hook_common(FdGuard::new(new_pid_fd)); + crate::child_hook_common(crate::ChildHookCommonArgs { + new_thr_fd: FdGuard::new(new_thr_fd), + new_proc_fd: if new_proc_fd == usize::MAX { + None + } else { + Some(FdGuard::new(new_proc_fd)) + }, + }); } -asmfunction!(__relibc_internal_fork_wrapper -> usize: [" +asmfunction!(__relibc_internal_fork_wrapper (usize) -> usize: [" .attribute arch, \"rv64gc\" # rust bug 80608 addi sp, sp, -200 sd s0, 0(sp) @@ -263,7 +273,8 @@ asmfunction!(__relibc_internal_sigentry: [" sd a1, ({tcb_sa_off} + {sa_tmp_a1})(t0) sd a2, ({tcb_sa_off} + {sa_tmp_a2})(t0) sd a7, ({tcb_sa_off} + {sa_tmp_a7})(t0) - li a0, {SYS_SIGDEQUEUE} + // FIXME: the following is wrong + li a0, {SYS_CALL} addi a1, t3, -32 add a2, t0, {tcb_sa_off} + {sa_tmp_rt_inf} // out pointer of dequeued realtime sig ecall @@ -531,7 +542,7 @@ __relibc_internal_sigentry_crit_fifth: inner = sym inner_c, pctl_off_pending = const offset_of!(SigProcControl, pending), pctl_off_sender_infos = const offset_of!(SigProcControl, sender_infos), - SYS_SIGDEQUEUE = const syscall::SYS_SIGDEQUEUE, + SYS_CALL = const syscall::SYS_CALL, ]); asmfunction!(__relibc_internal_rlct_clone_ret: [" @@ -620,3 +631,5 @@ pub unsafe fn arch_pre(stack: &mut SigStack, area: &mut SigArea) -> PosixStackt get_sigaltstack(area, stack.regs.int_regs[1] as usize).into() } +pub(crate) static PROC_FD: SyncUnsafeCell = SyncUnsafeCell::new(usize::MAX); +static PROC_CALL: [usize; 1] = [ProcCall::Sigdeq as usize]; From 8cfc7e8facd1cf40e8431245cea346e17236812f Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Fri, 18 Apr 2025 20:10:49 +0200 Subject: [PATCH 57/61] Do not treat ppid as constant. --- redox-rt/src/lib.rs | 5 +---- redox-rt/src/proc.rs | 2 -- redox-rt/src/protocol.rs | 2 ++ redox-rt/src/sys.rs | 11 +++++++---- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/redox-rt/src/lib.rs b/redox-rt/src/lib.rs index 28c427fb72..6e5beb3ef6 100644 --- a/redox-rt/src/lib.rs +++ b/redox-rt/src/lib.rs @@ -203,7 +203,6 @@ pub unsafe fn initialize(#[cfg(feature = "proc")] proc_fd: FdGuard) { STATIC_PROC_INFO.get().write(StaticProcInfo { pid: metadata.pid, - ppid: metadata.ppid, #[cfg(feature = "proc")] proc_fd: MaybeUninit::new(proc_fd), @@ -228,10 +227,9 @@ pub unsafe fn initialize(#[cfg(feature = "proc")] proc_fd: FdGuard) { } } -#[repr(C)] // TODO: is this required? +#[repr(C)] // TODO: is repr(C) required? pub(crate) struct StaticProcInfo { pid: u32, - ppid: u32, // TODO: dynamic proc_fd: MaybeUninit, has_proc_fd: bool, } @@ -292,7 +290,6 @@ unsafe fn child_hook_common(args: ChildHookCommonArgs) { .get() .replace(StaticProcInfo { pid: metadata.pid, - ppid: metadata.ppid, has_proc_fd: args.new_proc_fd.is_some(), proc_fd: args .new_proc_fd diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index cc6e713292..3af59fbc90 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -970,7 +970,6 @@ pub unsafe fn make_init() -> [&'static FdGuard; 2] { STATIC_PROC_INFO.get().write(crate::StaticProcInfo { pid: 1, - ppid: 1, proc_fd: MaybeUninit::new(proc_fd), has_proc_fd: true, }); @@ -991,7 +990,6 @@ pub unsafe fn make_init() -> [&'static FdGuard; 2] { pub(crate) static STATIC_PROC_INFO: SyncUnsafeCell = SyncUnsafeCell::new(StaticProcInfo { pid: 0, - ppid: 0, proc_fd: MaybeUninit::zeroed(), has_proc_fd: false, }); diff --git a/redox-rt/src/protocol.rs b/redox-rt/src/protocol.rs index 1d5feeefdf..345078964e 100644 --- a/redox-rt/src/protocol.rs +++ b/redox-rt/src/protocol.rs @@ -34,6 +34,7 @@ pub enum ProcCall { // TODO: replace with sendfd equivalent syscall for sending memory SyncSigPctl = 10, Sigdeq = 11, + Getppid = 12, } #[derive(Clone, Copy, Debug, Eq, PartialEq)] #[repr(usize)] @@ -59,6 +60,7 @@ impl ProcCall { 9 => Self::Sigq, 10 => Self::SyncSigPctl, 11 => Self::Sigdeq, + 12 => Self::Getppid, _ => return None, }) } diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs index d0a69da489..82ece48fdc 100644 --- a/redox-rt/src/sys.rs +++ b/redox-rt/src/sys.rs @@ -5,7 +5,7 @@ use core::{ }; use syscall::{ - error::{Error, Result, EINTR}, + error::{self, Error, Result, EINTR}, CallFlags, TimeSpec, EINVAL, ERESTART, }; @@ -76,7 +76,10 @@ pub fn posix_sigqueue(pid: usize, sig: usize, arg: usize) -> Result<()> { &[ProcCall::Sigq as u64, pid as u64, sig as u64], ) }) { - Ok(_) | Err(Error { errno: EINTR }) => Ok(()), + Ok(_) + | Err(Error { + errno: error::EINTR, + }) => Ok(()), Err(error) => Err(error), } } @@ -87,8 +90,8 @@ pub fn posix_getpid() -> u32 { } #[inline] pub fn posix_getppid() -> u32 { - // SAFETY: read-only except during program/fork child initialization - unsafe { addr_of!((*crate::STATIC_PROC_INFO.get()).ppid).read() } + this_proc_call(&mut [], CallFlags::empty(), &[ProcCall::Getppid as u64]).expect("cannot fail") + as u32 } #[inline] pub unsafe fn sys_futex_wait(addr: *mut u32, val: u32, deadline: Option<&TimeSpec>) -> Result<()> { From 0e0246bc69443583e724649d92c4414f8d2dccac Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Fri, 18 Apr 2025 22:08:14 +0200 Subject: [PATCH 58/61] Let procmgr handle process names. --- redox-rt/src/proc.rs | 37 +++++++++++++++++++------------------ redox-rt/src/protocol.rs | 2 ++ redox-rt/src/thread.rs | 2 -- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs index 3af59fbc90..ba8b290b42 100644 --- a/redox-rt/src/proc.rs +++ b/redox-rt/src/proc.rs @@ -430,8 +430,19 @@ where } // TODO: Restore old name if exec failed? - if let Ok(name_fd) = syscall::dup(**thread_fd, b"name").map(FdGuard::new) { - let _ = syscall::write(*name_fd, interp_override.as_ref().map_or(path, |o| &o.name)); + { + let mut buf = [0; 32]; + let new_name = interp_override.as_ref().map_or(path, |o| &o.name); + let len = new_name.len().min(32); + buf[..len].copy_from_slice(&new_name[..len]); + // XXX: takes &mut [] since it can mutate, but we could unsafe{}ly pass it directly + // otherwise + let _ = proc_call( + **proc_fd, + &mut buf, + CallFlags::empty(), + &[ProcCall::Rename as u64], + ); } if interp_override.is_some() { let mmap_min_fd = FdGuard::new(syscall::dup(*grants_fd, b"mmap-min-addr")?); @@ -745,8 +756,6 @@ pub fn fork_inner(initial_rsp: *mut usize, args: &ForkArgs) -> Result { new_thr_fd = thr_fd; new_pid = pid; - copy_str(**cur_thr_fd, *new_thr_fd, "name")?; - // Copy existing files into new file table, but do not reuse the same file table (i.e. new // parent FDs will not show up for the child). { @@ -921,6 +930,12 @@ pub fn new_child_process(args: &ForkArgs<'_>) -> Result { euid: 0, egid: 0, ens: 1, + debug_name: { + let mut buf = [0; 32]; + let src = b"[init]"; + buf[..src.len()].copy_from_slice(src); + buf + }, }; let attr_fd = FdGuard::new(syscall::dup( *thr_fd, @@ -936,20 +951,6 @@ pub fn new_child_process(args: &ForkArgs<'_>) -> Result { } } -pub fn copy_str(cur_pid_fd: usize, new_proc_fd: usize, key: &str) -> Result<()> { - let cur_name_fd = FdGuard::new(syscall::dup(cur_pid_fd, key.as_bytes())?); - let new_name_fd = FdGuard::new(syscall::dup(new_proc_fd, key.as_bytes())?); - - // TODO: Max path size? - let mut buf = [0_u8; 256]; - let len = syscall::read(*cur_name_fd, &mut buf)?; - let buf = buf.get(..len).ok_or(Error::new(ENAMETOOLONG))?; - - syscall::write(*new_name_fd, &buf)?; - - Ok(()) -} - pub unsafe fn make_init() -> [&'static FdGuard; 2] { let proc_fd = FdGuard::new( syscall::open("/scheme/proc/init", syscall::O_CLOEXEC).expect("failed to create init"), diff --git a/redox-rt/src/protocol.rs b/redox-rt/src/protocol.rs index 345078964e..75fe33f8ac 100644 --- a/redox-rt/src/protocol.rs +++ b/redox-rt/src/protocol.rs @@ -35,6 +35,7 @@ pub enum ProcCall { SyncSigPctl = 10, Sigdeq = 11, Getppid = 12, + Rename = 13, } #[derive(Clone, Copy, Debug, Eq, PartialEq)] #[repr(usize)] @@ -61,6 +62,7 @@ impl ProcCall { 10 => Self::SyncSigPctl, 11 => Self::Sigdeq, 12 => Self::Getppid, + 13 => Self::Rename, _ => return None, }) } diff --git a/redox-rt/src/thread.rs b/redox-rt/src/thread.rs index b1bc7e5652..fb57f27410 100644 --- a/redox-rt/src/thread.rs +++ b/redox-rt/src/thread.rs @@ -13,8 +13,6 @@ pub unsafe fn rlct_clone_impl(stack: *mut usize) -> Result { let cur_thr_fd = RtTcb::current().thread_fd(); let new_thr_fd = FdGuard::new(syscall::dup(**cur_proc_fd, b"new-thread")?); - copy_str(**cur_thr_fd, *new_thr_fd, "name")?; - // Inherit existing address space { let cur_addr_space_fd = FdGuard::new(syscall::dup(**cur_thr_fd, b"addrspace")?); From 2fe8dc8f6eb37212d65355b5bc282165e97ea733 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sat, 19 Apr 2025 02:37:55 +0200 Subject: [PATCH 59/61] Add (untested) riscv64 sighandler SYS_CALL asm. --- redox-rt/src/arch/riscv64.rs | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/redox-rt/src/arch/riscv64.rs b/redox-rt/src/arch/riscv64.rs index 0743594917..a1252f5829 100644 --- a/redox-rt/src/arch/riscv64.rs +++ b/redox-rt/src/arch/riscv64.rs @@ -24,6 +24,8 @@ pub struct SigArea { pub tmp_a0: u64, pub tmp_a1: u64, pub tmp_a2: u64, + pub tmp_a3: u64, + pub tmp_a4: u64, pub tmp_a7: u64, pub pctl: usize, // TODO: remove @@ -269,15 +271,30 @@ asmfunction!(__relibc_internal_sigentry: [" bnez t1, 10f // thread signal // otherwise, try (competitively) dequeueing realtime signal + + // SYS_CALL(fd, payload_base, payload_len, metadata_len, metadata_base) + // a7 a0 a1 a2 a3 a4 + + // TODO: This SYS_CALL invocation has not yet been tested due to toolchain issues. + sd a0, ({tcb_sa_off} + {sa_tmp_a0})(t0) sd a1, ({tcb_sa_off} + {sa_tmp_a1})(t0) sd a2, ({tcb_sa_off} + {sa_tmp_a2})(t0) + sd a3, ({tcb_sa_off} + {sa_tmp_a3})(t0) + sd a4, ({tcb_sa_off} + {sa_tmp_a4})(t0) sd a7, ({tcb_sa_off} + {sa_tmp_a7})(t0) - // FIXME: the following is wrong - li a0, {SYS_CALL} - addi a1, t3, -32 - add a2, t0, {tcb_sa_off} + {sa_tmp_rt_inf} // out pointer of dequeued realtime sig + li a7, {SYS_CALL} + addi a2, t3, -32 + add a1, t0, {tcb_sa_off} + {sa_tmp_rt_inf} // out pointer of dequeued realtime sig + sd a2, (a1) + li a2, {RTINF_SIZE} + li a3, 1 +1337: + auipc a4, %pcrel_hi({proc_fd}) + addi a4, a4, %pcrel_lo(1337b) ecall + ld a3, ({tcb_sa_off} + {sa_tmp_a3})(t0) + ld a4, ({tcb_sa_off} + {sa_tmp_a4})(t0) bnez a0, 99b // assumes error can only be EAGAIN j 9f @@ -531,6 +548,8 @@ __relibc_internal_sigentry_crit_fifth: sa_tmp_a0 = const offset_of!(SigArea, tmp_a0), sa_tmp_a1 = const offset_of!(SigArea, tmp_a1), sa_tmp_a2 = const offset_of!(SigArea, tmp_a2), + sa_tmp_a3 = const offset_of!(SigArea, tmp_a3), + sa_tmp_a4 = const offset_of!(SigArea, tmp_a4), sa_tmp_a7 = const offset_of!(SigArea, tmp_a7), sa_tmp_ip = const offset_of!(SigArea, tmp_ip), sa_tmp_id_inf = const offset_of!(SigArea, tmp_id_inf), @@ -543,6 +562,8 @@ __relibc_internal_sigentry_crit_fifth: pctl_off_pending = const offset_of!(SigProcControl, pending), pctl_off_sender_infos = const offset_of!(SigProcControl, sender_infos), SYS_CALL = const syscall::SYS_CALL, + RTINF_SIZE = const size_of::(), + proc_fd = sym PROC_FD, ]); asmfunction!(__relibc_internal_rlct_clone_ret: [" From 8f234edf6920ebfac60215b5050b6b7134587017 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sat, 19 Apr 2025 18:46:26 +0200 Subject: [PATCH 60/61] Fix riscv64 fork asm. --- redox-rt/src/arch/riscv64.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/redox-rt/src/arch/riscv64.rs b/redox-rt/src/arch/riscv64.rs index a1252f5829..22b8c20008 100644 --- a/redox-rt/src/arch/riscv64.rs +++ b/redox-rt/src/arch/riscv64.rs @@ -122,7 +122,8 @@ asmfunction!(__relibc_internal_fork_wrapper (usize) -> usize: [" fsd fs11, 192(sp) addi sp, sp, -32 - mv a0, sp + // a0 is forwarded from this function + mv a1, sp jal {fork_impl} addi sp, sp, 32 @@ -160,8 +161,9 @@ asmfunction!(__relibc_internal_fork_wrapper (usize) -> usize: [" asmfunction!(__relibc_internal_fork_ret: [" .attribute arch, \"rv64gc\" # rust bug 80608 - ld a0, 0(sp) - ld a1, 8(sp) + ld a0, 0(sp) // cur_filetable_fd + ld a1, 8(sp) // new_proc_fd + ld a2, 16(sp) // new_thr_fd jal {child_hook} mv a0, x0 From 9e73f93c5cd1bf4c7c2c2f530d2c0420737ad751 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sat, 19 Apr 2025 19:27:23 +0200 Subject: [PATCH 61/61] Use redox-os/syscall git dep. --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 83f396cea8..b24e0eda2c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -458,7 +458,7 @@ dependencies = [ [[package]] name = "redox_syscall" version = "0.5.11" -source = "git+https://gitlab.redox-os.org/4lDO2/syscall.git?branch=nuke_proc#8a80d1f58bc92d8c0eb73a939420fb30fe1e85d0" +source = "git+https://gitlab.redox-os.org/redox-os/syscall.git?branch=master#8f646a63ac9c3aa532a37ddfdc136ec19878f0d6" dependencies = [ "bitflags", ] diff --git a/Cargo.toml b/Cargo.toml index d576ffe53d..8846727afb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -81,4 +81,4 @@ panic = "abort" [patch.crates-io] cc-11 = { git = "https://github.com/tea/cc-rs", branch = "riscv-abi-arch-fix", package = "cc" } -redox_syscall = { git = "https://gitlab.redox-os.org/4lDO2/syscall.git", branch = "nuke_proc" } +redox_syscall = { git = "https://gitlab.redox-os.org/redox-os/syscall.git", branch = "master" }