1pub use super::signal_handling::sys_restart_syscall;
6use super::signalfd::SignalFd;
7use crate::mm::MemoryAccessorExt;
8use crate::security;
9use crate::signals::{
10 IntoSignalInfoOptions, SignalDetail, SignalInfo, UncheckedSignalInfo,
11 restore_from_signal_handler, send_signal,
12};
13use crate::task::{
14 CurrentTask, Pid, ProcessEntryRef, ProcessSelector, Task, TaskMutableState, ThreadGroup,
15 ThreadGroupLifecycleWaitValue, WaitResult, WaitableChildResult, Waiter,
16};
17use crate::vfs::{FdFlags, FdNumber};
18use fuchsia_rcu::RcuReadScope;
19use starnix_uapi::user_address::{ArchSpecific, MultiArchUserRef};
20use starnix_uapi::{tid_t, uapi};
21
22use starnix_logging::track_stub;
23use starnix_sync::InterruptibleEvent;
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 current_task: &CurrentTask,
59 signum: UncheckedSignal,
60 user_action: SigAction64Ptr,
61 user_old_action: SigAction64Ptr,
62 sigset_size: usize,
63) -> Result<(), Errno> {
64 if user_action.is_arch32() && sigset_size == std::mem::size_of::<uapi::arch32::sigset_t>() {
65 let user_action = SigActionPtr::from_32(user_action.addr().into());
66 let user_old_action = SigActionPtr::from_32(user_old_action.addr().into());
67 return rt_sigaction(current_task, signum, user_action, user_old_action);
68 }
69
70 if sigset_size != std::mem::size_of::<uapi::sigset_t>() {
71 return error!(EINVAL);
72 }
73 rt_sigaction(current_task, signum, user_action, user_old_action)
74}
75
76fn rt_sigaction<Arch32SigAction>(
77 current_task: &CurrentTask,
78 signum: UncheckedSignal,
79 user_action: MultiArchUserRef<uapi::sigaction_t, Arch32SigAction>,
80 user_old_action: MultiArchUserRef<uapi::sigaction_t, Arch32SigAction>,
81) -> Result<(), Errno>
82where
83 Arch32SigAction:
84 IntoBytes + FromBytes + Immutable + TryFrom<uapi::sigaction_t> + TryInto<uapi::sigaction_t>,
85{
86 let signal = Signal::try_from(signum)?;
87
88 let new_signal_action = if !user_action.is_null() {
89 if signal.is_unblockable() {
93 return error!(EINVAL);
94 }
95
96 let signal_action = current_task.read_multi_arch_object(user_action)?;
97 Some(signal_action)
98 } else {
99 None
100 };
101
102 let signal_actions = ¤t_task.thread_group().signal_actions;
103 let old_action = if let Some(new_signal_action) = new_signal_action {
104 signal_actions.set(signal, new_signal_action)
105 } else {
106 signal_actions.get(signal)
107 };
108
109 if !user_old_action.is_null() {
110 current_task.write_multi_arch_object(user_old_action, old_action)?;
111 }
112
113 Ok(())
114}
115
116pub fn sys_rt_sigpending(
126 current_task: &CurrentTask,
127 set: UserRef<SigSet>,
128 sigset_size: usize,
129) -> Result<(), Errno> {
130 if sigset_size != std::mem::size_of::<SigSet>() {
131 return error!(EINVAL);
132 }
133
134 let signals = current_task.read().pending_signals();
135 current_task.write_object(set, &signals)?;
136 Ok(())
137}
138
139pub fn sys_rt_sigprocmask(
152 current_task: &CurrentTask,
153 how: u32,
154 user_set: UserRef<SigSet>,
155 user_old_set: UserRef<SigSet>,
156 sigset_size: usize,
157) -> Result<(), Errno> {
158 if sigset_size != std::mem::size_of::<SigSet>() {
159 return error!(EINVAL);
160 }
161 match how {
162 SIG_BLOCK | SIG_UNBLOCK | SIG_SETMASK => (),
163 _ => return error!(EINVAL),
164 };
165
166 let mut new_mask = SigSet::default();
169 if !user_set.is_null() {
170 new_mask = current_task.read_object(user_set)?;
171 }
172
173 let mut state = current_task.write();
174 let signal_mask = state.signal_mask();
175 if !user_old_set.is_null() {
177 current_task.write_object(user_old_set, &signal_mask)?;
178 }
179
180 if user_set.is_null() {
182 return Ok(());
183 }
184
185 let signal_mask = match how {
186 SIG_BLOCK => signal_mask | new_mask,
187 SIG_UNBLOCK => signal_mask & !new_mask,
188 SIG_SETMASK => new_mask,
189 _ => return error!(EINVAL),
191 };
192 state.set_signal_mask(signal_mask);
193
194 Ok(())
195}
196
197type SigAltStackPtr = MultiArchUserRef<uapi::sigaltstack, uapi::arch32::sigaltstack>;
198
199pub fn sys_sigaltstack(
208 current_task: &CurrentTask,
209 user_ss: SigAltStackPtr,
210 user_old_ss: SigAltStackPtr,
211) -> Result<(), Errno> {
212 let stack_pointer_register = current_task.thread_state.registers.stack_pointer_register();
213 let mut state = current_task.write();
214 let on_signal_stack = state.on_signal_stack(stack_pointer_register);
215
216 let mut ss = sigaltstack::default();
217 if !user_ss.is_null() {
218 if on_signal_stack {
219 return error!(EPERM);
220 }
221 ss = current_task.read_multi_arch_object(user_ss)?;
222 if (ss.ss_flags & !((SS_AUTODISARM | SS_DISABLE) as i32)) != 0 {
223 return error!(EINVAL);
224 }
225 let min_stack_size =
226 if current_task.is_arch32() { uapi::arch32::MINSIGSTKSZ } else { uapi::MINSIGSTKSZ };
227 if ss.ss_flags & (SS_DISABLE as i32) == 0 && ss.ss_size < min_stack_size as u64 {
228 return error!(ENOMEM);
229 }
230 }
231
232 if !user_old_ss.is_null() {
233 let mut old_ss = match state.sigaltstack() {
234 Some(old_ss) => old_ss,
235 None => sigaltstack { ss_flags: SS_DISABLE as i32, ..sigaltstack::default() },
236 };
237 if on_signal_stack {
238 old_ss.ss_flags = SS_ONSTACK as i32;
239 }
240 current_task.write_multi_arch_object(user_old_ss, old_ss)?;
241 }
242
243 if !user_ss.is_null() {
244 if ss.ss_flags & (SS_DISABLE as i32) != 0 {
245 state.set_sigaltstack(None);
246 } else {
247 state.set_sigaltstack(Some(ss));
248 }
249 }
250
251 Ok(())
252}
253
254pub fn sys_rt_sigsuspend(
266 current_task: &mut CurrentTask,
267 user_mask: UserRef<SigSet>,
268 sigset_size: usize,
269) -> Result<(), Errno> {
270 if sigset_size != std::mem::size_of::<SigSet>() {
271 return error!(EINVAL);
272 }
273 let mask = current_task.read_object(user_mask)?;
274
275 let waiter = Waiter::new();
276 current_task
280 .wait_with_temporary_mask(mask, |current_task| waiter.wait(current_task))
281 .map_eintr(|| errno!(ERESTARTNOHAND))
282}
283
284pub fn sys_rt_sigtimedwait(
297 current_task: &mut CurrentTask,
298 set_addr: UserRef<SigSet>,
299 siginfo_addr: MultiArchUserRef<uapi::siginfo_t, uapi::arch32::siginfo_t>,
300 timeout_addr: MultiArchUserRef<uapi::timespec, uapi::arch32::timespec>,
301 sigset_size: usize,
302) -> Result<Signal, Errno> {
303 if sigset_size != std::mem::size_of::<SigSet>() {
304 return error!(EINVAL);
305 }
306
307 let set = current_task.read_object(set_addr)?;
309 let unblock = set & !UNBLOCKABLE_SIGNALS;
311 let deadline = if timeout_addr.is_null() {
312 zx::MonotonicInstant::INFINITE
313 } else {
314 let timeout = current_task.read_multi_arch_object(timeout_addr)?;
315 zx::MonotonicInstant::after(duration_from_timespec(timeout)?)
316 };
317
318 let signal_info = loop {
319 let waiter;
320
321 {
322 let mut task_state = current_task.write();
323 if let Some(signal) = task_state.take_signal_with_mask(!unblock) {
326 break signal;
327 }
328
329 waiter = Waiter::new();
330 task_state.wait_on_signal(&waiter);
331 }
332
333 let tmp_mask = current_task.read().signal_mask() & !unblock;
336
337 let waiter_result = current_task.wait_with_temporary_mask(tmp_mask, |current_task| {
339 waiter.wait_until(current_task, deadline)
340 });
341
342 current_task.write().restore_signal_mask();
344
345 if let Err(e) = waiter_result {
346 if e == EINTR {
347 if let Some(signal) = current_task.write().take_signal_with_mask(!unblock) {
349 break signal;
350 }
351 } else if e == ETIMEDOUT {
352 return error!(EAGAIN);
353 }
354
355 return Err(e);
356 }
357 };
358
359 if !siginfo_addr.is_null() {
360 signal_info.write(current_task, siginfo_addr)?;
361 }
362
363 Ok(signal_info.signal)
364}
365
366pub fn sys_signalfd4(
380 current_task: &CurrentTask,
381 fd: FdNumber,
382 mask_addr: UserRef<SigSet>,
383 mask_size: usize,
384 flags: u32,
385) -> Result<FdNumber, Errno> {
386 if flags & !(SFD_CLOEXEC | SFD_NONBLOCK) != 0 {
387 return error!(EINVAL);
388 }
389 if mask_size != std::mem::size_of::<SigSet>() {
390 return error!(EINVAL);
391 }
392 let mask = current_task.read_object(mask_addr)?;
393
394 if fd.raw() != -1 {
395 let file = current_task.files().get(fd)?;
396 let file = file.downcast_file::<SignalFd>().ok_or_else(|| errno!(EINVAL))?;
397 file.set_mask(mask);
398 Ok(fd)
399 } else {
400 let signalfd = SignalFd::new_file(current_task, mask, flags);
401 let flags = if flags & SFD_CLOEXEC != 0 { FdFlags::CLOEXEC } else { FdFlags::empty() };
402 let fd = current_task.add_file(signalfd, flags)?;
403 Ok(fd)
404 }
405}
406
407#[track_caller]
408fn send_unchecked_signal(
409 current_task: &CurrentTask,
410 target: &Task,
411 unchecked_signal: UncheckedSignal,
412 si_code: i32,
413) -> Result<(), Errno> {
414 current_task.can_signal(&target, unchecked_signal)?;
415
416 if unchecked_signal.is_zero() {
418 return Ok(());
419 }
420
421 let signal = Signal::try_from(unchecked_signal)?;
422 security::check_signal_access(current_task, &target, signal)?;
423
424 send_signal(
425 target,
426 SignalInfo::with_sender(
427 signal,
428 si_code,
429 SignalDetail::Kill {
430 pid: current_task.pid.clone(),
431 uid: current_task.current_creds().uid,
432 },
433 Some(current_task.weak_self.clone()),
434 ),
435 )
436}
437
438#[track_caller]
442fn send_unchecked_signal_info(
443 current_task: &CurrentTask,
444 target: &Task,
445 unchecked_signal: UncheckedSignal,
446 siginfo: UncheckedSignalInfo,
447) -> Result<(), Errno> {
448 current_task.can_signal(&target, unchecked_signal)?;
449
450 if unchecked_signal.is_zero() {
452 return Ok(());
453 }
454
455 let signal = Signal::try_from(unchecked_signal)?;
456 security::check_signal_access(current_task, &target, signal)?;
457
458 send_signal(&target, siginfo.into_signal_info(signal, IntoSignalInfoOptions::None)?)
459}
460
461pub fn sys_kill(
470 current_task: &CurrentTask,
471 pid: pid_t,
472 unchecked_signal: UncheckedSignal,
473) -> Result<(), Errno> {
474 let pids = ¤t_task.kernel().pids;
475 match pid {
476 pid if pid > 0 => {
477 let target_thread_group = {
480 let pid_entry = pids.get(pid)?;
481 match pid_entry.get_process() {
482 Some(ProcessEntryRef::Process(process)) => process,
483
484 Some(ProcessEntryRef::Zombie) => return Ok(()),
486
487 None => {
490 let task = pid_entry.get_task()?;
491 task.thread_group().clone()
492 }
493 }
494 };
495
496 target_thread_group.send_signal_unchecked(current_task, unchecked_signal)?;
497 }
498 pid if pid == -1 => {
499 let thread_groups: Vec<_> = pids
508 .get_thread_groups(&RcuReadScope::new())
509 .filter(|thread_group| {
510 if *current_task.thread_group() == *thread_group {
511 return false;
512 }
513 if thread_group.leader.id == 1 {
514 return false;
515 }
516 true
517 })
518 .collect();
519 signal_thread_groups(current_task, unchecked_signal, thread_groups)?;
520 }
521 _ => {
522 let pid = match pid {
528 0 => current_task.thread_group().pgid(),
529 _ => pids.get(negate_pid(pid)?)?,
530 };
531
532 let scope = RcuReadScope::new();
533 signal_thread_groups(current_task, unchecked_signal, pid.pgid_thread_groups(&scope))?;
534 }
535 };
536
537 Ok(())
538}
539
540fn verify_tgid_for_task(task: &Task, tgid: &Pid) -> Result<(), Errno> {
541 if &task.pid != tgid {
542 return error!(EINVAL);
543 } else {
544 Ok(())
545 }
546}
547
548pub fn sys_tkill(
560 current_task: &CurrentTask,
561 tid: tid_t,
562 unchecked_signal: UncheckedSignal,
563) -> Result<(), Errno> {
564 if tid <= 0 {
566 return error!(EINVAL);
567 }
568 let thread = current_task.get_task(tid)?;
569 send_unchecked_signal(current_task, &thread, unchecked_signal, SI_TKILL)
570}
571
572pub fn sys_tgkill(
583 current_task: &CurrentTask,
584 tgid: pid_t,
585 tid: tid_t,
586 unchecked_signal: UncheckedSignal,
587) -> Result<(), Errno> {
588 if tgid <= 0 || tid <= 0 {
590 return error!(EINVAL);
591 }
592 let pids = ¤t_task.kernel().pids;
593 let tid = pids.get(tid)?;
594 let tgid = pids.get(tgid)?;
595 let thread = tid.get_task()?;
596 verify_tgid_for_task(&thread, &tgid)?;
597 send_unchecked_signal(current_task, &thread, unchecked_signal, SI_TKILL)
598}
599
600pub fn sys_rt_sigreturn(current_task: &mut CurrentTask) -> Result<SyscallResult, Errno> {
609 restore_from_signal_handler(current_task)?;
610 Ok(current_task.thread_state.registers.return_register().into())
611}
612
613pub fn sys_rt_sigqueueinfo(
623 current_task: &CurrentTask,
624 tgid: pid_t,
625 unchecked_signal: UncheckedSignal,
626 siginfo_ref: UserAddress,
627) -> Result<(), Errno> {
628 let siginfo = UncheckedSignalInfo::read_from_siginfo(current_task, siginfo_ref)?;
629 if tgid != current_task.get_pid() {
630 siginfo.check_code()?;
631 }
632
633 let target_thread_group = {
634 let pid_entry = current_task.kernel().pids.get(tgid)?;
635 match pid_entry.get_process() {
636 Some(ProcessEntryRef::Process(process)) => process,
637 Some(ProcessEntryRef::Zombie) => return Ok(()),
638 None => {
639 let task = pid_entry.get_task()?;
640 task.thread_group().clone()
641 }
642 }
643 };
644 target_thread_group.send_signal_unchecked_with_info(
645 current_task,
646 unchecked_signal,
647 siginfo,
648 IntoSignalInfoOptions::None,
649 )
650}
651
652pub fn sys_rt_tgsigqueueinfo(
663 current_task: &CurrentTask,
664 tgid: pid_t,
665 tid: tid_t,
666 unchecked_signal: UncheckedSignal,
667 siginfo_ref: UserAddress,
668) -> Result<(), Errno> {
669 let siginfo = UncheckedSignalInfo::read_from_siginfo(current_task, siginfo_ref)?;
670 if tgid <= 0 || tid <= 0 {
672 return error!(EINVAL);
673 }
674 if tid != current_task.get_tid() {
677 siginfo.check_code()?;
678 }
679
680 let pids = ¤t_task.kernel().pids;
681
682 let task = pids.get(tid)?.get_task()?;
683 let tgid_entry = pids.get(tgid)?;
684 verify_tgid_for_task(&task, &tgid_entry)?;
685 send_unchecked_signal_info(current_task, &task, unchecked_signal, siginfo)
686}
687
688pub fn sys_pause(current_task: &CurrentTask) -> Result<(), Errno> {
693 let event = InterruptibleEvent::default();
694 let guard = event.begin_wait();
695 let result = current_task.block_until(guard, zx::MonotonicInstant::INFINITE);
696 result.map_eintr(|| errno!(ERESTARTNOHAND))
698}
699
700pub fn sys_pidfd_send_signal(
713 current_task: &CurrentTask,
714 pidfd: FdNumber,
715 unchecked_signal: UncheckedSignal,
716 siginfo_ref: UserAddress,
717 flags: u32,
718) -> Result<(), Errno> {
719 if flags != 0 {
720 return error!(EINVAL);
721 }
722
723 let file = current_task.files().get(pidfd)?;
724 let target = file.as_pid()?.get_thread_group()?;
725
726 if siginfo_ref.is_null() {
727 target.send_signal_unchecked(current_task, unchecked_signal)
728 } else {
729 let siginfo = UncheckedSignalInfo::read_from_siginfo(current_task, siginfo_ref)?;
730 if target.leader.id != current_task.get_pid() {
731 siginfo.check_code()?;
732 }
733 target.send_signal_unchecked_with_info(
734 current_task,
735 unchecked_signal,
736 siginfo,
737 IntoSignalInfoOptions::CheckSigno,
738 )
739 }
740}
741
742#[track_caller]
753fn signal_thread_groups<F>(
754 current_task: &CurrentTask,
755 unchecked_signal: UncheckedSignal,
756 thread_groups: F,
757) -> Result<(), Errno>
758where
759 F: IntoIterator<Item: AsRef<ThreadGroup>>,
760{
761 let mut last_error = None;
762 let mut sent_signal = false;
763
764 for thread_group in thread_groups.into_iter() {
767 match thread_group.as_ref().send_signal_unchecked(current_task, unchecked_signal) {
768 Ok(_) => sent_signal = true,
769 Err(errno) => last_error = Some(errno),
770 }
771 }
772
773 if sent_signal { Ok(()) } else { Err(last_error.unwrap_or_else(|| errno!(ESRCH))) }
774}
775
776#[derive(Debug)]
778pub struct WaitingOptions {
779 pub wait_for_exited: bool,
781 pub wait_for_stopped: bool,
783 pub wait_for_continued: bool,
785 pub wnohang: bool,
787 pub block: bool,
789 pub keep_waitable_state: bool,
791 pub wait_for_all: bool,
793 pub wait_for_clone: bool,
795}
796
797impl WaitingOptions {
798 fn new(options: u32) -> Self {
799 const_assert_eq!(WUNTRACED, WSTOPPED);
800 if options & __WNOTHREAD != 0 {
801 track_stub!(TODO("https://fxbug.dev/509926462"), "wait options wnothread");
802 }
803 Self {
804 wait_for_exited: options & WEXITED > 0,
805 wait_for_stopped: options & WSTOPPED > 0,
806 wait_for_continued: options & WCONTINUED > 0,
807 wnohang: options & WNOHANG > 0,
808 block: options & WNOHANG == 0,
809 keep_waitable_state: options & WNOWAIT > 0,
810 wait_for_all: options & __WALL > 0,
811 wait_for_clone: options & __WCLONE > 0,
812 }
813 }
814
815 pub fn new_for_waitid(options: u32) -> Result<Self, Errno> {
817 if options & !(__WCLONE | __WALL | WNOHANG | WNOWAIT | WSTOPPED | WEXITED | WCONTINUED) != 0
818 {
819 track_stub!(TODO("https://fxbug.dev/322874788"), "waitid options", options);
820 return error!(EINVAL);
821 }
822 if options & (WEXITED | WSTOPPED | WCONTINUED) == 0 {
823 return error!(EINVAL);
824 }
825 Ok(Self::new(options))
826 }
827
828 pub fn new_for_wait4(options: u32) -> Result<Self, Errno> {
830 if options & !(__WCLONE | __WNOTHREAD | __WALL | WNOHANG | WUNTRACED | WCONTINUED) != 0 {
831 track_stub!(TODO("https://fxbug.dev/322874017"), "wait4 options", options);
832 return error!(EINVAL);
833 }
834 Ok(Self::new(options | WEXITED))
835 }
836}
837
838fn wait_on_pid(
844 current_task: &CurrentTask,
845 selector: &ProcessSelector,
846 options: &WaitingOptions,
847) -> Result<Option<WaitResult>, Errno> {
848 let waiter = Waiter::new();
849 loop {
850 {
851 let mut pids = current_task.kernel().pids.lock();
852 if let Some(tracee) =
861 current_task.thread_group().get_waitable_ptracee(selector, options, &mut pids)
862 {
863 return Ok(Some(tracee));
864 }
865 let mut has_waitable_tracee = false;
866 let mut has_any_tracee = false;
867 current_task.thread_group().get_ptracees_and(
868 selector,
869 &mut |task: &Task, task_state: &TaskMutableState| {
870 if let Some(ptrace) = &task_state.ptrace {
871 has_any_tracee = true;
872 ptrace.tracer_waiters().wait_async(&waiter);
873 if ptrace.is_waitable(task.load_stopped(), options) {
874 has_waitable_tracee = true;
875 }
876 }
877 },
878 );
879 if has_waitable_tracee {
880 continue;
881 }
882
883 {
884 let mut thread_group = current_task.thread_group().write();
885
886 if thread_group.zombie_ptracees.has_zombie_matching(&selector) {
887 continue;
888 }
889 match thread_group.get_waitable_child(selector, options, &mut pids) {
890 WaitableChildResult::ReadyNow(child) => {
891 return Ok(Some(*child));
892 }
893 WaitableChildResult::ShouldWait => (),
894 WaitableChildResult::NoneFound => {
895 if !has_any_tracee {
896 return error!(ECHILD);
897 }
898 }
899 }
900 thread_group
901 .lifecycle_waiters
902 .wait_async_value(&waiter, ThreadGroupLifecycleWaitValue::ChildStatus);
903 }
904 }
905
906 if !options.block {
907 return Ok(None);
908 }
909 waiter.wait(current_task).map_eintr(|| errno!(ERESTARTSYS))?;
910 }
911}
912
913pub fn sys_waitid(
927 current_task: &CurrentTask,
928 id_type: u32,
929 id: i32,
930 user_info: MultiArchUserRef<uapi::siginfo_t, uapi::arch32::siginfo_t>,
931 options: u32,
932 user_rusage: RUsagePtr,
933) -> Result<(), Errno> {
934 let mut waiting_options = WaitingOptions::new_for_waitid(options)?;
935
936 let task_selector = match id_type {
937 P_PID => {
938 let pid = current_task.kernel().pids.get(id).map_err(|_| errno!(ECHILD))?;
939 ProcessSelector::Pid(pid)
940 }
941 P_ALL => ProcessSelector::Any,
942 P_PGID => {
943 let pid = if id == 0 {
944 current_task.thread_group().pgid()
945 } else {
946 current_task.kernel().pids.get(id).map_err(|_| errno!(ECHILD))?
947 };
948 ProcessSelector::Pgid(pid)
949 }
950 P_PIDFD => {
951 let fd = FdNumber::from_raw(id);
952 let file = current_task.files().get(fd)?;
953 if file.flags().contains(OpenFlags::NONBLOCK) {
954 waiting_options.block = false;
955 }
956 ProcessSelector::Pid(file.as_pid()?)
957 }
958 _ => return error!(EINVAL),
959 };
960
961 if let Some(waitable_process) = wait_on_pid(current_task, &task_selector, &waiting_options)? {
963 if !user_rusage.is_null() {
964 let usage = rusage {
965 ru_utime: timeval_from_duration(waitable_process.zombie_state.time_stats.user_time),
966 ru_stime: timeval_from_duration(
967 waitable_process.zombie_state.time_stats.system_time,
968 ),
969 ..Default::default()
970 };
971
972 track_stub!(TODO("https://fxbug.dev/322874712"), "real rusage from waitid");
973 current_task.write_multi_arch_object(user_rusage, usage)?;
974 }
975
976 if !user_info.is_null() {
977 let siginfo = waitable_process.as_signal_info();
978 siginfo.write(current_task, user_info)?;
979 }
980 } else if id_type == P_PIDFD && !waiting_options.wnohang {
981 return error!(EAGAIN);
990 } else {
991 if !user_rusage.is_null() {
994 current_task.write_multi_arch_object(user_rusage, rusage::default())?;
995 }
996
997 if !user_info.is_null() {
998 SignalInfo::zero(current_task, user_info)?;
999 }
1000 }
1001
1002 Ok(())
1003}
1004
1005pub fn sys_wait4(
1019 current_task: &CurrentTask,
1020 raw_selector: pid_t,
1021 user_wstatus: UserRef<i32>,
1022 options: u32,
1023 user_rusage: RUsagePtr,
1024) -> Result<pid_t, Errno> {
1025 let waiting_options = WaitingOptions::new_for_wait4(options)?;
1026
1027 let selector = if raw_selector == 0 {
1028 ProcessSelector::Pgid(current_task.thread_group().pgid())
1029 } else if raw_selector == -1 {
1030 ProcessSelector::Any
1031 } else if raw_selector > 0 {
1032 let pid = current_task.kernel().pids.get(raw_selector).map_err(|_| errno!(ECHILD))?;
1033 ProcessSelector::Pid(pid)
1034 } else if raw_selector < -1 {
1035 let pid = current_task
1036 .kernel()
1037 .pids
1038 .get(negate_pid(raw_selector)?)
1039 .map_err(|_| errno!(ECHILD))?;
1040 ProcessSelector::Pgid(pid)
1041 } else {
1042 track_stub!(
1043 TODO("https://fxbug.dev/322874213"),
1044 "wait4 with selector",
1045 raw_selector as u64
1046 );
1047 return error!(ENOSYS);
1048 };
1049
1050 if let Some(waitable_process) = wait_on_pid(current_task, &selector, &waiting_options)? {
1051 let status = waitable_process.zombie_state.exit_status.wait_status();
1052
1053 if !user_rusage.is_null() {
1054 track_stub!(TODO("https://fxbug.dev/322874768"), "real rusage from wait4");
1055 let usage = rusage {
1056 ru_utime: timeval_from_duration(waitable_process.zombie_state.time_stats.user_time),
1057 ru_stime: timeval_from_duration(
1058 waitable_process.zombie_state.time_stats.system_time,
1059 ),
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.id)
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_uapi::errors::Errno;
1086 use starnix_uapi::signals::SigSet;
1087 use starnix_uapi::user_address::UserRef;
1088
1089 pub fn sys_arch32_signalfd(
1104 current_task: &CurrentTask,
1105 fd: FdNumber,
1106 mask_addr: UserRef<SigSet>,
1107 mask_size: usize,
1108 ) -> Result<FdNumber, Errno> {
1109 super::sys_signalfd4(current_task, fd, mask_addr, mask_size, 0)
1110 }
1111
1112 pub use super::{
1113 sys_pidfd_send_signal as sys_arch32_pidfd_send_signal,
1114 sys_rt_sigaction as sys_arch32_rt_sigaction,
1115 sys_rt_sigqueueinfo as sys_arch32_rt_sigqueueinfo,
1116 sys_rt_sigtimedwait as sys_arch32_rt_sigtimedwait,
1117 sys_rt_tgsigqueueinfo as sys_arch32_rt_tgsigqueueinfo,
1118 sys_sigaltstack as sys_arch32_sigaltstack, sys_signalfd4 as sys_arch32_signalfd4,
1119 sys_waitid as sys_arch32_waitid,
1120 };
1121}
1122
1123#[cfg(target_arch = "aarch64")]
1124pub use arch32::*;
1125
1126#[cfg(test)]
1127mod tests {
1128 use super::*;
1129 use crate::mm::{MemoryAccessor, PAGE_SIZE};
1130 use crate::signals::testing::dequeue_signal_for_test;
1131 use crate::signals::{
1132 SI_HEADER_SIZE, SI_MAX_SIZE_AS_USIZE, SignalInfoHeader, send_standard_signal,
1133 };
1134 use crate::task::dynamic_thread_spawner::SpawnRequestBuilder;
1135 use crate::task::{EventHandler, ExitStatus, ZombieState};
1136 use crate::testing::*;
1137 use starnix_sync::{EventHandlerReadyQueueLock, LockDepMutex};
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, SIGWINCH,
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 |current_task| {
1155 let addr = map_memory(¤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(¤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(¤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(¤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(¤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(¤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 |current_task| {
1200 let addr = map_memory(¤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(¤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 =
1215 map_memory(¤t_task, UserAddress::default(), sigaltstack_addr_size as u64);
1216 ss.ss_sp = sigaltstack_addr.into();
1217 ss.ss_flags = 0;
1218 ss.ss_size = uapi::MINSIGSTKSZ as u64 - 1;
1219 current_task.write_object(user_ss, &ss).expect("failed to write struct");
1220 assert_eq!(
1221 sys_sigaltstack(¤t_task, user_ss.into(), nullptr.into()),
1222 error!(ENOMEM)
1223 );
1224 })
1225 .await;
1226 }
1227
1228 #[cfg(target_arch = "x86_64")]
1229 #[::fuchsia::test]
1230 async fn test_sigaltstack_active_stack() {
1231 spawn_kernel_and_run(async |current_task| {
1232 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1233
1234 let user_ss = UserRef::<sigaltstack>::new(addr);
1235 let nullptr = UserRef::<sigaltstack>::default();
1236
1237 sys_sigaltstack(¤t_task, nullptr.into(), user_ss.into())
1239 .expect("failed to call sigaltstack");
1240 let mut ss = current_task.read_object(user_ss).expect("failed to read struct");
1241 assert!(ss.ss_flags & (SS_DISABLE as i32) != 0);
1242
1243 let sigaltstack_addr_size = round_up_to_system_page_size(uapi::MINSIGSTKSZ as usize)
1245 .expect("failed to round up");
1246 let sigaltstack_addr =
1247 map_memory(¤t_task, UserAddress::default(), sigaltstack_addr_size as u64);
1248 ss.ss_sp = sigaltstack_addr.into();
1249 ss.ss_flags = 0;
1250 ss.ss_size = sigaltstack_addr_size as u64;
1251 current_task.write_object(user_ss, &ss).expect("failed to write struct");
1252 sys_sigaltstack(¤t_task, user_ss.into(), nullptr.into())
1253 .expect("failed to call sigaltstack");
1254
1255 let next_addr = (sigaltstack_addr + sigaltstack_addr_size).unwrap();
1257 current_task.thread_state.registers.rsp = next_addr.ptr() as u64;
1258 ss.ss_flags = SS_DISABLE as i32;
1259 current_task.write_object(user_ss, &ss).expect("failed to write struct");
1260 assert_eq!(
1261 sys_sigaltstack(¤t_task, user_ss.into(), nullptr.into()),
1262 error!(EPERM)
1263 );
1264
1265 let next_ss_addr = sigaltstack_addr
1268 .checked_add(sigaltstack_addr_size)
1269 .unwrap()
1270 .checked_add(0x1000usize)
1271 .unwrap();
1272 current_task.thread_state.registers.rsp = next_ss_addr.ptr() as u64;
1273 let ss = sigaltstack { ss_flags: SS_DISABLE as i32, ..sigaltstack::default() };
1274 current_task.write_object(user_ss, &ss).expect("failed to write struct");
1275 sys_sigaltstack(¤t_task, user_ss.into(), nullptr.into())
1276 .expect("failed to call sigaltstack");
1277 })
1278 .await;
1279 }
1280
1281 #[cfg(target_arch = "x86_64")]
1282 #[::fuchsia::test]
1283 async fn test_sigaltstack_active_stack_saturates() {
1284 spawn_kernel_and_run(async |current_task| {
1285 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1286
1287 let user_ss = UserRef::<sigaltstack>::new(addr);
1288 let nullptr = UserRef::<sigaltstack>::default();
1289
1290 sys_sigaltstack(¤t_task, nullptr.into(), user_ss.into())
1292 .expect("failed to call sigaltstack");
1293 let mut ss = current_task.read_object(user_ss).expect("failed to read struct");
1294 assert!(ss.ss_flags & (SS_DISABLE as i32) != 0);
1295
1296 let sigaltstack_addr_size = round_up_to_system_page_size(uapi::MINSIGSTKSZ as usize)
1298 .expect("failed to round up");
1299 let sigaltstack_addr =
1300 map_memory(¤t_task, UserAddress::default(), sigaltstack_addr_size as u64);
1301 ss.ss_sp = sigaltstack_addr.into();
1302 ss.ss_flags = 0;
1303 ss.ss_size = u64::MAX;
1304 current_task.write_object(user_ss, &ss).expect("failed to write struct");
1305 sys_sigaltstack(¤t_task, user_ss.into(), nullptr.into())
1306 .expect("failed to call sigaltstack");
1307
1308 current_task.thread_state.registers.rsp =
1310 (sigaltstack_addr + sigaltstack_addr_size).unwrap().ptr() as u64;
1311 ss.ss_flags = SS_DISABLE as i32;
1312 current_task.write_object(user_ss, &ss).expect("failed to write struct");
1313 assert_eq!(
1314 sys_sigaltstack(¤t_task, user_ss.into(), nullptr.into()),
1315 error!(EPERM)
1316 );
1317
1318 current_task.thread_state.registers.rsp = 0u64;
1320 let ss = sigaltstack { ss_flags: SS_DISABLE as i32, ..sigaltstack::default() };
1321 current_task.write_object(user_ss, &ss).expect("failed to write struct");
1322 sys_sigaltstack(¤t_task, user_ss.into(), nullptr.into())
1323 .expect("failed to call sigaltstack");
1324 })
1325 .await;
1326 }
1327
1328 #[::fuchsia::test]
1331 async fn test_sigprocmask_invalid_size() {
1332 spawn_kernel_and_run(async |current_task| {
1333 let set = UserRef::<SigSet>::default();
1334 let old_set = UserRef::<SigSet>::default();
1335 let how = 0;
1336
1337 assert_eq!(
1338 sys_rt_sigprocmask(
1339 ¤t_task,
1340 how,
1341 set,
1342 old_set,
1343 std::mem::size_of::<SigSet>() * 2
1344 ),
1345 error!(EINVAL)
1346 );
1347 assert_eq!(
1348 sys_rt_sigprocmask(
1349 ¤t_task,
1350 how,
1351 set,
1352 old_set,
1353 std::mem::size_of::<SigSet>() / 2
1354 ),
1355 error!(EINVAL)
1356 );
1357 })
1358 .await;
1359 }
1360
1361 #[::fuchsia::test]
1363 async fn test_sigprocmask_invalid_how() {
1364 spawn_kernel_and_run(async |current_task| {
1365 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1366
1367 let set = UserRef::<SigSet>::new(addr);
1368 let old_set = UserRef::<SigSet>::default();
1369 let how = SIG_SETMASK | SIG_UNBLOCK | SIG_BLOCK;
1370
1371 assert_eq!(
1372 sys_rt_sigprocmask(¤t_task, how, set, old_set, std::mem::size_of::<SigSet>()),
1373 error!(EINVAL)
1374 );
1375 })
1376 .await;
1377 }
1378
1379 #[::fuchsia::test]
1382 async fn test_sigprocmask_null_set() {
1383 spawn_kernel_and_run(async |current_task| {
1384 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1385 let original_mask = SigSet::from(SIGTRAP);
1386 {
1387 current_task.write().set_signal_mask(original_mask);
1388 }
1389
1390 let set = UserRef::<SigSet>::default();
1391 let old_set = UserRef::<SigSet>::new(addr);
1392 let how = SIG_SETMASK;
1393
1394 current_task
1395 .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>()])
1396 .expect("failed to clear struct");
1397
1398 assert_eq!(
1399 sys_rt_sigprocmask(¤t_task, how, set, old_set, std::mem::size_of::<SigSet>()),
1400 Ok(())
1401 );
1402
1403 let old_mask = current_task.read_object(old_set).expect("failed to read mask");
1404 assert_eq!(old_mask, original_mask);
1405 })
1406 .await;
1407 }
1408
1409 #[::fuchsia::test]
1412 async fn test_sigprocmask_null_set_and_old_set() {
1413 spawn_kernel_and_run(async |current_task| {
1414 let original_mask = SigSet::from(SIGTRAP);
1415 {
1416 current_task.write().set_signal_mask(original_mask);
1417 }
1418
1419 let set = UserRef::<SigSet>::default();
1420 let old_set = UserRef::<SigSet>::default();
1421 let how = SIG_SETMASK;
1422
1423 assert_eq!(
1424 sys_rt_sigprocmask(¤t_task, how, set, old_set, std::mem::size_of::<SigSet>()),
1425 Ok(())
1426 );
1427 assert_eq!(current_task.read().signal_mask(), original_mask);
1428 })
1429 .await;
1430 }
1431
1432 #[::fuchsia::test]
1434 async fn test_sigprocmask_setmask() {
1435 spawn_kernel_and_run(async |current_task| {
1436 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1437 current_task
1438 .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1439 .expect("failed to clear struct");
1440
1441 let original_mask = SigSet::from(SIGTRAP);
1442 {
1443 current_task.write().set_signal_mask(original_mask);
1444 }
1445
1446 let new_mask = SigSet::from(SIGIO);
1447 let set = UserRef::<SigSet>::new(addr);
1448 current_task.write_object(set, &new_mask).expect("failed to set mask");
1449
1450 let old_addr_range = (addr + std::mem::size_of::<SigSet>()).unwrap();
1451 let old_set = UserRef::<SigSet>::new(old_addr_range);
1452 let how = SIG_SETMASK;
1453
1454 assert_eq!(
1455 sys_rt_sigprocmask(¤t_task, how, set, old_set, std::mem::size_of::<SigSet>()),
1456 Ok(())
1457 );
1458
1459 let old_mask = current_task.read_object(old_set).expect("failed to read mask");
1460 assert_eq!(old_mask, original_mask);
1461 assert_eq!(current_task.read().signal_mask(), new_mask);
1462 })
1463 .await;
1464 }
1465
1466 #[::fuchsia::test]
1468 async fn test_sigprocmask_block() {
1469 spawn_kernel_and_run(async |current_task| {
1470 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1471 current_task
1472 .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1473 .expect("failed to clear struct");
1474
1475 let original_mask = SigSet::from(SIGTRAP);
1476 {
1477 current_task.write().set_signal_mask(original_mask);
1478 }
1479
1480 let new_mask = SigSet::from(SIGIO);
1481 let set = UserRef::<SigSet>::new(addr);
1482 current_task.write_object(set, &new_mask).expect("failed to set mask");
1483
1484 let old_addr_range = (addr + std::mem::size_of::<SigSet>()).unwrap();
1485 let old_set = UserRef::<SigSet>::new(old_addr_range);
1486 let how = SIG_BLOCK;
1487
1488 assert_eq!(
1489 sys_rt_sigprocmask(¤t_task, how, set, old_set, std::mem::size_of::<SigSet>()),
1490 Ok(())
1491 );
1492
1493 let old_mask = current_task.read_object(old_set).expect("failed to read mask");
1494 assert_eq!(old_mask, original_mask);
1495 assert_eq!(current_task.read().signal_mask(), new_mask | original_mask);
1496 })
1497 .await;
1498 }
1499
1500 #[::fuchsia::test]
1502 async fn test_sigprocmask_unblock() {
1503 spawn_kernel_and_run(async |current_task| {
1504 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1505 current_task
1506 .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1507 .expect("failed to clear struct");
1508
1509 let original_mask = SigSet::from(SIGTRAP) | SigSet::from(SIGIO);
1510 {
1511 current_task.write().set_signal_mask(original_mask);
1512 }
1513
1514 let new_mask = SigSet::from(SIGTRAP);
1515 let set = UserRef::<SigSet>::new(addr);
1516 current_task.write_object(set, &new_mask).expect("failed to set mask");
1517
1518 let old_addr_range = (addr + std::mem::size_of::<SigSet>()).unwrap();
1519 let old_set = UserRef::<SigSet>::new(old_addr_range);
1520 let how = SIG_UNBLOCK;
1521
1522 assert_eq!(
1523 sys_rt_sigprocmask(¤t_task, how, set, old_set, std::mem::size_of::<SigSet>()),
1524 Ok(())
1525 );
1526
1527 let old_mask = current_task.read_object(old_set).expect("failed to read mask");
1528 assert_eq!(old_mask, original_mask);
1529 assert_eq!(current_task.read().signal_mask(), SIGIO.into());
1530 })
1531 .await;
1532 }
1533
1534 #[::fuchsia::test]
1536 async fn test_sigprocmask_unblock_not_set() {
1537 spawn_kernel_and_run(async |current_task| {
1538 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1539 current_task
1540 .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1541 .expect("failed to clear struct");
1542
1543 let original_mask = SigSet::from(SIGIO);
1544 {
1545 current_task.write().set_signal_mask(original_mask);
1546 }
1547
1548 let new_mask = SigSet::from(SIGTRAP);
1549 let set = UserRef::<SigSet>::new(addr);
1550 current_task.write_object(set, &new_mask).expect("failed to set mask");
1551
1552 let old_addr_range = (addr + std::mem::size_of::<SigSet>()).unwrap();
1553 let old_set = UserRef::<SigSet>::new(old_addr_range);
1554 let how = SIG_UNBLOCK;
1555
1556 assert_eq!(
1557 sys_rt_sigprocmask(¤t_task, how, set, old_set, std::mem::size_of::<SigSet>()),
1558 Ok(())
1559 );
1560
1561 let old_mask = current_task.read_object(old_set).expect("failed to read mask");
1562 assert_eq!(old_mask, original_mask);
1563 assert_eq!(current_task.read().signal_mask(), original_mask);
1564 })
1565 .await;
1566 }
1567
1568 #[::fuchsia::test]
1570 async fn test_sigprocmask_kill_stop() {
1571 spawn_kernel_and_run(async |current_task| {
1572 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1573 current_task
1574 .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1575 .expect("failed to clear struct");
1576
1577 let original_mask = SigSet::from(SIGIO);
1578 {
1579 current_task.write().set_signal_mask(original_mask);
1580 }
1581
1582 let new_mask = UNBLOCKABLE_SIGNALS;
1583 let set = UserRef::<SigSet>::new(addr);
1584 current_task.write_object(set, &new_mask).expect("failed to set mask");
1585
1586 let old_addr_range = (addr + std::mem::size_of::<SigSet>()).unwrap();
1587 let old_set = UserRef::<SigSet>::new(old_addr_range);
1588 let how = SIG_BLOCK;
1589
1590 assert_eq!(
1591 sys_rt_sigprocmask(¤t_task, how, set, old_set, std::mem::size_of::<SigSet>()),
1592 Ok(())
1593 );
1594
1595 let old_mask = current_task.read_object(old_set).expect("failed to read mask");
1596 assert_eq!(old_mask, original_mask);
1597 assert_eq!(current_task.read().signal_mask(), original_mask);
1598 })
1599 .await;
1600 }
1601
1602 #[::fuchsia::test]
1603 async fn test_sigaction_invalid_signal() {
1604 spawn_kernel_and_run(async |current_task| {
1605 assert_eq!(
1606 sys_rt_sigaction(
1607 ¤t_task,
1608 UncheckedSignal::from(SIGKILL),
1609 UserRef::<sigaction_t>::new(UserAddress::from(10)).into(),
1611 UserRef::<sigaction_t>::default().into(),
1612 std::mem::size_of::<SigSet>(),
1613 ),
1614 error!(EINVAL)
1615 );
1616 assert_eq!(
1617 sys_rt_sigaction(
1618 ¤t_task,
1619 UncheckedSignal::from(SIGSTOP),
1620 UserRef::<sigaction_t>::new(UserAddress::from(10)).into(),
1622 UserRef::<sigaction_t>::default().into(),
1623 std::mem::size_of::<SigSet>(),
1624 ),
1625 error!(EINVAL)
1626 );
1627 assert_eq!(
1628 sys_rt_sigaction(
1629 ¤t_task,
1630 UncheckedSignal::from(Signal::NUM_SIGNALS + 1),
1631 UserRef::<sigaction_t>::new(UserAddress::from(10)).into(),
1633 UserRef::<sigaction_t>::default().into(),
1634 std::mem::size_of::<SigSet>(),
1635 ),
1636 error!(EINVAL)
1637 );
1638 })
1639 .await;
1640 }
1641
1642 #[::fuchsia::test]
1643 async fn test_sigaction_old_value_set() {
1644 spawn_kernel_and_run(async |current_task| {
1645 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1646 current_task
1647 .write_memory(addr, &[0u8; std::mem::size_of::<sigaction_t>()])
1648 .expect("failed to clear struct");
1649
1650 let org_mask = SigSet::from(SIGHUP) | SigSet::from(SIGINT);
1651 let original_action =
1652 sigaction_t { sa_mask: org_mask.into(), ..sigaction_t::default() };
1653
1654 {
1655 current_task.thread_group().signal_actions.set(SIGHUP, original_action);
1656 }
1657
1658 let old_action_ref = UserRef::<sigaction_t>::new(addr);
1659 assert_eq!(
1660 sys_rt_sigaction(
1661 ¤t_task,
1662 UncheckedSignal::from(SIGHUP),
1663 UserRef::<sigaction_t>::default().into(),
1664 old_action_ref.into(),
1665 std::mem::size_of::<SigSet>()
1666 ),
1667 Ok(())
1668 );
1669
1670 let old_action =
1671 current_task.read_object(old_action_ref).expect("failed to read action");
1672 assert_eq!(old_action.as_bytes(), original_action.as_bytes());
1673 })
1674 .await;
1675 }
1676
1677 #[::fuchsia::test]
1678 async fn test_sigaction_new_value_set() {
1679 spawn_kernel_and_run(async |current_task| {
1680 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1681 current_task
1682 .write_memory(addr, &[0u8; std::mem::size_of::<sigaction_t>()])
1683 .expect("failed to clear struct");
1684
1685 let org_mask = SigSet::from(SIGHUP) | SigSet::from(SIGINT);
1686 let original_action =
1687 sigaction_t { sa_mask: org_mask.into(), ..sigaction_t::default() };
1688 let set_action_ref = UserRef::<sigaction_t>::new(addr);
1689 current_task
1690 .write_object(set_action_ref, &original_action)
1691 .expect("failed to set action");
1692
1693 assert_eq!(
1694 sys_rt_sigaction(
1695 ¤t_task,
1696 UncheckedSignal::from(SIGINT),
1697 set_action_ref.into(),
1698 UserRef::<sigaction_t>::default().into(),
1699 std::mem::size_of::<SigSet>(),
1700 ),
1701 Ok(())
1702 );
1703
1704 assert_eq!(
1705 current_task.thread_group().signal_actions.get(SIGINT).as_bytes(),
1706 original_action.as_bytes()
1707 );
1708 })
1709 .await;
1710 }
1711
1712 #[::fuchsia::test]
1714 async fn test_kill_same_task() {
1715 spawn_kernel_and_run(async |current_task| {
1716 assert_eq!(sys_kill(¤t_task, current_task.tid.id, SIGINT.into()), Ok(()));
1717 })
1718 .await;
1719 }
1720
1721 #[::fuchsia::test]
1723 async fn test_kill_own_thread_group() {
1724 spawn_kernel_and_run(async |init_task| {
1725 let task1 = init_task.clone_task_for_test(0, Some(SIGCHLD));
1726 task1.thread_group().setsid().expect("setsid");
1727 let task2 = task1.clone_task_for_test(0, Some(SIGCHLD));
1728
1729 assert_eq!(sys_kill(&task1, 0, SIGINT.into()), Ok(()));
1730 assert_eq!(task1.read().queued_signal_count(SIGINT), 1);
1731 assert_eq!(task2.read().queued_signal_count(SIGINT), 1);
1732 assert_eq!(init_task.read().queued_signal_count(SIGINT), 0);
1733 })
1734 .await;
1735 }
1736
1737 #[::fuchsia::test]
1740 async fn test_kill_thread_group_ignored_signal() {
1741 spawn_kernel_and_run(async |init_task| {
1742 let task = init_task.clone_task_for_test(0, Some(SIGCHLD));
1743 task.thread_group().setsid().expect("setsid");
1744
1745 assert_eq!(sys_kill(&task, 0, SIGWINCH.into()), Ok(()));
1747 assert_eq!(task.read().queued_signal_count(SIGWINCH), 0);
1748
1749 task.write().set_signal_mask(SIGWINCH.into());
1750 assert_eq!(sys_kill(&task, 0, SIGWINCH.into()), Ok(()));
1751 assert_eq!(task.read().queued_signal_count(SIGWINCH), 1);
1752 })
1753 .await;
1754 }
1755
1756 #[::fuchsia::test]
1758 async fn test_kill_thread_group() {
1759 spawn_kernel_and_run(async |init_task| {
1760 let task1 = init_task.clone_task_for_test(0, Some(SIGCHLD));
1761 task1.thread_group().setsid().expect("setsid");
1762 let task2 = task1.clone_task_for_test(0, Some(SIGCHLD));
1763
1764 assert_eq!(sys_kill(&task1, -task1.tid.id, SIGINT.into()), Ok(()));
1765 assert_eq!(task1.read().queued_signal_count(SIGINT), 1);
1766 assert_eq!(task2.read().queued_signal_count(SIGINT), 1);
1767 assert_eq!(init_task.read().queued_signal_count(SIGINT), 0);
1768 })
1769 .await;
1770 }
1771
1772 #[::fuchsia::test]
1774 async fn test_kill_all() {
1775 spawn_kernel_and_run(async |init_task| {
1776 let task1 = init_task.clone_task_for_test(0, Some(SIGCHLD));
1777 task1.thread_group().setsid().expect("setsid");
1778 let task2 = task1.clone_task_for_test(0, Some(SIGCHLD));
1779
1780 assert_eq!(sys_kill(&task1, -1, SIGINT.into()), Ok(()));
1781 assert_eq!(task1.read().queued_signal_count(SIGINT), 0);
1782 assert_eq!(task2.read().queued_signal_count(SIGINT), 1);
1783 assert_eq!(init_task.read().queued_signal_count(SIGINT), 0);
1784 })
1785 .await;
1786 }
1787
1788 #[::fuchsia::test]
1790 async fn test_kill_inexistant_task() {
1791 spawn_kernel_and_run(async |current_task| {
1792 assert_eq!(sys_kill(¤t_task, 9, SIGINT.into()), error!(ESRCH));
1793 })
1794 .await;
1795 }
1796
1797 #[::fuchsia::test]
1799 async fn test_kill_invalid_task() {
1800 spawn_kernel_and_run(async |task1| {
1801 task1.set_creds(Credentials::with_ids(1, 1));
1803 let task2 = task1.clone_task_for_test(0, Some(SIGCHLD));
1804 task2.set_creds(Credentials::with_ids(2, 2));
1805
1806 assert!(task1.can_signal(&task2, SIGINT.into()).is_err());
1807 assert_eq!(sys_kill(&task2, task1.tid.id, SIGINT.into()), error!(EPERM));
1808 assert_eq!(task1.read().queued_signal_count(SIGINT), 0);
1809 })
1810 .await;
1811 }
1812
1813 #[::fuchsia::test]
1815 async fn test_kill_invalid_task_in_thread_group() {
1816 spawn_kernel_and_run(async |init_task| {
1817 let task1 = init_task.clone_task_for_test(0, Some(SIGCHLD));
1818 task1.thread_group().setsid().expect("setsid");
1819 let task2 = task1.clone_task_for_test(0, Some(SIGCHLD));
1820 task2.thread_group().setsid().expect("setsid");
1821 task2.set_creds(Credentials::with_ids(2, 2));
1822
1823 assert!(task2.can_signal(&task1, SIGINT.into()).is_err());
1824 assert_eq!(sys_kill(&task2, -task1.tid.id, SIGINT.into()), error!(EPERM));
1825 assert_eq!(task1.read().queued_signal_count(SIGINT), 0);
1826 })
1827 .await;
1828 }
1829
1830 #[::fuchsia::test]
1832 async fn test_kill_invalid_signal() {
1833 spawn_kernel_and_run(async |current_task| {
1834 assert_eq!(
1835 sys_kill(¤t_task, current_task.tid.id, UncheckedSignal::from(75)),
1836 error!(EINVAL)
1837 );
1838 })
1839 .await;
1840 }
1841
1842 #[::fuchsia::test]
1844 async fn test_blocked_signal_pending() {
1845 spawn_kernel_and_run(async |current_task| {
1846 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1847 current_task
1848 .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1849 .expect("failed to clear struct");
1850
1851 let new_mask = SigSet::from(SIGIO);
1852 let set = UserRef::<SigSet>::new(addr);
1853 current_task.write_object(set, &new_mask).expect("failed to set mask");
1854
1855 assert_eq!(
1856 sys_rt_sigprocmask(
1857 ¤t_task,
1858 SIG_BLOCK,
1859 set,
1860 UserRef::default(),
1861 std::mem::size_of::<SigSet>()
1862 ),
1863 Ok(())
1864 );
1865 assert_eq!(sys_kill(¤t_task, current_task.tid.id, SIGIO.into()), Ok(()));
1866 assert_eq!(current_task.read().queued_signal_count(SIGIO), 1);
1867
1868 assert_eq!(sys_kill(¤t_task, current_task.tid.id, SIGIO.into()), Ok(()));
1870 assert_eq!(current_task.read().queued_signal_count(SIGIO), 1);
1871 })
1872 .await;
1873 }
1874
1875 #[::fuchsia::test]
1877 async fn test_blocked_real_time_signal_pending() {
1878 spawn_kernel_and_run(async |current_task| {
1879 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1880 current_task
1881 .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1882 .expect("failed to clear struct");
1883
1884 let new_mask = SigSet::from(starnix_uapi::signals::SIGRTMIN);
1885 let set = UserRef::<SigSet>::new(addr);
1886 current_task.write_object(set, &new_mask).expect("failed to set mask");
1887
1888 assert_eq!(
1889 sys_rt_sigprocmask(
1890 ¤t_task,
1891 SIG_BLOCK,
1892 set,
1893 UserRef::default(),
1894 std::mem::size_of::<SigSet>()
1895 ),
1896 Ok(())
1897 );
1898 assert_eq!(sys_kill(¤t_task, current_task.tid.id, SIGRTMIN.into()), Ok(()));
1899 assert_eq!(current_task.read().queued_signal_count(starnix_uapi::signals::SIGRTMIN), 1);
1900
1901 assert_eq!(sys_kill(¤t_task, current_task.tid.id, SIGRTMIN.into()), Ok(()));
1903 assert_eq!(current_task.read().queued_signal_count(starnix_uapi::signals::SIGRTMIN), 2);
1904 })
1905 .await;
1906 }
1907
1908 #[::fuchsia::test]
1909 async fn test_suspend() {
1910 spawn_kernel_and_run(async |current_task| {
1911 let init_task_weak = current_task.weak_task();
1912 let (tx, rx) = std::sync::mpsc::sync_channel::<()>(0);
1913
1914 let closure = move |current_task: &CurrentTask| {
1915 let init_task_temp = init_task_weak.upgrade().expect("Task must be alive");
1916
1917 let mut suspended = false;
1919 while !suspended {
1920 suspended = init_task_temp.read().is_blocked();
1921 std::thread::sleep(std::time::Duration::from_millis(10));
1922 }
1923
1924 let _ =
1926 sys_kill(current_task, init_task_temp.tid.id, UncheckedSignal::from(SIGHUP));
1927
1928 rx.recv().expect("receive");
1930 assert!(!init_task_temp.read().is_blocked());
1931 };
1932 let (thread, req) =
1933 SpawnRequestBuilder::new().with_sync_closure(closure).build_with_async_result();
1934 current_task.kernel().kthreads.spawner().spawn_from_request(req);
1935
1936 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1937 let user_ref = UserRef::<SigSet>::new(addr);
1938
1939 let sigset = !SigSet::from(SIGHUP);
1940 current_task.write_object(user_ref, &sigset).expect("failed to set action");
1941
1942 assert_eq!(
1943 sys_rt_sigsuspend(current_task, user_ref, std::mem::size_of::<SigSet>()),
1944 error!(ERESTARTNOHAND)
1945 );
1946 tx.send(()).expect("send");
1947 futures::executor::block_on(thread).expect("join");
1948 })
1949 .await;
1950 }
1951
1952 #[::fuchsia::test]
1954 async fn test_waitid_options() {
1955 spawn_kernel_and_run(async |current_task| {
1956 let id = 1;
1957 assert_eq!(
1958 sys_waitid(
1959 ¤t_task,
1960 P_PID,
1961 id,
1962 MultiArchUserRef::null(current_task),
1963 0,
1964 UserRef::default().into()
1965 ),
1966 error!(EINVAL)
1967 );
1968 assert_eq!(
1969 sys_waitid(
1970 ¤t_task,
1971 P_PID,
1972 id,
1973 MultiArchUserRef::null(current_task),
1974 0xffff,
1975 UserRef::default().into()
1976 ),
1977 error!(EINVAL)
1978 );
1979 })
1980 .await;
1981 }
1982
1983 #[::fuchsia::test]
1985 async fn test_wait4_options() {
1986 spawn_kernel_and_run(async |current_task| {
1987 let id = 1;
1988 assert_eq!(
1989 sys_wait4(
1990 ¤t_task,
1991 id,
1992 UserRef::default(),
1993 WEXITED,
1994 RUsagePtr::null(current_task)
1995 ),
1996 error!(EINVAL)
1997 );
1998 assert_eq!(
1999 sys_wait4(
2000 ¤t_task,
2001 id,
2002 UserRef::default(),
2003 WNOWAIT,
2004 RUsagePtr::null(current_task)
2005 ),
2006 error!(EINVAL)
2007 );
2008 assert_eq!(
2009 sys_wait4(
2010 ¤t_task,
2011 id,
2012 UserRef::default(),
2013 0xffff,
2014 RUsagePtr::null(current_task)
2015 ),
2016 error!(EINVAL)
2017 );
2018 })
2019 .await;
2020 }
2021
2022 #[::fuchsia::test]
2023 async fn test_echild_when_no_zombie() {
2024 spawn_kernel_and_run(async |current_task| {
2025 assert!(
2027 sys_kill(¤t_task, current_task.get_pid(), UncheckedSignal::from(SIGCHLD))
2028 .is_ok()
2029 );
2030 assert_eq!(
2033 wait_on_pid(
2034 ¤t_task,
2035 &ProcessSelector::Any,
2036 &WaitingOptions::new_for_wait4(0).expect("WaitingOptions")
2037 ),
2038 error!(ECHILD)
2039 );
2040 })
2041 .await;
2042 }
2043
2044 #[::fuchsia::test]
2045 async fn test_no_error_when_zombie() {
2046 spawn_kernel_and_run(async |current_task| {
2047 let child = current_task.clone_task_for_test(0, Some(SIGCHLD));
2048 let expected_result = WaitResult {
2049 pid: child.tid.clone(),
2050 uid: 0,
2051 zombie_state: ZombieState {
2052 exit_status: ExitStatus::Exit(1),
2053 time_stats: Default::default(),
2054 },
2055 exit_signal: Some(SIGCHLD),
2056 };
2057 child.thread_group().kill(ExitStatus::Exit(1), None);
2058 std::mem::drop(child);
2059
2060 assert_eq!(
2061 wait_on_pid(
2062 ¤t_task,
2063 &ProcessSelector::Any,
2064 &WaitingOptions::new_for_wait4(0).expect("WaitingOptions")
2065 ),
2066 Ok(Some(expected_result))
2067 );
2068 })
2069 .await;
2070 }
2071
2072 #[::fuchsia::test]
2073 async fn test_waiting_for_child() {
2074 spawn_kernel_and_run(async |task| {
2075 let child = task.clone_task_builder_for_test(0, Some(SIGCHLD));
2076
2077 assert_eq!(
2079 wait_on_pid(
2080 &task,
2081 &ProcessSelector::Any,
2082 &WaitingOptions::new_for_wait4(WNOHANG).expect("WaitingOptions")
2083 ),
2084 Ok(None)
2085 );
2086
2087 let thread = std::thread::spawn({
2088 let task = task.weak_task();
2089 move || {
2090 let task = task.upgrade().expect("task must be alive");
2092 let child: AutoReleasableTask = child.into();
2093 while !task.read().is_blocked() {
2095 std::thread::sleep(std::time::Duration::from_millis(10));
2096 }
2097 child.thread_group().kill(ExitStatus::Exit(0), None);
2098 child.tid.clone()
2099 }
2100 });
2101
2102 let waited_child = wait_on_pid(
2104 &task,
2105 &ProcessSelector::Any,
2106 &WaitingOptions::new_for_wait4(0).expect("WaitingOptions"),
2107 )
2108 .expect("wait_on_pid")
2109 .unwrap();
2110
2111 let child_id = thread.join().expect("join");
2113 assert_eq!(waited_child.pid, child_id);
2114 })
2115 .await;
2116 }
2117
2118 #[::fuchsia::test]
2119 async fn test_waiting_for_child_with_signal_pending() {
2120 spawn_kernel_and_run(async |task| {
2121 task.thread_group().signal_actions.set(
2123 SIGUSR1,
2124 sigaction_t { sa_handler: uaddr { addr: 0xDEADBEEF }, ..sigaction_t::default() },
2125 );
2126
2127 let _child = task.clone_task_for_test(0, Some(SIGCHLD));
2129
2130 send_standard_signal(&task, SignalInfo::kernel(SIGUSR1));
2133
2134 let errno = wait_on_pid(
2135 &task,
2136 &ProcessSelector::Any,
2137 &WaitingOptions::new_for_wait4(0).expect("WaitingOptions"),
2138 )
2139 .expect_err("wait_on_pid");
2140 assert_eq!(errno, ERESTARTSYS);
2141 })
2142 .await;
2143 }
2144
2145 #[::fuchsia::test]
2146 async fn test_sigkill() {
2147 spawn_kernel_and_run(async |current_task| {
2148 let mut child = current_task.clone_task_for_test(0, Some(SIGCHLD));
2149
2150 send_standard_signal(&child, SignalInfo::kernel(SIGKILL));
2152 dequeue_signal_for_test(&mut child);
2153 std::mem::drop(child);
2154
2155 let address = map_memory(
2157 ¤t_task,
2158 UserAddress::default(),
2159 std::mem::size_of::<i32>() as u64,
2160 );
2161 let address_ref = UserRef::<i32>::new(address);
2162 sys_wait4(¤t_task, -1, address_ref, 0, RUsagePtr::null(current_task))
2163 .expect("wait4");
2164 let wstatus = current_task.read_object(address_ref).expect("read memory");
2165 assert_eq!(wstatus, SIGKILL.number() as i32);
2166 })
2167 .await;
2168 }
2169
2170 async fn test_exit_status_for_signal(
2171 sig: Signal,
2172 wait_status: i32,
2173 exit_signal: Option<Signal>,
2174 ) {
2175 spawn_kernel_and_run(async move |current_task| {
2176 let mut child = current_task.clone_task_for_test(0, exit_signal);
2177
2178 send_standard_signal(&child, SignalInfo::kernel(sig));
2180 dequeue_signal_for_test(&mut child);
2181 std::mem::drop(child);
2182
2183 let address = map_memory(
2185 ¤t_task,
2186 UserAddress::default(),
2187 std::mem::size_of::<i32>() as u64,
2188 );
2189 let address_ref = UserRef::<i32>::new(address);
2190 sys_wait4(¤t_task, -1, address_ref, 0, RUsagePtr::null(current_task))
2191 .expect("wait4");
2192 let wstatus = current_task.read_object(address_ref).expect("read memory");
2193 assert_eq!(wstatus, wait_status);
2194 })
2195 .await;
2196 }
2197
2198 #[::fuchsia::test]
2199 async fn test_exit_status() {
2200 test_exit_status_for_signal(SIGTERM, SIGTERM.number() as i32, Some(SIGCHLD)).await;
2202 test_exit_status_for_signal(SIGSEGV, (SIGSEGV.number() as i32) | 0x80, Some(SIGCHLD)).await;
2204 }
2205
2206 #[::fuchsia::test]
2207 async fn test_wait4_by_pgid() {
2208 spawn_kernel_and_run(async |current_task| {
2209 let child1 = current_task.clone_task_for_test(0, Some(SIGCHLD));
2210 let child1_pid = child1.tid.id;
2211 child1.thread_group().kill(ExitStatus::Exit(42), None);
2212 std::mem::drop(child1);
2213 let child2 = current_task.clone_task_for_test(0, Some(SIGCHLD));
2214 child2.thread_group().setsid().expect("setsid");
2215 let child2_pid = child2.tid.id;
2216 child2.thread_group().kill(ExitStatus::Exit(42), None);
2217 std::mem::drop(child2);
2218
2219 assert_eq!(
2220 sys_wait4(
2221 ¤t_task,
2222 -child2_pid,
2223 UserRef::default(),
2224 0,
2225 RUsagePtr::null(current_task)
2226 ),
2227 Ok(child2_pid)
2228 );
2229 assert_eq!(
2230 sys_wait4(¤t_task, 0, UserRef::default(), 0, RUsagePtr::null(current_task)),
2231 Ok(child1_pid)
2232 );
2233 })
2234 .await;
2235 }
2236
2237 #[::fuchsia::test]
2238 async fn test_waitid_by_pgid() {
2239 spawn_kernel_and_run(async |current_task| {
2240 let child1 = current_task.clone_task_for_test(0, Some(SIGCHLD));
2241 let child1_pid = child1.tid.id;
2242 child1.thread_group().kill(ExitStatus::Exit(42), None);
2243 std::mem::drop(child1);
2244 let child2 = current_task.clone_task_for_test(0, Some(SIGCHLD));
2245 child2.thread_group().setsid().expect("setsid");
2246 let child2_pid = child2.tid.id;
2247 child2.thread_group().kill(ExitStatus::Exit(42), None);
2248 std::mem::drop(child2);
2249
2250 let address: UserRef<uapi::siginfo_t> =
2251 map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE).into();
2252 assert_eq!(
2253 sys_waitid(
2254 ¤t_task,
2255 P_PGID,
2256 child2_pid,
2257 address.into(),
2258 WEXITED,
2259 UserRef::default().into()
2260 ),
2261 Ok(())
2262 );
2263 assert_eq!(
2265 current_task.thread_group().read().zombie_children[0].task.get_pid(),
2266 child1_pid
2267 );
2268
2269 assert_eq!(
2270 sys_waitid(
2271 ¤t_task,
2272 P_PGID,
2273 0,
2274 address.into(),
2275 WEXITED,
2276 UserRef::default().into()
2277 ),
2278 Ok(())
2279 );
2280 })
2281 .await;
2282 }
2283
2284 #[::fuchsia::test]
2285 async fn test_sigqueue() {
2286 spawn_kernel_and_run(async |current_task| {
2287 let current_uid = current_task.current_creds().uid;
2288 let current_pid = current_task.get_pid();
2289
2290 const TEST_VALUE: u64 = 101;
2291
2292 const ARCH64_SI_HEADER_SIZE: usize = SI_HEADER_SIZE + 4;
2294 const PID_DATA_OFFSET: usize = ARCH64_SI_HEADER_SIZE;
2296 const UID_DATA_OFFSET: usize = ARCH64_SI_HEADER_SIZE + 4;
2297 const VALUE_DATA_OFFSET: usize = ARCH64_SI_HEADER_SIZE + 8;
2298
2299 let mut data = vec![0u8; SI_MAX_SIZE_AS_USIZE];
2300 let header = SignalInfoHeader {
2301 signo: SIGIO.number(),
2302 code: SI_QUEUE,
2303 ..SignalInfoHeader::default()
2304 };
2305 let _ = header.write_to(&mut data[..SI_HEADER_SIZE]);
2306 data[PID_DATA_OFFSET..PID_DATA_OFFSET + 4].copy_from_slice(¤t_pid.to_ne_bytes());
2307 data[UID_DATA_OFFSET..UID_DATA_OFFSET + 4].copy_from_slice(¤t_uid.to_ne_bytes());
2308 data[VALUE_DATA_OFFSET..VALUE_DATA_OFFSET + 8]
2309 .copy_from_slice(&TEST_VALUE.to_ne_bytes());
2310
2311 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
2312 current_task.write_memory(addr, &data).unwrap();
2313 let second_current = create_task(current_task.kernel(), "second task");
2314 let second_pid = second_current.get_pid();
2315 let second_tid = second_current.get_tid();
2316 assert_eq!(second_current.read().queued_signal_count(SIGIO), 0);
2317
2318 assert_eq!(
2319 sys_rt_tgsigqueueinfo(
2320 ¤t_task,
2321 second_pid,
2322 second_tid,
2323 UncheckedSignal::from(SIGIO),
2324 addr
2325 ),
2326 Ok(())
2327 );
2328 assert_eq!(second_current.read().queued_signal_count(SIGIO), 1);
2329
2330 let signal = SignalInfo::with_detail(
2331 SIGIO,
2332 SI_QUEUE,
2333 SignalDetail::Kill {
2334 pid: current_task.pid.clone(),
2335 uid: current_task.current_creds().uid,
2336 },
2337 );
2338 let queued_signal = second_current.write().take_specific_signal(signal);
2339 if let Some(sig) = queued_signal {
2340 assert_eq!(sig.signal, SIGIO);
2341 assert_eq!(sig.errno, 0);
2342 assert_eq!(sig.code, SI_QUEUE);
2343 if let SignalDetail::Raw { data } = sig.detail {
2344 let offset_pid = PID_DATA_OFFSET - ARCH64_SI_HEADER_SIZE;
2346 let offset_uid = UID_DATA_OFFSET - ARCH64_SI_HEADER_SIZE;
2347 let offset_value = VALUE_DATA_OFFSET - ARCH64_SI_HEADER_SIZE;
2348 let pid =
2349 pid_t::from_ne_bytes(data[offset_pid..offset_pid + 4].try_into().unwrap());
2350 let uid =
2351 uid_t::from_ne_bytes(data[offset_uid..offset_uid + 4].try_into().unwrap());
2352 let value = u64::from_ne_bytes(
2353 data[offset_value..offset_value + 8].try_into().unwrap(),
2354 );
2355 assert_eq!(pid, current_pid);
2356 assert_eq!(uid, current_uid);
2357 assert_eq!(value, TEST_VALUE);
2358 } else {
2359 panic!("incorrect signal detail");
2360 }
2361 } else {
2362 panic!("expected a queued signal");
2363 }
2364 })
2365 .await;
2366 }
2367
2368 #[::fuchsia::test]
2369 async fn test_signalfd_filters_signals() {
2370 spawn_kernel_and_run(async |current_task| {
2371 let memory_for_masks = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
2372
2373 let term_int_mask = SigSet::from(SIGTERM) | SigSet::from(SIGINT);
2375 let term_int_mask_addr = UserRef::<SigSet>::new(memory_for_masks);
2376 current_task
2377 .write_object(term_int_mask_addr, &term_int_mask)
2378 .expect("failed to write mask");
2379 let sfd_term_int = sys_signalfd4(
2380 ¤t_task,
2381 FdNumber::from_raw(-1),
2382 term_int_mask_addr,
2383 std::mem::size_of::<SigSet>(),
2384 0,
2385 )
2386 .expect("failed to create SIGTERM/SIGINT signalfd");
2387
2388 let sigchld_mask = SigSet::from(SIGCHLD);
2390 let sigchld_mask_addr =
2391 UserRef::<SigSet>::new((memory_for_masks + std::mem::size_of::<SigSet>()).unwrap());
2392 current_task
2393 .write_object(sigchld_mask_addr, &sigchld_mask)
2394 .expect("failed to write mask");
2395 let sfd_chld = sys_signalfd4(
2396 ¤t_task,
2397 FdNumber::from_raw(-1),
2398 sigchld_mask_addr,
2399 std::mem::size_of::<SigSet>(),
2400 0,
2401 )
2402 .expect("failed to create SIGCHLD signalfd");
2403
2404 sys_rt_sigprocmask(
2406 ¤t_task,
2407 SIG_BLOCK,
2408 sigchld_mask_addr,
2409 UserRef::default(),
2410 std::mem::size_of::<SigSet>(),
2411 )
2412 .expect("failed to block SIGCHLD");
2413
2414 let child = current_task.clone_task_for_test(0, Some(SIGCHLD));
2416 child.thread_group().kill(ExitStatus::Exit(1), None);
2417 std::mem::drop(child);
2418
2419 let sfd_term_int_file =
2421 current_task.files().get(sfd_term_int).expect("failed to get sfd_term_int file");
2422 let sfd_chld_file =
2423 current_task.files().get(sfd_chld).expect("failed to get sfd_chld file");
2424
2425 let term_int_events = sfd_term_int_file
2426 .query_events(¤t_task)
2427 .expect("failed to query sfd_term_int events");
2428 let chld_events =
2429 sfd_chld_file.query_events(¤t_task).expect("failed to query sfd_chld events");
2430
2431 assert!(!term_int_events.contains(FdEvents::POLLIN));
2432 assert!(chld_events.contains(FdEvents::POLLIN));
2433 })
2434 .await;
2435 }
2436
2437 #[::fuchsia::test]
2438 async fn test_signalfd_filters_signals_async() {
2439 spawn_kernel_and_run(async |current_task| {
2440 let memory_for_masks = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
2441
2442 let term_int_mask = SigSet::from(SIGTERM) | SigSet::from(SIGINT);
2444 let term_int_mask_addr = UserRef::<SigSet>::new(memory_for_masks);
2445 current_task
2446 .write_object(term_int_mask_addr, &term_int_mask)
2447 .expect("failed to write mask");
2448 let sfd_term_int = sys_signalfd4(
2449 ¤t_task,
2450 FdNumber::from_raw(-1),
2451 term_int_mask_addr,
2452 std::mem::size_of::<SigSet>(),
2453 0,
2454 )
2455 .expect("failed to create SIGTERM/SIGINT signalfd");
2456
2457 let sigchld_mask = SigSet::from(SIGCHLD);
2459 let sigchld_mask_addr =
2460 UserRef::<SigSet>::new((memory_for_masks + std::mem::size_of::<SigSet>()).unwrap());
2461 current_task
2462 .write_object(sigchld_mask_addr, &sigchld_mask)
2463 .expect("failed to write mask");
2464 let sfd_chld = sys_signalfd4(
2465 ¤t_task,
2466 FdNumber::from_raw(-1),
2467 sigchld_mask_addr,
2468 std::mem::size_of::<SigSet>(),
2469 0,
2470 )
2471 .expect("failed to create SIGCHLD signalfd");
2472
2473 let waiter = Waiter::new();
2475 let ready_items =
2476 Arc::new(LockDepMutex::<_, EventHandlerReadyQueueLock>::new(VecDeque::new()));
2477
2478 let sfd_term_int_file =
2479 current_task.files().get(sfd_term_int).expect("failed to get sfd_term_int file");
2480 let sfd_chld_file =
2481 current_task.files().get(sfd_chld).expect("failed to get sfd_chld file");
2482
2483 sfd_term_int_file
2484 .wait_async(
2485 ¤t_task,
2486 &waiter,
2487 FdEvents::POLLIN,
2488 EventHandler::Enqueue {
2489 key: sfd_term_int.into(),
2490 queue: ready_items.clone(),
2491 sought_events: FdEvents::POLLIN,
2492 },
2493 )
2494 .expect("failed to wait on sfd_term_int");
2495
2496 sfd_chld_file
2497 .wait_async(
2498 ¤t_task,
2499 &waiter,
2500 FdEvents::POLLIN,
2501 EventHandler::Enqueue {
2502 key: sfd_chld.into(),
2503 queue: ready_items.clone(),
2504 sought_events: FdEvents::POLLIN,
2505 },
2506 )
2507 .expect("failed to wait on sfd_chld");
2508
2509 let sigchld_mask_ref = UserRef::<SigSet>::new(memory_for_masks);
2511 current_task
2512 .write_object(sigchld_mask_ref, &sigchld_mask)
2513 .expect("failed to write mask");
2514 sys_rt_sigprocmask(
2515 ¤t_task,
2516 SIG_BLOCK,
2517 sigchld_mask_ref,
2518 UserRef::default(),
2519 std::mem::size_of::<SigSet>(),
2520 )
2521 .expect("failed to block SIGCHLD");
2522
2523 let child = current_task.clone_task_for_test(0, Some(SIGCHLD));
2525 child.thread_group().kill(ExitStatus::Exit(1), None);
2526 std::mem::drop(child);
2527
2528 waiter.wait(¤t_task).expect("failed to wait");
2530
2531 let ready_items = ready_items.lock();
2533 assert_eq!(ready_items.len(), 1);
2534 assert_eq!(ready_items[0].key, sfd_chld.into());
2535 })
2536 .await;
2537 }
2538}