From 295cc820e60ff1a8afbaf49f32b9cd7088ceff70 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Tue, 18 Jun 2024 16:58:28 +0200 Subject: [PATCH] WIP: userspace signal handling --- src/arch/x86_64/consts.rs | 2 + src/context/context.rs | 58 ++++-------- src/context/memory.rs | 33 ++++++- src/context/mod.rs | 1 - src/context/signal.rs | 191 ++------------------------------------ src/context/switch.rs | 9 +- src/main.rs | 2 +- src/memory/mod.rs | 3 + src/scheme/proc.rs | 151 ++++++------------------------ src/syscall/mod.rs | 13 --- src/syscall/process.rs | 74 +-------------- syscall | 2 +- 12 files changed, 91 insertions(+), 448 deletions(-) diff --git a/src/arch/x86_64/consts.rs b/src/arch/x86_64/consts.rs index 17ee32fc86..fda5ed1bda 100644 --- a/src/arch/x86_64/consts.rs +++ b/src/arch/x86_64/consts.rs @@ -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; diff --git a/src/context/context.rs b/src/context/context.rs index d167f68094..5bb4464eea 100644 --- a/src/context/context.rs +++ b/src/context/context.rs @@ -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>>>, - /// Signal actions - pub actions: Arc>>, /// 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, } -#[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, + /// Offset to jump to when a program fault occurs. + pub excp_handler: Option, + /// Signal control page, required for signals to work. + pub control: Option, + /// 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, -} -#[derive(Clone, Copy, Debug)] -pub struct SignalHandler { - pub handler: NonZeroUsize, - pub altstack: Option, -} -#[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>> { - 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 { diff --git a/src/context/memory.rs b/src/context/memory.rs index 4e51e92fa6..7dc985b433 100644 --- a/src/context/memory.rs +++ b/src/context/memory.rs @@ -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, page: Page) -> Result { + 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> { diff --git a/src/context/mod.rs b/src/context/mod.rs index ceb5cf16a9..3dcfc5b8e0 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -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) }); diff --git a/src/context/signal.rs b/src/context/signal.rs index 2eb5d89f5a..8625b672a5 100644 --- a/src/context/signal.rs +++ b/src/context/signal.rs @@ -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(®s.stack_pointer()) => altstack.base.get() + altstack.len.get(), - _ => new_sp_unless_altstack, - } - size_of::(); - - 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::()) 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) { } diff --git a/src/context/switch.rs b/src/context/switch.rs index 44a39c7865..f94c92b8d1 100644 --- a/src/context/switch.rs +++ b/src/context/switch.rs @@ -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 } diff --git a/src/main.rs b/src/main.rs index 2b90b325b0..08c77a0862 100644 --- a/src/main.rs +++ b/src/main.rs @@ -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. diff --git a/src/memory/mod.rs b/src/memory/mod.rs index 7723ec78c6..b791e50f24 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -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 } diff --git a/src/scheme/proc.rs b/src/scheme/proc.rs index 7fe8d38d03..27be624e81 100644 --- a/src/scheme/proc.rs +++ b/src/scheme/proc.rs @@ -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>>), - Sigprocmask, - - // TODO: REMOVE - Sigignmask, - - CurrentSigactions, - AwaitingSigactionsChange(Arc>>), MmapMinAddr(Arc), } @@ -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 ProcScheme { 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 KernelScheme for ProcScheme { 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 KernelScheme for ProcScheme { 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::()) - } - 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 KernelScheme for ProcScheme { Operation::Sighandler => { let data = unsafe { buf.read_exact::()? }; - 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::()) } - 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 KernelScheme for ProcScheme { Ok(3 * mem::size_of::()) } - 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::()) - } Operation::MmapMinAddr(ref addrspace) => { let val = buf.read_usize()?; if val % PAGE_SIZE != 0 || val > crate::USER_END_OFFSET { @@ -1373,10 +1284,8 @@ impl KernelScheme for ProcScheme { 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 KernelScheme for ProcScheme { 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 { 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(); diff --git a/src/syscall/mod.rs b/src/syscall/mod.rs index 4455e47747..b72308aa03 100644 --- a/src/syscall/mod.rs +++ b/src/syscall/mod.rs @@ -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::())?.none_if_null(), - UserSlice::wo(d, core::mem::size_of::())?.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), diff --git a/src/syscall/process.rs b/src/syscall/process.rs index 9217f4d321..a1069afa28 100644 --- a/src/syscall/process.rs +++ b/src/syscall/process.rs @@ -160,7 +160,7 @@ pub fn kill(pid: ContextId, sig: usize) -> Result { 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 { } } -pub fn sigaction( - sig: usize, - act_opt: Option, - oldact_opt: Option, - 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::()? }, restorer); - } - - Ok(()) -} - -pub fn sigprocmask(how: usize, mask_ref_opt: Option, oldmask_out_opt: Option) -> 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::())?.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 { let previous; { diff --git a/syscall b/syscall index ef099bdd2e..16ced74677 160000 --- a/syscall +++ b/syscall @@ -1 +1 @@ -Subproject commit ef099bdd2e8578133c33aaf6055db29c383029e2 +Subproject commit 16ced74677201441a9b21947252974fa83670d3c