mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-21 08:26:30 +00:00
Support alternate signal stack
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
3734306398
commit
a91a35ebce
@ -265,6 +265,7 @@ int test_sigchld() {
|
||||
// child process
|
||||
printf("create a new proces successfully (pid = %d)\n", getpid());
|
||||
fflush(stdout);
|
||||
exit(0);
|
||||
} else {
|
||||
// parent process
|
||||
wait(NULL);
|
||||
@ -274,11 +275,82 @@ int test_sigchld() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Test handle signal on alternate signal stack
|
||||
// ============================================================================
|
||||
|
||||
#define MAX_ALTSTACK_RECURSION_LEVEL 2
|
||||
|
||||
stack_t g_old_ss;
|
||||
|
||||
static void handle_sigpipe(int num, siginfo_t *info, void *context) {
|
||||
static volatile int recursion_level = 0;
|
||||
printf("Hello from SIGPIPE signal handler on the alternate signal stack (recursion_level = %d)\n",
|
||||
recursion_level);
|
||||
|
||||
// save old_ss to check if we are on stack
|
||||
stack_t old_ss;
|
||||
sigaltstack(NULL, &old_ss);
|
||||
g_old_ss = old_ss;
|
||||
|
||||
recursion_level++;
|
||||
if (recursion_level <= MAX_ALTSTACK_RECURSION_LEVEL) {
|
||||
raise(SIGPIPE);
|
||||
}
|
||||
recursion_level--;
|
||||
}
|
||||
|
||||
#define SIGSTACKSIZE (4*4096)
|
||||
|
||||
int test_sigaltstack() {
|
||||
static char stack[SIGSTACKSIZE];
|
||||
stack_t expected_ss = {
|
||||
.ss_size = SIGSTACKSIZE,
|
||||
.ss_sp = stack,
|
||||
.ss_flags = 0,
|
||||
};
|
||||
if (sigaltstack(&expected_ss, NULL) < 0) {
|
||||
THROW_ERROR("failed to call sigaltstack");
|
||||
}
|
||||
stack_t actual_ss;
|
||||
if (sigaltstack(NULL, &actual_ss) < 0) {
|
||||
THROW_ERROR("failed to call sigaltstack");
|
||||
}
|
||||
if (actual_ss.ss_size != expected_ss.ss_size
|
||||
|| actual_ss.ss_sp != expected_ss.ss_sp
|
||||
|| actual_ss.ss_flags != expected_ss.ss_flags) {
|
||||
THROW_ERROR("failed to check the signal stack after set");
|
||||
}
|
||||
|
||||
struct sigaction new_action, old_action;
|
||||
memset(&new_action, 0, sizeof(struct sigaction));
|
||||
memset(&old_action, 0, sizeof(struct sigaction));
|
||||
new_action.sa_sigaction = handle_sigpipe;
|
||||
new_action.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK;
|
||||
if (sigaction(SIGPIPE, &new_action, &old_action) < 0) {
|
||||
THROW_ERROR("registering new signal handler failed");
|
||||
}
|
||||
if (old_action.sa_handler != SIG_DFL) {
|
||||
THROW_ERROR("unexpected old sig handler");
|
||||
}
|
||||
|
||||
raise(SIGPIPE);
|
||||
if (g_old_ss.ss_flags != SS_ONSTACK) {
|
||||
THROW_ERROR("check stack flags failed");
|
||||
}
|
||||
|
||||
if (sigaction(SIGPIPE, &old_action, NULL) < 0) {
|
||||
THROW_ERROR("restoring old signal handler failed");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
test_sigprocmask();
|
||||
test_raise();
|
||||
test_handle_sigfpe();
|
||||
test_handle_sigsegv();
|
||||
test_sigchld();
|
||||
test_sigaltstack();
|
||||
return 0;
|
||||
}
|
@ -92,7 +92,6 @@ impl PosixThreadBuilder {
|
||||
let thread = Arc::new_cyclic(|thread_ref| {
|
||||
let task = create_new_user_task(user_space, thread_ref.clone());
|
||||
let status = ThreadStatus::Init;
|
||||
let sig_context = Mutex::new(None);
|
||||
let posix_thread = PosixThread {
|
||||
process,
|
||||
is_main_thread,
|
||||
@ -102,7 +101,8 @@ impl PosixThreadBuilder {
|
||||
credentials,
|
||||
sig_mask: Mutex::new(sig_mask),
|
||||
sig_queues: Mutex::new(sig_queues),
|
||||
sig_context,
|
||||
sig_context: Mutex::new(None),
|
||||
sig_stack: Mutex::new(None),
|
||||
robust_list: Mutex::new(None),
|
||||
};
|
||||
|
||||
|
@ -3,7 +3,7 @@ use super::signal::sig_mask::SigMask;
|
||||
use super::signal::sig_num::SigNum;
|
||||
use super::signal::sig_queues::SigQueues;
|
||||
use super::signal::signals::Signal;
|
||||
use super::signal::{SigEvents, SigEventsFilter};
|
||||
use super::signal::{SigEvents, SigEventsFilter, SigStack};
|
||||
use super::{do_exit_group, Credentials, Process, TermStatus};
|
||||
use crate::events::Observer;
|
||||
use crate::prelude::*;
|
||||
@ -51,6 +51,7 @@ pub struct PosixThread {
|
||||
/// Signal handler ucontext address
|
||||
/// FIXME: This field may be removed. For glibc applications with RESTORER flag set, the sig_context is always equals with rsp.
|
||||
sig_context: Mutex<Option<Vaddr>>,
|
||||
sig_stack: Mutex<Option<SigStack>>,
|
||||
}
|
||||
|
||||
impl PosixThread {
|
||||
@ -152,6 +153,10 @@ impl PosixThread {
|
||||
&self.sig_context
|
||||
}
|
||||
|
||||
pub fn sig_stack(&self) -> &Mutex<Option<SigStack>> {
|
||||
&self.sig_stack
|
||||
}
|
||||
|
||||
pub fn robust_list(&self) -> &Mutex<Option<RobustListHead>> {
|
||||
&self.robust_list
|
||||
}
|
||||
|
@ -8,30 +8,27 @@ pub mod sig_disposition;
|
||||
pub mod sig_mask;
|
||||
pub mod sig_num;
|
||||
pub mod sig_queues;
|
||||
mod sig_stack;
|
||||
pub mod signals;
|
||||
|
||||
pub use events::{SigEvents, SigEventsFilter};
|
||||
pub use pauser::Pauser;
|
||||
pub use poll::{Pollee, Poller};
|
||||
|
||||
use core::mem;
|
||||
pub use sig_stack::{SigStack, SigStackFlags, SigStackStatus};
|
||||
|
||||
use align_ext::AlignExt;
|
||||
use jinux_frame::{cpu::UserContext, task::Task};
|
||||
use core::mem;
|
||||
use jinux_frame::cpu::UserContext;
|
||||
use jinux_frame::task::Task;
|
||||
|
||||
use self::c_types::siginfo_t;
|
||||
use self::sig_mask::SigMask;
|
||||
use self::sig_num::SigNum;
|
||||
use crate::current_thread;
|
||||
use crate::process::posix_thread::PosixThreadExt;
|
||||
use crate::process::signal::c_types::ucontext_t;
|
||||
use crate::process::signal::sig_action::SigActionFlags;
|
||||
use super::posix_thread::{PosixThread, PosixThreadExt};
|
||||
use crate::prelude::*;
|
||||
use crate::process::{do_exit_group, TermStatus};
|
||||
use crate::util::{write_bytes_to_user, write_val_to_user};
|
||||
use crate::{
|
||||
prelude::*,
|
||||
process::signal::sig_action::{SigAction, SigDefaultAction},
|
||||
};
|
||||
use c_types::{siginfo_t, ucontext_t};
|
||||
use sig_action::{SigAction, SigActionFlags, SigDefaultAction};
|
||||
use sig_mask::SigMask;
|
||||
use sig_num::SigNum;
|
||||
|
||||
/// Handle pending signal for current process
|
||||
pub fn handle_pending_signal(context: &mut UserContext) -> Result<()> {
|
||||
@ -134,19 +131,24 @@ pub fn handle_user_signal(
|
||||
// block signals in sigmask when running signal handler
|
||||
posix_thread.sig_mask().lock().block(mask.as_u64());
|
||||
|
||||
// Set up signal stack in user stack,
|
||||
// to avoid corrupting user stack, we minus 128 first.
|
||||
let mut user_rsp = context.rsp() as u64;
|
||||
user_rsp -= 128;
|
||||
// Set up signal stack.
|
||||
let mut stack_pointer = if let Some(sp) = use_alternate_signal_stack(posix_thread) {
|
||||
sp as u64
|
||||
} else {
|
||||
// just use user stack
|
||||
context.rsp() as u64
|
||||
};
|
||||
|
||||
// To avoid corrupting signal stack, we minus 128 first.
|
||||
stack_pointer -= 128;
|
||||
|
||||
// 1. write siginfo_t
|
||||
user_rsp -= mem::size_of::<siginfo_t>() as u64;
|
||||
write_val_to_user(user_rsp as _, &sig_info)?;
|
||||
let siginfo_addr = user_rsp;
|
||||
// debug!("siginfo_addr = 0x{:x}", siginfo_addr);
|
||||
stack_pointer -= mem::size_of::<siginfo_t>() as u64;
|
||||
write_val_to_user(stack_pointer as _, &sig_info)?;
|
||||
let siginfo_addr = stack_pointer;
|
||||
|
||||
// 2. write ucontext_t.
|
||||
user_rsp = alloc_aligned_in_user_stack(user_rsp, mem::size_of::<ucontext_t>(), 16)?;
|
||||
stack_pointer = alloc_aligned_in_user_stack(stack_pointer, mem::size_of::<ucontext_t>(), 16)?;
|
||||
let mut ucontext = ucontext_t {
|
||||
uc_sigmask: mask.as_u64(),
|
||||
..Default::default()
|
||||
@ -159,18 +161,17 @@ pub fn handle_user_signal(
|
||||
ucontext.uc_link = 0;
|
||||
}
|
||||
// TODO: store fp regs in ucontext
|
||||
write_val_to_user(user_rsp as _, &ucontext)?;
|
||||
let ucontext_addr = user_rsp;
|
||||
// Store the ucontext addr in sig context of current process.
|
||||
write_val_to_user(stack_pointer as _, &ucontext)?;
|
||||
let ucontext_addr = stack_pointer;
|
||||
// Store the ucontext addr in sig context of current thread.
|
||||
*sig_context = Some(ucontext_addr as Vaddr);
|
||||
// current.sig_context().lock().push_back(ucontext_addr as _);
|
||||
|
||||
// 3. Set the address of the trampoline code.
|
||||
if flags.contains(SigActionFlags::SA_RESTORER) {
|
||||
// If contains SA_RESTORER flag, trampoline code is provided by libc in restorer_addr.
|
||||
// We just store restorer_addr on user stack to allow user code just to trampoline code.
|
||||
user_rsp = write_u64_to_user_stack(user_rsp, restorer_addr as u64)?;
|
||||
trace!("After set restorer addr: user_rsp = 0x{:x}", user_rsp);
|
||||
stack_pointer = write_u64_to_user_stack(stack_pointer, restorer_addr as u64)?;
|
||||
trace!("After set restorer addr: user_rsp = 0x{:x}", stack_pointer);
|
||||
} else {
|
||||
// Otherwise we create a trampoline.
|
||||
// FIXME: This may cause problems if we read old_context from rsp.
|
||||
@ -179,14 +180,14 @@ pub fn handle_user_signal(
|
||||
0x0f, 0x05, // syscall (call rt_sigreturn)
|
||||
0x90, // nop (for alignment)
|
||||
];
|
||||
user_rsp -= TRAMPOLINE.len() as u64;
|
||||
let trampoline_rip = user_rsp;
|
||||
write_bytes_to_user(user_rsp as Vaddr, TRAMPOLINE)?;
|
||||
user_rsp = write_u64_to_user_stack(user_rsp, trampoline_rip)?;
|
||||
stack_pointer -= TRAMPOLINE.len() as u64;
|
||||
let trampoline_rip = stack_pointer;
|
||||
write_bytes_to_user(stack_pointer as Vaddr, TRAMPOLINE)?;
|
||||
stack_pointer = write_u64_to_user_stack(stack_pointer, trampoline_rip)?;
|
||||
}
|
||||
// 4. Set correct register values
|
||||
context.set_rip(handler_addr as _);
|
||||
context.set_rsp(user_rsp as usize);
|
||||
context.set_rsp(stack_pointer as usize);
|
||||
// parameters of signal handler
|
||||
context.set_rdi(sig_num.as_u8() as usize); // signal number
|
||||
if flags.contains(SigActionFlags::SA_SIGINFO) {
|
||||
@ -200,6 +201,34 @@ pub fn handle_user_signal(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Use an alternate signal stack, which was installed by sigaltstack.
|
||||
/// It the stack is already active, we just increase the handler counter and return None, since
|
||||
/// the stack pointer can be read from context.
|
||||
/// It the stack is not used by any handler, we will return the new sp in alternate signal stack.
|
||||
fn use_alternate_signal_stack(posix_thread: &PosixThread) -> Option<usize> {
|
||||
let mut sig_stack = posix_thread.sig_stack().lock();
|
||||
|
||||
let Some(sig_stack) = &mut *sig_stack else {
|
||||
return None;
|
||||
};
|
||||
|
||||
if sig_stack.is_disabled() {
|
||||
return None;
|
||||
}
|
||||
|
||||
if sig_stack.is_active() {
|
||||
// The stack is already active, so we just use sp in context.
|
||||
sig_stack.increase_handler_counter();
|
||||
return None;
|
||||
}
|
||||
|
||||
sig_stack.increase_handler_counter();
|
||||
|
||||
// Make sp align at 16. FIXME: is this required?
|
||||
let stack_pointer = (sig_stack.base() + sig_stack.size()).align_down(16);
|
||||
Some(stack_pointer)
|
||||
}
|
||||
|
||||
fn write_u64_to_user_stack(rsp: u64, value: u64) -> Result<u64> {
|
||||
let rsp = rsp - 8;
|
||||
write_val_to_user(rsp as Vaddr, &value)?;
|
||||
|
@ -103,7 +103,6 @@ impl SigActionFlags {
|
||||
self.intersects(
|
||||
SigActionFlags::SA_NOCLDSTOP
|
||||
| SigActionFlags::SA_NOCLDWAIT
|
||||
| SigActionFlags::SA_ONSTACK
|
||||
| SigActionFlags::SA_RESETHAND,
|
||||
)
|
||||
}
|
||||
|
93
services/libs/jinux-std/src/process/signal/sig_stack.rs
Normal file
93
services/libs/jinux-std/src/process/signal/sig_stack.rs
Normal file
@ -0,0 +1,93 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
/// User-provided signal stack. `SigStack` is per-thread, and each thread can have
|
||||
/// at most one `SigStack`. If one signal handler specifying the `SA_ONSTACK` flag,
|
||||
/// the handler should be executed on the `SigStack`, instead of on the default stack.
|
||||
///
|
||||
/// SigStack can be registered and unregistered by syscall `sigaltstack`.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SigStack {
|
||||
base: Vaddr,
|
||||
flags: SigStackFlags,
|
||||
size: usize,
|
||||
/// The number of handlers that are currently using the stack
|
||||
handler_counter: usize,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
pub struct SigStackFlags: u32 {
|
||||
const SS_AUTODISARM = 1 << 31;
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
|
||||
pub enum SigStackStatus {
|
||||
#[default]
|
||||
SS_INACTIVE = 0,
|
||||
// The thread is currently executing on the alternate signal stack
|
||||
SS_ONSTACK = 1,
|
||||
// The stack is currently disabled.
|
||||
SS_DISABLE = 2,
|
||||
}
|
||||
|
||||
impl SigStack {
|
||||
pub fn new(base: Vaddr, flags: SigStackFlags, size: usize) -> Self {
|
||||
Self {
|
||||
base,
|
||||
flags,
|
||||
size,
|
||||
handler_counter: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn base(&self) -> Vaddr {
|
||||
self.base
|
||||
}
|
||||
|
||||
pub fn flags(&self) -> SigStackFlags {
|
||||
self.flags
|
||||
}
|
||||
|
||||
pub fn size(&self) -> usize {
|
||||
self.size
|
||||
}
|
||||
|
||||
pub fn status(&self) -> SigStackStatus {
|
||||
if self.handler_counter == 0 {
|
||||
return SigStackStatus::SS_INACTIVE;
|
||||
}
|
||||
|
||||
// Learning From [sigaltstack doc](https://man7.org/linux/man-pages/man2/sigaltstack.2.html):
|
||||
// If the stack is currently executed on,
|
||||
// 1. If the stack was established with flag SS_AUTODISARM, the stack status is DISABLE,
|
||||
// 2. otherwise, the stack status is ONSTACK
|
||||
if self.flags.contains(SigStackFlags::SS_AUTODISARM) {
|
||||
SigStackStatus::SS_DISABLE
|
||||
} else {
|
||||
SigStackStatus::SS_ONSTACK
|
||||
}
|
||||
}
|
||||
|
||||
/// Mark the stack is currently used by a signal handler.
|
||||
pub fn increase_handler_counter(&mut self) {
|
||||
self.handler_counter += 1;
|
||||
}
|
||||
|
||||
// Mark the stack is freed by current handler.
|
||||
pub fn decrease_handler_counter(&mut self) {
|
||||
// FIXME: deal with SS_AUTODISARM flag
|
||||
self.handler_counter -= 1
|
||||
}
|
||||
|
||||
/// Determins whether the stack is executed on by any signal handler
|
||||
pub fn is_active(&self) -> bool {
|
||||
// FIXME: can DISABLE stack be used?
|
||||
self.handler_counter != 0 && !self.flags.contains(SigStackFlags::SS_AUTODISARM)
|
||||
}
|
||||
|
||||
pub fn is_disabled(&self) -> bool {
|
||||
self.handler_counter != 0 && self.flags.contains(SigStackFlags::SS_AUTODISARM)
|
||||
}
|
||||
}
|
@ -99,6 +99,7 @@ use self::setsid::sys_setsid;
|
||||
use self::setsockopt::sys_setsockopt;
|
||||
use self::setuid::sys_setuid;
|
||||
use self::shutdown::sys_shutdown;
|
||||
use self::sigaltstack::sys_sigaltstack;
|
||||
use self::socket::sys_socket;
|
||||
use self::socketpair::sys_socketpair;
|
||||
|
||||
@ -185,6 +186,7 @@ mod setsid;
|
||||
mod setsockopt;
|
||||
mod setuid;
|
||||
mod shutdown;
|
||||
mod sigaltstack;
|
||||
mod socket;
|
||||
mod socketpair;
|
||||
mod stat;
|
||||
@ -316,6 +318,7 @@ define_syscall_nums!(
|
||||
SYS_SETFSUID = 122,
|
||||
SYS_SETFSGID = 123,
|
||||
SYS_GETSID = 124,
|
||||
SYS_SIGALTSTACK = 131,
|
||||
SYS_STATFS = 137,
|
||||
SYS_FSTATFS = 138,
|
||||
SYS_PRCTL = 157,
|
||||
@ -491,6 +494,7 @@ pub fn syscall_dispatch(
|
||||
SYS_SETFSUID => syscall_handler!(1, sys_setfsuid, args),
|
||||
SYS_SETFSGID => syscall_handler!(1, sys_setfsgid, args),
|
||||
SYS_GETSID => syscall_handler!(1, sys_getsid, args),
|
||||
SYS_SIGALTSTACK => syscall_handler!(2, sys_sigaltstack, args),
|
||||
SYS_STATFS => syscall_handler!(2, sys_statfs, args),
|
||||
SYS_FSTATFS => syscall_handler!(2, sys_fstatfs, args),
|
||||
SYS_PRCTL => syscall_handler!(5, sys_prctl, args),
|
||||
|
@ -23,6 +23,15 @@ pub fn sys_rt_sigreturn(context: &mut UserContext) -> Result<SyscallReturn> {
|
||||
debug_assert!(sig_context_addr == context.rsp() as Vaddr);
|
||||
|
||||
let ucontext = read_val_from_user::<ucontext_t>(sig_context_addr)?;
|
||||
|
||||
// If the sig stack is active and used by current handler, decrease handler counter.
|
||||
if let Some(sig_stack) = posix_thread.sig_stack().lock().as_mut() {
|
||||
let rsp = context.rsp();
|
||||
if rsp >= sig_stack.base() && rsp <= sig_stack.base() + sig_stack.size() {
|
||||
sig_stack.decrease_handler_counter();
|
||||
}
|
||||
}
|
||||
|
||||
// Set previous ucontext address
|
||||
if ucontext.uc_link == 0 {
|
||||
*sig_context = None;
|
||||
@ -33,5 +42,6 @@ pub fn sys_rt_sigreturn(context: &mut UserContext) -> Result<SyscallReturn> {
|
||||
// unblock sig mask
|
||||
let sig_mask = ucontext.uc_sigmask;
|
||||
posix_thread.sig_mask().lock().unblock(sig_mask);
|
||||
|
||||
Ok(SyscallReturn::NoReturn)
|
||||
}
|
||||
|
112
services/libs/jinux-std/src/syscall/sigaltstack.rs
Normal file
112
services/libs/jinux-std/src/syscall/sigaltstack.rs
Normal file
@ -0,0 +1,112 @@
|
||||
use crate::log_syscall_entry;
|
||||
use crate::prelude::*;
|
||||
use crate::process::posix_thread::PosixThreadExt;
|
||||
use crate::process::signal::SigStack;
|
||||
use crate::process::signal::SigStackFlags;
|
||||
use crate::util::read_val_from_user;
|
||||
use crate::util::write_val_to_user;
|
||||
|
||||
use super::{SyscallReturn, SYS_SIGALTSTACK};
|
||||
|
||||
pub fn sys_sigaltstack(sig_stack_addr: Vaddr, old_sig_stack_addr: Vaddr) -> Result<SyscallReturn> {
|
||||
log_syscall_entry!(SYS_SIGALTSTACK);
|
||||
|
||||
debug!(
|
||||
"sig_stack_addr = 0x{:x}, old_sig_stack_addr: 0x{:x}",
|
||||
sig_stack_addr, old_sig_stack_addr
|
||||
);
|
||||
|
||||
let old_stack = {
|
||||
let current_thread = current_thread!();
|
||||
let posix_thread = current_thread.as_posix_thread().unwrap();
|
||||
let sig_stack = posix_thread.sig_stack().lock();
|
||||
sig_stack.clone()
|
||||
};
|
||||
|
||||
get_old_stack(old_sig_stack_addr, old_stack.as_ref())?;
|
||||
set_new_stack(sig_stack_addr, old_stack.as_ref())?;
|
||||
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
||||
|
||||
fn get_old_stack(old_sig_stack_addr: Vaddr, old_stack: Option<&SigStack>) -> Result<()> {
|
||||
if old_sig_stack_addr == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let Some(old_stack) = old_stack else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
debug!("old stack = {:?}", old_stack);
|
||||
|
||||
let stack = stack_t::from(old_stack.clone());
|
||||
write_val_to_user(old_sig_stack_addr, &stack)
|
||||
}
|
||||
|
||||
fn set_new_stack(sig_stack_addr: Vaddr, old_stack: Option<&SigStack>) -> Result<()> {
|
||||
if sig_stack_addr == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if let Some(old_stack) = old_stack && old_stack.is_active() {
|
||||
return_errno_with_message!(Errno::EPERM, "the old stack is active now");
|
||||
}
|
||||
|
||||
let new_stack = {
|
||||
let stack = read_val_from_user::<stack_t>(sig_stack_addr)?;
|
||||
SigStack::try_from(stack)?
|
||||
};
|
||||
|
||||
debug!("new_stack = {:?}", new_stack);
|
||||
|
||||
let current_thread = current_thread!();
|
||||
let posix_thread = current_thread.as_posix_thread().unwrap();
|
||||
*posix_thread.sig_stack().lock() = Some(new_stack);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Debug, Clone, Copy, Pod)]
|
||||
#[repr(C)]
|
||||
struct stack_t {
|
||||
// Base address of stack
|
||||
sp: Vaddr,
|
||||
flags: i32,
|
||||
// Number of bytes in stack
|
||||
size: usize,
|
||||
}
|
||||
|
||||
impl TryFrom<stack_t> for SigStack {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(stack: stack_t) -> Result<Self> {
|
||||
if stack.flags < 0 {
|
||||
return_errno_with_message!(Errno::EINVAL, "negative flags");
|
||||
}
|
||||
|
||||
let flags = SigStackFlags::from_bits(stack.flags as u32)
|
||||
.ok_or_else(|| Error::with_message(Errno::EINVAL, "invalid flags"))?;
|
||||
|
||||
if stack.size < MINSTKSZ {
|
||||
return_errno_with_message!(Errno::ENOMEM, "stack size is less than MINSTKSZ");
|
||||
}
|
||||
|
||||
Ok(Self::new(stack.sp, flags, stack.size))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SigStack> for stack_t {
|
||||
fn from(stack: SigStack) -> Self {
|
||||
let flags = stack.flags().bits() as i32 | stack.status() as i32;
|
||||
Self {
|
||||
sp: stack.base(),
|
||||
flags,
|
||||
size: stack.size(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const SIGSTKSZ: usize = 8192;
|
||||
const MINSTKSZ: usize = 2048;
|
Reference in New Issue
Block a user