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