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