Implement sigaltstack.

This commit is contained in:
4lDO2
2024-07-01 19:52:48 +02:00
parent 6d5d0eb61e
commit c639fd37ba
9 changed files with 130 additions and 24 deletions
+8
View File
@@ -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
}
+9
View File
@@ -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
View File
@@ -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;
+3 -10
View File
@@ -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]
+7 -2
View File
@@ -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 {
+1 -1
View File
@@ -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;
+1 -4
View File
@@ -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(
+47 -4
View File
@@ -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
View File
@@ -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.