Files
asterinas/kernel/aster-nix/src/syscall/sigaltstack.rs
2024-08-09 18:01:01 +08:00

116 lines
2.9 KiB
Rust

// SPDX-License-Identifier: MPL-2.0
#![allow(dead_code)]
use super::SyscallReturn;
use crate::{
prelude::*,
process::{
posix_thread::PosixThreadExt,
signal::{SigStack, SigStackFlags},
},
};
pub fn sys_sigaltstack(sig_stack_addr: Vaddr, old_sig_stack_addr: Vaddr) -> Result<SyscallReturn> {
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());
CurrentUserSpace::get().write_val(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 = CurrentUserSpace::get().read_val::<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;