diff --git a/redox-rt/src/arch/x86_64.rs b/redox-rt/src/arch/x86_64.rs index d918a181896fa30ea9d213d2cc6b72fd9618db03..6b9849e6cec503d1e8972991566619d4b06fc440 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 106fadc264738dc804a7cc1276f9b8d9408e8f9a..fa25e97a934d1b456e5117f599fb32a3206d5a3f 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 300564c1fd26791a3d9574031ae60b7abacc2908..3573b0326614c55f03f1a903518a8153bc5ad437 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 78fa0879e92ebe8912abc8dc4b876f16eb0b0744..45779f6b8995fe3082d776cdce295e6b8599d5cf 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 6e2b45426fcb8e8da34689ceab5115c5afb58bcb..d0cf2c942fc439b36a0b58741240c57e6779c73d 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 2b4071dd84dad5af1c241849e24428aa87aa9aae..9fd855a7da06f8df89b81748388f835567f8745b 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 95c7b89847d340da8413ac7fe3fe11001aed79e7..a3bda34315391cf95119f5fdc410d729b07d662d 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 3be1da8441d73b66b5eda4cdc03c2f306bc925b9..abcb486ce53ef5a570030a93a51021f8b5ffcfa1 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 31e5a61c83003936f0fa5325d5d6cf0033a7fe26..f44322081dd9fb39914dc15a60317ea4ec43b53c 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);