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::{CurrentTask, ExitStatus, Task, TaskFlags, TaskWriteGuard, ThreadState, Waiter};
12use extended_pstate::ExtendedPstateState;
13use starnix_logging::{log_info, log_trace, log_warn};
14use starnix_registers::{RegisterState, RegisterStorageEnum};
15use starnix_sync::{LockBefore, Locked, ThreadGroupLimits, Unlocked};
16use starnix_syscalls::SyscallResult;
17use starnix_types::arch::ArchWidth;
18use starnix_uapi::errors::{EINTR, ERESTART_RESTARTBLOCK, Errno};
19use starnix_uapi::resource_limits::Resource;
20use starnix_uapi::signals::{
21 SIGABRT, SIGALRM, SIGBUS, SIGCHLD, SIGCONT, SIGFPE, SIGHUP, SIGILL, SIGINT, SIGIO, SIGKILL,
22 SIGPIPE, SIGPROF, SIGPWR, SIGQUIT, SIGSEGV, SIGSTKFLT, SIGSTOP, SIGSYS, SIGTERM, SIGTRAP,
23 SIGTSTP, SIGTTIN, SIGTTOU, SIGURG, SIGUSR1, SIGUSR2, SIGVTALRM, SIGWINCH, SIGXCPU, SIGXFSZ,
24 SigSet, sigaltstack_contains_pointer,
25};
26use starnix_uapi::user_address::UserAddress;
27use starnix_uapi::{
28 SA_NODEFER, SA_ONSTACK, SA_RESETHAND, SA_SIGINFO, SIG_DFL, SIG_IGN, errno, error, sigaction_t,
29};
30
31#[derive(PartialEq)]
34enum SignalPriority {
35 First,
36 Last,
37}
38
39pub fn send_signal_first<L>(
42 locked: &mut Locked<L>,
43 task: &Task,
44 task_state: TaskWriteGuard<'_>,
45 siginfo: SignalInfo,
46) where
47 L: LockBefore<ThreadGroupLimits>,
48{
49 send_signal_prio(locked, task, task_state, siginfo.into(), SignalPriority::First, true)
50 .expect("send_signal(SignalPriority::First) is not expected to fail")
51}
52
53pub fn send_standard_signal<L>(locked: &mut Locked<L>, task: &Task, siginfo: SignalInfo)
55where
56 L: LockBefore<ThreadGroupLimits>,
57{
58 debug_assert!(!siginfo.signal.is_real_time());
59 let state = task.write();
60 send_signal_prio(locked, task, state, siginfo.into(), SignalPriority::Last, false)
61 .expect("send_signal(SignalPriority::Last) is not expected to fail for standard signals.")
62}
63
64pub fn send_signal<L>(locked: &mut Locked<L>, task: &Task, siginfo: SignalInfo) -> Result<(), Errno>
65where
66 L: LockBefore<ThreadGroupLimits>,
67{
68 let state = task.write();
69 send_signal_prio(locked, task, state, siginfo.into(), SignalPriority::Last, false)
70}
71
72pub fn send_freeze_signal<L>(
73 locked: &mut Locked<L>,
74 task: &Task,
75 waiter: Waiter,
76) -> Result<(), Errno>
77where
78 L: LockBefore<ThreadGroupLimits>,
79{
80 let state = task.write();
81 send_signal_prio(
82 locked,
83 task,
84 state,
85 KernelSignalInfo::Freeze(waiter),
86 SignalPriority::First,
87 true,
88 )
89}
90
91fn send_signal_prio<L>(
92 locked: &mut Locked<L>,
93 task: &Task,
94 mut task_state: TaskWriteGuard<'_>,
95 kernel_siginfo: KernelSignalInfo,
96 prio: SignalPriority,
97 force_wake: bool,
98) -> Result<(), Errno>
99where
100 L: LockBefore<ThreadGroupLimits>,
101{
102 let (siginfo, signal, is_masked, was_masked, is_real_time, sigaction, action) =
103 match kernel_siginfo {
104 KernelSignalInfo::User(ref user_siginfo) => {
105 let signal = user_siginfo.signal;
106 let is_masked = task_state.is_signal_masked(signal);
107 let was_masked = task_state.is_signal_masked_by_saved_mask(signal);
108 let sigaction = task.get_signal_action(signal);
109 let action = action_for_signal(&user_siginfo, sigaction);
110 (
111 Some(user_siginfo.clone()),
112 Some(signal),
113 is_masked,
114 was_masked,
115 signal.is_real_time(),
116 Some(sigaction),
117 Some(action),
118 )
119 }
120 KernelSignalInfo::Freeze(_) => (None, None, false, false, false, None, None),
121 };
122
123 if is_real_time && prio != SignalPriority::First {
124 if task_state.pending_signal_count()
125 >= task.thread_group().get_rlimit(locked, Resource::SIGPENDING) as usize
126 {
127 return error!(EAGAIN);
128 }
129 }
130
131 let is_queued = action.is_none()
136 || action != Some(DeliveryAction::Ignore)
137 || is_masked
138 || was_masked
139 || task_state.is_ptraced();
140 if is_queued {
141 match kernel_siginfo {
142 KernelSignalInfo::User(ref siginfo) => {
143 if prio == SignalPriority::First {
144 task_state.enqueue_signal_front(siginfo.clone());
145 } else {
146 task_state.enqueue_signal(siginfo.clone());
147 }
148 task_state.set_flags(TaskFlags::SIGNALS_AVAILABLE, true);
149 }
150 KernelSignalInfo::Freeze(waiter) => {
151 task_state.enqueue_kernel_signal(KernelSignal::Freeze(waiter))
152 }
153 }
154 }
155
156 if action == Some(DeliveryAction::CoreDump) && !task_state.is_ptraced() {
157 log_info!(
160 "Sending a core dump signal {signal:?} to task {}. Take a backtrace of the sender for debugging",
161 task.tid
162 );
163 debug::backtrace_request_current_thread();
164 }
165
166 drop(task_state);
167 if is_queued
168 && !is_masked
169 && action.map_or_else(|| true, |action| action.must_interrupt(sigaction))
170 {
171 task.interrupt();
174 }
175
176 if signal == Some(SIGKILL) {
179 task.write().thaw();
180 task.thread_group().set_stopped(StopState::ForceWaking, siginfo, false);
181 task.write().set_stopped(StopState::ForceWaking, None, None, None);
182 } else if signal == Some(SIGCONT) || force_wake {
183 task.thread_group().set_stopped(StopState::Waking, siginfo, false);
184 task.write().set_stopped(StopState::Waking, None, None, None);
185 }
186
187 Ok(())
188}
189
190#[derive(Debug, PartialEq)]
194pub enum DeliveryAction {
195 Ignore,
196 CallHandler,
197 Terminate,
198 CoreDump,
199 Stop,
200 Continue,
201}
202
203impl DeliveryAction {
204 pub fn must_interrupt(&self, sigaction: Option<sigaction_t>) -> bool {
209 match *self {
210 Self::Continue => false,
211 Self::Ignore => sigaction.map_or(false, |sa| sa.sa_handler == SIG_IGN),
212 _ => true,
213 }
214 }
215}
216
217pub fn action_for_signal(siginfo: &SignalInfo, sigaction: sigaction_t) -> DeliveryAction {
218 let handler = if siginfo.force && sigaction.sa_handler == SIG_IGN {
219 SIG_DFL
220 } else {
221 sigaction.sa_handler
222 };
223 match handler {
224 SIG_DFL => match siginfo.signal {
225 SIGCHLD | SIGURG | SIGWINCH => DeliveryAction::Ignore,
226 sig if sig.is_real_time() => DeliveryAction::Ignore,
227 SIGHUP | SIGINT | SIGKILL | SIGPIPE | SIGALRM | SIGTERM | SIGUSR1 | SIGUSR2
228 | SIGPROF | SIGVTALRM | SIGSTKFLT | SIGIO | SIGPWR => DeliveryAction::Terminate,
229 SIGQUIT | SIGILL | SIGABRT | SIGFPE | SIGSEGV | SIGBUS | SIGSYS | SIGTRAP | SIGXCPU
230 | SIGXFSZ => DeliveryAction::CoreDump,
231 SIGSTOP | SIGTSTP | SIGTTIN | SIGTTOU => DeliveryAction::Stop,
232 SIGCONT => DeliveryAction::Continue,
233 _ => panic!("Unknown signal"),
234 },
235 SIG_IGN => DeliveryAction::Ignore,
236 _ => DeliveryAction::CallHandler,
237 }
238}
239
240pub fn dequeue_signal(locked: &mut Locked<Unlocked>, current_task: &mut CurrentTask) {
242 let &mut CurrentTask { ref task, ref mut thread_state, .. } = current_task;
243 if !task.should_check_for_pending_signals() {
244 return;
245 }
246
247 let mut task_state = task.write();
248 if task.load_stopped().is_stopping_or_stopped() {
251 return;
252 }
253
254 let kernel_signal = task_state.take_kernel_signal();
256 let siginfo = if kernel_signal.is_some() { None } else { task_state.take_any_signal() };
257 prepare_to_restart_syscall(
258 thread_state,
259 siginfo.as_ref().map(|siginfo| task.thread_group().signal_actions.get(siginfo.signal)),
260 );
261
262 if let Some(ref siginfo) = siginfo {
263 if task_state.ptrace_on_signal_consume() && siginfo.signal != SIGKILL {
264 task_state.set_stopped(
268 StopState::SignalDeliveryStopping,
269 Some(siginfo.clone()),
270 None,
271 None,
272 );
273 return;
274 }
275 }
276
277 task_state.restore_signal_mask();
280 {
281 let (clear, set) = if task_state.pending_signal_count() == 0 {
282 (TaskFlags::SIGNALS_AVAILABLE, TaskFlags::empty())
283 } else {
284 (TaskFlags::empty(), TaskFlags::SIGNALS_AVAILABLE)
285 };
286 task_state.update_flags(clear | TaskFlags::TEMPORARY_SIGNAL_MASK, set);
287 };
288
289 if let Some(kernel_signal) = kernel_signal {
290 let KernelSignal::Freeze(waiter) = kernel_signal;
291 drop(task_state);
292
293 waiter.freeze(locked, current_task);
294 } else if let Some(ref siginfo) = siginfo {
295 if let SignalDetail::Timer { timer } = &siginfo.detail {
296 timer.on_signal_delivered();
297 }
298 if let Some(status) = deliver_signal(
299 &task,
300 current_task.thread_state.arch_width,
301 task_state,
302 siginfo.clone(),
303 &mut current_task.thread_state.registers,
304 ¤t_task.thread_state.extended_pstate,
305 None,
306 ) {
307 current_task.thread_group_exit(locked, status);
308 }
309 };
310}
311
312pub fn deliver_signal(
313 task: &Task,
314 arch_width: ArchWidth,
315 mut task_state: TaskWriteGuard<'_>,
316 mut siginfo: SignalInfo,
317 registers: &mut RegisterState<RegisterStorageEnum>,
318 extended_pstate: &ExtendedPstateState,
319 restricted_exception: Option<zx::ExceptionReport>,
320) -> Option<ExitStatus> {
321 loop {
322 let sigaction = task.thread_group().signal_actions.get(siginfo.signal);
323 let action = action_for_signal(&siginfo, sigaction);
324 log_trace!("handling signal {:?} with action {:?}", siginfo, action);
325 match action {
326 DeliveryAction::Ignore => {}
327 DeliveryAction::CallHandler => {
328 let sigaction = task.thread_group().signal_actions.get(siginfo.signal);
329 let signal = siginfo.signal;
330 match dispatch_signal_handler(
331 task,
332 arch_width,
333 registers,
334 extended_pstate,
335 task_state.signals_mut(),
336 siginfo,
337 sigaction,
338 ) {
339 Ok(_) => {
340 if sigaction.sa_flags & (SA_RESETHAND as u64) != 0 {
342 let new_sigaction = sigaction_t {
343 sa_handler: SIG_DFL,
344 sa_flags: sigaction.sa_flags & !(SA_RESETHAND as u64),
345 ..sigaction
346 };
347 task.thread_group().signal_actions.set(signal, new_sigaction);
348 }
349 }
350 Err(err) => {
351 log_warn!("failed to deliver signal {:?}: {:?}", signal, err);
352
353 siginfo = SignalInfo::default(SIGSEGV);
354 let sigaction = task.thread_group().signal_actions.get(siginfo.signal);
360 let action = action_for_signal(&siginfo, sigaction);
361 let masked_signals = task_state.signal_mask();
362 if signal == SIGSEGV
363 || masked_signals.has_signal(SIGSEGV)
364 || action == DeliveryAction::Ignore
365 {
366 task_state.set_signal_mask(masked_signals & !SigSet::from(SIGSEGV));
367 task.thread_group().signal_actions.set(SIGSEGV, sigaction_t::default());
368 }
369
370 continue;
377 }
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",
394 );
395 }
396 return Some(ExitStatus::CoreDump(siginfo));
397 }
398 DeliveryAction::Stop => {
399 drop(task_state);
400 task.thread_group().set_stopped(StopState::GroupStopping, Some(siginfo), false);
401 }
402 DeliveryAction::Continue => {
403 }
405 };
406 break;
407 }
408 None
409}
410
411fn dispatch_signal_handler(
415 task: &Task,
416 arch_width: ArchWidth,
417 registers: &mut RegisterState<RegisterStorageEnum>,
418 extended_pstate: &ExtendedPstateState,
419 signal_state: &mut SignalState,
420 siginfo: SignalInfo,
421 action: sigaction_t,
422) -> Result<(), Errno> {
423 let main_stack = registers.stack_pointer_register().checked_sub(RED_ZONE_SIZE);
424 let stack_bottom = if (action.sa_flags & SA_ONSTACK as u64) != 0 {
425 match signal_state.alt_stack {
426 Some(sigaltstack) => {
427 match main_stack {
428 Some(sp) if sigaltstack_contains_pointer(&sigaltstack, sp) => main_stack,
430 _ => {
431 sigaltstack
435 .ss_sp
436 .addr
437 .checked_add(sigaltstack.ss_size)
438 .map(|sp| sp as u64)
439 .or(main_stack)
440 }
441 }
442 }
443 None => main_stack,
444 }
445 } else {
446 main_stack
447 }
448 .ok_or_else(|| errno!(EINVAL))?;
449
450 let stack_pointer =
451 align_stack_pointer(stack_bottom.checked_sub(SIG_STACK_SIZE as u64).ok_or_else(|| {
452 errno!(
453 EINVAL,
454 format!(
455 "Subtracting SIG_STACK_SIZE ({}) from stack bottom ({}) overflowed",
456 SIG_STACK_SIZE, stack_bottom
457 )
458 )
459 })?);
460
461 if let Some(alt_stack) = signal_state.alt_stack {
464 if sigaltstack_contains_pointer(&alt_stack, stack_pointer)
465 != sigaltstack_contains_pointer(&alt_stack, stack_bottom)
466 {
467 return error!(EINVAL);
468 }
469 }
470
471 let signal_stack_frame = SignalStackFrame::new(
472 task,
473 arch_width,
474 registers,
475 extended_pstate,
476 signal_state,
477 &siginfo,
478 action,
479 UserAddress::from(stack_pointer),
480 )?;
481
482 task.write_memory(UserAddress::from(stack_pointer), signal_stack_frame.as_bytes())?;
484
485 let mut mask: SigSet = action.sa_mask.into();
486 if action.sa_flags & (SA_NODEFER as u64) == 0 {
487 mask = mask | siginfo.signal.into();
488 }
489
490 signal_state.set_mask(mask | signal_state.mask());
492
493 registers.set_stack_pointer_register(stack_pointer);
494 registers.set_arg0_register(siginfo.signal.number() as u64);
495 if (action.sa_flags & SA_SIGINFO as u64) != 0 {
496 registers.set_arg1_register(
497 stack_pointer + memoffset::offset_of!(SignalStackFrame, siginfo_bytes) as u64,
498 );
499 registers.set_arg2_register(
500 stack_pointer + memoffset::offset_of!(SignalStackFrame, context) as u64,
501 );
502 }
503 registers.set_instruction_pointer_register(action.sa_handler.addr);
504 registers.reset_flags(); Ok(())
507}
508
509pub fn restore_from_signal_handler(current_task: &mut CurrentTask) -> Result<(), Errno> {
510 let signal_frame_address = UserAddress::from(align_stack_pointer(
512 current_task.thread_state.registers.stack_pointer_register(),
513 ));
514 let signal_stack_bytes =
515 current_task.read_memory_to_array::<SIG_STACK_SIZE>(signal_frame_address)?;
516
517 let signal_stack_frame = SignalStackFrame::from_bytes(signal_stack_bytes);
519 restore_registers(current_task, &signal_stack_frame, signal_frame_address)?;
520
521 current_task.write().set_signal_mask(signal_stack_frame.get_signal_mask());
523
524 Ok(())
525}
526
527pub fn prepare_to_restart_syscall(
531 thread_state: &mut ThreadState<RegisterStorageEnum>,
532 sigaction: Option<sigaction_t>,
533) {
534 let Some(err) = thread_state.restart_code.take() else {
536 return;
539 };
540
541 if err.should_restart(sigaction) {
542 if err == ERESTART_RESTARTBLOCK {
546 thread_state.registers.prepare_for_custom_restart();
547 } else {
548 thread_state.registers.restore_original_return_register();
549 }
550
551 thread_state.registers.rewind_syscall_instruction();
553 } else {
554 thread_state.registers.set_return_register(EINTR.return_value());
555 }
556}
557
558pub fn sys_restart_syscall(
559 locked: &mut Locked<Unlocked>,
560 current_task: &mut CurrentTask,
561) -> Result<SyscallResult, Errno> {
562 match current_task.thread_state.syscall_restart_func.take() {
563 Some(f) => f(locked, current_task),
564 None => {
565 log_warn!("restart_syscall called, but nothing to restart");
569 error!(EINTR)
570 }
571 }
572}
573
574#[cfg(test)]
576pub(crate) mod testing {
577 use super::*;
578 use crate::testing::AutoReleasableTask;
579 use std::ops::DerefMut as _;
580
581 pub(crate) fn dequeue_signal_for_test(
582 locked: &mut Locked<Unlocked>,
583 current_task: &mut AutoReleasableTask,
584 ) {
585 dequeue_signal(locked, current_task.deref_mut());
586 }
587}