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