From f6761407e58dfa1f2341ef759792f4dc8f9c5f11 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Thu, 1 Aug 2024 19:51:30 +0200 Subject: [PATCH] Pass si_pid to all realtime signals. --- redox-rt/src/arch/x86_64.rs | 20 ++------------------ redox-rt/src/lib.rs | 22 +++++++++++++++++++--- redox-rt/src/signal.rs | 22 ++++++++++++++++++---- redox-rt/src/sys.rs | 9 ++++++++- src/ld_so/start.rs | 5 ++++- src/platform/mod.rs | 8 +++++--- src/platform/redox/mod.rs | 2 +- src/platform/redox/signal.rs | 1 + tests/sigqueue.c | 6 ++++++ 9 files changed, 64 insertions(+), 31 deletions(-) diff --git a/redox-rt/src/arch/x86_64.rs b/redox-rt/src/arch/x86_64.rs index d918a1818..6b9849e6c 100644 --- a/redox-rt/src/arch/x86_64.rs +++ b/redox-rt/src/arch/x86_64.rs @@ -97,11 +97,7 @@ unsafe extern "sysv64" fn fork_impl(initial_rsp: *mut usize) -> usize { unsafe extern "sysv64" fn child_hook(cur_filetable_fd: usize, new_pid_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(FdGuard::new(new_pid_fd)); } asmfunction!(__relibc_internal_fork_wrapper -> usize: [" @@ -425,11 +421,7 @@ extern "C" { fn __relibc_internal_sigentry_crit_third(); } /// Fixes some edge cases, and calculates the value for uc_stack. -pub unsafe fn arch_pre( - stack: &mut SigStack, - area: &mut SigArea, - targeted_thread: bool, -) -> PosixStackt { +pub unsafe fn arch_pre(stack: &mut SigStack, area: &mut SigArea) -> PosixStackt { // It is impossible to update RSP and RIP atomically on x86_64, without using IRETQ, which is // almost as slow as calling a SIGRETURN syscall would be. Instead, we abuse the fact that // signals are disabled in the prologue of the signal trampoline, which allows us to emulate @@ -451,14 +443,6 @@ pub unsafe fn arch_pre( stack.regs.rip = area.tmp_rip; } - stack.sig_code = if (stack.sig_num - 1) / 32 == 1 && !targeted_thread { - area.tmp_inf.code as u32 - } else { - // TODO: SIGCHLD information when applicable - 0 - }; - stack.sival = area.tmp_inf.arg; - PosixStackt { sp: stack.regs.rsp as *mut (), size: 0, // TODO diff --git a/redox-rt/src/lib.rs b/redox-rt/src/lib.rs index 106fadc26..fa25e97a9 100644 --- a/redox-rt/src/lib.rs +++ b/redox-rt/src/lib.rs @@ -9,7 +9,7 @@ )] #![forbid(unreachable_patterns)] -use core::cell::UnsafeCell; +use core::cell::{SyncUnsafeCell, UnsafeCell}; use generic_rt::{ExpectTlsFree, GenericTcb}; use syscall::{Sigcontrol, O_CLOEXEC}; @@ -120,13 +120,13 @@ pub unsafe fn tcb_activate(tcb: &RtTcb, tls_end_and_tcb_start: usize, _tls_len: } /// Initialize redox-rt in situations where relibc is not used -pub fn initialize_freestanding() { +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 // is initialized properly. // TODO: TLS - let page = unsafe { + let page = { &mut *(syscall::fmap( !0, &syscall::Map { @@ -155,4 +155,20 @@ pub fn initialize_freestanding() { let abi_ptr = core::ptr::addr_of_mut!(page.tcb_ptr); core::arch::asm!("msr tpidr_el0, {}", in(reg) abi_ptr); } + initialize(); +} +pub unsafe fn initialize() { + THIS_PID + .get() + .write(Some(syscall::getpid().unwrap().try_into().unwrap()).unwrap()); +} + +static THIS_PID: SyncUnsafeCell<u32> = SyncUnsafeCell::new(0); + +unsafe fn child_hook_common(new_pid_fd: FdGuard) { + // 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()); } diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index 300564c1f..3573b0326 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -81,13 +81,27 @@ unsafe fn inner(stack: &mut SigStack) { // asm counts from 0 stack.sig_num += 1; - stack.old_stack = arch_pre(stack, &mut *os.arch.get(), targeted_thread_not_process); + + let (sender_pid, sender_uid) = { + let area = &mut *os.arch.get(); + + stack.sival = area.tmp_inf.arg; + stack.old_stack = arch_pre(stack, area); + + if (stack.sig_num - 1) / 32 == 1 && !targeted_thread_not_process { + stack.sig_code = area.tmp_inf.code as u32; + (area.tmp_inf.pid, area.tmp_inf.uid) + } else { + // TODO: SIGCHLD information when applicable + stack.sig_code = 0; + (0, 0) // TODO + } + }; let sigaction = { let guard = SIGACTIONS_LOCK.lock(); let action = convert_old(&PROC_CONTROL_STRUCT.actions[stack.sig_num as usize - 1]); if action.flags.contains(SigactionFlags::RESETHAND) { - // TODO: other things that must be set drop(guard); sigaction( stack.sig_num as u8, @@ -159,9 +173,9 @@ unsafe fn inner(stack: &mut SigStack) { si_addr: core::ptr::null_mut(), si_code: stack.sig_code as i32, si_errno: 0, - si_pid: 0, // TODO + si_pid: sender_pid as i32, si_status: 0, - si_uid: 0, // TODO + si_uid: sender_uid as i32, si_value: stack.sival, }; sigaction( diff --git a/redox-rt/src/sys.rs b/redox-rt/src/sys.rs index 78fa0879e..45779f6b8 100644 --- a/redox-rt/src/sys.rs +++ b/redox-rt/src/sys.rs @@ -49,7 +49,9 @@ pub fn posix_kill(pid: usize, sig: usize) -> Result<()> { pub fn posix_sigqueue(pid: usize, sig: usize, arg: usize) -> Result<()> { let siginf = RtSigInfo { arg, - code: usize::wrapping_neg(1), // TODO: SI_QUEUE + 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) @@ -59,6 +61,11 @@ 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() } +} +#[inline] pub fn posix_killpg(pgrp: usize, sig: usize) -> Result<()> { match wrapper(false, || syscall::kill(usize::wrapping_neg(pgrp), sig)) { Ok(_) | Err(Error { errno: EINTR }) => Ok(()), diff --git a/src/ld_so/start.rs b/src/ld_so/start.rs index 6e2b45426..d0cf2c942 100644 --- a/src/ld_so/start.rs +++ b/src/ld_so/start.rs @@ -141,6 +141,7 @@ 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 { // We get the arguments, the environment, and the auxilary vector @@ -184,7 +185,9 @@ pub extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: usize) -> } // TODO: Fix memory leak, although minimal. - crate::platform::init(auxv.clone()); + unsafe { + crate::platform::init(auxv.clone()); + } // Some variables that will be overridden by environment and auxiliary vectors let ld_library_path = envs.get("LD_LIBRARY_PATH").map(|s| s.to_owned()); diff --git a/src/platform/mod.rs b/src/platform/mod.rs index 2b4071dd8..9fd855a7d 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -283,15 +283,17 @@ pub fn get_auxv(auxvs: &[[usize; 2]], key: usize) -> Option<usize> { #[cold] #[cfg(target_os = "redox")] -pub fn init(auxvs: Box<[[usize; 2]]>) { +// 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::*; if let (Some(cwd_ptr), Some(cwd_len)) = ( get_auxv(&auxvs, AT_REDOX_INITIAL_CWD_PTR), get_auxv(&auxvs, AT_REDOX_INITIAL_CWD_LEN), ) { - let cwd_bytes: &'static [u8] = - unsafe { core::slice::from_raw_parts(cwd_ptr as *const u8, cwd_len) }; + let cwd_bytes: &'static [u8] = core::slice::from_raw_parts(cwd_ptr as *const u8, cwd_len); if let Ok(cwd) = core::str::from_utf8(cwd_bytes) { self::sys::path::set_cwd_manual(cwd.into()); } diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index 95c7b8984..a3bda3431 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -470,7 +470,7 @@ impl Pal for Sys { } fn getpid() -> pid_t { - e(syscall::getpid()) as pid_t + redox_rt::sys::posix_getpid() as pid_t } fn getppid() -> pid_t { diff --git a/src/platform/redox/signal.rs b/src/platform/redox/signal.rs index 3be1da844..abcb486ce 100644 --- a/src/platform/redox/signal.rs +++ b/src/platform/redox/signal.rs @@ -39,6 +39,7 @@ pub struct ucontext_t { } const _: () = { + #[track_caller] const fn assert_eq(a: usize, b: usize) { if a != b { panic!("compile-time struct verification failed"); diff --git a/tests/sigqueue.c b/tests/sigqueue.c index 31e5a61c8..f44322081 100644 --- a/tests/sigqueue.c +++ b/tests/sigqueue.c @@ -12,12 +12,15 @@ volatile sig_atomic_t num = 1; +int parent; + void action(int sig, siginfo_t *info, void *context) { (void)context; assert(sig == THE_SIG); assert(info->si_signo == THE_SIG); assert(info->si_value.sival_int == num); assert(info->si_code == SI_QUEUE); + assert(info->si_pid == parent); num++; write(1, "action\n", 7); } @@ -28,6 +31,9 @@ int main(void) { status = pipe(fds); ERROR_IF(pipe, status, == -1); + parent = getpid(); + assert(parent != 0); + int child = fork(); ERROR_IF(fork, child, == -1); -- GitLab