WIP: userspace signal handling

This commit is contained in:
4lDO2
2024-06-18 16:58:28 +02:00
parent 198151a355
commit 295cc820e6
12 changed files with 91 additions and 448 deletions
+2
View File
@@ -29,4 +29,6 @@ pub const PHYS_OFFSET: usize = 0xFFFF_8000_0000_0000;
pub const PHYS_PML4: usize = (PHYS_OFFSET & PML4_MASK) / PML4_SIZE;
/// End offset of the user image, i.e. kernel start
// TODO: Make this offset at least PAGE_SIZE less? There are known hardware bugs on some arches,
// for example on x86 if instructions execute near the 48-bit canonical address boundary.
pub const USER_END_OFFSET: usize = 256 * PML4_SIZE;
+18 -40
View File
@@ -140,6 +140,7 @@ pub struct Context {
/// The effective namespace id
pub ens: SchemeNamespace,
/// Signal handler
pub sig: SignalState,
/// Process umask
@@ -191,8 +192,6 @@ pub struct Context {
pub name: Cow<'static, str>,
/// The open files in the scheme
pub files: Arc<RwLock<Vec<Option<FileDescriptor>>>>,
/// Signal actions
pub actions: Arc<RwLock<Vec<(SigAction, usize)>>>,
/// All contexts except kmain will primarily live in userspace, and enter the kernel only when
/// interrupts or syscalls occur. This flag is set for all contexts but kmain.
pub userspace: bool,
@@ -203,25 +202,20 @@ pub struct Context {
pub fmap_ret: Option<Frame>,
}
#[derive(Clone, Copy, Debug)]
#[derive(Debug)]
pub struct SignalState {
/// Bitset of pending signals.
pub pending: u64,
/// Bitset of procmasked signals.
pub procmask: u64,
/// Offset to jump to when a signal is received.
pub user_handler: Option<NonZeroUsize>,
/// Offset to jump to when a program fault occurs.
pub excp_handler: Option<NonZeroUsize>,
/// Signal control page, required for signals to work.
pub control: Option<RaiiFrame>,
/// Offset within the control page of a naturally aligned, semiatomically accessed, u128.
pub sigword_off: u16,
/// A function pointer to the userspace signal handler.
pub handler: Option<SignalHandler>,
}
#[derive(Clone, Copy, Debug)]
pub struct SignalHandler {
pub handler: NonZeroUsize,
pub altstack: Option<Altstack>,
}
#[derive(Clone, Copy, Debug)]
pub struct Altstack {
pub base: NonZeroUsize,
pub len: NonZeroUsize,
/// Set whenever the kernel is about to have the context jump to its signal trampoline, but the
/// context is currently running.
pub is_pending: bool,
}
impl Context {
@@ -238,9 +232,11 @@ impl Context {
egid: 0,
ens: SchemeNamespace::from(0),
sig: SignalState {
pending: 0,
procmask: !0,
handler: None,
user_handler: None,
excp_handler: None,
control: None,
sigword_off: 0,
is_pending: false,
},
umask: 0o022,
status: Status::HardBlocked { reason: HardBlockedReason::NotYetStarted },
@@ -261,7 +257,6 @@ impl Context {
addr_space: None,
name: Cow::Borrowed(""),
files: Arc::new(RwLock::new(Vec::new())),
actions: Self::empty_actions(),
userspace: false,
ptrace_stop: false,
fmap_ret: None,
@@ -431,16 +426,6 @@ impl Context {
core::mem::replace(&mut self.addr_space, addr_space)
}
pub fn empty_actions() -> Arc<RwLock<Vec<(SigAction, usize)>>> {
Arc::new(RwLock::new(vec![(
SigAction {
sa_handler: unsafe { mem::transmute(SIG_DFL) },
sa_mask: 0,
sa_flags: SigActionFlags::empty(),
},
0
); 128]))
}
pub fn caller_ctx(&self) -> CallerCtx {
CallerCtx {
pid: self.id.into(),
@@ -473,13 +458,6 @@ impl Context {
}
}
impl SignalState {
pub fn deliverable(&self) -> u64 {
const CANT_BLOCK: u64 = (1 << (SIGKILL - 1)) | (1 << (SIGSTOP - 1));
self.pending & (CANT_BLOCK | !self.procmask)
}
}
/// Wrapper struct for borrowing the syscall head or tail buf.
#[derive(Debug)]
pub struct BorrowedHtBuf {
+32 -1
View File
@@ -8,7 +8,7 @@ use syscall::{error::*, flag::MapFlags, GrantFlags, MunmapFlags};
use crate::{
arch::paging::PAGE_SIZE, cpu_set::LogicalCpuSet, memory::{
deallocate_frame, deallocate_p2frame, get_page_info, init_frame, the_zeroed_frame, AddRefError, Enomem, Frame, PageInfo, RefCount, RefKind
deallocate_frame, deallocate_p2frame, get_page_info, init_frame, the_zeroed_frame, AddRefError, Enomem, Frame, PageInfo, RaiiFrame, RefCount, RefKind
}, paging::{
Page, PageFlags, PageMapper, RmmA, TableKind, VirtualAddress,
}, percpu::PercpuBlock, scheme::{self, KernelSchemes}
@@ -466,6 +466,37 @@ impl AddrSpaceWrapper {
Ok(dst_base)
}
/// Borrows a page from user memory, requiring that the frame be Allocated and read/write. This
/// is intended to be used for user-kernel shared memory.
pub fn borrow_frame_enforce_rw_allocated(self: &Arc<Self>, page: Page) -> Result<RaiiFrame> {
let mut guard = self.acquire_write();
let (_start_page, info) = guard.grants.contains(page).ok_or(Error::new(EINVAL))?;
if !info.can_have_flags(MapFlags::PROT_READ | MapFlags::PROT_WRITE) {
return Err(Error::new(EPERM));
}
if !matches!(info.provider, Provider::Allocated { .. }) {
return Err(Error::new(EPERM));
}
let frame = if let Some((f, fl)) = guard.table.utable.translate(page.start_address()) && fl.has_write() {
Frame::containing(f)
} else {
let (frame, flush, new_guard) = correct_inner(self, guard, page, AccessMode::Write, 0).map_err(|_| Error::new(ENOMEM))?;
flush.flush();
guard = new_guard;
frame
};
match get_page_info(frame).expect("missing page info for Allocated grant").add_ref(RefKind::Shared) {
Ok(_) => Ok(unsafe { RaiiFrame::new_unchecked(frame) }),
Err(AddRefError::RcOverflow) => Err(Error::new(ENOMEM)),
Err(AddRefError::SharedToCow) => unreachable!(),
Err(AddRefError::CowToShared) => unreachable!("if it was CoW, it was read-only, but in that case we already called correct_inner"),
}
}
}
impl AddrSpace {
pub fn current() -> Result<Arc<AddrSpaceWrapper>> {
-1
View File
@@ -76,7 +76,6 @@ pub fn init() {
context.sched_affinity = LogicalCpuSet::empty();
context.sched_affinity.atomic_set(crate::cpu_id());
context.name = Cow::Borrowed("kmain");
context.sig.procmask = 0;
self::arch::EMPTY_CR3.call_once(|| unsafe { RmmA::table(TableKind::User) });
+6 -185
View File
@@ -17,7 +17,7 @@ use crate::{
use super::ContextId;
pub fn kmain_signal_handler() {
if context::context_id() != ContextId::new(1) {
/*if context::context_id() != ContextId::new(1) {
log::warn!("kmain signal didn't target PID 1, ignoring");
return;
}
@@ -37,194 +37,15 @@ pub fn kmain_signal_handler() {
}
} else {
log::warn!("Spurious kmain signal, bitmask {bits:#0x}.");
}
}*/
}
// TODO: Move everything but SIGKILL to userspace. SIGCONT and SIGSTOP do not necessarily need to
// be done from this current context.
pub fn signal_handler() {
let (action, sig) = {
// FIXME: Can any low-level state become corrupt if a panic occurs here?
let context_lock = context::current().expect("context::signal_handler not inside of context");
let mut context = context_lock.write();
// Lowest-numbered signal first.
// TODO: randomly?
if context.sig.deliverable() == 0 {
return;
}
let bits = context.sig.deliverable();
// Always prioritize SIGKILL and SIGSTOP, so processes can't simply keep themselves alive
// by killing themselves.
let selected = if bits & (1 << (SIGKILL - 1)) != 0 {
SIGKILL
} else if bits & (1 << (SIGSTOP - 1)) != 0 {
SIGSTOP
} else {
bits.trailing_zeros() as usize + 1
};
context.sig.pending &= !(1 << (selected - 1));
let actions = context.actions.read();
(actions[selected - 1].0, selected)
};
let handler = action.sa_handler.map(|ptr| ptr as usize).unwrap_or(0);
let thumbs_down = ptrace::breakpoint_callback(
/*let thumbs_down = ptrace::breakpoint_callback(
PTRACE_STOP_SIGNAL,
Some(ptrace_event!(PTRACE_STOP_SIGNAL, sig, handler)),
)
.and_then(|_| ptrace::next_breakpoint().map(|f| f.contains(PTRACE_FLAG_IGNORE)));
if sig != SIGKILL && thumbs_down.unwrap_or(false) {
// If signal can be and was ignored
return;
}
if handler == SIG_DFL {
match sig {
SIGCHLD => {
// println!("SIGCHLD");
}
SIGCONT => {
// println!("Continue");
{
let contexts = context::contexts();
let (pid, pgid, ppid) = {
let context_lock = contexts
.current()
.expect("context::signal_handler not inside of context");
let mut context = context_lock.write();
context.status = Status::Runnable;
(context.id, context.pgid, context.ppid)
};
if let Some(parent_lock) = contexts.get(ppid) {
let waitpid = {
let parent = parent_lock.write();
Arc::clone(&parent.waitpid)
};
waitpid.send(
WaitpidKey {
pid: Some(pid),
pgid: Some(pgid),
},
(pid, 0xFFFF),
);
} else {
println!("{}: {} not found for continue", pid.get(), ppid.get());
}
}
}
// FIXME: SIGSTOP shouldn't be overridable
SIGSTOP | SIGTSTP | SIGTTIN | SIGTTOU => {
// println!("Stop {}", sig);
{
let contexts = context::contexts();
let (pid, pgid, ppid) = {
let context_lock = contexts
.current()
.expect("context::signal_handler not inside of context");
let mut context = context_lock.write();
context.status = Status::Stopped(sig);
(context.id, context.pgid, context.ppid)
};
if let Some(parent_lock) = contexts.get(ppid) {
let waitpid = {
let parent = parent_lock.write();
Arc::clone(&parent.waitpid)
};
waitpid.send(
WaitpidKey {
pid: Some(pid),
pgid: Some(pgid),
},
(pid, (sig << 8) | 0x7F),
);
} else {
println!("{}: {} not found for stop", pid.get(), ppid.get());
}
}
switch();
}
_ => {
// println!("Exit {}", sig);
crate::syscall::exit(sig);
}
}
} else if handler == SIG_IGN {
// println!("Ignore");
} else {
// println!("Call {:X}", handler);
// TODO: Move more of this to userspace
let context_lock = context::current()
.expect("context::signal_handler not inside of context");
let mut context = context_lock.write();
let Some(handler) = context.sig.handler else {
log::debug!("signal ignored since context did not setup sighandler");
return;
};
let Some(regs) = context.regs_mut() else {
log::warn!("cannot send signal to context without userspace registers");
return;
};
let mut intregs = IntRegisters::default();
regs.save(&mut intregs);
const STACK_ADJUST: usize = 256;
// TODO: 16 bytes alignment is sufficient unless XSAVE is enabled.
const STACK_ALIGN: usize = 64;
let new_sp_unless_altstack = (regs.stack_pointer() - STACK_ADJUST) / STACK_ALIGN * STACK_ALIGN;
let new_sp = match handler.altstack {
Some(altstack) if !(altstack.base.get()..altstack.base.get() + altstack.len.get()).contains(&regs.stack_pointer()) => altstack.base.get() + altstack.len.get(),
_ => new_sp_unless_altstack,
} - size_of::<SignalStack>();
let old_procmask = context.sig.procmask;
context.sig.procmask |= action.sa_mask;
if !action.sa_flags.contains(SigActionFlags::SA_NODEFER) {
context.sig.procmask |= 1 << (sig - 1);
}
let Some(regs) = context.regs_mut() else {
return;
};
regs.set_stack_pointer(new_sp);
regs.set_instr_pointer(handler.handler.get());
drop(context);
let Ok(slice) = UserSlice::wo(new_sp, size_of::<SignalStack>()) else {
return;
};
let stack = SignalStack {
intregs,
old_procmask,
sa_mask: action.sa_mask,
sa_flags: action.sa_flags.bits() as u32,
sig_num: sig as u32,
sa_handler: action.sa_handler.map_or(0, |h| h as usize),
};
let Ok(()) = slice.copy_from_slice(&stack) else {
return;
};
}
.and_then(|_| ptrace::next_breakpoint().map(|f| f.contains(PTRACE_FLAG_IGNORE)));*/
}
pub fn excp_handler(signal: usize) {
}
+1 -8
View File
@@ -37,13 +37,6 @@ unsafe fn update_runnable(context: &mut Context, cpu_id: LogicalCpuId) -> Update
return UpdateResult::Skip;
}
let signal = context.sig.deliverable() != 0;
// Unblock when there are pending nonmasked signals.
if matches!(context.status, Status::Blocked) && signal {
context.unblock_no_ipi();
}
// Wake from sleep
if context.status.is_soft_blocked() && context.wake.is_some() {
let wake = context.wake.expect("context::switch: wake not set");
@@ -57,7 +50,7 @@ unsafe fn update_runnable(context: &mut Context, cpu_id: LogicalCpuId) -> Update
// Switch to context if it needs to run
if context.status.is_runnable() {
UpdateResult::CanSwitch { signal }
UpdateResult::CanSwitch { signal: mem::take(&mut context.sig.is_pending) }
} else {
UpdateResult::Skip
}
+1 -1
View File
@@ -271,7 +271,7 @@ pub fn ksignal(signal: usize) {
context.sig.pending |= 1 << (signal - 1);
}
}
crate::context::signal::signal_handler();
crate::context::signal::excp_handler(signal);
}
// TODO: Use this macro on aarch64 too.
+3
View File
@@ -303,6 +303,9 @@ impl RaiiFrame {
.map_err(|_| Enomem)
.map(|inner| Self { inner })
}
pub unsafe fn new_unchecked(inner: Frame) -> Self {
Self { inner }
}
pub fn get(&self) -> Frame {
self.inner
}
+26 -125
View File
@@ -1,7 +1,7 @@
use crate::{
arch::paging::{Page, RmmA, RmmArch, VirtualAddress},
context::{
self, context::{Altstack, HardBlockedReason, SignalHandler}, file::{FileDescriptor, InternalFlags}, memory::{handle_notify_files, AddrSpaceWrapper, Grant, PageSpan}, Context, ContextId, Status
self, context::{HardBlockedReason, SignalState}, file::{FileDescriptor, InternalFlags}, memory::{handle_notify_files, AddrSpace, AddrSpaceWrapper, Grant, PageSpan}, Context, ContextId, Status
},
memory::PAGE_SIZE,
ptrace,
@@ -142,16 +142,7 @@ enum Operation {
// TODO: Remove this once openat is implemented, or allow openat-via-dup via e.g. the top-level
// directory.
OpenViaDup,
SchedAffinity,
Sigactions(Arc<RwLock<Vec<(SigAction, usize)>>>),
Sigprocmask,
// TODO: REMOVE
Sigignmask,
CurrentSigactions,
AwaitingSigactionsChange(Arc<RwLock<Vec<(SigAction, usize)>>>),
MmapMinAddr(Arc<AddrSpaceWrapper>),
}
@@ -173,12 +164,7 @@ impl Operation {
| Self::AddrSpace { .. }
| Self::CurrentAddrSpace
| Self::CurrentFiletable
| Self::Sigactions(_)
| Self::CurrentSigactions
| Self::AwaitingSigactionsChange(_)
| Self::Sighandler
| Self::Sigprocmask
| Self::Sigignmask
)
}
fn needs_root(&self) -> bool {
@@ -300,16 +286,10 @@ impl<const FULL: bool> ProcScheme<FULL> {
Some("name") => (Operation::Name, true),
Some("session_id") => (Operation::SessionId, true),
Some("sighandler") => (Operation::Sighandler, false),
Some("sigprocmask") => (Operation::Sigprocmask, false),
Some("sigignmask") => (Operation::Sigignmask, false),
Some("start") => (Operation::Start, false),
Some("uid") => (Operation::Attr(Attr::Uid), true),
Some("gid") => (Operation::Attr(Attr::Gid), true),
Some("open_via_dup") => (Operation::OpenViaDup, false),
Some("sigactions") => {
(Operation::Sigactions(Arc::clone(&get_context(pid)?.read().actions)), false)
}
Some("current-sigactions") => (Operation::CurrentSigactions, false),
Some("mmap-min-addr") => (Operation::MmapMinAddr(Arc::clone(
get_context(pid)?
.read()
@@ -654,12 +634,6 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
Ok(())
})?
}
Operation::AwaitingSigactionsChange(new) => {
with_context_mut(handle.info.pid, |context: &mut Context| {
context.actions = new;
Ok(())
})?
}
Operation::Trace => {
ptrace::close_session(handle.info.pid);
@@ -926,40 +900,6 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
offset,
),
Operation::Sighandler => {
let handler = context::contexts().get(info.pid).ok_or(Error::new(ESRCH))?.read().sig.handler;
let altstack = handler.and_then(|h| h.altstack);
let data = SetSighandlerData {
entry: handler.map_or(0, |h| h.handler.get()),
altstack_base: altstack.map_or(0, |a| a.base.get()),
altstack_len: altstack.map_or(0, |a| a.len.get()),
};
buf.copy_exactly(&data)?;
Ok(mem::size_of::<SetSighandlerData>())
}
Operation::Sigprocmask => {
let procmask = context::contexts().get(info.pid).ok_or(Error::new(ESRCH))?.read().sig.procmask;
buf.write_u64(procmask)?;
Ok(8)
}
Operation::Sigignmask => {
let mut ignmask = 0_u64;
{
let contexts = context::contexts();
let context = contexts.get(info.pid).ok_or(Error::new(ESRCH))?;
let context = context.read();
let actions = context.actions.read();
for (idx, (action, _)) in actions.iter().enumerate() {
if action.sa_handler == unsafe { core::mem::transmute(SIG_IGN) } {
ignmask |= 1 << idx;
}
}
}
buf.write_u64(ignmask)?;
Ok(8)
}
Operation::Attr(attr) => {
let src_buf = match (
attr,
@@ -1189,42 +1129,35 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
Operation::Sighandler => {
let data = unsafe { buf.read_exact::<SetSighandlerData>()? };
let new_handler = match NonZeroUsize::new(data.entry) {
Some(handler) => Some(SignalHandler {
handler,
altstack: match (NonZeroUsize::new(data.altstack_base), NonZeroUsize::new(data.altstack_len)) {
(Some(base), Some(len)) => Some(Altstack { base, len }),
_ => None,
}
}),
None => None,
if data.user_handler >= crate::USER_END_OFFSET || data.excp_handler >= crate::USER_END_OFFSET {
return Err(Error::new(EPERM));
}
let (control, sigword_off) = if data.word_addr != 0 {
let offset = u16::try_from(data.word_addr % PAGE_SIZE).unwrap();
if offset % 16 != 0 {
return Err(Error::new(EINVAL));
}
let frame = AddrSpace::current()?
.borrow_frame_enforce_rw_allocated(Page::containing_address(VirtualAddress::new(data.word_addr)))?;
(Some(frame), offset)
} else {
(None, 0)
};
context::contexts().get(info.pid).ok_or(Error::new(ESRCH))?.write().sig.handler = new_handler;
context::contexts().get(info.pid).ok_or(Error::new(ESRCH))?.write().sig = SignalState {
user_handler: NonZeroUsize::new(data.user_handler),
excp_handler: NonZeroUsize::new(data.excp_handler),
control,
sigword_off,
is_pending: false,
};
Ok(mem::size_of::<SetSighandlerData>())
}
Operation::Sigprocmask => {
let new_procmask = buf.read_u64()?;
context::contexts().get(info.pid).ok_or(Error::new(ESRCH))?.write().sig.procmask = new_procmask;
Ok(8)
}
// TODO: Remove!
Operation::Sigignmask => {
let new_ignmask = buf.read_u64()?;
let contexts = context::contexts();
let context = contexts.get(info.pid).ok_or(Error::new(ESRCH))?;
let context = context.read();
let mut actions = context.actions.write();
for bit in (0..64).filter(|bit| new_ignmask & (1 << bit) != 0) {
actions[bit] = (SigAction {
sa_flags: SigActionFlags::empty(),
sa_mask: 0,
sa_handler: unsafe { core::mem::transmute(SIG_IGN) },
}, 0);
}
Ok(8)
}
Operation::Start => match context::contexts().get(info.pid).ok_or(Error::new(ESRCH))?.write().status {
ref mut status @ Status::HardBlocked { reason: HardBlockedReason::NotYetStarted } => {
*status = Status::Runnable;
@@ -1311,28 +1244,6 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
Ok(3 * mem::size_of::<usize>())
}
Operation::CurrentSigactions => {
let sigactions_fd = buf.read_usize()?;
let (hopefully_this_scheme, number) = extract_scheme_number(sigactions_fd)?;
verify_scheme(hopefully_this_scheme)?;
let mut handles = HANDLES.write();
let Operation::Sigactions(ref sigactions) = handles
.get(&number)
.ok_or(Error::new(EBADF))?
.info
.operation
else {
return Err(Error::new(EBADF));
};
handles
.get_mut(&id)
.ok_or(Error::new(EBADF))?
.info
.operation = Operation::AwaitingSigactionsChange(Arc::clone(sigactions));
Ok(mem::size_of::<usize>())
}
Operation::MmapMinAddr(ref addrspace) => {
let val = buf.read_usize()?;
if val % PAGE_SIZE != 0 || val > crate::USER_END_OFFSET {
@@ -1373,10 +1284,8 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
Operation::Attr(Attr::Gid) => "gid",
Operation::Filetable { .. } => "filetable",
Operation::AddrSpace { .. } => "addrspace",
Operation::Sigactions(_) => "sigactions",
Operation::CurrentAddrSpace => "current-addrspace",
Operation::CurrentFiletable => "current-filetable",
Operation::CurrentSigactions => "current-sigactions",
Operation::OpenViaDup => "open-via-dup",
Operation::MmapMinAddr(_) => "mmap-min-addr",
Operation::SchedAffinity => "sched-affinity",
@@ -1523,14 +1432,6 @@ impl<const FULL: bool> KernelScheme for ProcScheme<FULL> {
handle(operation, OperationData::Offset, true)
}
Operation::Sigactions(ref sigactions) => {
let new = match buf {
b"empty" => Context::empty_actions(),
b"copy" => Arc::new(RwLock::new(sigactions.read().clone())),
_ => return Err(Error::new(EINVAL)),
};
handle(Operation::Sigactions(new), OperationData::Other, false)
}
_ => return Err(Error::new(EINVAL)),
})
.map(|(r, fl)| OpenResult::SchemeLocal(r, fl))
@@ -1546,7 +1447,7 @@ fn inherit_context() -> Result<ContextId> {
let current_context_lock = Arc::clone(context::contexts().current().ok_or(Error::new(ESRCH))?);
let new_context_lock = Arc::clone(context::contexts_mut().spawn(true, clone_handler)?);
// (Starts with "all signals blocked".)
// (Signals are initially disabled.)
let current_context = current_context_lock.read();
let mut new_context = new_context_lock.write();
-13
View File
@@ -224,19 +224,6 @@ pub fn syscall(
SYS_SETREUID => setreuid(b as u32, c as u32),
SYS_SETRENS => setrens(SchemeNamespace::from(b), SchemeNamespace::from(c)),
SYS_SETREGID => setregid(b as u32, c as u32),
SYS_SIGACTION => sigaction(
b,
UserSlice::ro(c, core::mem::size_of::<SigAction>())?.none_if_null(),
UserSlice::wo(d, core::mem::size_of::<SigAction>())?.none_if_null(),
e,
)
.map(|()| 0),
SYS_SIGPROCMASK => sigprocmask(
b,
UserSlice::ro(c, 8)?.none_if_null(),
UserSlice::wo(d, 8)?.none_if_null(),
).map(|()| 0),
SYS_SIGRETURN => sigreturn().map(|()| 0),
SYS_UMASK => umask(b),
SYS_VIRTTOPHYS => virttophys(b),
+1 -73
View File
@@ -160,7 +160,7 @@ pub fn kill(pid: ContextId, sig: usize) -> Result<usize> {
return true;
}
context.sig.pending |= 1_u64 << (sig - 1);
todo!();
// Convert stopped processes to blocked if sending SIGCONT
if sig == SIGCONT {
@@ -266,78 +266,6 @@ pub fn setpgid(pid: ContextId, pgid: ContextId) -> Result<usize> {
}
}
pub fn sigaction(
sig: usize,
act_opt: Option<UserSliceRo>,
oldact_opt: Option<UserSliceWo>,
restorer: usize,
) -> Result<()> {
if sig == 0 || sig > 0x7F {
return Err(Error::new(EINVAL));
}
let contexts = context::contexts();
let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
let context = context_lock.read();
let mut actions = context.actions.write();
if let Some(oldact) = oldact_opt {
oldact.copy_exactly(&actions[sig - 1].0)?;
}
if let Some(act) = act_opt {
actions[sig - 1] = (unsafe { act.read_exact::<SigAction>()? }, restorer);
}
Ok(())
}
pub fn sigprocmask(how: usize, mask_ref_opt: Option<UserSliceRo>, oldmask_out_opt: Option<UserSliceWo>) -> Result<()> {
let mask_opt = mask_ref_opt.map(|m| m.read_u64()).transpose()?;
let old_sigmask;
{
let context_lock = context::current()?;
let mut context = context_lock.write();
old_sigmask = context.sig.procmask;
if let Some(arg) = mask_opt {
match how {
SIG_BLOCK => context.sig.procmask |= arg,
SIG_UNBLOCK => context.sig.procmask &= !arg,
SIG_SETMASK => context.sig.procmask = arg,
_ => {
return Err(Error::new(EINVAL));
}
}
}
};
if let Some(oldmask_out) = oldmask_out_opt {
oldmask_out.write_u64(old_sigmask)?;
}
Ok(())
}
pub fn sigreturn() -> Result<()> {
let context = context::current()?;
let mut stack = SignalStack::default();
// Kernel-only contexts can't call sigreturn in the first place, so a panic would be
// acceptable, but handle it anyway.
let stack_ptr = context.read().regs().ok_or(Error::new(EINVAL))?.stack_pointer();
UserSlice::ro(stack_ptr, mem::size_of::<SignalStack>())?.copy_to_slice(&mut stack)?;
let mut context = context.write();
context.regs_mut().ok_or(Error::new(EINVAL))?.load(&stack.intregs);
context.sig.procmask = stack.old_procmask;
Ok(())
}
pub fn umask(mask: usize) -> Result<usize> {
let previous;
{
+1 -1
Submodule syscall updated: ef099bdd2e...16ced74677