diff --git a/kernel/src/signal/mod.rs b/kernel/src/signal/mod.rs index 75ea2667..d750e691 100644 --- a/kernel/src/signal/mod.rs +++ b/kernel/src/signal/mod.rs @@ -134,7 +134,7 @@ pub fn handle_signal(thread: &Arc, tf: &mut UserContext) -> bool { .iter() .enumerate() .find_map(|(idx, &(info, tid))| { - if tid == -1 + if (tid == -1 || tid as usize == thread.tid) && !thread .inner .lock() @@ -184,15 +184,27 @@ pub fn handle_signal(thread: &Arc, tf: &mut UserContext) -> bool { _ => { info!("goto handler at {:#x}", action.handler); - thread.inner.lock().signal_alternate_stack.flags |= - SignalStackFlags::ONSTACK.bits(); + // save original signal alternate stack let stack = thread.inner.lock().signal_alternate_stack; + let sig_sp = { + // use signal alternate stack when SA_ONSTACK is set + // fallback to default stack when unavailable + // man sigaction(2) if action_flags.contains(SignalActionFlags::ONSTACK) { let stack_flags = SignalStackFlags::from_bits_truncate(stack.flags); if stack_flags.contains(SignalStackFlags::DISABLE) { tf.get_sp() } else { + let mut inner = thread.inner.lock(); + inner.signal_alternate_stack.flags |= SignalStackFlags::ONSTACK.bits(); + + // handle auto disarm + if stack_flags.contains(SignalStackFlags::AUTODISARM) { + inner.signal_alternate_stack.flags |= + SignalStackFlags::DISABLE.bits(); + } + // top of stack stack.sp + stack.size } @@ -268,6 +280,7 @@ pub struct SignalStack { impl Default for SignalStack { fn default() -> Self { + // default to disabled SignalStack { sp: 0, flags: SignalStackFlags::DISABLE.bits, diff --git a/kernel/src/syscall/proc.rs b/kernel/src/syscall/proc.rs index e79de3a6..b5474a82 100644 --- a/kernel/src/syscall/proc.rs +++ b/kernel/src/syscall/proc.rs @@ -258,6 +258,11 @@ impl Syscall<'_> { // Modify exec path proc.exec_path = path.clone(); + + // reset disposition (man signal(7)) + for d in proc.dispositions.iter_mut() { + *d = SignalAction::default(); + } drop(proc); // Modify the TrapFrame diff --git a/kernel/src/syscall/signal.rs b/kernel/src/syscall/signal.rs index bf40eca4..b6f162ca 100644 --- a/kernel/src/syscall/signal.rs +++ b/kernel/src/syscall/signal.rs @@ -47,42 +47,18 @@ impl Syscall<'_> { pub fn sys_rt_sigreturn(&mut self) -> SysResult { info!("rt_sigreturn"); - // FIXME: adapt arch - //let frame = unsafe { &*((self.tf.get_sp() - 8) as *mut SignalFrame) }; - let frame: SignalFrame = todo!(); - // frame.info.signo - /* - { - let mut process = self.process(); - process.sigaltstack.flags ^= - process.sigaltstack.flags & SignalStackFlags::ONSTACK.bits(); - } - */ + // 8: return addr + let ptr: UserInPtr = UserInPtr::from(self.context.get_sp() - 8); + let frame: SignalFrame = ptr.read()?; - // *self.tf = TrapFrame::from_mcontext(&frame.ucontext.mcontext); - todo!(); - //*self.tf = frame.tf.clone(); - /* - let mc = &frame.ucontext.mcontext; - self.tf.general.r15 = mc.r15; - self.tf.general.r14 = mc.r14; - self.tf.general.r13 = mc.r13; - self.tf.general.r12 = mc.r12; - self.tf.general.rbp = mc.rbp; - self.tf.general.rbx = mc.rbx; - self.tf.general.r11 = mc.r11; - self.tf.general.r10 = mc.r10; - self.tf.general.r9 = mc.r9; - self.tf.general.r8 = mc.r8; - self.tf.general.rsi = mc.rsi; - self.tf.general.rdi = mc.rdi; - self.tf.general.rdx = mc.rdx; - self.tf.general.rcx = mc.rcx; - self.tf.general.rax = mc.rax; - self.tf.general.rip = mc.rip; - self.tf.general.rsp = mc.rsp; - */ + // restore signal alternate stack + let mut inner = self.thread.inner.lock(); + inner.signal_alternate_stack = frame.ucontext.stack; + drop(inner); + *self.context = frame.ucontext.context; + + // small hack: don't change ret when restoring let ret = self.context.get_syscall_ret() as isize; if ret >= 0 { Ok(ret as usize) @@ -224,12 +200,17 @@ impl Syscall<'_> { let ss = ss.read()?; info!("new stack: {:?}", ss); + // check stack size when not disable const MINSIGSTKSZ: usize = 2048; - if ss.flags & 2 != 0 && ss.size < MINSIGSTKSZ { + if ss.flags & SignalStackFlags::DISABLE.bits() != 0 && ss.size < MINSIGSTKSZ { return Err(ENOMEM); } - // only allow SS_AUTODISARM or SS_DISABLE - if ss.flags != ss.flags & 0x8000002 { + + // only allow SS_AUTODISARM and SS_DISABLE + if ss.flags + != ss.flags + & (SignalStackFlags::AUTODISARM.bits() | SignalStackFlags::DISABLE.bits()) + { return Err(EINVAL); } @@ -237,6 +218,8 @@ impl Syscall<'_> { let old_ss = &mut inner.signal_alternate_stack; let flags = SignalStackFlags::from_bits_truncate(old_ss.flags); if flags.contains(SignalStackFlags::ONSTACK) { + // cannot change signal alternate stack when we are on it + // see man sigaltstack(2) return Err(EPERM); } *old_ss = ss;