From 98a2a566d91e1f6c3431b0e180c8208a6d0e9e79 Mon Sep 17 00:00:00 2001
From: 4lDO2 <4lDO2@protonmail.com>
Date: Sun, 23 Jun 2024 23:30:34 +0200
Subject: [PATCH] Almost succeed at repeatedly accepting signals.

---
 redox-rt/src/arch/x86_64.rs | 26 +++++++++++++++-----------
 redox-rt/src/proc.rs        | 14 ++++++++------
 redox-rt/src/signal.rs      | 19 ++++++++++++-------
 3 files changed, 35 insertions(+), 24 deletions(-)

diff --git a/redox-rt/src/arch/x86_64.rs b/redox-rt/src/arch/x86_64.rs
index 54a57ae1..7349809f 100644
--- a/redox-rt/src/arch/x86_64.rs
+++ b/redox-rt/src/arch/x86_64.rs
@@ -150,13 +150,13 @@ asmfunction!(__relibc_internal_sigentry: ["
     and eax, ecx
     and eax, {SIGW1_PENDING_MASK}
     bsf eax, eax
-    jnz 4f
+    jnz 7f
     add eax, 32
 2:
     // By now we have selected a signal, stored in eax (6-bit). We now need to choose whether or
     // not to switch to the alternate signal stack. If SA_ONSTACK is clear for this signal, then
     // skip the sigaltstack logic.
-    bt fs:[{tcb_sa_off} + {sa_onstack}], edx
+    bt fs:[{tcb_sa_off} + {sa_onstack}], eax
     jc 3f
 
     // Otherwise, the altstack is already active. The sigaltstack being disabled, is equivalent
@@ -180,10 +180,10 @@ asmfunction!(__relibc_internal_sigentry: ["
 4:
     // Now that we have a stack, we can finally start initializing the signal stack!
 
-    push 0 // SS
+    push 0x23 // SS
     push fs:[{tcb_sc_off} + {sc_saved_rsp}]
     push fs:[{tcb_sc_off} + {sc_saved_rflags}]
-    push 0 // CS
+    push 0x2b // CS
     push fs:[{tcb_sc_off} + {sc_saved_rip}]
 
     push rdi
@@ -202,7 +202,7 @@ asmfunction!(__relibc_internal_sigentry: ["
     push r14
     push r15
 
-    push rdx // selected signal
+    push rax // selected signal
 
     sub rsp, 4096 + 24
 
@@ -214,7 +214,7 @@ asmfunction!(__relibc_internal_sigentry: ["
 
     // TODO: self-modifying?
     cmp byte ptr [rip + {supports_xsave}], 0
-    je 3f
+    je 6f
 
     mov eax, 0xffffffff
     mov edx, eax
@@ -227,8 +227,8 @@ asmfunction!(__relibc_internal_sigentry: ["
     mov edx, eax
     xrstor [rsp]
 
-    add rsp, 4096 + 24
-2:
+5:
+    add rsp, 4096 + 32
     pop r15
     pop r14
     pop r13
@@ -245,20 +245,24 @@ asmfunction!(__relibc_internal_sigentry: ["
     pop rsi
     pop rdi
 
+    iretq
+    /*
     pop qword ptr fs:[{tcb_sa_off} + {sa_tmp}]
     add rsp, 8
     popfq
     pop rsp
     jmp qword ptr fs:[{tcb_sa_off} + {sa_tmp}]
-3:
+    */
+6:
     fxsave64 [rsp]
 
     mov rdi, rsp
     call {inner}
 
     fxrstor64 [rsp]
-    jmp 2b
-4:
+    jmp 5b
+7:
+    ud2
     // Spurious signal
 "] <= [
     inner = sym inner_c,
diff --git a/redox-rt/src/proc.rs b/redox-rt/src/proc.rs
index 218bf18d..e4564bb7 100644
--- a/redox-rt/src/proc.rs
+++ b/redox-rt/src/proc.rs
@@ -795,6 +795,14 @@ pub fn fork_inner(initial_rsp: *mut usize) -> Result<usize> {
                 }
             }
 
+            let buf = create_set_addr_space_buf(
+                *new_addr_space_fd,
+                __relibc_internal_fork_ret as usize,
+                initial_rsp as usize,
+            );
+            let _ = syscall::write(*new_addr_space_sel_fd, &buf)?;
+        }
+        {
             // Reuse the same sigaltstack and signal entry (all memory will be re-mapped CoW later).
             //
             // Do this after the address space is cloned, since the kernel will get a shared
@@ -804,12 +812,6 @@ pub fn fork_inner(initial_rsp: *mut usize) -> Result<usize> {
                 let _ = syscall::write(*new_sighandler_fd, &crate::signal::current_setsighandler_struct())?;
             }
 
-            let buf = create_set_addr_space_buf(
-                *new_addr_space_fd,
-                __relibc_internal_fork_ret as usize,
-                initial_rsp as usize,
-            );
-            let _ = syscall::write(*new_addr_space_sel_fd, &buf)?;
         }
         copy_env_regs(*cur_pid_fd, *new_pid_fd)?;
     }
diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs
index d90c2c89..2ec1e76c 100644
--- a/redox-rt/src/signal.rs
+++ b/redox-rt/src/signal.rs
@@ -2,7 +2,7 @@ use core::cell::{Cell, UnsafeCell};
 use core::ffi::c_int;
 use core::sync::atomic::{AtomicU64, Ordering};
 
-use syscall::{Error, IntRegisters, Result, SetSighandlerData, SigProcControl, Sigcontrol, EINVAL, SIGCHLD, SIGCONT, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGW0_NOCLDSTOP_BIT, SIGW0_TSTP_IS_STOP_BIT, SIGW0_TTIN_IS_STOP_BIT, SIGW0_TTOU_IS_STOP_BIT, SIGWINCH};
+use syscall::{Error, IntRegisters, Result, SetSighandlerData, SigProcControl, Sigcontrol, SigcontrolFlags, EINVAL, SIGCHLD, SIGCONT, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGW0_NOCLDSTOP_BIT, SIGW0_TSTP_IS_STOP_BIT, SIGW0_TTIN_IS_STOP_BIT, SIGW0_TTOU_IS_STOP_BIT, SIGWINCH};
 
 use crate::{arch::*, Tcb};
 use crate::sync::Mutex;
@@ -28,25 +28,30 @@ pub fn sighandler_function() -> usize {
 
 #[repr(C)]
 pub struct SigStack {
-    sa_handler: usize,
-    sig_num: usize,
-
     #[cfg(target_arch = "x86_64")]
     fx: [u8; 4096],
 
     #[cfg(target_arch = "x86")]
     fx: [u8; 512],
 
-    _pad: [usize; 4], // pad to 192 = 3 * 64 bytes
+    _pad: [usize; 3], // pad to 192 = 3 * 64 = 168 + 24 bytes
+    sig_num: usize,
     regs: IntRegisters, // 160 bytes currently
 }
 
 #[inline(always)]
 unsafe fn inner(stack: &mut SigStack) {
+    // TODO: Set procmask based on SA_NODEFER, SA_RESETHAND, and sa_mask.
+
+    // Re-enable signals again.
+    let control_flags = &Tcb::current().unwrap().os_specific.control.control_flags;
+    control_flags.store(control_flags.load(Ordering::Relaxed) & !SigcontrolFlags::INHIBIT_DELIVERY.bits(), Ordering::Release);
+    core::sync::atomic::compiler_fence(Ordering::Acquire);
+
     let _ = syscall::write(1, b"INNER SIGNAL HANDLER\n");
-    loop {}
+    /*loop {}
     let handler: extern "C" fn(c_int) = core::mem::transmute(stack.sa_handler);
-    handler(stack.sig_num as c_int)
+    handler(stack.sig_num as c_int)*/
 }
 #[cfg(not(target_arch = "x86"))]
 pub(crate) unsafe extern "C" fn inner_c(stack: usize) {
-- 
GitLab