Implement sigaltstack.
This commit is contained in:
@@ -272,3 +272,11 @@ pub unsafe fn manually_enter_trampoline() {
|
||||
sc_saved_eip = const offset_of!(Sigcontrol, saved_ip),
|
||||
);
|
||||
}
|
||||
/// Get current stack pointer, weak granularity guarantees.
|
||||
pub fn current_sp() -> usize {
|
||||
let sp: usize;
|
||||
unsafe {
|
||||
core::arch::asm!("mov {}, esp", out(reg) sp);
|
||||
}
|
||||
sp
|
||||
}
|
||||
|
||||
@@ -375,3 +375,12 @@ pub unsafe fn manually_enter_trampoline() {
|
||||
sc_saved_rip = const offset_of!(Sigcontrol, saved_ip),
|
||||
);
|
||||
}
|
||||
|
||||
/// Get current stack pointer, weak granularity guarantees.
|
||||
pub fn current_sp() -> usize {
|
||||
let sp: usize;
|
||||
unsafe {
|
||||
core::arch::asm!("mov {}, rsp", out(reg) sp);
|
||||
}
|
||||
sp
|
||||
}
|
||||
|
||||
+52
-1
@@ -2,7 +2,7 @@ use core::cell::{Cell, UnsafeCell};
|
||||
use core::ffi::c_int;
|
||||
use core::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
use syscall::{RawAction, SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGQUIT, SIGSEGV, SIGSYS, SIGTRAP, SIGXCPU, SIGXFSZ};
|
||||
use syscall::{RawAction, ENOMEM, EPERM, 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};
|
||||
@@ -213,6 +213,7 @@ pub struct Sigaction {
|
||||
pub mask: u64,
|
||||
pub flags: SigactionFlags,
|
||||
}
|
||||
|
||||
impl Sigaction {
|
||||
fn ip(&self) -> usize {
|
||||
unsafe {
|
||||
@@ -446,3 +447,53 @@ pub fn current_setsighandler_struct() -> SetSighandlerData {
|
||||
proc_control_addr: &PROC_CONTROL_STRUCT as *const SigProcControl as usize,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Default, PartialEq)]
|
||||
pub enum Sigaltstack {
|
||||
#[default]
|
||||
Disabled,
|
||||
|
||||
Enabled { onstack: bool, base: *mut (), size: usize },
|
||||
}
|
||||
pub unsafe fn sigaltstack(new: Option<&Sigaltstack>, old_out: Option<&mut Sigaltstack>) -> Result<()> {
|
||||
let _g = tmp_disable_signals();
|
||||
let tcb = &mut *Tcb::current().unwrap().os_specific.arch.get();
|
||||
|
||||
let old = if tcb.altstack_bottom == 0 && tcb.altstack_top == usize::MAX {
|
||||
Sigaltstack::Disabled
|
||||
} else {
|
||||
Sigaltstack::Enabled {
|
||||
base: tcb.altstack_bottom as *mut (),
|
||||
size: tcb.altstack_top - tcb.altstack_bottom,
|
||||
onstack: (tcb.altstack_bottom..tcb.altstack_top).contains(&crate::arch::current_sp()),
|
||||
}
|
||||
};
|
||||
|
||||
if matches!(old, Sigaltstack::Enabled { onstack: true, .. }) && new != Some(&old) {
|
||||
return Err(Error::new(EPERM));
|
||||
}
|
||||
|
||||
if let Some(old_out) = old_out {
|
||||
*old_out = old;
|
||||
}
|
||||
if let Some(new) = new {
|
||||
match *new {
|
||||
Sigaltstack::Disabled => {
|
||||
tcb.altstack_bottom = 0;
|
||||
tcb.altstack_top = usize::MAX;
|
||||
}
|
||||
Sigaltstack::Enabled { onstack: true, .. } => return Err(Error::new(EINVAL)),
|
||||
Sigaltstack::Enabled { base, size, onstack: false } => {
|
||||
if size < MIN_SIGALTSTACK_SIZE {
|
||||
return Err(Error::new(ENOMEM));
|
||||
}
|
||||
|
||||
tcb.altstack_bottom = base as usize;
|
||||
tcb.altstack_top = base as usize + size;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub const MIN_SIGALTSTACK_SIZE: usize = 8192;
|
||||
|
||||
@@ -127,16 +127,9 @@ pub unsafe extern "C" fn sigaddset(set: *mut sigset_t, signo: c_int) -> c_int {
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn sigaltstack(ss: *const stack_t, old_ss: *mut stack_t) -> c_int {
|
||||
if !ss.is_null() {
|
||||
if (*ss).ss_flags != SS_DISABLE as c_int {
|
||||
return errno::EINVAL;
|
||||
}
|
||||
if (*ss).ss_size < MINSIGSTKSZ {
|
||||
return errno::ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
Sys::sigaltstack(ss, old_ss)
|
||||
Sys::sigaltstack(ss.as_ref(), old_ss.as_mut())
|
||||
.map(|()| 0)
|
||||
.or_minus_one_errno()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
||||
@@ -65,8 +65,13 @@ impl PalSignal for Sys {
|
||||
.map(|_| ())
|
||||
}
|
||||
|
||||
unsafe fn sigaltstack(ss: *const stack_t, old_ss: *mut stack_t) -> c_int {
|
||||
e(syscall!(SIGALTSTACK, ss, old_ss)) as c_int
|
||||
unsafe fn sigaltstack(ss: Option<&stack_t>, old_ss: Option<&mut stack_t>) -> Result<(), Errno> {
|
||||
e_raw(syscall!(
|
||||
SIGALTSTACK,
|
||||
ss.map_or_else(core::ptr::null, |x| x as *const _),
|
||||
old_ss.map_or_else(core::ptr::null_mut, |x| x as *mut _)
|
||||
))
|
||||
.map(|_| ())
|
||||
}
|
||||
|
||||
unsafe fn sigpending(set: *mut sigset_t) -> c_int {
|
||||
|
||||
@@ -25,7 +25,7 @@ pub trait PalSignal: Pal {
|
||||
oact: Option<&mut sigaction>,
|
||||
) -> Result<(), Errno>;
|
||||
|
||||
unsafe fn sigaltstack(ss: *const stack_t, old_ss: *mut stack_t) -> c_int;
|
||||
unsafe fn sigaltstack(ss: Option<&stack_t>, old_ss: Option<&mut stack_t>) -> Result<(), Errno>;
|
||||
|
||||
unsafe fn sigpending(set: *mut sigset_t) -> c_int;
|
||||
|
||||
|
||||
@@ -148,10 +148,7 @@ pub unsafe extern "C" fn redox_dup2_v1(
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn redox_read_v1(fd: usize, dst_base: *mut u8, dst_len: usize) -> RawResult {
|
||||
Error::mux(posix_read(
|
||||
fd,
|
||||
slice::from_raw_parts_mut(dst_base, dst_len),
|
||||
))
|
||||
Error::mux(posix_read(fd, slice::from_raw_parts_mut(dst_base, dst_len)))
|
||||
}
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn redox_write_v1(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use core::mem;
|
||||
use redox_rt::signal::{Sigaction, SigactionFlags, SigactionKind, SignalHandler};
|
||||
use redox_rt::signal::{Sigaction, SigactionFlags, SigactionKind, Sigaltstack, SignalHandler};
|
||||
use syscall::{self, Result};
|
||||
|
||||
use super::{
|
||||
@@ -11,7 +11,7 @@ use crate::{
|
||||
errno::{EINVAL, ENOSYS},
|
||||
signal::{
|
||||
sigaction, siginfo_t, sigset_t, stack_t, SA_SIGINFO, SIG_BLOCK, SIG_DFL, SIG_IGN,
|
||||
SIG_SETMASK, SIG_UNBLOCK,
|
||||
SIG_SETMASK, SIG_UNBLOCK, SS_DISABLE, SS_ONSTACK,
|
||||
},
|
||||
sys_time::{itimerval, ITIMER_REAL},
|
||||
time::timespec,
|
||||
@@ -176,8 +176,51 @@ impl PalSignal for Sys {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
unsafe fn sigaltstack(ss: *const stack_t, old_ss: *mut stack_t) -> c_int {
|
||||
unimplemented!()
|
||||
unsafe fn sigaltstack(
|
||||
new_c: Option<&stack_t>,
|
||||
old_c: Option<&mut stack_t>,
|
||||
) -> Result<(), Errno> {
|
||||
let new = new_c
|
||||
.map(|c_stack| {
|
||||
let flags = usize::try_from(c_stack.ss_flags).map_err(|_| Errno(EINVAL))?;
|
||||
if flags != flags & (SS_DISABLE | SS_ONSTACK) {
|
||||
return Err(Errno(EINVAL));
|
||||
}
|
||||
|
||||
Ok(if flags & SS_DISABLE == SS_DISABLE {
|
||||
Sigaltstack::Disabled
|
||||
} else {
|
||||
Sigaltstack::Enabled {
|
||||
onstack: false,
|
||||
base: c_stack.ss_sp.cast(),
|
||||
size: c_stack.ss_size,
|
||||
}
|
||||
})
|
||||
})
|
||||
.transpose()?;
|
||||
|
||||
let mut old = old_c.as_ref().map(|_| Sigaltstack::default());
|
||||
redox_rt::signal::sigaltstack(new.as_ref(), old.as_mut())?;
|
||||
|
||||
if let (Some(old_c_stack), Some(old)) = (old_c, old) {
|
||||
*old_c_stack = match old {
|
||||
Sigaltstack::Disabled => stack_t {
|
||||
ss_sp: core::ptr::null_mut(),
|
||||
ss_size: 0,
|
||||
ss_flags: SS_DISABLE.try_into().unwrap(),
|
||||
},
|
||||
Sigaltstack::Enabled {
|
||||
onstack,
|
||||
base,
|
||||
size,
|
||||
} => stack_t {
|
||||
ss_sp: base.cast(),
|
||||
ss_size: size,
|
||||
ss_flags: SS_ONSTACK.try_into().unwrap(),
|
||||
},
|
||||
};
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
unsafe fn sigpending(set: *mut sigset_t) -> c_int {
|
||||
|
||||
+2
-2
@@ -139,8 +139,8 @@ pub(crate) unsafe fn create(
|
||||
let mut current_sigmask = 0_u64;
|
||||
#[cfg(target_os = "redox")]
|
||||
{
|
||||
current_sigmask = redox_rt::signal::get_sigmask()
|
||||
.expect("failed to obtain sigprocmask for caller");
|
||||
current_sigmask =
|
||||
redox_rt::signal::get_sigmask().expect("failed to obtain sigprocmask for caller");
|
||||
}
|
||||
|
||||
// Create a locked mutex, unlocked by the thread after it has started.
|
||||
|
||||
Reference in New Issue
Block a user