1pub use super::signal_handling::sys_restart_syscall;
6use super::signalfd::SignalFd;
7use crate::mm::MemoryAccessorExt;
8use crate::security;
9use crate::signals::{
10 IntoSignalInfoOptions, RunState, SI_MAX_SIZE_AS_USIZE, SignalDetail, SignalInfo,
11 UncheckedSignalInfo, restore_from_signal_handler, send_signal,
12};
13use crate::task::{
14 CurrentTask, PidTable, ProcessEntryRef, ProcessSelector, Task, TaskMutableState, ThreadGroup,
15 ThreadGroupLifecycleWaitValue, WaitResult, WaitableChildResult, Waiter,
16};
17use crate::vfs::{FdFlags, FdNumber};
18use starnix_sync::{LockBefore, RwLockReadGuard, ThreadGroupLimits};
19use starnix_uapi::user_address::{ArchSpecific, MultiArchUserRef};
20use starnix_uapi::{tid_t, uapi};
21
22use starnix_logging::track_stub;
23use starnix_sync::{InterruptibleEvent, Locked, Unlocked, WakeReason};
24use starnix_syscalls::SyscallResult;
25use starnix_types::time::{duration_from_timespec, timeval_from_duration};
26use starnix_uapi::errors::{EINTR, ETIMEDOUT, Errno, ErrnoResultExt};
27use starnix_uapi::open_flags::OpenFlags;
28use starnix_uapi::signals::{SigSet, Signal, UNBLOCKABLE_SIGNALS, UncheckedSignal};
29use starnix_uapi::user_address::{UserAddress, UserRef};
30use starnix_uapi::{
31 __WALL, __WCLONE, __WNOTHREAD, P_ALL, P_PGID, P_PID, P_PIDFD, SFD_CLOEXEC, SFD_NONBLOCK,
32 SI_TKILL, SIG_BLOCK, SIG_SETMASK, SIG_UNBLOCK, SS_AUTODISARM, SS_DISABLE, SS_ONSTACK,
33 WCONTINUED, WEXITED, WNOHANG, WNOWAIT, WSTOPPED, WUNTRACED, errno, error, pid_t, rusage,
34 sigaltstack,
35};
36use static_assertions::const_assert_eq;
37use zerocopy::{FromBytes, Immutable, IntoBytes};
38
39pub type RUsagePtr = MultiArchUserRef<uapi::rusage, uapi::arch32::rusage>;
40type SigAction64Ptr = MultiArchUserRef<uapi::sigaction_t, uapi::arch32::sigaction64_t>;
41type SigActionPtr = MultiArchUserRef<uapi::sigaction_t, uapi::arch32::sigaction_t>;
42
43pub fn sys_rt_sigaction(
58 _locked: &mut Locked<Unlocked>,
59 current_task: &CurrentTask,
60 signum: UncheckedSignal,
61 user_action: SigAction64Ptr,
62 user_old_action: SigAction64Ptr,
63 sigset_size: usize,
64) -> Result<(), Errno> {
65 if user_action.is_arch32() && sigset_size == std::mem::size_of::<uapi::arch32::sigset_t>() {
66 let user_action = SigActionPtr::from_32(user_action.addr().into());
67 let user_old_action = SigActionPtr::from_32(user_old_action.addr().into());
68 return rt_sigaction(current_task, signum, user_action, user_old_action);
69 }
70
71 if sigset_size != std::mem::size_of::<uapi::sigset_t>() {
72 return error!(EINVAL);
73 }
74 rt_sigaction(current_task, signum, user_action, user_old_action)
75}
76
77fn rt_sigaction<Arch32SigAction>(
78 current_task: &CurrentTask,
79 signum: UncheckedSignal,
80 user_action: MultiArchUserRef<uapi::sigaction_t, Arch32SigAction>,
81 user_old_action: MultiArchUserRef<uapi::sigaction_t, Arch32SigAction>,
82) -> Result<(), Errno>
83where
84 Arch32SigAction:
85 IntoBytes + FromBytes + Immutable + TryFrom<uapi::sigaction_t> + TryInto<uapi::sigaction_t>,
86{
87 let signal = Signal::try_from(signum)?;
88
89 let new_signal_action = if !user_action.is_null() {
90 if signal.is_unblockable() {
94 return error!(EINVAL);
95 }
96
97 let signal_action = current_task.read_multi_arch_object(user_action)?;
98 Some(signal_action)
99 } else {
100 None
101 };
102
103 let signal_actions = ¤t_task.thread_group().signal_actions;
104 let old_action = if let Some(new_signal_action) = new_signal_action {
105 signal_actions.set(signal, new_signal_action)
106 } else {
107 signal_actions.get(signal)
108 };
109
110 if !user_old_action.is_null() {
111 current_task.write_multi_arch_object(user_old_action, old_action)?;
112 }
113
114 Ok(())
115}
116
117pub fn sys_rt_sigpending(
127 _locked: &mut Locked<Unlocked>,
128 current_task: &CurrentTask,
129 set: UserRef<SigSet>,
130 sigset_size: usize,
131) -> Result<(), Errno> {
132 if sigset_size != std::mem::size_of::<SigSet>() {
133 return error!(EINVAL);
134 }
135
136 let signals = current_task.read().pending_signals();
137 current_task.write_object(set, &signals)?;
138 Ok(())
139}
140
141pub fn sys_rt_sigprocmask(
154 _locked: &mut Locked<Unlocked>,
155 current_task: &CurrentTask,
156 how: u32,
157 user_set: UserRef<SigSet>,
158 user_old_set: UserRef<SigSet>,
159 sigset_size: usize,
160) -> Result<(), Errno> {
161 if sigset_size != std::mem::size_of::<SigSet>() {
162 return error!(EINVAL);
163 }
164 match how {
165 SIG_BLOCK | SIG_UNBLOCK | SIG_SETMASK => (),
166 _ => return error!(EINVAL),
167 };
168
169 let mut new_mask = SigSet::default();
172 if !user_set.is_null() {
173 new_mask = current_task.read_object(user_set)?;
174 }
175
176 let mut state = current_task.write();
177 let signal_mask = state.signal_mask();
178 if !user_old_set.is_null() {
180 current_task.write_object(user_old_set, &signal_mask)?;
181 }
182
183 if user_set.is_null() {
185 return Ok(());
186 }
187
188 let signal_mask = match how {
189 SIG_BLOCK => signal_mask | new_mask,
190 SIG_UNBLOCK => signal_mask & !new_mask,
191 SIG_SETMASK => new_mask,
192 _ => return error!(EINVAL),
194 };
195 state.set_signal_mask(signal_mask);
196
197 Ok(())
198}
199
200type SigAltStackPtr = MultiArchUserRef<uapi::sigaltstack, uapi::arch32::sigaltstack>;
201
202pub fn sys_sigaltstack(
211 _locked: &mut Locked<Unlocked>,
212 current_task: &CurrentTask,
213 user_ss: SigAltStackPtr,
214 user_old_ss: SigAltStackPtr,
215) -> Result<(), Errno> {
216 let stack_pointer_register = current_task.thread_state.registers.stack_pointer_register();
217 let mut state = current_task.write();
218 let on_signal_stack = state.on_signal_stack(stack_pointer_register);
219
220 let mut ss = sigaltstack::default();
221 if !user_ss.is_null() {
222 if on_signal_stack {
223 return error!(EPERM);
224 }
225 ss = current_task.read_multi_arch_object(user_ss)?;
226 if (ss.ss_flags & !((SS_AUTODISARM | SS_DISABLE) as i32)) != 0 {
227 return error!(EINVAL);
228 }
229 let min_stack_size =
230 if current_task.is_arch32() { uapi::arch32::MINSIGSTKSZ } else { uapi::MINSIGSTKSZ };
231 if ss.ss_flags & (SS_DISABLE as i32) == 0 && ss.ss_size < min_stack_size as u64 {
232 return error!(ENOMEM);
233 }
234 }
235
236 if !user_old_ss.is_null() {
237 let mut old_ss = match state.sigaltstack() {
238 Some(old_ss) => old_ss,
239 None => sigaltstack { ss_flags: SS_DISABLE as i32, ..sigaltstack::default() },
240 };
241 if on_signal_stack {
242 old_ss.ss_flags = SS_ONSTACK as i32;
243 }
244 current_task.write_multi_arch_object(user_old_ss, old_ss)?;
245 }
246
247 if !user_ss.is_null() {
248 if ss.ss_flags & (SS_DISABLE as i32) != 0 {
249 state.set_sigaltstack(None);
250 } else {
251 state.set_sigaltstack(Some(ss));
252 }
253 }
254
255 Ok(())
256}
257
258pub fn sys_rt_sigsuspend(
270 locked: &mut Locked<Unlocked>,
271 current_task: &mut CurrentTask,
272 user_mask: UserRef<SigSet>,
273 sigset_size: usize,
274) -> Result<(), Errno> {
275 if sigset_size != std::mem::size_of::<SigSet>() {
276 return error!(EINVAL);
277 }
278 let mask = current_task.read_object(user_mask)?;
279
280 let waiter = Waiter::new();
281 current_task
285 .wait_with_temporary_mask(locked, mask, |locked, current_task| {
286 waiter.wait(locked, current_task)
287 })
288 .map_eintr(|| errno!(ERESTARTNOHAND))
289}
290
291pub fn sys_rt_sigtimedwait(
304 locked: &mut Locked<Unlocked>,
305 current_task: &mut CurrentTask,
306 set_addr: UserRef<SigSet>,
307 siginfo_addr: MultiArchUserRef<uapi::siginfo_t, uapi::arch32::siginfo_t>,
308 timeout_addr: MultiArchUserRef<uapi::timespec, uapi::arch32::timespec>,
309 sigset_size: usize,
310) -> Result<Signal, Errno> {
311 if sigset_size != std::mem::size_of::<SigSet>() {
312 return error!(EINVAL);
313 }
314
315 let set = current_task.read_object(set_addr)?;
317 let unblock = set & !UNBLOCKABLE_SIGNALS;
319 let deadline = if timeout_addr.is_null() {
320 zx::MonotonicInstant::INFINITE
321 } else {
322 let timeout = current_task.read_multi_arch_object(timeout_addr)?;
323 zx::MonotonicInstant::after(duration_from_timespec(timeout)?)
324 };
325
326 let signal_info = loop {
327 let waiter;
328
329 {
330 let mut task_state = current_task.write();
331 if let Some(signal) = task_state.take_signal_with_mask(!unblock) {
334 break signal;
335 }
336
337 waiter = Waiter::new();
338 task_state.wait_on_signal(&waiter);
339 }
340
341 let tmp_mask = current_task.read().signal_mask() & !unblock;
344
345 let waiter_result =
347 current_task.wait_with_temporary_mask(locked, tmp_mask, |locked, current_task| {
348 waiter.wait_until(locked, current_task, deadline)
349 });
350
351 current_task.write().restore_signal_mask();
353
354 if let Err(e) = waiter_result {
355 if e == EINTR {
356 if let Some(signal) = current_task.write().take_signal_with_mask(!unblock) {
358 break signal;
359 }
360 } else if e == ETIMEDOUT {
361 return error!(EAGAIN);
362 }
363
364 return Err(e);
365 }
366 };
367
368 if !siginfo_addr.is_null() {
369 signal_info.write(current_task, siginfo_addr)?;
370 }
371
372 Ok(signal_info.signal)
373}
374
375pub fn sys_signalfd4(
389 locked: &mut Locked<Unlocked>,
390 current_task: &CurrentTask,
391 fd: FdNumber,
392 mask_addr: UserRef<SigSet>,
393 mask_size: usize,
394 flags: u32,
395) -> Result<FdNumber, Errno> {
396 if flags & !(SFD_CLOEXEC | SFD_NONBLOCK) != 0 {
397 return error!(EINVAL);
398 }
399 if mask_size != std::mem::size_of::<SigSet>() {
400 return error!(EINVAL);
401 }
402 let mask = current_task.read_object(mask_addr)?;
403
404 if fd.raw() != -1 {
405 let file = current_task.get_file(fd)?;
406 let file = file.downcast_file::<SignalFd>().ok_or_else(|| errno!(EINVAL))?;
407 file.set_mask(mask);
408 Ok(fd)
409 } else {
410 let signalfd = SignalFd::new_file(locked, current_task, mask, flags);
411 let flags = if flags & SFD_CLOEXEC != 0 { FdFlags::CLOEXEC } else { FdFlags::empty() };
412 let fd = current_task.add_file(locked, signalfd, flags)?;
413 Ok(fd)
414 }
415}
416
417#[track_caller]
418fn send_unchecked_signal<L>(
419 locked: &mut Locked<L>,
420 current_task: &CurrentTask,
421 target: &Task,
422 unchecked_signal: UncheckedSignal,
423 si_code: i32,
424) -> Result<(), Errno>
425where
426 L: LockBefore<ThreadGroupLimits>,
427{
428 current_task.can_signal(&target, unchecked_signal)?;
429
430 if unchecked_signal.is_zero() {
432 return Ok(());
433 }
434
435 let signal = Signal::try_from(unchecked_signal)?;
436 security::check_signal_access(current_task, &target, signal)?;
437
438 send_signal(
439 locked,
440 target,
441 SignalInfo::with_sender(
442 signal,
443 si_code,
444 SignalDetail::Kill {
445 pid: current_task.thread_group().leader,
446 uid: current_task.current_creds().uid,
447 },
448 Some(current_task.weak_self.clone()),
449 ),
450 )
451}
452
453#[track_caller]
454fn send_unchecked_signal_info<L>(
455 locked: &mut Locked<L>,
456 current_task: &CurrentTask,
457 target: &Task,
458 unchecked_signal: UncheckedSignal,
459 siginfo_ref: UserAddress,
460) -> Result<(), Errno>
461where
462 L: LockBefore<ThreadGroupLimits>,
463{
464 current_task.can_signal(&target, unchecked_signal)?;
465
466 if unchecked_signal.is_zero() {
468 current_task.read_memory_to_array::<SI_MAX_SIZE_AS_USIZE>(siginfo_ref)?;
470 return Ok(());
471 }
472
473 let signal = Signal::try_from(unchecked_signal)?;
474 security::check_signal_access(current_task, &target, signal)?;
475
476 let siginfo = UncheckedSignalInfo::read_from_siginfo(current_task, siginfo_ref)?;
477 if target.get_pid() != current_task.get_pid()
478 && (siginfo.code() >= 0 || siginfo.code() == SI_TKILL)
479 {
480 return error!(EINVAL);
481 }
482
483 send_signal(locked, &target, siginfo.into_signal_info(signal, IntoSignalInfoOptions::None)?)
484}
485
486pub fn sys_kill(
495 locked: &mut Locked<Unlocked>,
496 current_task: &CurrentTask,
497 pid: pid_t,
498 unchecked_signal: UncheckedSignal,
499) -> Result<(), Errno> {
500 let pids = current_task.kernel().pids.read();
501 match pid {
502 pid if pid > 0 => {
503 let target_thread_group = {
506 match pids.get_process(pid) {
507 Some(ProcessEntryRef::Process(process)) => process,
508
509 Some(ProcessEntryRef::Zombie(_zombie)) => return Ok(()),
511
512 None => {
515 let task = pids.get_task(pid)?;
516 task.thread_group().clone()
517 }
518 }
519 };
520
521 target_thread_group.send_signal_unchecked(current_task, unchecked_signal)?;
522 }
523 pid if pid == -1 => {
524 let thread_groups: Vec<_> = pids
533 .get_thread_groups()
534 .into_iter()
535 .filter(|thread_group| {
536 if *current_task.thread_group() == *thread_group {
537 return false;
538 }
539 if thread_group.leader == 1 {
540 return false;
541 }
542 true
543 })
544 .collect();
545 signal_thread_groups(current_task, unchecked_signal, thread_groups)?;
546 }
547 _ => {
548 let process_group_id = match pid {
554 0 => current_task.thread_group().read().process_group.leader,
555 _ => negate_pid(pid)?,
556 };
557
558 let process_group = pids.get_process_group(process_group_id);
559 let thread_groups = process_group
560 .iter()
561 .flat_map(|pg| pg.read(locked).thread_groups().collect::<Vec<_>>());
562 signal_thread_groups(current_task, unchecked_signal, thread_groups)?;
563 }
564 };
565
566 Ok(())
567}
568
569fn verify_tgid_for_task(
570 task: &Task,
571 tgid: pid_t,
572 pids: &RwLockReadGuard<'_, PidTable>,
573) -> Result<(), Errno> {
574 let thread_group = match pids.get_process(tgid) {
575 Some(ProcessEntryRef::Process(proc)) => proc,
576 Some(ProcessEntryRef::Zombie(_)) => return error!(EINVAL),
577 None => return error!(ESRCH),
578 };
579 if *task.thread_group() != thread_group {
580 return error!(EINVAL);
581 } else {
582 Ok(())
583 }
584}
585
586pub fn sys_tkill(
598 locked: &mut Locked<Unlocked>,
599 current_task: &CurrentTask,
600 tid: tid_t,
601 unchecked_signal: UncheckedSignal,
602) -> Result<(), Errno> {
603 if tid <= 0 {
605 return error!(EINVAL);
606 }
607 let thread = current_task.get_task(tid)?;
608 send_unchecked_signal(locked, current_task, &thread, unchecked_signal, SI_TKILL)
609}
610
611pub fn sys_tgkill(
622 locked: &mut Locked<Unlocked>,
623 current_task: &CurrentTask,
624 tgid: pid_t,
625 tid: tid_t,
626 unchecked_signal: UncheckedSignal,
627) -> Result<(), Errno> {
628 if tgid <= 0 || tid <= 0 {
630 return error!(EINVAL);
631 }
632 let pids = current_task.kernel().pids.read();
633
634 let thread = pids.get_task(tid)?;
635 verify_tgid_for_task(&thread, tgid, &pids)?;
636 send_unchecked_signal(locked, current_task, &thread, unchecked_signal, SI_TKILL)
637}
638
639pub fn sys_rt_sigreturn(
648 _locked: &mut Locked<Unlocked>,
649 current_task: &mut CurrentTask,
650) -> Result<SyscallResult, Errno> {
651 restore_from_signal_handler(current_task)?;
652 Ok(current_task.thread_state.registers.return_register().into())
653}
654
655pub fn sys_rt_sigqueueinfo(
665 _locked: &mut Locked<Unlocked>,
666 current_task: &CurrentTask,
667 tgid: pid_t,
668 unchecked_signal: UncheckedSignal,
669 siginfo_ref: UserAddress,
670) -> Result<(), Errno> {
671 let task = current_task.kernel().pids.read().get_task(tgid)?;
672 task.thread_group().send_signal_unchecked_with_info(
673 current_task,
674 unchecked_signal,
675 siginfo_ref,
676 IntoSignalInfoOptions::None,
677 )
678}
679
680pub fn sys_rt_tgsigqueueinfo(
691 locked: &mut Locked<Unlocked>,
692 current_task: &CurrentTask,
693 tgid: pid_t,
694 tid: tid_t,
695 unchecked_signal: UncheckedSignal,
696 siginfo_ref: UserAddress,
697) -> Result<(), Errno> {
698 let pids = current_task.kernel().pids.read();
699
700 let task = pids.get_task(tid)?;
701 verify_tgid_for_task(&task, tgid, &pids)?;
702 send_unchecked_signal_info(locked, current_task, &task, unchecked_signal, siginfo_ref)
703}
704
705pub fn sys_pause(_locked: &mut Locked<Unlocked>, current_task: &CurrentTask) -> Result<(), Errno> {
710 let event = InterruptibleEvent::new();
711 let guard = event.begin_wait();
712 let result = current_task.run_in_state(RunState::Event(event.clone()), || {
713 match guard.block_until(None, zx::MonotonicInstant::INFINITE) {
714 Err(WakeReason::Interrupted) => error!(ERESTARTNOHAND),
715 Err(WakeReason::DeadlineExpired) => panic!("blocking forever cannot time out"),
716 Ok(()) => Ok(()),
717 }
718 });
719 result.map_eintr(|| errno!(ERESTARTNOHAND))
721}
722
723pub fn sys_pidfd_send_signal(
736 _locked: &mut Locked<Unlocked>,
737 current_task: &CurrentTask,
738 pidfd: FdNumber,
739 unchecked_signal: UncheckedSignal,
740 siginfo_ref: UserAddress,
741 flags: u32,
742) -> Result<(), Errno> {
743 if flags != 0 {
744 return error!(EINVAL);
745 }
746
747 let file = current_task.get_file(pidfd)?;
748 let target = file.as_thread_group_key()?;
749 let target = target.upgrade().ok_or_else(|| errno!(ESRCH))?;
750
751 if siginfo_ref.is_null() {
752 target.send_signal_unchecked(current_task, unchecked_signal)
753 } else {
754 target.send_signal_unchecked_with_info(
755 current_task,
756 unchecked_signal,
757 siginfo_ref,
758 IntoSignalInfoOptions::CheckSigno,
759 )
760 }
761}
762
763#[track_caller]
774fn signal_thread_groups<F>(
775 current_task: &CurrentTask,
776 unchecked_signal: UncheckedSignal,
777 thread_groups: F,
778) -> Result<(), Errno>
779where
780 F: IntoIterator<Item: AsRef<ThreadGroup>>,
781{
782 let mut last_error = None;
783 let mut sent_signal = false;
784
785 for thread_group in thread_groups.into_iter() {
788 match thread_group.as_ref().send_signal_unchecked(current_task, unchecked_signal) {
789 Ok(_) => sent_signal = true,
790 Err(errno) => last_error = Some(errno),
791 }
792 }
793
794 if sent_signal { Ok(()) } else { Err(last_error.unwrap_or_else(|| errno!(ESRCH))) }
795}
796
797#[derive(Debug)]
799pub struct WaitingOptions {
800 pub wait_for_exited: bool,
802 pub wait_for_stopped: bool,
804 pub wait_for_continued: bool,
806 pub block: bool,
808 pub keep_waitable_state: bool,
810 pub wait_for_all: bool,
812 pub wait_for_clone: bool,
814}
815
816impl WaitingOptions {
817 fn new(options: u32) -> Self {
818 const_assert_eq!(WUNTRACED, WSTOPPED);
819 if options & __WNOTHREAD != 0 {
820 track_stub!(TODO("https://fxbug.dev/509926462"), "wait options wnothread");
821 }
822 Self {
823 wait_for_exited: options & WEXITED > 0,
824 wait_for_stopped: options & WSTOPPED > 0,
825 wait_for_continued: options & WCONTINUED > 0,
826 block: options & WNOHANG == 0,
827 keep_waitable_state: options & WNOWAIT > 0,
828 wait_for_all: options & __WALL > 0,
829 wait_for_clone: options & __WCLONE > 0,
830 }
831 }
832
833 pub fn new_for_waitid(options: u32) -> Result<Self, Errno> {
835 if options & !(__WCLONE | __WALL | WNOHANG | WNOWAIT | WSTOPPED | WEXITED | WCONTINUED) != 0
836 {
837 track_stub!(TODO("https://fxbug.dev/322874788"), "waitid options", options);
838 return error!(EINVAL);
839 }
840 if options & (WEXITED | WSTOPPED | WCONTINUED) == 0 {
841 return error!(EINVAL);
842 }
843 Ok(Self::new(options))
844 }
845
846 pub fn new_for_wait4(options: u32) -> Result<Self, Errno> {
848 if options & !(__WCLONE | __WNOTHREAD | __WALL | WNOHANG | WUNTRACED | WCONTINUED) != 0 {
849 track_stub!(TODO("https://fxbug.dev/322874017"), "wait4 options", options);
850 return error!(EINVAL);
851 }
852 Ok(Self::new(options | WEXITED))
853 }
854}
855
856fn wait_on_pid(
862 locked: &mut Locked<Unlocked>,
863 current_task: &CurrentTask,
864 selector: &ProcessSelector,
865 options: &WaitingOptions,
866) -> Result<Option<WaitResult>, Errno> {
867 let waiter = Waiter::new();
868 loop {
869 {
870 let mut pids = current_task.kernel().pids.write();
871 if let Some(tracee) =
880 current_task.thread_group().get_waitable_ptracee(selector, options, &mut pids)
881 {
882 return Ok(Some(tracee));
883 }
884 {
885 let mut thread_group = current_task.thread_group().write();
886
887 let mut has_waitable_tracee = false;
890 let mut has_any_tracee = false;
891 current_task.thread_group().get_ptracees_and(
892 selector,
893 &pids,
894 &mut |task: &Task, task_state: &TaskMutableState| {
895 if let Some(ptrace) = &task_state.ptrace {
896 has_any_tracee = true;
897 ptrace.tracer_waiters().wait_async(&waiter);
898 if ptrace.is_waitable(task.load_stopped(), options) {
899 has_waitable_tracee = true;
900 }
901 }
902 },
903 );
904 if has_waitable_tracee
905 || thread_group.zombie_ptracees.has_zombie_matching(&selector)
906 {
907 continue;
908 }
909 match thread_group.get_waitable_child(selector, options, &mut pids) {
910 WaitableChildResult::ReadyNow(child) => {
911 return Ok(Some(*child));
912 }
913 WaitableChildResult::ShouldWait => (),
914 WaitableChildResult::NoneFound => {
915 if !has_any_tracee {
916 return error!(ECHILD);
917 }
918 }
919 }
920 thread_group
921 .lifecycle_waiters
922 .wait_async_value(&waiter, ThreadGroupLifecycleWaitValue::ChildStatus);
923 }
924 }
925
926 if !options.block {
927 return Ok(None);
928 }
929 waiter.wait(locked, current_task).map_eintr(|| errno!(ERESTARTSYS))?;
930 }
931}
932
933pub fn sys_waitid(
947 locked: &mut Locked<Unlocked>,
948 current_task: &CurrentTask,
949 id_type: u32,
950 id: i32,
951 user_info: MultiArchUserRef<uapi::siginfo_t, uapi::arch32::siginfo_t>,
952 options: u32,
953 user_rusage: RUsagePtr,
954) -> Result<(), Errno> {
955 let mut waiting_options = WaitingOptions::new_for_waitid(options)?;
956
957 let task_selector = match id_type {
958 P_PID => ProcessSelector::Pid(id),
959 P_ALL => ProcessSelector::Any,
960 P_PGID => ProcessSelector::Pgid(if id == 0 {
961 current_task.thread_group().read().process_group.leader
962 } else {
963 id
964 }),
965 P_PIDFD => {
966 let fd = FdNumber::from_raw(id);
967 let file = current_task.get_file(fd)?;
968 if file.flags().contains(OpenFlags::NONBLOCK) {
969 waiting_options.block = false;
970 }
971 ProcessSelector::Process(file.as_thread_group_key()?)
972 }
973 _ => return error!(EINVAL),
974 };
975
976 if let Some(waitable_process) =
979 wait_on_pid(locked, current_task, &task_selector, &waiting_options)?
980 {
981 if !user_rusage.is_null() {
982 let usage = rusage {
983 ru_utime: timeval_from_duration(waitable_process.time_stats.user_time),
984 ru_stime: timeval_from_duration(waitable_process.time_stats.system_time),
985 ..Default::default()
986 };
987
988 track_stub!(TODO("https://fxbug.dev/322874712"), "real rusage from waitid");
989 current_task.write_multi_arch_object(user_rusage, usage)?;
990 }
991
992 if !user_info.is_null() {
993 let siginfo = waitable_process.as_signal_info();
994 siginfo.write(current_task, user_info)?;
995 }
996 } else if id_type == P_PIDFD {
997 return error!(EAGAIN);
1006 }
1007
1008 Ok(())
1009}
1010
1011pub fn sys_wait4(
1025 locked: &mut Locked<Unlocked>,
1026 current_task: &CurrentTask,
1027 raw_selector: pid_t,
1028 user_wstatus: UserRef<i32>,
1029 options: u32,
1030 user_rusage: RUsagePtr,
1031) -> Result<pid_t, Errno> {
1032 let waiting_options = WaitingOptions::new_for_wait4(options)?;
1033
1034 let selector = if raw_selector == 0 {
1035 ProcessSelector::Pgid(current_task.thread_group().read().process_group.leader)
1036 } else if raw_selector == -1 {
1037 ProcessSelector::Any
1038 } else if raw_selector > 0 {
1039 ProcessSelector::Pid(raw_selector)
1040 } else if raw_selector < -1 {
1041 ProcessSelector::Pgid(negate_pid(raw_selector)?)
1042 } else {
1043 track_stub!(
1044 TODO("https://fxbug.dev/322874213"),
1045 "wait4 with selector",
1046 raw_selector as u64
1047 );
1048 return error!(ENOSYS);
1049 };
1050
1051 if let Some(waitable_process) = wait_on_pid(locked, current_task, &selector, &waiting_options)?
1052 {
1053 let status = waitable_process.exit_info.status.wait_status();
1054
1055 if !user_rusage.is_null() {
1056 track_stub!(TODO("https://fxbug.dev/322874768"), "real rusage from wait4");
1057 let usage = rusage {
1058 ru_utime: timeval_from_duration(waitable_process.time_stats.user_time),
1059 ru_stime: timeval_from_duration(waitable_process.time_stats.system_time),
1060 ..Default::default()
1061 };
1062 current_task.write_multi_arch_object(user_rusage, usage)?;
1063 }
1064
1065 if !user_wstatus.is_null() {
1066 current_task.write_object(user_wstatus, &status)?;
1067 }
1068
1069 Ok(waitable_process.pid)
1070 } else {
1071 Ok(0)
1072 }
1073}
1074
1075fn negate_pid(pid: pid_t) -> Result<pid_t, Errno> {
1077 pid.checked_neg().ok_or_else(|| errno!(ESRCH))
1078}
1079
1080#[cfg(target_arch = "aarch64")]
1082mod arch32 {
1083 use crate::task::CurrentTask;
1084 use crate::vfs::FdNumber;
1085 use starnix_sync::{Locked, Unlocked};
1086 use starnix_uapi::errors::Errno;
1087 use starnix_uapi::signals::SigSet;
1088 use starnix_uapi::user_address::UserRef;
1089
1090 pub fn sys_arch32_signalfd(
1105 locked: &mut Locked<Unlocked>,
1106 current_task: &CurrentTask,
1107 fd: FdNumber,
1108 mask_addr: UserRef<SigSet>,
1109 mask_size: usize,
1110 ) -> Result<FdNumber, Errno> {
1111 super::sys_signalfd4(locked, current_task, fd, mask_addr, mask_size, 0)
1112 }
1113
1114 pub use super::{
1115 sys_pidfd_send_signal as sys_arch32_pidfd_send_signal,
1116 sys_rt_sigaction as sys_arch32_rt_sigaction,
1117 sys_rt_sigqueueinfo as sys_arch32_rt_sigqueueinfo,
1118 sys_rt_sigtimedwait as sys_arch32_rt_sigtimedwait,
1119 sys_rt_tgsigqueueinfo as sys_arch32_rt_tgsigqueueinfo,
1120 sys_sigaltstack as sys_arch32_sigaltstack, sys_signalfd4 as sys_arch32_signalfd4,
1121 sys_waitid as sys_arch32_waitid,
1122 };
1123}
1124
1125#[cfg(target_arch = "aarch64")]
1126pub use arch32::*;
1127
1128#[cfg(test)]
1129mod tests {
1130 use super::*;
1131 use crate::mm::{MemoryAccessor, PAGE_SIZE};
1132 use crate::signals::testing::dequeue_signal_for_test;
1133 use crate::signals::{SI_HEADER_SIZE, SignalInfoHeader, send_standard_signal};
1134 use crate::task::dynamic_thread_spawner::SpawnRequestBuilder;
1135 use crate::task::{EventHandler, ExitStatus, ProcessExitInfo};
1136 use crate::testing::*;
1137 use starnix_sync::Mutex;
1138 use starnix_types::math::round_up_to_system_page_size;
1139 use starnix_uapi::auth::Credentials;
1140 use starnix_uapi::errors::ERESTARTSYS;
1141 use starnix_uapi::signals::{
1142 SIGCHLD, SIGHUP, SIGINT, SIGIO, SIGKILL, SIGRTMIN, SIGSEGV, SIGSTOP, SIGTERM, SIGTRAP,
1143 SIGUSR1,
1144 };
1145 use starnix_uapi::vfs::FdEvents;
1146 use starnix_uapi::{SI_QUEUE, sigaction_t, uaddr, uid_t};
1147 use std::collections::VecDeque;
1148 use std::sync::Arc;
1149 use zerocopy::IntoBytes;
1150
1151 #[cfg(target_arch = "x86_64")]
1152 #[::fuchsia::test]
1153 async fn test_sigaltstack() {
1154 spawn_kernel_and_run(async |locked, current_task| {
1155 let addr = map_memory(locked, ¤t_task, UserAddress::default(), *PAGE_SIZE);
1156
1157 let user_ss = UserRef::<sigaltstack>::new(addr);
1158 let nullptr = UserRef::<sigaltstack>::default();
1159
1160 sys_sigaltstack(locked, ¤t_task, nullptr.into(), user_ss.into())
1162 .expect("failed to call sigaltstack");
1163 let mut ss = current_task.read_object(user_ss).expect("failed to read struct");
1164 assert!(ss.ss_flags & (SS_DISABLE as i32) != 0);
1165
1166 ss.ss_sp = uaddr { addr: 0x7FFFF };
1168 ss.ss_size = 0x1000;
1169 ss.ss_flags = SS_AUTODISARM as i32;
1170 current_task.write_object(user_ss, &ss).expect("failed to write struct");
1171 sys_sigaltstack(locked, ¤t_task, user_ss.into(), nullptr.into())
1172 .expect("failed to call sigaltstack");
1173 current_task
1174 .write_memory(addr, &[0u8; std::mem::size_of::<sigaltstack>()])
1175 .expect("failed to clear struct");
1176 sys_sigaltstack(locked, ¤t_task, nullptr.into(), user_ss.into())
1177 .expect("failed to call sigaltstack");
1178 let another_ss = current_task.read_object(user_ss).expect("failed to read struct");
1179 assert_eq!(ss.as_bytes(), another_ss.as_bytes());
1180
1181 let ss = sigaltstack { ss_flags: SS_DISABLE as i32, ..sigaltstack::default() };
1183 current_task.write_object(user_ss, &ss).expect("failed to write struct");
1184 sys_sigaltstack(locked, ¤t_task, user_ss.into(), nullptr.into())
1185 .expect("failed to call sigaltstack");
1186 current_task
1187 .write_memory(addr, &[0u8; std::mem::size_of::<sigaltstack>()])
1188 .expect("failed to clear struct");
1189 sys_sigaltstack(locked, ¤t_task, nullptr.into(), user_ss.into())
1190 .expect("failed to call sigaltstack");
1191 let ss = current_task.read_object(user_ss).expect("failed to read struct");
1192 assert!(ss.ss_flags & (SS_DISABLE as i32) != 0);
1193 })
1194 .await;
1195 }
1196
1197 #[::fuchsia::test]
1198 async fn test_sigaltstack_invalid_size() {
1199 spawn_kernel_and_run(async |locked, current_task| {
1200 let addr = map_memory(locked, ¤t_task, UserAddress::default(), *PAGE_SIZE);
1201
1202 let user_ss = UserRef::<sigaltstack>::new(addr);
1203 let nullptr = UserRef::<sigaltstack>::default();
1204
1205 sys_sigaltstack(locked, ¤t_task, nullptr.into(), user_ss.into())
1207 .expect("failed to call sigaltstack");
1208 let mut ss = current_task.read_object(user_ss).expect("failed to read struct");
1209 assert!(ss.ss_flags & (SS_DISABLE as i32) != 0);
1210
1211 let sigaltstack_addr_size = round_up_to_system_page_size(uapi::MINSIGSTKSZ as usize)
1213 .expect("failed to round up");
1214 let sigaltstack_addr = map_memory(
1215 locked,
1216 ¤t_task,
1217 UserAddress::default(),
1218 sigaltstack_addr_size as u64,
1219 );
1220 ss.ss_sp = sigaltstack_addr.into();
1221 ss.ss_flags = 0;
1222 ss.ss_size = uapi::MINSIGSTKSZ as u64 - 1;
1223 current_task.write_object(user_ss, &ss).expect("failed to write struct");
1224 assert_eq!(
1225 sys_sigaltstack(locked, ¤t_task, user_ss.into(), nullptr.into()),
1226 error!(ENOMEM)
1227 );
1228 })
1229 .await;
1230 }
1231
1232 #[cfg(target_arch = "x86_64")]
1233 #[::fuchsia::test]
1234 async fn test_sigaltstack_active_stack() {
1235 spawn_kernel_and_run(async |locked, current_task| {
1236 let addr = map_memory(locked, ¤t_task, UserAddress::default(), *PAGE_SIZE);
1237
1238 let user_ss = UserRef::<sigaltstack>::new(addr);
1239 let nullptr = UserRef::<sigaltstack>::default();
1240
1241 sys_sigaltstack(locked, ¤t_task, nullptr.into(), user_ss.into())
1243 .expect("failed to call sigaltstack");
1244 let mut ss = current_task.read_object(user_ss).expect("failed to read struct");
1245 assert!(ss.ss_flags & (SS_DISABLE as i32) != 0);
1246
1247 let sigaltstack_addr_size = round_up_to_system_page_size(uapi::MINSIGSTKSZ as usize)
1249 .expect("failed to round up");
1250 let sigaltstack_addr = map_memory(
1251 locked,
1252 ¤t_task,
1253 UserAddress::default(),
1254 sigaltstack_addr_size as u64,
1255 );
1256 ss.ss_sp = sigaltstack_addr.into();
1257 ss.ss_flags = 0;
1258 ss.ss_size = sigaltstack_addr_size as u64;
1259 current_task.write_object(user_ss, &ss).expect("failed to write struct");
1260 sys_sigaltstack(locked, ¤t_task, user_ss.into(), nullptr.into())
1261 .expect("failed to call sigaltstack");
1262
1263 let next_addr = (sigaltstack_addr + sigaltstack_addr_size).unwrap();
1265 current_task.thread_state.registers.rsp = next_addr.ptr() as u64;
1266 ss.ss_flags = SS_DISABLE as i32;
1267 current_task.write_object(user_ss, &ss).expect("failed to write struct");
1268 assert_eq!(
1269 sys_sigaltstack(locked, ¤t_task, user_ss.into(), nullptr.into()),
1270 error!(EPERM)
1271 );
1272
1273 let next_ss_addr = sigaltstack_addr
1276 .checked_add(sigaltstack_addr_size)
1277 .unwrap()
1278 .checked_add(0x1000usize)
1279 .unwrap();
1280 current_task.thread_state.registers.rsp = next_ss_addr.ptr() as u64;
1281 let ss = sigaltstack { ss_flags: SS_DISABLE as i32, ..sigaltstack::default() };
1282 current_task.write_object(user_ss, &ss).expect("failed to write struct");
1283 sys_sigaltstack(locked, ¤t_task, user_ss.into(), nullptr.into())
1284 .expect("failed to call sigaltstack");
1285 })
1286 .await;
1287 }
1288
1289 #[cfg(target_arch = "x86_64")]
1290 #[::fuchsia::test]
1291 async fn test_sigaltstack_active_stack_saturates() {
1292 spawn_kernel_and_run(async |locked, current_task| {
1293 let addr = map_memory(locked, ¤t_task, UserAddress::default(), *PAGE_SIZE);
1294
1295 let user_ss = UserRef::<sigaltstack>::new(addr);
1296 let nullptr = UserRef::<sigaltstack>::default();
1297
1298 sys_sigaltstack(locked, ¤t_task, nullptr.into(), user_ss.into())
1300 .expect("failed to call sigaltstack");
1301 let mut ss = current_task.read_object(user_ss).expect("failed to read struct");
1302 assert!(ss.ss_flags & (SS_DISABLE as i32) != 0);
1303
1304 let sigaltstack_addr_size = round_up_to_system_page_size(uapi::MINSIGSTKSZ as usize)
1306 .expect("failed to round up");
1307 let sigaltstack_addr = map_memory(
1308 locked,
1309 ¤t_task,
1310 UserAddress::default(),
1311 sigaltstack_addr_size as u64,
1312 );
1313 ss.ss_sp = sigaltstack_addr.into();
1314 ss.ss_flags = 0;
1315 ss.ss_size = u64::MAX;
1316 current_task.write_object(user_ss, &ss).expect("failed to write struct");
1317 sys_sigaltstack(locked, ¤t_task, user_ss.into(), nullptr.into())
1318 .expect("failed to call sigaltstack");
1319
1320 current_task.thread_state.registers.rsp =
1322 (sigaltstack_addr + sigaltstack_addr_size).unwrap().ptr() as u64;
1323 ss.ss_flags = SS_DISABLE as i32;
1324 current_task.write_object(user_ss, &ss).expect("failed to write struct");
1325 assert_eq!(
1326 sys_sigaltstack(locked, ¤t_task, user_ss.into(), nullptr.into()),
1327 error!(EPERM)
1328 );
1329
1330 current_task.thread_state.registers.rsp = 0u64;
1332 let ss = sigaltstack { ss_flags: SS_DISABLE as i32, ..sigaltstack::default() };
1333 current_task.write_object(user_ss, &ss).expect("failed to write struct");
1334 sys_sigaltstack(locked, ¤t_task, user_ss.into(), nullptr.into())
1335 .expect("failed to call sigaltstack");
1336 })
1337 .await;
1338 }
1339
1340 #[::fuchsia::test]
1343 async fn test_sigprocmask_invalid_size() {
1344 spawn_kernel_and_run(async |locked, current_task| {
1345 let set = UserRef::<SigSet>::default();
1346 let old_set = UserRef::<SigSet>::default();
1347 let how = 0;
1348
1349 assert_eq!(
1350 sys_rt_sigprocmask(
1351 locked,
1352 ¤t_task,
1353 how,
1354 set,
1355 old_set,
1356 std::mem::size_of::<SigSet>() * 2
1357 ),
1358 error!(EINVAL)
1359 );
1360 assert_eq!(
1361 sys_rt_sigprocmask(
1362 locked,
1363 ¤t_task,
1364 how,
1365 set,
1366 old_set,
1367 std::mem::size_of::<SigSet>() / 2
1368 ),
1369 error!(EINVAL)
1370 );
1371 })
1372 .await;
1373 }
1374
1375 #[::fuchsia::test]
1377 async fn test_sigprocmask_invalid_how() {
1378 spawn_kernel_and_run(async |locked, current_task| {
1379 let addr = map_memory(locked, ¤t_task, UserAddress::default(), *PAGE_SIZE);
1380
1381 let set = UserRef::<SigSet>::new(addr);
1382 let old_set = UserRef::<SigSet>::default();
1383 let how = SIG_SETMASK | SIG_UNBLOCK | SIG_BLOCK;
1384
1385 assert_eq!(
1386 sys_rt_sigprocmask(
1387 locked,
1388 ¤t_task,
1389 how,
1390 set,
1391 old_set,
1392 std::mem::size_of::<SigSet>()
1393 ),
1394 error!(EINVAL)
1395 );
1396 })
1397 .await;
1398 }
1399
1400 #[::fuchsia::test]
1403 async fn test_sigprocmask_null_set() {
1404 spawn_kernel_and_run(async |locked, current_task| {
1405 let addr = map_memory(locked, ¤t_task, UserAddress::default(), *PAGE_SIZE);
1406 let original_mask = SigSet::from(SIGTRAP);
1407 {
1408 current_task.write().set_signal_mask(original_mask);
1409 }
1410
1411 let set = UserRef::<SigSet>::default();
1412 let old_set = UserRef::<SigSet>::new(addr);
1413 let how = SIG_SETMASK;
1414
1415 current_task
1416 .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>()])
1417 .expect("failed to clear struct");
1418
1419 assert_eq!(
1420 sys_rt_sigprocmask(
1421 locked,
1422 ¤t_task,
1423 how,
1424 set,
1425 old_set,
1426 std::mem::size_of::<SigSet>()
1427 ),
1428 Ok(())
1429 );
1430
1431 let old_mask = current_task.read_object(old_set).expect("failed to read mask");
1432 assert_eq!(old_mask, original_mask);
1433 })
1434 .await;
1435 }
1436
1437 #[::fuchsia::test]
1440 async fn test_sigprocmask_null_set_and_old_set() {
1441 spawn_kernel_and_run(async |locked, current_task| {
1442 let original_mask = SigSet::from(SIGTRAP);
1443 {
1444 current_task.write().set_signal_mask(original_mask);
1445 }
1446
1447 let set = UserRef::<SigSet>::default();
1448 let old_set = UserRef::<SigSet>::default();
1449 let how = SIG_SETMASK;
1450
1451 assert_eq!(
1452 sys_rt_sigprocmask(
1453 locked,
1454 ¤t_task,
1455 how,
1456 set,
1457 old_set,
1458 std::mem::size_of::<SigSet>()
1459 ),
1460 Ok(())
1461 );
1462 assert_eq!(current_task.read().signal_mask(), original_mask);
1463 })
1464 .await;
1465 }
1466
1467 #[::fuchsia::test]
1469 async fn test_sigprocmask_setmask() {
1470 spawn_kernel_and_run(async |locked, current_task| {
1471 let addr = map_memory(locked, ¤t_task, UserAddress::default(), *PAGE_SIZE);
1472 current_task
1473 .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1474 .expect("failed to clear struct");
1475
1476 let original_mask = SigSet::from(SIGTRAP);
1477 {
1478 current_task.write().set_signal_mask(original_mask);
1479 }
1480
1481 let new_mask = SigSet::from(SIGIO);
1482 let set = UserRef::<SigSet>::new(addr);
1483 current_task.write_object(set, &new_mask).expect("failed to set mask");
1484
1485 let old_addr_range = (addr + std::mem::size_of::<SigSet>()).unwrap();
1486 let old_set = UserRef::<SigSet>::new(old_addr_range);
1487 let how = SIG_SETMASK;
1488
1489 assert_eq!(
1490 sys_rt_sigprocmask(
1491 locked,
1492 ¤t_task,
1493 how,
1494 set,
1495 old_set,
1496 std::mem::size_of::<SigSet>()
1497 ),
1498 Ok(())
1499 );
1500
1501 let old_mask = current_task.read_object(old_set).expect("failed to read mask");
1502 assert_eq!(old_mask, original_mask);
1503 assert_eq!(current_task.read().signal_mask(), new_mask);
1504 })
1505 .await;
1506 }
1507
1508 #[::fuchsia::test]
1510 async fn test_sigprocmask_block() {
1511 spawn_kernel_and_run(async |locked, current_task| {
1512 let addr = map_memory(locked, ¤t_task, UserAddress::default(), *PAGE_SIZE);
1513 current_task
1514 .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1515 .expect("failed to clear struct");
1516
1517 let original_mask = SigSet::from(SIGTRAP);
1518 {
1519 current_task.write().set_signal_mask(original_mask);
1520 }
1521
1522 let new_mask = SigSet::from(SIGIO);
1523 let set = UserRef::<SigSet>::new(addr);
1524 current_task.write_object(set, &new_mask).expect("failed to set mask");
1525
1526 let old_addr_range = (addr + std::mem::size_of::<SigSet>()).unwrap();
1527 let old_set = UserRef::<SigSet>::new(old_addr_range);
1528 let how = SIG_BLOCK;
1529
1530 assert_eq!(
1531 sys_rt_sigprocmask(
1532 locked,
1533 ¤t_task,
1534 how,
1535 set,
1536 old_set,
1537 std::mem::size_of::<SigSet>()
1538 ),
1539 Ok(())
1540 );
1541
1542 let old_mask = current_task.read_object(old_set).expect("failed to read mask");
1543 assert_eq!(old_mask, original_mask);
1544 assert_eq!(current_task.read().signal_mask(), new_mask | original_mask);
1545 })
1546 .await;
1547 }
1548
1549 #[::fuchsia::test]
1551 async fn test_sigprocmask_unblock() {
1552 spawn_kernel_and_run(async |locked, current_task| {
1553 let addr = map_memory(locked, ¤t_task, UserAddress::default(), *PAGE_SIZE);
1554 current_task
1555 .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1556 .expect("failed to clear struct");
1557
1558 let original_mask = SigSet::from(SIGTRAP) | SigSet::from(SIGIO);
1559 {
1560 current_task.write().set_signal_mask(original_mask);
1561 }
1562
1563 let new_mask = SigSet::from(SIGTRAP);
1564 let set = UserRef::<SigSet>::new(addr);
1565 current_task.write_object(set, &new_mask).expect("failed to set mask");
1566
1567 let old_addr_range = (addr + std::mem::size_of::<SigSet>()).unwrap();
1568 let old_set = UserRef::<SigSet>::new(old_addr_range);
1569 let how = SIG_UNBLOCK;
1570
1571 assert_eq!(
1572 sys_rt_sigprocmask(
1573 locked,
1574 ¤t_task,
1575 how,
1576 set,
1577 old_set,
1578 std::mem::size_of::<SigSet>()
1579 ),
1580 Ok(())
1581 );
1582
1583 let old_mask = current_task.read_object(old_set).expect("failed to read mask");
1584 assert_eq!(old_mask, original_mask);
1585 assert_eq!(current_task.read().signal_mask(), SIGIO.into());
1586 })
1587 .await;
1588 }
1589
1590 #[::fuchsia::test]
1592 async fn test_sigprocmask_unblock_not_set() {
1593 spawn_kernel_and_run(async |locked, current_task| {
1594 let addr = map_memory(locked, ¤t_task, UserAddress::default(), *PAGE_SIZE);
1595 current_task
1596 .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1597 .expect("failed to clear struct");
1598
1599 let original_mask = SigSet::from(SIGIO);
1600 {
1601 current_task.write().set_signal_mask(original_mask);
1602 }
1603
1604 let new_mask = SigSet::from(SIGTRAP);
1605 let set = UserRef::<SigSet>::new(addr);
1606 current_task.write_object(set, &new_mask).expect("failed to set mask");
1607
1608 let old_addr_range = (addr + std::mem::size_of::<SigSet>()).unwrap();
1609 let old_set = UserRef::<SigSet>::new(old_addr_range);
1610 let how = SIG_UNBLOCK;
1611
1612 assert_eq!(
1613 sys_rt_sigprocmask(
1614 locked,
1615 ¤t_task,
1616 how,
1617 set,
1618 old_set,
1619 std::mem::size_of::<SigSet>()
1620 ),
1621 Ok(())
1622 );
1623
1624 let old_mask = current_task.read_object(old_set).expect("failed to read mask");
1625 assert_eq!(old_mask, original_mask);
1626 assert_eq!(current_task.read().signal_mask(), original_mask);
1627 })
1628 .await;
1629 }
1630
1631 #[::fuchsia::test]
1633 async fn test_sigprocmask_kill_stop() {
1634 spawn_kernel_and_run(async |locked, current_task| {
1635 let addr = map_memory(locked, ¤t_task, UserAddress::default(), *PAGE_SIZE);
1636 current_task
1637 .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1638 .expect("failed to clear struct");
1639
1640 let original_mask = SigSet::from(SIGIO);
1641 {
1642 current_task.write().set_signal_mask(original_mask);
1643 }
1644
1645 let new_mask = UNBLOCKABLE_SIGNALS;
1646 let set = UserRef::<SigSet>::new(addr);
1647 current_task.write_object(set, &new_mask).expect("failed to set mask");
1648
1649 let old_addr_range = (addr + std::mem::size_of::<SigSet>()).unwrap();
1650 let old_set = UserRef::<SigSet>::new(old_addr_range);
1651 let how = SIG_BLOCK;
1652
1653 assert_eq!(
1654 sys_rt_sigprocmask(
1655 locked,
1656 ¤t_task,
1657 how,
1658 set,
1659 old_set,
1660 std::mem::size_of::<SigSet>()
1661 ),
1662 Ok(())
1663 );
1664
1665 let old_mask = current_task.read_object(old_set).expect("failed to read mask");
1666 assert_eq!(old_mask, original_mask);
1667 assert_eq!(current_task.read().signal_mask(), original_mask);
1668 })
1669 .await;
1670 }
1671
1672 #[::fuchsia::test]
1673 async fn test_sigaction_invalid_signal() {
1674 spawn_kernel_and_run(async |locked, current_task| {
1675 assert_eq!(
1676 sys_rt_sigaction(
1677 locked,
1678 ¤t_task,
1679 UncheckedSignal::from(SIGKILL),
1680 UserRef::<sigaction_t>::new(UserAddress::from(10)).into(),
1682 UserRef::<sigaction_t>::default().into(),
1683 std::mem::size_of::<SigSet>(),
1684 ),
1685 error!(EINVAL)
1686 );
1687 assert_eq!(
1688 sys_rt_sigaction(
1689 locked,
1690 ¤t_task,
1691 UncheckedSignal::from(SIGSTOP),
1692 UserRef::<sigaction_t>::new(UserAddress::from(10)).into(),
1694 UserRef::<sigaction_t>::default().into(),
1695 std::mem::size_of::<SigSet>(),
1696 ),
1697 error!(EINVAL)
1698 );
1699 assert_eq!(
1700 sys_rt_sigaction(
1701 locked,
1702 ¤t_task,
1703 UncheckedSignal::from(Signal::NUM_SIGNALS + 1),
1704 UserRef::<sigaction_t>::new(UserAddress::from(10)).into(),
1706 UserRef::<sigaction_t>::default().into(),
1707 std::mem::size_of::<SigSet>(),
1708 ),
1709 error!(EINVAL)
1710 );
1711 })
1712 .await;
1713 }
1714
1715 #[::fuchsia::test]
1716 async fn test_sigaction_old_value_set() {
1717 spawn_kernel_and_run(async |locked, current_task| {
1718 let addr = map_memory(locked, ¤t_task, UserAddress::default(), *PAGE_SIZE);
1719 current_task
1720 .write_memory(addr, &[0u8; std::mem::size_of::<sigaction_t>()])
1721 .expect("failed to clear struct");
1722
1723 let org_mask = SigSet::from(SIGHUP) | SigSet::from(SIGINT);
1724 let original_action =
1725 sigaction_t { sa_mask: org_mask.into(), ..sigaction_t::default() };
1726
1727 {
1728 current_task.thread_group().signal_actions.set(SIGHUP, original_action);
1729 }
1730
1731 let old_action_ref = UserRef::<sigaction_t>::new(addr);
1732 assert_eq!(
1733 sys_rt_sigaction(
1734 locked,
1735 ¤t_task,
1736 UncheckedSignal::from(SIGHUP),
1737 UserRef::<sigaction_t>::default().into(),
1738 old_action_ref.into(),
1739 std::mem::size_of::<SigSet>()
1740 ),
1741 Ok(())
1742 );
1743
1744 let old_action =
1745 current_task.read_object(old_action_ref).expect("failed to read action");
1746 assert_eq!(old_action.as_bytes(), original_action.as_bytes());
1747 })
1748 .await;
1749 }
1750
1751 #[::fuchsia::test]
1752 async fn test_sigaction_new_value_set() {
1753 spawn_kernel_and_run(async |locked, current_task| {
1754 let addr = map_memory(locked, ¤t_task, UserAddress::default(), *PAGE_SIZE);
1755 current_task
1756 .write_memory(addr, &[0u8; std::mem::size_of::<sigaction_t>()])
1757 .expect("failed to clear struct");
1758
1759 let org_mask = SigSet::from(SIGHUP) | SigSet::from(SIGINT);
1760 let original_action =
1761 sigaction_t { sa_mask: org_mask.into(), ..sigaction_t::default() };
1762 let set_action_ref = UserRef::<sigaction_t>::new(addr);
1763 current_task
1764 .write_object(set_action_ref, &original_action)
1765 .expect("failed to set action");
1766
1767 assert_eq!(
1768 sys_rt_sigaction(
1769 locked,
1770 ¤t_task,
1771 UncheckedSignal::from(SIGINT),
1772 set_action_ref.into(),
1773 UserRef::<sigaction_t>::default().into(),
1774 std::mem::size_of::<SigSet>(),
1775 ),
1776 Ok(())
1777 );
1778
1779 assert_eq!(
1780 current_task.thread_group().signal_actions.get(SIGINT).as_bytes(),
1781 original_action.as_bytes()
1782 );
1783 })
1784 .await;
1785 }
1786
1787 #[::fuchsia::test]
1789 async fn test_kill_same_task() {
1790 spawn_kernel_and_run(async |locked, current_task| {
1791 assert_eq!(sys_kill(locked, ¤t_task, current_task.tid, SIGINT.into()), Ok(()));
1792 })
1793 .await;
1794 }
1795
1796 #[::fuchsia::test]
1798 async fn test_kill_own_thread_group() {
1799 spawn_kernel_and_run(async |locked, init_task| {
1800 let task1 = init_task.clone_task_for_test(locked, 0, Some(SIGCHLD));
1801 task1.thread_group().setsid(locked).expect("setsid");
1802 let task2 = task1.clone_task_for_test(locked, 0, Some(SIGCHLD));
1803
1804 assert_eq!(sys_kill(locked, &task1, 0, SIGINT.into()), Ok(()));
1805 assert_eq!(task1.read().queued_signal_count(SIGINT), 1);
1806 assert_eq!(task2.read().queued_signal_count(SIGINT), 1);
1807 assert_eq!(init_task.read().queued_signal_count(SIGINT), 0);
1808 })
1809 .await;
1810 }
1811
1812 #[::fuchsia::test]
1814 async fn test_kill_thread_group() {
1815 spawn_kernel_and_run(async |locked, init_task| {
1816 let task1 = init_task.clone_task_for_test(locked, 0, Some(SIGCHLD));
1817 task1.thread_group().setsid(locked).expect("setsid");
1818 let task2 = task1.clone_task_for_test(locked, 0, Some(SIGCHLD));
1819
1820 assert_eq!(sys_kill(locked, &task1, -task1.tid, SIGINT.into()), Ok(()));
1821 assert_eq!(task1.read().queued_signal_count(SIGINT), 1);
1822 assert_eq!(task2.read().queued_signal_count(SIGINT), 1);
1823 assert_eq!(init_task.read().queued_signal_count(SIGINT), 0);
1824 })
1825 .await;
1826 }
1827
1828 #[::fuchsia::test]
1830 async fn test_kill_all() {
1831 spawn_kernel_and_run(async |locked, init_task| {
1832 let task1 = init_task.clone_task_for_test(locked, 0, Some(SIGCHLD));
1833 task1.thread_group().setsid(locked).expect("setsid");
1834 let task2 = task1.clone_task_for_test(locked, 0, Some(SIGCHLD));
1835
1836 assert_eq!(sys_kill(locked, &task1, -1, SIGINT.into()), Ok(()));
1837 assert_eq!(task1.read().queued_signal_count(SIGINT), 0);
1838 assert_eq!(task2.read().queued_signal_count(SIGINT), 1);
1839 assert_eq!(init_task.read().queued_signal_count(SIGINT), 0);
1840 })
1841 .await;
1842 }
1843
1844 #[::fuchsia::test]
1846 async fn test_kill_inexistant_task() {
1847 spawn_kernel_and_run(async |locked, current_task| {
1848 assert_eq!(sys_kill(locked, ¤t_task, 9, SIGINT.into()), error!(ESRCH));
1849 })
1850 .await;
1851 }
1852
1853 #[::fuchsia::test]
1855 async fn test_kill_invalid_task() {
1856 spawn_kernel_and_run(async |locked, task1| {
1857 task1.set_creds(Credentials::with_ids(1, 1));
1859 let task2 = task1.clone_task_for_test(locked, 0, Some(SIGCHLD));
1860 task2.set_creds(Credentials::with_ids(2, 2));
1861
1862 assert!(task1.can_signal(&task2, SIGINT.into()).is_err());
1863 assert_eq!(sys_kill(locked, &task2, task1.tid, SIGINT.into()), error!(EPERM));
1864 assert_eq!(task1.read().queued_signal_count(SIGINT), 0);
1865 })
1866 .await;
1867 }
1868
1869 #[::fuchsia::test]
1871 async fn test_kill_invalid_task_in_thread_group() {
1872 spawn_kernel_and_run(async |locked, init_task| {
1873 let task1 = init_task.clone_task_for_test(locked, 0, Some(SIGCHLD));
1874 task1.thread_group().setsid(locked).expect("setsid");
1875 let task2 = task1.clone_task_for_test(locked, 0, Some(SIGCHLD));
1876 task2.thread_group().setsid(locked).expect("setsid");
1877 task2.set_creds(Credentials::with_ids(2, 2));
1878
1879 assert!(task2.can_signal(&task1, SIGINT.into()).is_err());
1880 assert_eq!(sys_kill(locked, &task2, -task1.tid, SIGINT.into()), error!(EPERM));
1881 assert_eq!(task1.read().queued_signal_count(SIGINT), 0);
1882 })
1883 .await;
1884 }
1885
1886 #[::fuchsia::test]
1888 async fn test_kill_invalid_signal() {
1889 spawn_kernel_and_run(async |locked, current_task| {
1890 assert_eq!(
1891 sys_kill(locked, ¤t_task, current_task.tid, UncheckedSignal::from(75)),
1892 error!(EINVAL)
1893 );
1894 })
1895 .await;
1896 }
1897
1898 #[::fuchsia::test]
1900 async fn test_blocked_signal_pending() {
1901 spawn_kernel_and_run(async |locked, current_task| {
1902 let addr = map_memory(locked, ¤t_task, UserAddress::default(), *PAGE_SIZE);
1903 current_task
1904 .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1905 .expect("failed to clear struct");
1906
1907 let new_mask = SigSet::from(SIGIO);
1908 let set = UserRef::<SigSet>::new(addr);
1909 current_task.write_object(set, &new_mask).expect("failed to set mask");
1910
1911 assert_eq!(
1912 sys_rt_sigprocmask(
1913 locked,
1914 ¤t_task,
1915 SIG_BLOCK,
1916 set,
1917 UserRef::default(),
1918 std::mem::size_of::<SigSet>()
1919 ),
1920 Ok(())
1921 );
1922 assert_eq!(sys_kill(locked, ¤t_task, current_task.tid, SIGIO.into()), Ok(()));
1923 assert_eq!(current_task.read().queued_signal_count(SIGIO), 1);
1924
1925 assert_eq!(sys_kill(locked, ¤t_task, current_task.tid, SIGIO.into()), Ok(()));
1927 assert_eq!(current_task.read().queued_signal_count(SIGIO), 1);
1928 })
1929 .await;
1930 }
1931
1932 #[::fuchsia::test]
1934 async fn test_blocked_real_time_signal_pending() {
1935 spawn_kernel_and_run(async |locked, current_task| {
1936 let addr = map_memory(locked, ¤t_task, UserAddress::default(), *PAGE_SIZE);
1937 current_task
1938 .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1939 .expect("failed to clear struct");
1940
1941 let new_mask = SigSet::from(starnix_uapi::signals::SIGRTMIN);
1942 let set = UserRef::<SigSet>::new(addr);
1943 current_task.write_object(set, &new_mask).expect("failed to set mask");
1944
1945 assert_eq!(
1946 sys_rt_sigprocmask(
1947 locked,
1948 ¤t_task,
1949 SIG_BLOCK,
1950 set,
1951 UserRef::default(),
1952 std::mem::size_of::<SigSet>()
1953 ),
1954 Ok(())
1955 );
1956 assert_eq!(sys_kill(locked, ¤t_task, current_task.tid, SIGRTMIN.into()), Ok(()));
1957 assert_eq!(current_task.read().queued_signal_count(starnix_uapi::signals::SIGRTMIN), 1);
1958
1959 assert_eq!(sys_kill(locked, ¤t_task, current_task.tid, SIGRTMIN.into()), Ok(()));
1961 assert_eq!(current_task.read().queued_signal_count(starnix_uapi::signals::SIGRTMIN), 2);
1962 })
1963 .await;
1964 }
1965
1966 #[::fuchsia::test]
1967 async fn test_suspend() {
1968 spawn_kernel_and_run(async |locked, current_task| {
1969 let init_task_weak = current_task.weak_task();
1970 let (tx, rx) = std::sync::mpsc::sync_channel::<()>(0);
1971
1972 let closure = move |locked: &mut Locked<Unlocked>, current_task: &CurrentTask| {
1973 let init_task_temp = init_task_weak.upgrade().expect("Task must be alive");
1974
1975 let mut suspended = false;
1977 while !suspended {
1978 suspended = init_task_temp.read().is_blocked();
1979 std::thread::sleep(std::time::Duration::from_millis(10));
1980 }
1981
1982 let _ = sys_kill(
1984 locked,
1985 current_task,
1986 init_task_temp.tid,
1987 UncheckedSignal::from(SIGHUP),
1988 );
1989
1990 rx.recv().expect("receive");
1992 assert!(!init_task_temp.read().is_blocked());
1993 };
1994 let (thread, req) =
1995 SpawnRequestBuilder::new().with_sync_closure(closure).build_with_async_result();
1996 current_task.kernel().kthreads.spawner().spawn_from_request(req);
1997
1998 let addr = map_memory(locked, ¤t_task, UserAddress::default(), *PAGE_SIZE);
1999 let user_ref = UserRef::<SigSet>::new(addr);
2000
2001 let sigset = !SigSet::from(SIGHUP);
2002 current_task.write_object(user_ref, &sigset).expect("failed to set action");
2003
2004 assert_eq!(
2005 sys_rt_sigsuspend(locked, current_task, user_ref, std::mem::size_of::<SigSet>()),
2006 error!(ERESTARTNOHAND)
2007 );
2008 tx.send(()).expect("send");
2009 futures::executor::block_on(thread).expect("join");
2010 })
2011 .await;
2012 }
2013
2014 #[::fuchsia::test]
2016 async fn test_waitid_options() {
2017 spawn_kernel_and_run(async |locked, current_task| {
2018 let id = 1;
2019 assert_eq!(
2020 sys_waitid(
2021 locked,
2022 ¤t_task,
2023 P_PID,
2024 id,
2025 MultiArchUserRef::null(current_task),
2026 0,
2027 UserRef::default().into()
2028 ),
2029 error!(EINVAL)
2030 );
2031 assert_eq!(
2032 sys_waitid(
2033 locked,
2034 ¤t_task,
2035 P_PID,
2036 id,
2037 MultiArchUserRef::null(current_task),
2038 0xffff,
2039 UserRef::default().into()
2040 ),
2041 error!(EINVAL)
2042 );
2043 })
2044 .await;
2045 }
2046
2047 #[::fuchsia::test]
2049 async fn test_wait4_options() {
2050 spawn_kernel_and_run(async |locked, current_task| {
2051 let id = 1;
2052 assert_eq!(
2053 sys_wait4(
2054 locked,
2055 ¤t_task,
2056 id,
2057 UserRef::default(),
2058 WEXITED,
2059 RUsagePtr::null(current_task)
2060 ),
2061 error!(EINVAL)
2062 );
2063 assert_eq!(
2064 sys_wait4(
2065 locked,
2066 ¤t_task,
2067 id,
2068 UserRef::default(),
2069 WNOWAIT,
2070 RUsagePtr::null(current_task)
2071 ),
2072 error!(EINVAL)
2073 );
2074 assert_eq!(
2075 sys_wait4(
2076 locked,
2077 ¤t_task,
2078 id,
2079 UserRef::default(),
2080 0xffff,
2081 RUsagePtr::null(current_task)
2082 ),
2083 error!(EINVAL)
2084 );
2085 })
2086 .await;
2087 }
2088
2089 #[::fuchsia::test]
2090 async fn test_echild_when_no_zombie() {
2091 spawn_kernel_and_run(async |locked, current_task| {
2092 assert!(
2094 sys_kill(
2095 locked,
2096 ¤t_task,
2097 current_task.get_pid(),
2098 UncheckedSignal::from(SIGCHLD)
2099 )
2100 .is_ok()
2101 );
2102 assert_eq!(
2105 wait_on_pid(
2106 locked,
2107 ¤t_task,
2108 &ProcessSelector::Any,
2109 &WaitingOptions::new_for_wait4(0).expect("WaitingOptions")
2110 ),
2111 error!(ECHILD)
2112 );
2113 })
2114 .await;
2115 }
2116
2117 #[::fuchsia::test]
2118 async fn test_no_error_when_zombie() {
2119 spawn_kernel_and_run(async |locked, current_task| {
2120 let child = current_task.clone_task_for_test(locked, 0, Some(SIGCHLD));
2121 let expected_result = WaitResult {
2122 pid: child.tid,
2123 uid: 0,
2124 exit_info: ProcessExitInfo {
2125 status: ExitStatus::Exit(1),
2126 exit_signal: Some(SIGCHLD),
2127 },
2128 time_stats: Default::default(),
2129 };
2130 child.thread_group().exit(locked, ExitStatus::Exit(1), None);
2131 std::mem::drop(child);
2132
2133 assert_eq!(
2134 wait_on_pid(
2135 locked,
2136 ¤t_task,
2137 &ProcessSelector::Any,
2138 &WaitingOptions::new_for_wait4(0).expect("WaitingOptions")
2139 ),
2140 Ok(Some(expected_result))
2141 );
2142 })
2143 .await;
2144 }
2145
2146 #[::fuchsia::test]
2147 async fn test_waiting_for_child() {
2148 spawn_kernel_and_run(async |locked, task| {
2149 let child = task.clone_task_builder_for_test(locked, 0, Some(SIGCHLD));
2150
2151 assert_eq!(
2153 wait_on_pid(
2154 locked,
2155 &task,
2156 &ProcessSelector::Any,
2157 &WaitingOptions::new_for_wait4(WNOHANG).expect("WaitingOptions")
2158 ),
2159 Ok(None)
2160 );
2161
2162 let thread = std::thread::spawn({
2163 let task = task.weak_task();
2164 move || {
2165 #[allow(
2167 clippy::undocumented_unsafe_blocks,
2168 reason = "Force documented unsafe blocks in Starnix"
2169 )]
2170 let locked = unsafe { Unlocked::new() };
2171 let task = task.upgrade().expect("task must be alive");
2172 let child: AutoReleasableTask = child.into();
2173 while !task.read().is_blocked() {
2175 std::thread::sleep(std::time::Duration::from_millis(10));
2176 }
2177 child.thread_group().exit(locked, ExitStatus::Exit(0), None);
2178 child.tid
2179 }
2180 });
2181
2182 let waited_child = wait_on_pid(
2184 locked,
2185 &task,
2186 &ProcessSelector::Any,
2187 &WaitingOptions::new_for_wait4(0).expect("WaitingOptions"),
2188 )
2189 .expect("wait_on_pid")
2190 .unwrap();
2191
2192 let child_id = thread.join().expect("join");
2194 assert_eq!(waited_child.pid, child_id);
2195 })
2196 .await;
2197 }
2198
2199 #[::fuchsia::test]
2200 async fn test_waiting_for_child_with_signal_pending() {
2201 spawn_kernel_and_run(async |locked, task| {
2202 task.thread_group().signal_actions.set(
2204 SIGUSR1,
2205 sigaction_t { sa_handler: uaddr { addr: 0xDEADBEEF }, ..sigaction_t::default() },
2206 );
2207
2208 let _child = task.clone_task_for_test(locked, 0, Some(SIGCHLD));
2210
2211 send_standard_signal(locked, &task, SignalInfo::kernel(SIGUSR1));
2214
2215 let errno = wait_on_pid(
2216 locked,
2217 &task,
2218 &ProcessSelector::Any,
2219 &WaitingOptions::new_for_wait4(0).expect("WaitingOptions"),
2220 )
2221 .expect_err("wait_on_pid");
2222 assert_eq!(errno, ERESTARTSYS);
2223 })
2224 .await;
2225 }
2226
2227 #[::fuchsia::test]
2228 async fn test_sigkill() {
2229 spawn_kernel_and_run(async |locked, current_task| {
2230 let mut child = current_task.clone_task_for_test(locked, 0, Some(SIGCHLD));
2231
2232 send_standard_signal(locked, &child, SignalInfo::kernel(SIGKILL));
2234 dequeue_signal_for_test(locked, &mut child);
2235 std::mem::drop(child);
2236
2237 let address = map_memory(
2239 locked,
2240 ¤t_task,
2241 UserAddress::default(),
2242 std::mem::size_of::<i32>() as u64,
2243 );
2244 let address_ref = UserRef::<i32>::new(address);
2245 sys_wait4(locked, ¤t_task, -1, address_ref, 0, RUsagePtr::null(current_task))
2246 .expect("wait4");
2247 let wstatus = current_task.read_object(address_ref).expect("read memory");
2248 assert_eq!(wstatus, SIGKILL.number() as i32);
2249 })
2250 .await;
2251 }
2252
2253 async fn test_exit_status_for_signal(
2254 sig: Signal,
2255 wait_status: i32,
2256 exit_signal: Option<Signal>,
2257 ) {
2258 spawn_kernel_and_run(async move |locked, current_task| {
2259 let mut child = current_task.clone_task_for_test(locked, 0, exit_signal);
2260
2261 send_standard_signal(locked, &child, SignalInfo::kernel(sig));
2263 dequeue_signal_for_test(locked, &mut child);
2264 std::mem::drop(child);
2265
2266 let address = map_memory(
2268 locked,
2269 ¤t_task,
2270 UserAddress::default(),
2271 std::mem::size_of::<i32>() as u64,
2272 );
2273 let address_ref = UserRef::<i32>::new(address);
2274 sys_wait4(locked, ¤t_task, -1, address_ref, 0, RUsagePtr::null(current_task))
2275 .expect("wait4");
2276 let wstatus = current_task.read_object(address_ref).expect("read memory");
2277 assert_eq!(wstatus, wait_status);
2278 })
2279 .await;
2280 }
2281
2282 #[::fuchsia::test]
2283 async fn test_exit_status() {
2284 test_exit_status_for_signal(SIGTERM, SIGTERM.number() as i32, Some(SIGCHLD)).await;
2286 test_exit_status_for_signal(SIGSEGV, (SIGSEGV.number() as i32) | 0x80, Some(SIGCHLD)).await;
2288 }
2289
2290 #[::fuchsia::test]
2291 async fn test_wait4_by_pgid() {
2292 spawn_kernel_and_run(async |locked, current_task| {
2293 let child1 = current_task.clone_task_for_test(locked, 0, Some(SIGCHLD));
2294 let child1_pid = child1.tid;
2295 child1.thread_group().exit(locked, ExitStatus::Exit(42), None);
2296 std::mem::drop(child1);
2297 let child2 = current_task.clone_task_for_test(locked, 0, Some(SIGCHLD));
2298 child2.thread_group().setsid(locked).expect("setsid");
2299 let child2_pid = child2.tid;
2300 child2.thread_group().exit(locked, ExitStatus::Exit(42), None);
2301 std::mem::drop(child2);
2302
2303 assert_eq!(
2304 sys_wait4(
2305 locked,
2306 ¤t_task,
2307 -child2_pid,
2308 UserRef::default(),
2309 0,
2310 RUsagePtr::null(current_task)
2311 ),
2312 Ok(child2_pid)
2313 );
2314 assert_eq!(
2315 sys_wait4(
2316 locked,
2317 ¤t_task,
2318 0,
2319 UserRef::default(),
2320 0,
2321 RUsagePtr::null(current_task)
2322 ),
2323 Ok(child1_pid)
2324 );
2325 })
2326 .await;
2327 }
2328
2329 #[::fuchsia::test]
2330 async fn test_waitid_by_pgid() {
2331 spawn_kernel_and_run(async |locked, current_task| {
2332 let child1 = current_task.clone_task_for_test(locked, 0, Some(SIGCHLD));
2333 let child1_pid = child1.tid;
2334 child1.thread_group().exit(locked, ExitStatus::Exit(42), None);
2335 std::mem::drop(child1);
2336 let child2 = current_task.clone_task_for_test(locked, 0, Some(SIGCHLD));
2337 child2.thread_group().setsid(locked).expect("setsid");
2338 let child2_pid = child2.tid;
2339 child2.thread_group().exit(locked, ExitStatus::Exit(42), None);
2340 std::mem::drop(child2);
2341
2342 let address: UserRef<uapi::siginfo_t> =
2343 map_memory(locked, ¤t_task, UserAddress::default(), *PAGE_SIZE).into();
2344 assert_eq!(
2345 sys_waitid(
2346 locked,
2347 ¤t_task,
2348 P_PGID,
2349 child2_pid,
2350 address.into(),
2351 WEXITED,
2352 UserRef::default().into()
2353 ),
2354 Ok(())
2355 );
2356 assert_eq!(current_task.thread_group().read().zombie_children[0].pid(), child1_pid);
2358
2359 assert_eq!(
2360 sys_waitid(
2361 locked,
2362 ¤t_task,
2363 P_PGID,
2364 0,
2365 address.into(),
2366 WEXITED,
2367 UserRef::default().into()
2368 ),
2369 Ok(())
2370 );
2371 })
2372 .await;
2373 }
2374
2375 #[::fuchsia::test]
2376 async fn test_sigqueue() {
2377 spawn_kernel_and_run(async |locked, current_task| {
2378 let current_uid = current_task.current_creds().uid;
2379 let current_pid = current_task.get_pid();
2380
2381 const TEST_VALUE: u64 = 101;
2382
2383 const ARCH64_SI_HEADER_SIZE: usize = SI_HEADER_SIZE + 4;
2385 const PID_DATA_OFFSET: usize = ARCH64_SI_HEADER_SIZE;
2387 const UID_DATA_OFFSET: usize = ARCH64_SI_HEADER_SIZE + 4;
2388 const VALUE_DATA_OFFSET: usize = ARCH64_SI_HEADER_SIZE + 8;
2389
2390 let mut data = vec![0u8; SI_MAX_SIZE_AS_USIZE];
2391 let header = SignalInfoHeader {
2392 signo: SIGIO.number(),
2393 code: SI_QUEUE,
2394 ..SignalInfoHeader::default()
2395 };
2396 let _ = header.write_to(&mut data[..SI_HEADER_SIZE]);
2397 data[PID_DATA_OFFSET..PID_DATA_OFFSET + 4].copy_from_slice(¤t_pid.to_ne_bytes());
2398 data[UID_DATA_OFFSET..UID_DATA_OFFSET + 4].copy_from_slice(¤t_uid.to_ne_bytes());
2399 data[VALUE_DATA_OFFSET..VALUE_DATA_OFFSET + 8]
2400 .copy_from_slice(&TEST_VALUE.to_ne_bytes());
2401
2402 let addr = map_memory(locked, ¤t_task, UserAddress::default(), *PAGE_SIZE);
2403 current_task.write_memory(addr, &data).unwrap();
2404 let second_current = create_task(locked, current_task.kernel(), "second task");
2405 let second_pid = second_current.get_pid();
2406 let second_tid = second_current.get_tid();
2407 assert_eq!(second_current.read().queued_signal_count(SIGIO), 0);
2408
2409 assert_eq!(
2410 sys_rt_tgsigqueueinfo(
2411 locked,
2412 ¤t_task,
2413 second_pid,
2414 second_tid,
2415 UncheckedSignal::from(SIGIO),
2416 addr
2417 ),
2418 Ok(())
2419 );
2420 assert_eq!(second_current.read().queued_signal_count(SIGIO), 1);
2421
2422 let signal = SignalInfo::with_detail(
2423 SIGIO,
2424 SI_QUEUE,
2425 SignalDetail::Kill {
2426 pid: current_task.thread_group().leader,
2427 uid: current_task.current_creds().uid,
2428 },
2429 );
2430 let queued_signal = second_current.write().take_specific_signal(signal);
2431 if let Some(sig) = queued_signal {
2432 assert_eq!(sig.signal, SIGIO);
2433 assert_eq!(sig.errno, 0);
2434 assert_eq!(sig.code, SI_QUEUE);
2435 if let SignalDetail::Raw { data } = sig.detail {
2436 let offset_pid = PID_DATA_OFFSET - SI_HEADER_SIZE;
2438 let offset_uid = UID_DATA_OFFSET - SI_HEADER_SIZE;
2439 let offset_value = VALUE_DATA_OFFSET - SI_HEADER_SIZE;
2440 let pid =
2441 pid_t::from_ne_bytes(data[offset_pid..offset_pid + 4].try_into().unwrap());
2442 let uid =
2443 uid_t::from_ne_bytes(data[offset_uid..offset_uid + 4].try_into().unwrap());
2444 let value = u64::from_ne_bytes(
2445 data[offset_value..offset_value + 8].try_into().unwrap(),
2446 );
2447 assert_eq!(pid, current_pid);
2448 assert_eq!(uid, current_uid);
2449 assert_eq!(value, TEST_VALUE);
2450 } else {
2451 panic!("incorrect signal detail");
2452 }
2453 } else {
2454 panic!("expected a queued signal");
2455 }
2456 })
2457 .await;
2458 }
2459
2460 #[::fuchsia::test]
2461 async fn test_signalfd_filters_signals() {
2462 spawn_kernel_and_run(async |locked, current_task| {
2463 let memory_for_masks =
2464 map_memory(locked, ¤t_task, UserAddress::default(), *PAGE_SIZE);
2465
2466 let term_int_mask = SigSet::from(SIGTERM) | SigSet::from(SIGINT);
2468 let term_int_mask_addr = UserRef::<SigSet>::new(memory_for_masks);
2469 current_task
2470 .write_object(term_int_mask_addr, &term_int_mask)
2471 .expect("failed to write mask");
2472 let sfd_term_int = sys_signalfd4(
2473 locked,
2474 ¤t_task,
2475 FdNumber::from_raw(-1),
2476 term_int_mask_addr,
2477 std::mem::size_of::<SigSet>(),
2478 0,
2479 )
2480 .expect("failed to create SIGTERM/SIGINT signalfd");
2481
2482 let sigchld_mask = SigSet::from(SIGCHLD);
2484 let sigchld_mask_addr =
2485 UserRef::<SigSet>::new((memory_for_masks + std::mem::size_of::<SigSet>()).unwrap());
2486 current_task
2487 .write_object(sigchld_mask_addr, &sigchld_mask)
2488 .expect("failed to write mask");
2489 let sfd_chld = sys_signalfd4(
2490 locked,
2491 ¤t_task,
2492 FdNumber::from_raw(-1),
2493 sigchld_mask_addr,
2494 std::mem::size_of::<SigSet>(),
2495 0,
2496 )
2497 .expect("failed to create SIGCHLD signalfd");
2498
2499 let child = current_task.clone_task_for_test(locked, 0, Some(SIGCHLD));
2501 child.thread_group().exit(locked, ExitStatus::Exit(1), None);
2502 std::mem::drop(child);
2503
2504 let sfd_term_int_file = current_task
2506 .live()
2507 .files
2508 .get(sfd_term_int)
2509 .expect("failed to get sfd_term_int file");
2510 let sfd_chld_file =
2511 current_task.get_file(sfd_chld).expect("failed to get sfd_chld file");
2512
2513 let term_int_events = sfd_term_int_file
2514 .query_events(locked, ¤t_task)
2515 .expect("failed to query sfd_term_int events");
2516 let chld_events = sfd_chld_file
2517 .query_events(locked, ¤t_task)
2518 .expect("failed to query sfd_chld events");
2519
2520 assert!(!term_int_events.contains(FdEvents::POLLIN));
2521 assert!(chld_events.contains(FdEvents::POLLIN));
2522 })
2523 .await;
2524 }
2525
2526 #[::fuchsia::test]
2527 async fn test_signalfd_filters_signals_async() {
2528 spawn_kernel_and_run(async |locked, current_task| {
2529 let memory_for_masks =
2530 map_memory(locked, ¤t_task, UserAddress::default(), *PAGE_SIZE);
2531
2532 let term_int_mask = SigSet::from(SIGTERM) | SigSet::from(SIGINT);
2534 let term_int_mask_addr = UserRef::<SigSet>::new(memory_for_masks);
2535 current_task
2536 .write_object(term_int_mask_addr, &term_int_mask)
2537 .expect("failed to write mask");
2538 let sfd_term_int = sys_signalfd4(
2539 locked,
2540 ¤t_task,
2541 FdNumber::from_raw(-1),
2542 term_int_mask_addr,
2543 std::mem::size_of::<SigSet>(),
2544 0,
2545 )
2546 .expect("failed to create SIGTERM/SIGINT signalfd");
2547
2548 let sigchld_mask = SigSet::from(SIGCHLD);
2550 let sigchld_mask_addr =
2551 UserRef::<SigSet>::new((memory_for_masks + std::mem::size_of::<SigSet>()).unwrap());
2552 current_task
2553 .write_object(sigchld_mask_addr, &sigchld_mask)
2554 .expect("failed to write mask");
2555 let sfd_chld = sys_signalfd4(
2556 locked,
2557 ¤t_task,
2558 FdNumber::from_raw(-1),
2559 sigchld_mask_addr,
2560 std::mem::size_of::<SigSet>(),
2561 0,
2562 )
2563 .expect("failed to create SIGCHLD signalfd");
2564
2565 let waiter = Waiter::new();
2567 let ready_items = Arc::new(Mutex::new(VecDeque::new()));
2568
2569 let sfd_term_int_file = current_task
2570 .live()
2571 .files
2572 .get(sfd_term_int)
2573 .expect("failed to get sfd_term_int file");
2574 let sfd_chld_file =
2575 current_task.get_file(sfd_chld).expect("failed to get sfd_chld file");
2576
2577 sfd_term_int_file
2578 .wait_async(
2579 locked,
2580 ¤t_task,
2581 &waiter,
2582 FdEvents::POLLIN,
2583 EventHandler::Enqueue {
2584 key: sfd_term_int.into(),
2585 queue: ready_items.clone(),
2586 sought_events: FdEvents::POLLIN,
2587 },
2588 )
2589 .expect("failed to wait on sfd_term_int");
2590
2591 sfd_chld_file
2592 .wait_async(
2593 locked,
2594 ¤t_task,
2595 &waiter,
2596 FdEvents::POLLIN,
2597 EventHandler::Enqueue {
2598 key: sfd_chld.into(),
2599 queue: ready_items.clone(),
2600 sought_events: FdEvents::POLLIN,
2601 },
2602 )
2603 .expect("failed to wait on sfd_chld");
2604
2605 let sigchld_mask_ref = UserRef::<SigSet>::new(memory_for_masks);
2607 current_task
2608 .write_object(sigchld_mask_ref, &sigchld_mask)
2609 .expect("failed to write mask");
2610 sys_rt_sigprocmask(
2611 locked,
2612 ¤t_task,
2613 SIG_BLOCK,
2614 sigchld_mask_ref,
2615 UserRef::default(),
2616 std::mem::size_of::<SigSet>(),
2617 )
2618 .expect("failed to block SIGCHLD");
2619
2620 let child = current_task.clone_task_for_test(locked, 0, Some(SIGCHLD));
2622 child.thread_group().exit(locked, ExitStatus::Exit(1), None);
2623 std::mem::drop(child);
2624
2625 waiter.wait(locked, ¤t_task).expect("failed to wait");
2627
2628 let ready_items = ready_items.lock();
2630 assert_eq!(ready_items.len(), 1);
2631 assert_eq!(ready_items[0].key, sfd_chld.into());
2632 })
2633 .await;
2634 }
2635}