From 63509e75ce127fdb05c07a464e975687e8ef2977 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sat, 29 Jun 2024 14:01:38 +0200 Subject: [PATCH] Use new signal ABI where 'actions' are in shmem. --- redox-rt/src/arch/x86_64.rs | 4 +- redox-rt/src/signal.rs | 163 ++++++++++++++++++++---------------- src/header/signal/redox.rs | 14 ++-- 3 files changed, 99 insertions(+), 82 deletions(-) diff --git a/redox-rt/src/arch/x86_64.rs b/redox-rt/src/arch/x86_64.rs index b597928f..689b1ff8 100644 --- a/redox-rt/src/arch/x86_64.rs +++ b/redox-rt/src/arch/x86_64.rs @@ -317,9 +317,7 @@ __relibc_internal_sigentry_crit_second: tcb_sa_off = const offset_of!(crate::Tcb, os_specific) + offset_of!(RtSigarea, arch), tcb_sc_off = const offset_of!(crate::Tcb, os_specific) + offset_of!(RtSigarea, control), supports_xsave = sym SUPPORTS_XSAVE, - SIGW0_PENDING_MASK = const !( - SIGW0_TSTP_IS_STOP_BIT | SIGW0_TTIN_IS_STOP_BIT | SIGW0_TTOU_IS_STOP_BIT | SIGW0_NOCLDSTOP_BIT | SIGW0_UNUSED1 | SIGW0_UNUSED2 - ), + SIGW0_PENDING_MASK = const !0, SIGW1_PENDING_MASK = const !0, REDZONE_SIZE = const 128, STACK_ALIGN = const 64, // if xsave is used diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index 7c93c8a7..0e9eb427 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -1,8 +1,9 @@ use core::cell::{Cell, UnsafeCell}; use core::ffi::c_int; -use core::sync::atomic::Ordering; +use core::sync::atomic::{AtomicUsize, Ordering}; -use syscall::{Error, 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, data::AtomicU64}; +use syscall::{RawAction, SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGQUIT, SIGSEGV, SIGSYS, SIGTRAP, SIGXCPU, SIGXFSZ}; +use syscall::{Error, Result, SetSighandlerData, SigProcControl, Sigcontrol, SigcontrolFlags, EINVAL, SIGCHLD, SIGCONT, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGWINCH, data::AtomicU64}; use crate::{arch::*, Tcb}; use crate::sync::Mutex; @@ -57,11 +58,16 @@ unsafe fn inner(stack: &mut SigStack) { arch_pre(stack, &mut *os.arch.get()); let sigaction = { - let mut guard = SIGACTIONS.lock(); - let action = guard[stack.sig_num]; + let mut guard = SIGACTIONS_LOCK.lock(); + let action = convert_old(&PROC_CONTROL_STRUCT.actions[stack.sig_num - 1]); if action.flags.contains(SigactionFlags::RESETHAND) { // TODO: other things that must be set - guard[stack.sig_num].kind = SigactionKind::Default; + drop(guard); + sigaction(stack.sig_num as u8, Some(&Sigaction { + kind: SigactionKind::Default, + mask: 0, + flags: SigactionFlags::empty(), + }), None); } action }; @@ -191,6 +197,44 @@ pub struct Sigaction { pub mask: u64, pub flags: SigactionFlags, } +impl Sigaction { + fn ip(&self) -> usize { + unsafe { + match self.kind { + SigactionKind::Handled { handler } => if self.flags.contains(SigactionFlags::SIGINFO) { + handler.sigaction.map_or(0, |a| a as usize) + } else { + handler.handler.map_or(0, |a| a as usize) + } + _ => 0, + } + } + } +} + +const MASK_DONTCARE: u64 = !0; + +fn convert_old(action: &RawAction) -> Sigaction { + let old_first = action.first.load(Ordering::Relaxed); + let old_mask = action.user_data.load(Ordering::Relaxed); + + let handler = (old_first & !(u64::from(STORED_FLAGS) << 32)) as usize; + let flags = SigactionFlags::from_bits_retain(((old_first >> 32) as u32) & STORED_FLAGS); + + let kind = if handler == default_handler as usize { + SigactionKind::Default + } else if flags.contains(SigactionFlags::IGNORED) { + SigactionKind::Ignore + } else { + SigactionKind::Handled { handler: unsafe { core::mem::transmute(handler as usize) } } + }; + + Sigaction { + mask: old_mask, + flags, + kind, + } +} pub fn sigaction(signal: u8, new: Option<&Sigaction>, old: Option<&mut Sigaction>) -> Result<()> { if matches!(usize::from(signal), 0 | 32 | SIGKILL | SIGSTOP | 65..) { @@ -199,62 +243,46 @@ pub fn sigaction(signal: u8, new: Option<&Sigaction>, old: Option<&mut Sigaction let _sigguard = tmp_disable_signals(); let ctl = current_sigctl(); - let mut guard = SIGACTIONS.lock(); - let old_ignmask = IGNMASK.load(Ordering::Relaxed); + + let action = &PROC_CONTROL_STRUCT.actions[usize::from(signal) - 1]; if let Some(old) = old { - *old = guard[usize::from(signal)]; + *old = convert_old(action); } let Some(new) = new else { return Ok(()); }; - guard[usize::from(signal)] = *new; - let sig_group = usize::from(signal) / 32; - let sig_bit32 = 1 << ((signal - 1) % 32); + let explicit_handler = new.ip(); - match (usize::from(signal), new.kind) { + let (mask, flags, handler) = match (usize::from(signal), new.kind) { (_, SigactionKind::Ignore) | (SIGURG | SIGWINCH, SigactionKind::Default) => { - IGNMASK.store(old_ignmask | sig_bit(signal.into()), Ordering::Relaxed); - - // mark the signal as masked - ctl.word[sig_group].fetch_and(!(sig_bit32 << 32), Ordering::Relaxed); - - // POSIX specifies that pending signals shall be discarded if set to SIG_IGN by + // TODO: POSIX specifies that pending signals shall be discarded if set to SIG_IGN by // sigaction. // TODO: handle tmp_disable_signals + (MASK_DONTCARE, SigactionFlags::IGNORED, if matches!(new.kind, SigactionKind::Default) { + default_handler as usize + } else { + 0 + }) } // TODO: Handle pending signals before these flags are set. - (SIGTSTP, SigactionKind::Default) => { - PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_TSTP_IS_STOP_BIT, Ordering::SeqCst); - } - (SIGTTIN, SigactionKind::Default) => { - PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_TTIN_IS_STOP_BIT, Ordering::SeqCst); - } - (SIGTTOU, SigactionKind::Default) => { - PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_TTOU_IS_STOP_BIT, Ordering::SeqCst); - } + (SIGTSTP | SIGTTOU | SIGTTIN, SigactionKind::Default) => (MASK_DONTCARE, SigactionFlags::SIG_SPECIFIC, default_handler as usize), (SIGCHLD, SigactionKind::Default) => { - if new.flags.contains(SigactionFlags::NOCLDSTOP) { - PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_NOCLDSTOP_BIT, Ordering::SeqCst); - } else { - PROC_CONTROL_STRUCT.word[0].fetch_and(!SIGW0_NOCLDSTOP_BIT, Ordering::SeqCst); - } - IGNMASK.store(old_ignmask | sig_bit(signal.into()), Ordering::Relaxed); - - // mark the signal as masked - ctl.word[sig_group].fetch_or(sig_bit32, Ordering::Relaxed); + let nocldstop_bit = new.flags & SigactionFlags::SIG_SPECIFIC; + (MASK_DONTCARE, SigactionFlags::IGNORED | nocldstop_bit, default_handler as usize) } (_, SigactionKind::Default) => { - IGNMASK.store(old_ignmask & !sig_bit(signal.into()), Ordering::Relaxed); - - // TODO: update mask - //ctl.word[usize::from(signal)].fetch_or(); + (new.mask, new.flags, default_handler as usize) }, - (_, SigactionKind::Handled { .. }) => (), - } + (_, SigactionKind::Handled { .. }) => { + (new.mask, new.flags, explicit_handler) + } + }; + action.first.store((handler as u64) | (u64::from(flags.bits() & STORED_FLAGS) << 32), Ordering::Relaxed); + action.user_data.store(mask, Ordering::Relaxed); Ok(()) } @@ -296,26 +324,23 @@ bitflags::bitflags! { // Some flags are ignored by the rt, but they match relibc's 1:1 to simplify conversion. #[derive(Clone, Copy, Default)] pub struct SigactionFlags: u32 { - const NOCLDSTOP = 1; const NOCLDWAIT = 2; - const SIGINFO = 4; - const RESTORER = 0x0400_0000; - const ONSTACK = 0x0800_0000; - const RESTART = 0x1000_0000; - const NODEFER = 0x4000_0000; - const RESETHAND = 0x8000_0000; + const RESTORER = 4; + const SIGINFO = 0x0200_0000; + const ONSTACK = 0x0400_0000; + const RESTART = 0x0800_0000; + const NODEFER = 0x1000_0000; + const RESETHAND = 0x2000_0000; + const SIG_SPECIFIC = 0x4000_0000; + const IGNORED = 0x8000_0000; } } -fn default_term_handler(sig: c_int) { - syscall::exit((sig as usize) << 8); -} -fn default_core_handler(sig: c_int) { + +const STORED_FLAGS: u32 = 0xfe00_0000; + +fn default_handler(sig: c_int) { syscall::exit((sig as usize) << 8); } -fn default_ign_handler(_: c_int) { -} -fn stop_handler_sentinel(_: c_int) { -} #[derive(Clone, Copy)] pub union SignalHandler { @@ -323,22 +348,16 @@ pub union SignalHandler { pub sigaction: Option<unsafe extern "C" fn(c_int, *const (), *mut ())>, } -struct TheDefault { - actions: [Sigaction; 64], - ignmask: u64, -} - -// indexed directly by signal number -static SIGACTIONS: Mutex<[Sigaction; 64]> = Mutex::new([Sigaction { flags: SigactionFlags::empty(), mask: 0, kind: SigactionKind::Default }; 64]); - -static IGNMASK: AtomicU64 = AtomicU64::new(sig_bit(SIGCHLD) | sig_bit(SIGURG) | sig_bit(SIGWINCH)); +static SIGACTIONS_LOCK: Mutex<()> = Mutex::new(()); static PROC_CONTROL_STRUCT: SigProcControl = SigProcControl { - word: [ - //AtomicU64::new(SIGW0_TSTP_IS_STOP_BIT | SIGW0_TTIN_IS_STOP_BIT | SIGW0_TTOU_IS_STOP_BIT | 0xffff_ffff_0000_0000), - AtomicU64::new(0xffff_ffff_0000_0000), // "allow all, no pending" - AtomicU64::new(0xffff_ffff_0000_0000), // "allow all, no pending" - ], + pending: AtomicU64::new(0), + actions: [const { + RawAction { + first: AtomicU64::new(0), + user_data: AtomicU64::new(0), + } + }; 64], }; fn combine_allowset([lo, hi]: [u64; 2]) -> u64 { @@ -353,7 +372,7 @@ const fn sig_bit(sig: usize) -> u64 { pub fn setup_sighandler(area: &RtSigarea) { { - let mut sigactions = SIGACTIONS.lock(); + let mut sigactions = SIGACTIONS_LOCK.lock(); } let arch = unsafe { &mut *area.arch.get() }; { diff --git a/src/header/signal/redox.rs b/src/header/signal/redox.rs index 8e878dda..689b9da3 100644 --- a/src/header/signal/redox.rs +++ b/src/header/signal/redox.rs @@ -36,14 +36,14 @@ pub const NSIG: usize = 32; pub const SIGRTMIN: usize = 35; pub const SIGRTMAX: usize = 64; -pub const SA_NOCLDSTOP: usize = 0x0000_0001; pub const SA_NOCLDWAIT: usize = 0x0000_0002; -pub const SA_SIGINFO: usize = 0x0000_0004; -pub const SA_RESTORER: usize = 0x0400_0000; -pub const SA_ONSTACK: usize = 0x0800_0000; -pub const SA_RESTART: usize = 0x1000_0000; -pub const SA_NODEFER: usize = 0x4000_0000; -pub const SA_RESETHAND: usize = 0x8000_0000; +pub const SA_RESTORER: usize = 0x0000_0004; // TODO: remove +pub const SA_SIGINFO: usize = 0x0200_0000; +pub const SA_ONSTACK: usize = 0x0400_0000; +pub const SA_RESTART: usize = 0x0800_0000; +pub const SA_NODEFER: usize = 0x1000_0000; +pub const SA_RESETHAND: usize = 0x2000_0000; +pub const SA_NOCLDSTOP: usize = 0x4000_0000; pub const SS_ONSTACK: usize = 0x00000001; pub const SS_DISABLE: usize = 0x00000002; -- GitLab