Skip to content
Snippets Groups Projects
Verified Commit a2ab86d2 authored by Jacob Lorentzon's avatar Jacob Lorentzon :speech_balloon:
Browse files

Implement signal selection in asm, for SA_ONSTACK.

parent d45adade
Branches
No related tags found
No related merge requests found
...@@ -16,6 +16,7 @@ pub struct SigArea { ...@@ -16,6 +16,7 @@ pub struct SigArea {
altstack_top: usize, altstack_top: usize,
altstack_bottom: usize, altstack_bottom: usize,
tmp: usize, tmp: usize,
pub onstack: u64,
pub disable_signals_depth: u64, pub disable_signals_depth: u64,
} }
...@@ -128,18 +129,41 @@ asmfunction!(__relibc_internal_rlct_clone_ret -> usize: [" ...@@ -128,18 +129,41 @@ asmfunction!(__relibc_internal_rlct_clone_ret -> usize: ["
"] <= []); "] <= []);
asmfunction!(__relibc_internal_sigentry: [" asmfunction!(__relibc_internal_sigentry: ["
// Get offset to TCB // First, select signal, always pick first available bit
mov rax, gs:[0]
// Read first signal word
mov rdx, fs:[{tcb_sc_off} + {sc_word}]
mov rcx, rdx
shr rcx, 32
and edx, ecx
bsf edx, edx
jnz 2f
// Read second signal word
mov rdx, fs:[{tcb_sc_off} + {sc_word} + 8]
mov rcx, rdx
shr rcx, 32
and edx, ecx
bsf edx, edx
jnz 4f
add edx, 32
2:
// By now we have selected a signal, stored in edx (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
jc 3f
// If current RSP is above altstack region, switch to altstack // If current RSP is above altstack region, switch to altstack
mov rdx, [rax + {tcb_sa_off} + {sa_altstack_top}] mov rdx, fs:[{tcb_sa_off} + {sa_altstack_top}]
cmp rdx, rsp cmp rdx, rsp
cmova rsp, rdx cmova rsp, rdx
// If current RSP is below altstack region, also switch to altstack // If current RSP is below altstack region, also switch to altstack
mov rdx, [rax + {tcb_sa_off} + {sa_altstack_bottom}] mov rdx, fs:[{tcb_sa_off} + {sa_altstack_bottom}]
cmp rdx, rax cmp rdx, rsp
cmovbe rsp, rdx cmovbe rsp, rdx
3:
// Otherwise, the altstack is already active. The sigaltstack being disabled, is equivalent // Otherwise, the altstack is already active. The sigaltstack being disabled, is equivalent
// to setting 'top' to usize::MAX and 'bottom' to 0. // to setting 'top' to usize::MAX and 'bottom' to 0.
...@@ -147,16 +171,16 @@ asmfunction!(__relibc_internal_sigentry: [" ...@@ -147,16 +171,16 @@ asmfunction!(__relibc_internal_sigentry: ["
// Now that we have a stack, we can finally start initializing the signal stack! // Now that we have a stack, we can finally start initializing the signal stack!
push 0 // SS push 0 // SS
push [rax + {tcb_sc_off} + {sc_saved_rsp}] push fs:[{tcb_sc_off} + {sc_saved_rsp}]
push [rax + {tcb_sc_off} + {sc_saved_rflags}] push fs:[{tcb_sc_off} + {sc_saved_rflags}]
push 0 // CS push 0 // CS
push [rax + {tcb_sc_off} + {sc_saved_rip}] push fs:[{tcb_sc_off} + {sc_saved_rip}]
push rdi push rdi
push rsi push rsi
push [rax + {tcb_sc_off} + {sc_saved_rdx}] push fs:[{tcb_sc_off} + {sc_saved_rdx}]
push rcx push rcx
push [rax + {tcb_sc_off} + {sc_saved_rax}] push fs:[{tcb_sc_off} + {sc_saved_rax}]
push r8 push r8
push r9 push r9
push r10 push r10
...@@ -168,12 +192,14 @@ asmfunction!(__relibc_internal_sigentry: [" ...@@ -168,12 +192,14 @@ asmfunction!(__relibc_internal_sigentry: ["
push r14 push r14
push r15 push r15
sub rsp, 4096 + 32 push rdx // selected signal
sub rsp, 4096 + 24
cld cld
mov rdi, rsp mov rdi, rsp
xor eax, eax xor eax, eax
mov ecx, 4096 + 32 mov ecx, 4096 + 24
rep stosb rep stosb
// TODO: self-modifying? // TODO: self-modifying?
...@@ -191,7 +217,7 @@ asmfunction!(__relibc_internal_sigentry: [" ...@@ -191,7 +217,7 @@ asmfunction!(__relibc_internal_sigentry: ["
mov edx, eax mov edx, eax
xrstor [rsp] xrstor [rsp]
add rsp, 4096 + 32 add rsp, 4096 + 24
2: 2:
pop r15 pop r15
pop r14 pop r14
...@@ -209,11 +235,11 @@ asmfunction!(__relibc_internal_sigentry: [" ...@@ -209,11 +235,11 @@ asmfunction!(__relibc_internal_sigentry: ["
pop rsi pop rsi
pop rdi pop rdi
pop qword ptr gs:[{tcb_sa_off} + {sa_tmp}] pop qword ptr fs:[{tcb_sa_off} + {sa_tmp}]
add rsp, 8 add rsp, 8
popfq popfq
pop rsp pop rsp
jmp qword ptr gs:[{tcb_sa_off} + {sa_tmp}] jmp qword ptr fs:[{tcb_sa_off} + {sa_tmp}]
3: 3:
fxsave64 [rsp] fxsave64 [rsp]
...@@ -222,16 +248,20 @@ asmfunction!(__relibc_internal_sigentry: [" ...@@ -222,16 +248,20 @@ asmfunction!(__relibc_internal_sigentry: ["
fxrstor64 [rsp] fxrstor64 [rsp]
jmp 2b jmp 2b
4:
// Spurious signal
"] <= [ "] <= [
inner = sym inner_c, inner = sym inner_c,
sa_tmp = const offset_of!(SigArea, tmp), sa_tmp = const offset_of!(SigArea, tmp),
sa_altstack_top = const offset_of!(SigArea, altstack_top), sa_altstack_top = const offset_of!(SigArea, altstack_top),
sa_altstack_bottom = const offset_of!(SigArea, altstack_bottom), sa_altstack_bottom = const offset_of!(SigArea, altstack_bottom),
sa_onstack = const offset_of!(SigArea, onstack),
sc_saved_rax = const offset_of!(Sigcontrol, saved_scratch_a), sc_saved_rax = const offset_of!(Sigcontrol, saved_scratch_a),
sc_saved_rdx = const offset_of!(Sigcontrol, saved_scratch_b), sc_saved_rdx = const offset_of!(Sigcontrol, saved_scratch_b),
sc_saved_rflags = const offset_of!(Sigcontrol, saved_flags), sc_saved_rflags = const offset_of!(Sigcontrol, saved_flags),
sc_saved_rip = const offset_of!(Sigcontrol, saved_ip), sc_saved_rip = const offset_of!(Sigcontrol, saved_ip),
sc_saved_rsp = const offset_of!(Sigcontrol, saved_sp), sc_saved_rsp = const offset_of!(Sigcontrol, saved_sp),
sc_word = const offset_of!(Sigcontrol, word),
tcb_sa_off = const offset_of!(crate::Tcb, os_specific) + offset_of!(RtSigarea, arch), 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), tcb_sc_off = const offset_of!(crate::Tcb, os_specific) + offset_of!(RtSigarea, control),
supports_xsave = sym SUPPORTS_XSAVE, supports_xsave = sym SUPPORTS_XSAVE,
......
...@@ -2,7 +2,7 @@ use core::cell::Cell; ...@@ -2,7 +2,7 @@ use core::cell::Cell;
use core::ffi::c_int; use core::ffi::c_int;
use core::sync::atomic::{AtomicU64, Ordering}; use core::sync::atomic::{AtomicU64, Ordering};
use syscall::{Error, IntRegisters, Result, SetSighandlerData, SigProcControl, Sigcontrol, EINVAL, SIGCHLD, SIGCONT, SIGKILL, SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGW0_TSTP_IS_STOP_BIT, SIGW0_TTIN_IS_STOP_BIT, SIGW0_TTOU_IS_STOP_BIT, SIGWINCH}; 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 crate::{arch::*, Tcb}; use crate::{arch::*, Tcb};
use crate::sync::Mutex; use crate::sync::Mutex;
...@@ -104,16 +104,24 @@ fn modify_sigmask(old: Option<&mut u64>, op: Option<impl FnMut(u32, bool) -> u32 ...@@ -104,16 +104,24 @@ fn modify_sigmask(old: Option<&mut u64>, op: Option<impl FnMut(u32, bool) -> u32
Ok(()) Ok(())
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy, Default)]
pub enum Sigaction { pub enum SigactionKind {
#[default]
Default, Default,
Ignore, Ignore,
Handled { Handled {
handler: SignalHandler, handler: SignalHandler,
mask: u64,
flags: SigactionFlags,
}, },
} }
#[derive(Clone, Copy, Default)]
pub struct Sigaction {
pub kind: SigactionKind,
pub mask: u64,
pub flags: SigactionFlags,
}
pub fn sigaction(signal: u8, new: Option<&Sigaction>, old: Option<&mut Sigaction>) -> Result<()> { pub fn sigaction(signal: u8, new: Option<&Sigaction>, old: Option<&mut Sigaction>) -> Result<()> {
if matches!(usize::from(signal), 0 | 32 | SIGKILL | SIGSTOP | 65..) { if matches!(usize::from(signal), 0 | 32 | SIGKILL | SIGSTOP | 65..) {
return Err(Error::new(EINVAL)); return Err(Error::new(EINVAL));
...@@ -125,39 +133,59 @@ pub fn sigaction(signal: u8, new: Option<&Sigaction>, old: Option<&mut Sigaction ...@@ -125,39 +133,59 @@ pub fn sigaction(signal: u8, new: Option<&Sigaction>, old: Option<&mut Sigaction
let old_ignmask = IGNMASK.load(Ordering::Relaxed); let old_ignmask = IGNMASK.load(Ordering::Relaxed);
if let Some(old) = old { if let Some(old) = old {
// TODO
} }
let Some(new) = new else { let Some(new) = new else {
return Ok(()); return Ok(());
}; };
match (usize::from(signal), new) { let sig_group = usize::from(signal) / 32;
(_, Sigaction::Ignore) | (SIGCHLD | SIGURG | SIGWINCH, Sigaction::Default) => { let sig_bit32 = 1 << ((signal - 1) % 32);
match (usize::from(signal), new.kind) {
(_, SigactionKind::Ignore) | (SIGURG | SIGWINCH, SigactionKind::Default) => {
IGNMASK.store(old_ignmask | sig_bit(signal.into()), Ordering::Relaxed); IGNMASK.store(old_ignmask | sig_bit(signal.into()), Ordering::Relaxed);
// mark the signal as masked // mark the signal as masked
ctl.word[usize::from(signal) / 32].fetch_or(1 << ((signal - 1) % 32), Ordering::Relaxed); ctl.word[sig_group].fetch_or(sig_bit32, Ordering::Relaxed);
// POSIX specifies that pending signals shall be discarded if set to SIG_IGN by // POSIX specifies that pending signals shall be discarded if set to SIG_IGN by
// sigaction. // sigaction.
// TODO: handle tmp_disable_signals // TODO: handle tmp_disable_signals
} }
// TODO: Handle pending signals before these flags are set. // TODO: Handle pending signals before these flags are set.
(SIGTSTP, Sigaction::Default) => { (SIGTSTP, SigactionKind::Default) => {
PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_TSTP_IS_STOP_BIT, Ordering::SeqCst); PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_TSTP_IS_STOP_BIT, Ordering::SeqCst);
} }
(SIGTTIN, Sigaction::Default) => { (SIGTTIN, SigactionKind::Default) => {
PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_TTIN_IS_STOP_BIT, Ordering::SeqCst); PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_TTIN_IS_STOP_BIT, Ordering::SeqCst);
} }
(SIGTTOU, Sigaction::Default) => { (SIGTTOU, SigactionKind::Default) => {
PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_TTOU_IS_STOP_BIT, Ordering::SeqCst); PROC_CONTROL_STRUCT.word[0].fetch_or(SIGW0_TTOU_IS_STOP_BIT, Ordering::SeqCst);
} }
(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);
}
(_, SigactionKind::Default) => {
IGNMASK.store(old_ignmask & !sig_bit(signal.into()), Ordering::Relaxed);
(_, Sigaction::Default) => (), // TODO: update mask
(_, Sigaction::Handled { .. }) => (), //ctl.word[usize::from(signal)].fetch_or();
},
(_, SigactionKind::Handled { .. }) => (),
} }
todo!() Ok(())
} }
fn current_sigctl() -> &'static Sigcontrol { fn current_sigctl() -> &'static Sigcontrol {
...@@ -192,7 +220,7 @@ impl Drop for TmpDisableSignalsGuard { ...@@ -192,7 +220,7 @@ impl Drop for TmpDisableSignalsGuard {
bitflags::bitflags! { bitflags::bitflags! {
// Some flags are ignored by the rt, but they match relibc's 1:1 to simplify conversion. // Some flags are ignored by the rt, but they match relibc's 1:1 to simplify conversion.
#[derive(Clone, Copy)] #[derive(Clone, Copy, Default)]
pub struct SigactionFlags: u32 { pub struct SigactionFlags: u32 {
const NOCLDSTOP = 1; const NOCLDSTOP = 1;
const NOCLDWAIT = 2; const NOCLDWAIT = 2;
...@@ -226,7 +254,7 @@ struct TheDefault { ...@@ -226,7 +254,7 @@ struct TheDefault {
ignmask: u64, ignmask: u64,
} }
static SIGACTIONS: Mutex<[Sigaction; 64]> = Mutex::new([Sigaction::Default; 64]); 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 IGNMASK: AtomicU64 = AtomicU64::new(sig_bit(SIGCHLD) | sig_bit(SIGURG) | sig_bit(SIGWINCH));
static PROC_CONTROL_STRUCT: SigProcControl = SigProcControl { static PROC_CONTROL_STRUCT: SigProcControl = SigProcControl {
......
use core::mem; use core::mem;
use redox_rt::signal::{Sigaction, SigactionFlags, SignalHandler}; use redox_rt::signal::{Sigaction, SigactionFlags, SigactionKind, SignalHandler};
use syscall::{self, Result}; use syscall::{self, Result};
use super::{ use super::{
...@@ -111,49 +111,53 @@ impl PalSignal for Sys { ...@@ -111,49 +111,53 @@ impl PalSignal for Sys {
let new_action = c_act.map(|c_act| { let new_action = c_act.map(|c_act| {
let handler = c_act.sa_handler.map_or(0, |f| f as usize); let handler = c_act.sa_handler.map_or(0, |f| f as usize);
if handler == SIG_DFL { let kind = if handler == SIG_DFL {
Sigaction::Default SigactionKind::Default
} else if handler == SIG_IGN { } else if handler == SIG_IGN {
Sigaction::Ignore SigactionKind::Ignore
} else { } else {
Sigaction::Handled { SigactionKind::Handled {
handler: if c_act.sa_flags & crate::header::signal::SA_SIGINFO as u64 != 0 { handler: if c_act.sa_flags & crate::header::signal::SA_SIGINFO as u64 != 0 {
SignalHandler { sigaction: unsafe { core::mem::transmute(c_act.sa_handler) } } SignalHandler { sigaction: unsafe { core::mem::transmute(c_act.sa_handler) } }
} else { } else {
SignalHandler { handler: c_act.sa_handler } SignalHandler { handler: c_act.sa_handler }
}, },
mask: c_act.sa_mask,
flags: SigactionFlags::from_bits_retain(c_act.sa_flags as u32),
} }
};
Sigaction {
kind,
mask: c_act.sa_mask,
flags: SigactionFlags::from_bits_retain(c_act.sa_flags as u32),
} }
}); });
let mut old_action = c_oact.as_ref().map(|_| Sigaction::Default); let mut old_action = c_oact.as_ref().map(|_| Sigaction::default());
redox_rt::signal::sigaction(sig, new_action.as_ref(), old_action.as_mut())?; redox_rt::signal::sigaction(sig, new_action.as_ref(), old_action.as_mut())?;
if let (Some(c_oact), Some(old_action)) = (c_oact, old_action) { if let (Some(c_oact), Some(old_action)) = (c_oact, old_action) {
*c_oact = match old_action { *c_oact = match old_action.kind {
Sigaction::Ignore => sigaction { SigactionKind::Ignore => sigaction {
sa_handler: unsafe { core::mem::transmute(SIG_IGN) }, sa_handler: unsafe { core::mem::transmute(SIG_IGN) },
sa_flags: 0, sa_flags: 0,
sa_restorer: None, sa_restorer: None,
sa_mask: 0, sa_mask: 0,
}, },
Sigaction::Default => sigaction { SigactionKind::Default => sigaction {
sa_handler: unsafe { core::mem::transmute(SIG_DFL) }, sa_handler: unsafe { core::mem::transmute(SIG_DFL) },
sa_flags: 0, sa_flags: 0,
sa_restorer: None, sa_restorer: None,
sa_mask: 0, sa_mask: 0,
}, },
Sigaction::Handled { handler, mask, flags } => sigaction { SigactionKind::Handled { handler } => sigaction {
sa_handler: if flags.contains(SigactionFlags::SIGINFO) { sa_handler: if old_action.flags.contains(SigactionFlags::SIGINFO) {
unsafe { core::mem::transmute(handler.sigaction) } unsafe { core::mem::transmute(handler.sigaction) }
} else { } else {
unsafe { handler.handler } unsafe { handler.handler }
}, },
sa_restorer: None, sa_restorer: None,
sa_flags: flags.bits().into(), sa_flags: old_action.flags.bits().into(),
sa_mask: mask, sa_mask: old_action.mask,
}, },
}; };
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment