1use crate::arch::signal_handling::{
6 RED_ZONE_SIZE, SIG_STACK_SIZE, SignalStackFrame, align_stack_pointer, restore_registers,
7};
8use crate::mm::{MemoryAccessor, MemoryAccessorExt};
9use crate::ptrace::StopState;
10use crate::signals::{KernelSignal, KernelSignalInfo, SignalDetail, SignalInfo, SignalState};
11use crate::task::{
12 ArchExtendedPstateStorage, CurrentTask, ExitStatus, Task, TaskFlags, TaskWriteGuard,
13 ThreadState, Waiter,
14};
15use starnix_logging::{log_info, log_trace, log_warn};
16use starnix_registers::{RegisterState, RegisterStorageEnum};
17use starnix_syscalls::SyscallResult;
18use starnix_types::arch::ArchWidth;
19use starnix_uapi::errors::{EINTR, ERESTART_RESTARTBLOCK, Errno};
20use starnix_uapi::resource_limits::Resource;
21use starnix_uapi::signals::{
22 SIGABRT, SIGALRM, SIGBUS, SIGCHLD, SIGCONT, SIGFPE, SIGHUP, SIGILL, SIGINT, SIGIO, SIGKILL,
23 SIGPIPE, SIGPROF, SIGPWR, SIGQUIT, SIGSEGV, SIGSTKFLT, SIGSTOP, SIGSYS, SIGTERM, SIGTRAP,
24 SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGUSR1, SIGUSR2, SIGVTALRM, SIGWINCH, SIGXCPU, SIGXFSZ,
25 SigSet, sigaltstack_contains_pointer,
26};
27use starnix_uapi::user_address::{ArchSpecific, UserAddress};
28use starnix_uapi::{
29 SA_NODEFER, SA_ONSTACK, SA_RESETHAND, SA_SIGINFO, SIG_DFL, SIG_IGN, errno, error, sigaction_t,
30};
31
32#[derive(PartialEq)]
35enum SignalPriority {
36 First,
37 Last,
38}
39
40pub fn send_signal_first(task: &Task, task_state: TaskWriteGuard<'_>, signal_info: SignalInfo) {
48 send_signal_prio(
49 task,
50 task_state,
51 signal_info.into(),
52 SignalPriority::First,
53 true,
54 )
55 .expect("send_signal(SignalPriority::First) is not expected to fail")
56}
57
58pub fn send_standard_signal(task: &Task, signal_info: SignalInfo) {
63 debug_assert!(!signal_info.signal.is_real_time());
64 let state = task.write();
65 send_signal_prio(
66 task,
67 state,
68 signal_info.into(),
69 SignalPriority::Last,
70 false,
71 )
72 .expect("send_signal(SignalPriority::Last) is not expected to fail for standard signals.")
73}
74
75pub fn send_signal(task: &Task, signal_info: SignalInfo) -> Result<(), Errno> {
83 let state = task.write();
84 send_signal_prio(
85 task,
86 state,
87 signal_info.into(),
88 SignalPriority::Last,
89 false,
90 )
91}
92
93pub fn send_freeze_signal(task: &Task, waiter: Waiter) -> Result<(), Errno> {
94 let state = task.write();
95 send_signal_prio(
96 task,
97 state,
98 KernelSignalInfo::Freeze(waiter),
99 SignalPriority::First,
100 true,
101 )
102}
103
104fn send_signal_prio(
105 task: &Task,
106 mut task_state: TaskWriteGuard<'_>,
107 kernel_signal_info: KernelSignalInfo,
108 prio: SignalPriority,
109 force_wake: bool,
110) -> Result<(), Errno> {
111 let (signal_info, signal, is_masked, was_masked, is_real_time, sigaction, action) =
112 match kernel_signal_info {
113 KernelSignalInfo::User(ref user_signal_info) => {
114 if user_signal_info.signal == SIGKILL {
115 drop(task_state);
116 task.thread_group().write().force_exit_for_sigkill(user_signal_info.clone());
122 return Ok(());
123 }
124 let signal = user_signal_info.signal;
125 let is_masked = task_state.is_signal_masked(signal);
126 let was_masked = task_state.is_signal_masked_by_saved_mask(signal);
127 let sigaction = task.get_signal_action(signal);
128 let action = action_for_signal(user_signal_info, sigaction);
129 (
130 Some(user_signal_info.clone()),
131 Some(signal),
132 is_masked,
133 was_masked,
134 signal.is_real_time(),
135 Some(sigaction),
136 Some(action),
137 )
138 }
139 KernelSignalInfo::Freeze(_) => (None, None, false, false, false, None, None),
140 };
141
142 if is_real_time && prio != SignalPriority::First {
143 if task_state.pending_signal_count()
144 >= task.thread_group().get_rlimit(Resource::SIGPENDING) as usize
145 {
146 return error!(EAGAIN);
147 }
148 }
149
150 let is_queued = action.is_none()
155 || action != Some(DeliveryAction::Ignore)
156 || is_masked
157 || was_masked
158 || task_state.is_ptraced();
159 if is_queued {
160 match kernel_signal_info {
161 KernelSignalInfo::User(ref signal_info) => {
162 if prio == SignalPriority::First {
163 task_state.enqueue_signal_front(signal_info.clone());
164 } else {
165 task_state.enqueue_signal(signal_info.clone());
166 }
167 task_state.set_flags(TaskFlags::SIGNALS_AVAILABLE, true);
168 }
169 KernelSignalInfo::Freeze(waiter) => {
170 task_state.enqueue_kernel_signal(KernelSignal::Freeze(waiter))
171 }
172 }
173 }
174
175 drop(task_state);
176 if is_queued
177 && !is_masked
178 && action.map_or_else(|| true, |action| action.must_interrupt(sigaction))
179 {
180 task.interrupt();
183 }
184
185 if signal == Some(SIGCONT) || force_wake {
189 task.thread_group().set_stopped(
190 StopState::Waking,
191 signal_info,
192 false,
193 );
194 task.write().set_stopped(
195 StopState::Waking,
196 None,
197 None,
198 None,
199 );
200 }
201
202 Ok(())
203}
204
205#[derive(Debug, PartialEq)]
209pub enum DeliveryAction {
210 Ignore,
211 CallHandler,
212 Terminate,
213 CoreDump,
214 Stop,
215 Continue,
216}
217
218impl DeliveryAction {
219 pub fn must_interrupt(&self, sigaction: Option<sigaction_t>) -> bool {
225 match *self {
226 Self::Continue => false,
227 Self::Ignore => sigaction.map_or(false, |sa| sa.sa_handler == SIG_IGN),
228 _ => true,
229 }
230 }
231}
232
233pub fn action_for_signal(siginfo: &SignalInfo, sigaction: sigaction_t) -> DeliveryAction {
234 let handler = if siginfo.force && sigaction.sa_handler == SIG_IGN {
235 SIG_DFL
236 } else {
237 sigaction.sa_handler
238 };
239 match handler {
240 SIG_DFL => match siginfo.signal {
241 SIGCHLD | SIGURG | SIGWINCH => DeliveryAction::Ignore,
242 sig if sig.is_real_time() => DeliveryAction::Ignore,
243 SIGHUP | SIGINT | SIGKILL | SIGPIPE | SIGALRM | SIGTERM | SIGUSR1 | SIGUSR2
244 | SIGPROF | SIGVTALRM | SIGSTKFLT | SIGIO | SIGPWR => DeliveryAction::Terminate,
245 SIGQUIT | SIGILL | SIGABRT | SIGFPE | SIGSEGV | SIGBUS | SIGSYS | SIGTRAP | SIGXCPU
246 | SIGXFSZ => DeliveryAction::CoreDump,
247 SIGSTOP | SIGTSTP | SIGTTIN | SIGTTOU => DeliveryAction::Stop,
248 SIGCONT => DeliveryAction::Continue,
249 _ => panic!("Unknown signal"),
250 },
251 SIG_IGN => DeliveryAction::Ignore,
252 _ => DeliveryAction::CallHandler,
253 }
254}
255
256pub fn dequeue_signal(current_task: &mut CurrentTask) {
258 let &mut CurrentTask { ref task, ref mut thread_state, .. } = current_task;
259 if !task.should_check_for_pending_signals() {
260 return;
261 }
262
263 let mut task_state = task.write();
264 if task.load_stopped().is_stopping_or_stopped() {
267 return;
268 }
269
270 let kernel_signal = task_state.take_kernel_signal();
272 let siginfo = if kernel_signal.is_some() { None } else { task_state.take_any_signal() };
273 prepare_to_restart_syscall(
274 thread_state,
275 siginfo.as_ref().map(|siginfo| task.thread_group().signal_actions.get(siginfo.signal)),
276 );
277
278 if let Some(ref siginfo) = siginfo {
279 if task_state.ptrace_on_signal_consume() && siginfo.signal != SIGKILL {
280 task_state.set_stopped(
284 StopState::SignalDeliveryStopping,
285 Some(siginfo.clone()),
286 None,
287 None,
288 );
289 return;
290 }
291 }
292
293 task_state.restore_signal_mask();
296
297 if let Some(kernel_signal) = kernel_signal {
298 let KernelSignal::Freeze(waiter) = kernel_signal;
299 drop(task_state);
300
301 waiter.freeze(current_task);
302 } else if let Some(ref siginfo) = siginfo {
303 if let SignalDetail::Timer { timer } = &siginfo.detail {
304 timer.on_signal_delivered();
305 }
306 if let Some(status) = deliver_signal(
307 &task,
308 current_task.thread_state.arch_width(),
309 task_state,
310 siginfo.clone(),
311 &mut current_task.thread_state.registers,
312 ¤t_task.thread_state.extended_pstate,
313 None,
314 ) {
315 current_task.kill_thread_group(status);
316 }
317 };
318}
319
320fn deliver_signal(
321 task: &Task,
322 arch_width: ArchWidth,
323 mut task_state: TaskWriteGuard<'_>,
324 mut siginfo: SignalInfo,
325 registers: &mut RegisterState<RegisterStorageEnum>,
326 extended_pstate: &ArchExtendedPstateStorage,
327 restricted_exception: Option<zx::ExceptionReport>,
328) -> Option<ExitStatus> {
329 loop {
330 let signal = siginfo.signal;
331 let mut sigaction = task.thread_group().signal_actions.get(signal);
332 let masked_signals = task_state.signal_mask();
333 if siginfo.force && (masked_signals.has_signal(signal) || sigaction.sa_handler == SIG_IGN) {
343 task_state.set_signal_mask(masked_signals & !SigSet::from(signal));
344 sigaction = sigaction_t::default();
345 task.thread_group().signal_actions.set(signal, sigaction);
346 }
347
348 let action = action_for_signal(&siginfo, sigaction);
349 log_trace!("handling signal {:?} with action {:?}", siginfo, action);
350 match action {
351 DeliveryAction::Ignore => {}
352 DeliveryAction::CallHandler => {
353 if sigaction.sa_flags & (SA_RESETHAND as u64) != 0 {
356 let new_sigaction = sigaction_t {
357 sa_handler: SIG_DFL,
358 sa_flags: sigaction.sa_flags & !(SA_RESETHAND as u64),
359 ..sigaction
360 };
361 task.thread_group().signal_actions.set(signal, new_sigaction);
362 }
363 if let Err(err) = dispatch_signal_handler(
364 task,
365 arch_width,
366 registers,
367 extended_pstate,
368 task_state.signals_mut(),
369 siginfo,
370 sigaction,
371 ) {
372 log_warn!("failed to deliver signal {:?}: {:?}", signal, err);
373 if signal == SIGSEGV {
374 task.thread_group().signal_actions.set(SIGSEGV, sigaction_t::default());
375 }
376 siginfo = SignalInfo::forced(SIGSEGV);
377 continue;
378 }
379 }
380 DeliveryAction::Terminate => {
381 drop(task_state);
384 return Some(ExitStatus::Kill(siginfo));
385 }
386 DeliveryAction::CoreDump => {
387 task_state.set_flags(TaskFlags::DUMP_ON_EXIT, true);
388 drop(task_state);
389 if let Some(exception) = restricted_exception {
390 log_info!(
391 registers:?=registers,
392 exception:?=exception;
393 "Restricted mode exception caused core dump",
395 );
397 if let SignalDetail::SigFault { addr } = siginfo.detail {
398 if let Ok(mm) = task.mm() {
399 mm.log_memory_map(task, UserAddress::from(addr));
400 }
401 }
402 }
403 return Some(ExitStatus::CoreDump(siginfo));
404 }
405 DeliveryAction::Stop => {
406 drop(task_state);
407 task.thread_group().set_stopped(StopState::GroupStopping, Some(siginfo), false);
408 }
409 DeliveryAction::Continue => {
410 }
412 };
413 break;
414 }
415 None
416}
417
418pub fn force_signal(
424 current_task: &mut CurrentTask,
425 mut siginfo: SignalInfo,
426 restricted_exception: Option<zx::ExceptionReport>,
427) {
428 siginfo.force = true;
429 let mut task_state = current_task.task.write();
430 if task_state.ptrace_on_signal_consume() && siginfo.signal != SIGKILL {
431 task_state.set_stopped(
432 StopState::SignalDeliveryStopping,
433 Some(siginfo),
434 Some(current_task),
435 None,
436 );
437 return;
438 }
439
440 if let Some(status) = deliver_signal(
441 ¤t_task.task,
442 current_task.thread_state.arch_width(),
443 task_state,
444 siginfo,
445 &mut current_task.thread_state.registers,
446 ¤t_task.thread_state.extended_pstate,
447 restricted_exception,
448 ) {
449 current_task.kill_thread_group(status);
450 }
451}
452
453fn dispatch_signal_handler(
457 task: &Task,
458 arch_width: ArchWidth,
459 registers: &mut RegisterState<RegisterStorageEnum>,
460 extended_pstate: &ArchExtendedPstateStorage,
461 signal_state: &mut SignalState,
462 siginfo: SignalInfo,
463 action: sigaction_t,
464) -> Result<(), Errno> {
465 let stack_pointer_register = registers.stack_pointer_register();
466 let on_sigaltstack = signal_state.alt_stack.is_some_and(|sigaltstack| {
467 sigaltstack_contains_pointer(&sigaltstack, stack_pointer_register)
468 });
469 let main_stack = stack_pointer_register.checked_sub(RED_ZONE_SIZE);
470 let stack_bottom = if (action.sa_flags & SA_ONSTACK as u64) != 0 {
471 match signal_state.alt_stack {
472 Some(sigaltstack) => {
473 if on_sigaltstack {
475 main_stack
476 } else {
477 sigaltstack
481 .ss_sp
482 .addr
483 .checked_add(sigaltstack.ss_size)
484 .map(|sp| sp as u64)
485 .or(main_stack)
486 }
487 }
488 None => main_stack,
489 }
490 } else {
491 main_stack
492 }
493 .ok_or_else(|| errno!(EINVAL))?;
494
495 let stack_pointer =
496 align_stack_pointer(stack_bottom.checked_sub(SIG_STACK_SIZE as u64).ok_or_else(|| {
497 errno!(
498 EINVAL,
499 format!(
500 "Subtracting SIG_STACK_SIZE ({}) from stack bottom ({}) overflowed",
501 SIG_STACK_SIZE, stack_bottom
502 )
503 )
504 })?);
505
506 if let Some(alt_stack) = signal_state.alt_stack {
509 if sigaltstack_contains_pointer(&alt_stack, stack_pointer)
510 != (on_sigaltstack || sigaltstack_contains_pointer(&alt_stack, stack_bottom))
511 {
512 return error!(EINVAL);
513 }
514 }
515
516 let signal_stack_frame = SignalStackFrame::new(
517 task,
518 arch_width,
519 registers,
520 extended_pstate,
521 signal_state,
522 &siginfo,
523 action,
524 UserAddress::from(stack_pointer),
525 )?;
526
527 task.write_memory(UserAddress::from(stack_pointer), signal_stack_frame.as_bytes())?;
529
530 let mut mask: SigSet = action.sa_mask.into();
531 if action.sa_flags & (SA_NODEFER as u64) == 0 {
532 mask = mask | siginfo.signal.into();
533 }
534
535 signal_state.set_mask(mask | signal_state.mask());
537
538 registers.set_stack_pointer_register(stack_pointer);
539 registers.set_arg0_register(siginfo.signal.number() as u64);
540 if (action.sa_flags & SA_SIGINFO as u64) != 0 {
541 registers.set_arg1_register(
542 stack_pointer + memoffset::offset_of!(SignalStackFrame, siginfo_bytes) as u64,
543 );
544 registers.set_arg2_register(
545 stack_pointer + memoffset::offset_of!(SignalStackFrame, context) as u64,
546 );
547 }
548 registers.set_instruction_pointer_register(action.sa_handler.addr);
549 registers.reset_flags(); Ok(())
552}
553
554pub fn restore_from_signal_handler(current_task: &mut CurrentTask) -> Result<(), Errno> {
555 let signal_frame_address = UserAddress::from(align_stack_pointer(
557 current_task.thread_state.registers.stack_pointer_register(),
558 ));
559 let signal_stack_bytes =
560 current_task.read_memory_to_array::<SIG_STACK_SIZE>(signal_frame_address)?;
561
562 let signal_stack_frame = SignalStackFrame::from_bytes(signal_stack_bytes);
564 restore_registers(current_task, &signal_stack_frame, signal_frame_address)?;
565
566 current_task
568 .write()
569 .set_signal_mask(signal_stack_frame.get_signal_mask(current_task.is_arch32()));
570
571 Ok(())
572}
573
574pub fn prepare_to_restart_syscall(
578 thread_state: &mut ThreadState<RegisterStorageEnum>,
579 sigaction: Option<sigaction_t>,
580) {
581 let Some(err) = thread_state.restart_code.take() else {
583 return;
586 };
587
588 if err.should_restart(sigaction) {
589 if err == ERESTART_RESTARTBLOCK {
593 thread_state.registers.prepare_for_custom_restart();
594 } else {
595 thread_state.registers.restore_original_return_register();
596 }
597
598 thread_state.registers.rewind_syscall_instruction();
600 } else {
601 thread_state.registers.set_return_register(EINTR.return_value());
602 }
603}
604
605pub fn sys_restart_syscall(current_task: &mut CurrentTask) -> Result<SyscallResult, Errno> {
606 match current_task.thread_state.syscall_restart_func.take() {
607 Some(f) => f(current_task),
608 None => {
609 log_warn!("restart_syscall called, but nothing to restart");
613 error!(EINTR)
614 }
615 }
616}
617
618#[cfg(test)]
620pub(crate) mod testing {
621 use super::*;
622 use crate::testing::AutoReleasableTask;
623 use std::ops::DerefMut as _;
624
625 pub(crate) fn dequeue_signal_for_test(current_task: &mut AutoReleasableTask) {
626 dequeue_signal(current_task.deref_mut());
627 }
628}