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 {
169 match *self {
170 Self::Continue => false,
171 Self::Ignore => sigaction.map_or(false, |sa| sa.sa_handler == SIG_IGN),
172 _ => true,
173 }
174 }
175}
176
177pub fn action_for_signal(siginfo: &SignalInfo, sigaction: sigaction_t) -> DeliveryAction {
178 let handler = if siginfo.force && sigaction.sa_handler == SIG_IGN {
179 SIG_DFL
180 } else {
181 sigaction.sa_handler
182 };
183 match handler {
184 SIG_DFL => match siginfo.signal {
185 SIGCHLD | SIGURG | SIGWINCH => DeliveryAction::Ignore,
186 sig if sig.is_real_time() => DeliveryAction::Ignore,
187 SIGHUP | SIGINT | SIGKILL | SIGPIPE | SIGALRM | SIGTERM | SIGUSR1 | SIGUSR2
188 | SIGPROF | SIGVTALRM | SIGSTKFLT | SIGIO | SIGPWR => DeliveryAction::Terminate,
189 SIGQUIT | SIGILL | SIGABRT | SIGFPE | SIGSEGV | SIGBUS | SIGSYS | SIGTRAP | SIGXCPU
190 | SIGXFSZ => DeliveryAction::CoreDump,
191 SIGSTOP | SIGTSTP | SIGTTIN | SIGTTOU => DeliveryAction::Stop,
192 SIGCONT => DeliveryAction::Continue,
193 _ => panic!("Unknown signal"),
194 },
195 SIG_IGN => DeliveryAction::Ignore,
196 _ => DeliveryAction::CallHandler,
197 }
198}
199
200pub fn dequeue_signal(current_task: &mut CurrentTask) {
202 let &mut CurrentTask { ref task, ref mut thread_state, .. } = current_task;
203 if !task.should_check_for_pending_signals() {
204 return;
205 }
206
207 let mut task_state = task.write();
208 if task.load_stopped().is_stopping_or_stopped() {
211 return;
212 }
213
214 let kernel_signal = task_state.take_kernel_signal();
216 let siginfo = if kernel_signal.is_some() { None } else { task_state.take_any_signal() };
217 prepare_to_restart_syscall(
218 thread_state,
219 siginfo.as_ref().map(|siginfo| task.thread_group().signal_actions.get(siginfo.signal)),
220 );
221
222 if let Some(ref siginfo) = siginfo {
223 if task_state.ptrace_on_signal_consume() && siginfo.signal != SIGKILL {
224 task_state.set_stopped(
228 StopState::SignalDeliveryStopping,
229 Some(siginfo.clone()),
230 None,
231 None,
232 );
233 return;
234 }
235 }
236
237 task_state.restore_signal_mask();
240 {
241 let (clear, set) = if task_state.pending_signal_count() == 0 {
242 (TaskFlags::SIGNALS_AVAILABLE, TaskFlags::empty())
243 } else {
244 (TaskFlags::empty(), TaskFlags::SIGNALS_AVAILABLE)
245 };
246 task_state.update_flags(clear | TaskFlags::TEMPORARY_SIGNAL_MASK, set);
247 };
248
249 if let Some(kernel_signal) = kernel_signal {
250 let KernelSignal::Freeze(waiter) = kernel_signal;
251 drop(task_state);
252
253 waiter.freeze(current_task);
254 } else if let Some(ref siginfo) = siginfo {
255 if let SignalDetail::Timer { timer } = &siginfo.detail {
256 timer.on_signal_delivered();
257 }
258 if let Some(status) = deliver_signal(
259 &task,
260 current_task.thread_state.arch_width(),
261 task_state,
262 siginfo.clone(),
263 &mut current_task.thread_state.registers,
264 ¤t_task.thread_state.extended_pstate,
265 None,
266 ) {
267 current_task.kill_thread_group(status);
268 }
269 };
270}
271
272pub fn deliver_signal(
273 task: &Task,
274 arch_width: ArchWidth,
275 mut task_state: TaskWriteGuard<'_>,
276 mut siginfo: SignalInfo,
277 registers: &mut RegisterState<RegisterStorageEnum>,
278 extended_pstate: &ArchExtendedPstateStorage,
279 restricted_exception: Option<zx::ExceptionReport>,
280) -> Option<ExitStatus> {
281 loop {
282 let sigaction = task.thread_group().signal_actions.get(siginfo.signal);
283 let action = action_for_signal(&siginfo, sigaction);
284 log_trace!("handling signal {:?} with action {:?}", siginfo, action);
285 match action {
286 DeliveryAction::Ignore => {}
287 DeliveryAction::CallHandler => {
288 let sigaction = task.thread_group().signal_actions.get(siginfo.signal);
289 let signal = siginfo.signal;
290 match dispatch_signal_handler(
291 task,
292 arch_width,
293 registers,
294 extended_pstate,
295 task_state.signals_mut(),
296 siginfo,
297 sigaction,
298 ) {
299 Ok(_) => {
300 if sigaction.sa_flags & (SA_RESETHAND as u64) != 0 {
302 let new_sigaction = sigaction_t {
303 sa_handler: SIG_DFL,
304 sa_flags: sigaction.sa_flags & !(SA_RESETHAND as u64),
305 ..sigaction
306 };
307 task.thread_group().signal_actions.set(signal, new_sigaction);
308 }
309 }
310 Err(err) => {
311 log_warn!("failed to deliver signal {:?}: {:?}", signal, err);
312
313 siginfo = SignalInfo::kernel(SIGSEGV);
314 let sigaction = task.thread_group().signal_actions.get(siginfo.signal);
320 let action = action_for_signal(&siginfo, sigaction);
321 let masked_signals = task_state.signal_mask();
322 if signal == SIGSEGV
323 || masked_signals.has_signal(SIGSEGV)
324 || action == DeliveryAction::Ignore
325 {
326 task_state.set_signal_mask(masked_signals & !SigSet::from(SIGSEGV));
327 task.thread_group().signal_actions.set(SIGSEGV, sigaction_t::default());
328 }
329
330 continue;
337 }
338 }
339 }
340 DeliveryAction::Terminate => {
341 drop(task_state);
344 return Some(ExitStatus::Kill(siginfo));
345 }
346 DeliveryAction::CoreDump => {
347 task_state.set_flags(TaskFlags::DUMP_ON_EXIT, true);
348 drop(task_state);
349 if let Some(exception) = restricted_exception {
350 log_info!(
351 registers:?=registers,
352 exception:?=exception;
353 "Restricted mode exception caused core dump",
355 );
357 if let SignalDetail::SigFault { addr } = siginfo.detail {
358 if let Ok(mm) = task.mm() {
359 mm.log_memory_map(task, UserAddress::from(addr));
360 }
361 }
362 }
363 return Some(ExitStatus::CoreDump(siginfo));
364 }
365 DeliveryAction::Stop => {
366 drop(task_state);
367 task.thread_group().set_stopped(StopState::GroupStopping, Some(siginfo), false);
368 }
369 DeliveryAction::Continue => {
370 }
372 };
373 break;
374 }
375 None
376}
377
378fn dispatch_signal_handler(
382 task: &Task,
383 arch_width: ArchWidth,
384 registers: &mut RegisterState<RegisterStorageEnum>,
385 extended_pstate: &ArchExtendedPstateStorage,
386 signal_state: &mut SignalState,
387 siginfo: SignalInfo,
388 action: sigaction_t,
389) -> Result<(), Errno> {
390 let main_stack = registers.stack_pointer_register().checked_sub(RED_ZONE_SIZE);
391 let stack_bottom = if (action.sa_flags & SA_ONSTACK as u64) != 0 {
392 match signal_state.alt_stack {
393 Some(sigaltstack) => {
394 match main_stack {
395 Some(sp) if sigaltstack_contains_pointer(&sigaltstack, sp) => main_stack,
397 _ => {
398 sigaltstack
402 .ss_sp
403 .addr
404 .checked_add(sigaltstack.ss_size)
405 .map(|sp| sp as u64)
406 .or(main_stack)
407 }
408 }
409 }
410 None => main_stack,
411 }
412 } else {
413 main_stack
414 }
415 .ok_or_else(|| errno!(EINVAL))?;
416
417 let stack_pointer =
418 align_stack_pointer(stack_bottom.checked_sub(SIG_STACK_SIZE as u64).ok_or_else(|| {
419 errno!(
420 EINVAL,
421 format!(
422 "Subtracting SIG_STACK_SIZE ({}) from stack bottom ({}) overflowed",
423 SIG_STACK_SIZE, stack_bottom
424 )
425 )
426 })?);
427
428 if let Some(alt_stack) = signal_state.alt_stack {
431 if sigaltstack_contains_pointer(&alt_stack, stack_pointer)
432 != sigaltstack_contains_pointer(&alt_stack, stack_bottom)
433 {
434 return error!(EINVAL);
435 }
436 }
437
438 let signal_stack_frame = SignalStackFrame::new(
439 task,
440 arch_width,
441 registers,
442 extended_pstate,
443 signal_state,
444 &siginfo,
445 action,
446 UserAddress::from(stack_pointer),
447 )?;
448
449 task.write_memory(UserAddress::from(stack_pointer), signal_stack_frame.as_bytes())?;
451
452 let mut mask: SigSet = action.sa_mask.into();
453 if action.sa_flags & (SA_NODEFER as u64) == 0 {
454 mask = mask | siginfo.signal.into();
455 }
456
457 signal_state.set_mask(mask | signal_state.mask());
459
460 registers.set_stack_pointer_register(stack_pointer);
461 registers.set_arg0_register(siginfo.signal.number() as u64);
462 if (action.sa_flags & SA_SIGINFO as u64) != 0 {
463 registers.set_arg1_register(
464 stack_pointer + memoffset::offset_of!(SignalStackFrame, siginfo_bytes) as u64,
465 );
466 registers.set_arg2_register(
467 stack_pointer + memoffset::offset_of!(SignalStackFrame, context) as u64,
468 );
469 }
470 registers.set_instruction_pointer_register(action.sa_handler.addr);
471 registers.reset_flags(); Ok(())
474}
475
476pub fn restore_from_signal_handler(current_task: &mut CurrentTask) -> Result<(), Errno> {
477 let signal_frame_address = UserAddress::from(align_stack_pointer(
479 current_task.thread_state.registers.stack_pointer_register(),
480 ));
481 let signal_stack_bytes =
482 current_task.read_memory_to_array::<SIG_STACK_SIZE>(signal_frame_address)?;
483
484 let signal_stack_frame = SignalStackFrame::from_bytes(signal_stack_bytes);
486 restore_registers(current_task, &signal_stack_frame, signal_frame_address)?;
487
488 current_task
490 .write()
491 .set_signal_mask(signal_stack_frame.get_signal_mask(current_task.is_arch32()));
492
493 Ok(())
494}
495
496pub fn prepare_to_restart_syscall(
500 thread_state: &mut ThreadState<RegisterStorageEnum>,
501 sigaction: Option<sigaction_t>,
502) {
503 let Some(err) = thread_state.restart_code.take() else {
505 return;
508 };
509
510 if err.should_restart(sigaction) {
511 if err == ERESTART_RESTARTBLOCK {
515 thread_state.registers.prepare_for_custom_restart();
516 } else {
517 thread_state.registers.restore_original_return_register();
518 }
519
520 thread_state.registers.rewind_syscall_instruction();
522 } else {
523 thread_state.registers.set_return_register(EINTR.return_value());
524 }
525}
526
527pub fn sys_restart_syscall(current_task: &mut CurrentTask) -> Result<SyscallResult, Errno> {
528 match current_task.thread_state.syscall_restart_func.take() {
529 Some(f) => f(current_task),
530 None => {
531 log_warn!("restart_syscall called, but nothing to restart");
535 error!(EINTR)
536 }
537 }
538}
539
540#[cfg(test)]
542pub(crate) mod testing {
543 use super::*;
544 use crate::testing::AutoReleasableTask;
545 use std::ops::DerefMut as _;
546
547 pub(crate) fn dequeue_signal_for_test(current_task: &mut AutoReleasableTask) {
548 dequeue_signal(current_task.deref_mut());
549 }
550}