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, RunState, Task, TaskMutableState,
15 ThreadGroup, 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, 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 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]
439fn send_unchecked_signal_info(
440 current_task: &CurrentTask,
441 target: &Task,
442 unchecked_signal: UncheckedSignal,
443 siginfo_ref: UserAddress,
444) -> Result<(), Errno> {
445 let siginfo = UncheckedSignalInfo::read_from_siginfo(current_task, siginfo_ref)?;
446 if target.get_pid() != current_task.get_pid()
447 && (siginfo.code() >= 0 || siginfo.code() == SI_TKILL)
448 {
449 return error!(EINVAL);
450 }
451
452 current_task.can_signal(&target, unchecked_signal)?;
453
454 if unchecked_signal.is_zero() {
456 return Ok(());
457 }
458
459 let signal = Signal::try_from(unchecked_signal)?;
460 security::check_signal_access(current_task, &target, signal)?;
461
462 send_signal(&target, siginfo.into_signal_info(signal, IntoSignalInfoOptions::None)?)
463}
464
465pub fn sys_kill(
474 current_task: &CurrentTask,
475 pid: pid_t,
476 unchecked_signal: UncheckedSignal,
477) -> Result<(), Errno> {
478 let pids = ¤t_task.kernel().pids;
479 match pid {
480 pid if pid > 0 => {
481 let target_thread_group = {
484 let pid_entry = pids.get(pid)?;
485 match pid_entry.get_process() {
486 Some(ProcessEntryRef::Process(process)) => process,
487
488 Some(ProcessEntryRef::Zombie) => return Ok(()),
490
491 None => {
494 let task = pid_entry.get_task()?;
495 task.thread_group().clone()
496 }
497 }
498 };
499
500 target_thread_group.send_signal_unchecked(current_task, unchecked_signal)?;
501 }
502 pid if pid == -1 => {
503 let thread_groups: Vec<_> = pids
512 .get_thread_groups(&RcuReadScope::new())
513 .filter(|thread_group| {
514 if *current_task.thread_group() == *thread_group {
515 return false;
516 }
517 if thread_group.leader.id == 1 {
518 return false;
519 }
520 true
521 })
522 .collect();
523 signal_thread_groups(current_task, unchecked_signal, thread_groups)?;
524 }
525 _ => {
526 let pid = match pid {
532 0 => current_task.thread_group().read().process_group.clone(),
533 _ => pids.get(negate_pid(pid)?)?,
534 };
535
536 let scope = RcuReadScope::new();
537 signal_thread_groups(current_task, unchecked_signal, pid.pgid_thread_groups(&scope))?;
538 }
539 };
540
541 Ok(())
542}
543
544fn verify_tgid_for_task(task: &Task, tgid: &Pid) -> Result<(), Errno> {
545 if &task.pid != tgid {
546 return error!(EINVAL);
547 } else {
548 Ok(())
549 }
550}
551
552pub fn sys_tkill(
564 current_task: &CurrentTask,
565 tid: tid_t,
566 unchecked_signal: UncheckedSignal,
567) -> Result<(), Errno> {
568 if tid <= 0 {
570 return error!(EINVAL);
571 }
572 let thread = current_task.get_task(tid)?;
573 send_unchecked_signal(current_task, &thread, unchecked_signal, SI_TKILL)
574}
575
576pub fn sys_tgkill(
587 current_task: &CurrentTask,
588 tgid: pid_t,
589 tid: tid_t,
590 unchecked_signal: UncheckedSignal,
591) -> Result<(), Errno> {
592 if tgid <= 0 || tid <= 0 {
594 return error!(EINVAL);
595 }
596 let pids = ¤t_task.kernel().pids;
597 let tid = pids.get(tid)?;
598 let tgid = pids.get(tgid)?;
599 let thread = tid.get_task()?;
600 verify_tgid_for_task(&thread, &tgid)?;
601 send_unchecked_signal(current_task, &thread, unchecked_signal, SI_TKILL)
602}
603
604pub fn sys_rt_sigreturn(current_task: &mut CurrentTask) -> Result<SyscallResult, Errno> {
613 restore_from_signal_handler(current_task)?;
614 Ok(current_task.thread_state.registers.return_register().into())
615}
616
617pub fn sys_rt_sigqueueinfo(
627 current_task: &CurrentTask,
628 tgid: pid_t,
629 unchecked_signal: UncheckedSignal,
630 siginfo_ref: UserAddress,
631) -> Result<(), Errno> {
632 let task = current_task.get_task(tgid)?;
633 task.thread_group().send_signal_unchecked_with_info(
634 current_task,
635 unchecked_signal,
636 siginfo_ref,
637 IntoSignalInfoOptions::None,
638 )
639}
640
641pub fn sys_rt_tgsigqueueinfo(
652 current_task: &CurrentTask,
653 tgid: pid_t,
654 tid: tid_t,
655 unchecked_signal: UncheckedSignal,
656 siginfo_ref: UserAddress,
657) -> Result<(), Errno> {
658 let pids = ¤t_task.kernel().pids;
659
660 let task = pids.get(tid)?.get_task()?;
661 let tgid = pids.get(tgid)?;
662 verify_tgid_for_task(&task, &tgid)?;
663 send_unchecked_signal_info(current_task, &task, unchecked_signal, siginfo_ref)
664}
665
666pub fn sys_pause(current_task: &CurrentTask) -> Result<(), Errno> {
671 let event = InterruptibleEvent::new();
672 let guard = event.begin_wait();
673 let result = current_task.run_in_state(RunState::Event(event.clone()), || {
674 match guard.block_until(None, zx::MonotonicInstant::INFINITE) {
675 Err(WakeReason::Interrupted) => error!(ERESTARTNOHAND),
676 Err(WakeReason::DeadlineExpired) => panic!("blocking forever cannot time out"),
677 Ok(()) => Ok(()),
678 }
679 });
680 result.map_eintr(|| errno!(ERESTARTNOHAND))
682}
683
684pub fn sys_pidfd_send_signal(
697 current_task: &CurrentTask,
698 pidfd: FdNumber,
699 unchecked_signal: UncheckedSignal,
700 siginfo_ref: UserAddress,
701 flags: u32,
702) -> Result<(), Errno> {
703 if flags != 0 {
704 return error!(EINVAL);
705 }
706
707 let file = current_task.files().get(pidfd)?;
708 let target = file.as_pid()?.get_thread_group()?;
709
710 if siginfo_ref.is_null() {
711 target.send_signal_unchecked(current_task, unchecked_signal)
712 } else {
713 target.send_signal_unchecked_with_info(
714 current_task,
715 unchecked_signal,
716 siginfo_ref,
717 IntoSignalInfoOptions::CheckSigno,
718 )
719 }
720}
721
722#[track_caller]
733fn signal_thread_groups<F>(
734 current_task: &CurrentTask,
735 unchecked_signal: UncheckedSignal,
736 thread_groups: F,
737) -> Result<(), Errno>
738where
739 F: IntoIterator<Item: AsRef<ThreadGroup>>,
740{
741 let mut last_error = None;
742 let mut sent_signal = false;
743
744 for thread_group in thread_groups.into_iter() {
747 match thread_group.as_ref().send_signal_unchecked(current_task, unchecked_signal) {
748 Ok(_) => sent_signal = true,
749 Err(errno) => last_error = Some(errno),
750 }
751 }
752
753 if sent_signal { Ok(()) } else { Err(last_error.unwrap_or_else(|| errno!(ESRCH))) }
754}
755
756#[derive(Debug)]
758pub struct WaitingOptions {
759 pub wait_for_exited: bool,
761 pub wait_for_stopped: bool,
763 pub wait_for_continued: bool,
765 pub wnohang: bool,
767 pub block: bool,
769 pub keep_waitable_state: bool,
771 pub wait_for_all: bool,
773 pub wait_for_clone: bool,
775}
776
777impl WaitingOptions {
778 fn new(options: u32) -> Self {
779 const_assert_eq!(WUNTRACED, WSTOPPED);
780 if options & __WNOTHREAD != 0 {
781 track_stub!(TODO("https://fxbug.dev/509926462"), "wait options wnothread");
782 }
783 Self {
784 wait_for_exited: options & WEXITED > 0,
785 wait_for_stopped: options & WSTOPPED > 0,
786 wait_for_continued: options & WCONTINUED > 0,
787 wnohang: options & WNOHANG > 0,
788 block: options & WNOHANG == 0,
789 keep_waitable_state: options & WNOWAIT > 0,
790 wait_for_all: options & __WALL > 0,
791 wait_for_clone: options & __WCLONE > 0,
792 }
793 }
794
795 pub fn new_for_waitid(options: u32) -> Result<Self, Errno> {
797 if options & !(__WCLONE | __WALL | WNOHANG | WNOWAIT | WSTOPPED | WEXITED | WCONTINUED) != 0
798 {
799 track_stub!(TODO("https://fxbug.dev/322874788"), "waitid options", options);
800 return error!(EINVAL);
801 }
802 if options & (WEXITED | WSTOPPED | WCONTINUED) == 0 {
803 return error!(EINVAL);
804 }
805 Ok(Self::new(options))
806 }
807
808 pub fn new_for_wait4(options: u32) -> Result<Self, Errno> {
810 if options & !(__WCLONE | __WNOTHREAD | __WALL | WNOHANG | WUNTRACED | WCONTINUED) != 0 {
811 track_stub!(TODO("https://fxbug.dev/322874017"), "wait4 options", options);
812 return error!(EINVAL);
813 }
814 Ok(Self::new(options | WEXITED))
815 }
816}
817
818fn wait_on_pid(
824 current_task: &CurrentTask,
825 selector: &ProcessSelector,
826 options: &WaitingOptions,
827) -> Result<Option<WaitResult>, Errno> {
828 let waiter = Waiter::new();
829 loop {
830 {
831 let mut pids = current_task.kernel().pids.lock();
832 if let Some(tracee) =
841 current_task.thread_group().get_waitable_ptracee(selector, options, &mut pids)
842 {
843 return Ok(Some(tracee));
844 }
845 let mut has_waitable_tracee = false;
846 let mut has_any_tracee = false;
847 current_task.thread_group().get_ptracees_and(
848 selector,
849 &mut |task: &Task, task_state: &TaskMutableState| {
850 if let Some(ptrace) = &task_state.ptrace {
851 has_any_tracee = true;
852 ptrace.tracer_waiters().wait_async(&waiter);
853 if ptrace.is_waitable(task.load_stopped(), options) {
854 has_waitable_tracee = true;
855 }
856 }
857 },
858 );
859 if has_waitable_tracee {
860 continue;
861 }
862
863 {
864 let mut thread_group = current_task.thread_group().write();
865
866 if thread_group.zombie_ptracees.has_zombie_matching(&selector) {
867 continue;
868 }
869 match thread_group.get_waitable_child(selector, options, &mut pids) {
870 WaitableChildResult::ReadyNow(child) => {
871 return Ok(Some(*child));
872 }
873 WaitableChildResult::ShouldWait => (),
874 WaitableChildResult::NoneFound => {
875 if !has_any_tracee {
876 return error!(ECHILD);
877 }
878 }
879 }
880 thread_group
881 .lifecycle_waiters
882 .wait_async_value(&waiter, ThreadGroupLifecycleWaitValue::ChildStatus);
883 }
884 }
885
886 if !options.block {
887 return Ok(None);
888 }
889 waiter.wait(current_task).map_eintr(|| errno!(ERESTARTSYS))?;
890 }
891}
892
893pub fn sys_waitid(
907 current_task: &CurrentTask,
908 id_type: u32,
909 id: i32,
910 user_info: MultiArchUserRef<uapi::siginfo_t, uapi::arch32::siginfo_t>,
911 options: u32,
912 user_rusage: RUsagePtr,
913) -> Result<(), Errno> {
914 let mut waiting_options = WaitingOptions::new_for_waitid(options)?;
915
916 let task_selector = match id_type {
917 P_PID => {
918 let pid = current_task.kernel().pids.get(id).map_err(|_| errno!(ECHILD))?;
919 ProcessSelector::Pid(pid)
920 }
921 P_ALL => ProcessSelector::Any,
922 P_PGID => {
923 let pid = if id == 0 {
924 current_task.thread_group().read().process_group.clone()
925 } else {
926 current_task.kernel().pids.get(id).map_err(|_| errno!(ECHILD))?
927 };
928 ProcessSelector::Pgid(pid)
929 }
930 P_PIDFD => {
931 let fd = FdNumber::from_raw(id);
932 let file = current_task.files().get(fd)?;
933 if file.flags().contains(OpenFlags::NONBLOCK) {
934 waiting_options.block = false;
935 }
936 ProcessSelector::Pid(file.as_pid()?)
937 }
938 _ => return error!(EINVAL),
939 };
940
941 if let Some(waitable_process) = wait_on_pid(current_task, &task_selector, &waiting_options)? {
943 if !user_rusage.is_null() {
944 let usage = rusage {
945 ru_utime: timeval_from_duration(waitable_process.zombie_state.time_stats.user_time),
946 ru_stime: timeval_from_duration(
947 waitable_process.zombie_state.time_stats.system_time,
948 ),
949 ..Default::default()
950 };
951
952 track_stub!(TODO("https://fxbug.dev/322874712"), "real rusage from waitid");
953 current_task.write_multi_arch_object(user_rusage, usage)?;
954 }
955
956 if !user_info.is_null() {
957 let siginfo = waitable_process.as_signal_info();
958 siginfo.write(current_task, user_info)?;
959 }
960 } else if id_type == P_PIDFD && !waiting_options.wnohang {
961 return error!(EAGAIN);
970 } else {
971 if !user_rusage.is_null() {
974 current_task.write_multi_arch_object(user_rusage, rusage::default())?;
975 }
976
977 if !user_info.is_null() {
978 SignalInfo::zero(current_task, user_info)?;
979 }
980 }
981
982 Ok(())
983}
984
985pub fn sys_wait4(
999 current_task: &CurrentTask,
1000 raw_selector: pid_t,
1001 user_wstatus: UserRef<i32>,
1002 options: u32,
1003 user_rusage: RUsagePtr,
1004) -> Result<pid_t, Errno> {
1005 let waiting_options = WaitingOptions::new_for_wait4(options)?;
1006
1007 let selector = if raw_selector == 0 {
1008 ProcessSelector::Pgid(current_task.thread_group().read().process_group.clone())
1009 } else if raw_selector == -1 {
1010 ProcessSelector::Any
1011 } else if raw_selector > 0 {
1012 let pid = current_task.kernel().pids.get(raw_selector).map_err(|_| errno!(ECHILD))?;
1013 ProcessSelector::Pid(pid)
1014 } else if raw_selector < -1 {
1015 let pid = current_task
1016 .kernel()
1017 .pids
1018 .get(negate_pid(raw_selector)?)
1019 .map_err(|_| errno!(ECHILD))?;
1020 ProcessSelector::Pgid(pid)
1021 } else {
1022 track_stub!(
1023 TODO("https://fxbug.dev/322874213"),
1024 "wait4 with selector",
1025 raw_selector as u64
1026 );
1027 return error!(ENOSYS);
1028 };
1029
1030 if let Some(waitable_process) = wait_on_pid(current_task, &selector, &waiting_options)? {
1031 let status = waitable_process.zombie_state.exit_status.wait_status();
1032
1033 if !user_rusage.is_null() {
1034 track_stub!(TODO("https://fxbug.dev/322874768"), "real rusage from wait4");
1035 let usage = rusage {
1036 ru_utime: timeval_from_duration(waitable_process.zombie_state.time_stats.user_time),
1037 ru_stime: timeval_from_duration(
1038 waitable_process.zombie_state.time_stats.system_time,
1039 ),
1040 ..Default::default()
1041 };
1042 current_task.write_multi_arch_object(user_rusage, usage)?;
1043 }
1044
1045 if !user_wstatus.is_null() {
1046 current_task.write_object(user_wstatus, &status)?;
1047 }
1048
1049 Ok(waitable_process.pid.id)
1050 } else {
1051 Ok(0)
1052 }
1053}
1054
1055fn negate_pid(pid: pid_t) -> Result<pid_t, Errno> {
1057 pid.checked_neg().ok_or_else(|| errno!(ESRCH))
1058}
1059
1060#[cfg(target_arch = "aarch64")]
1062mod arch32 {
1063 use crate::task::CurrentTask;
1064 use crate::vfs::FdNumber;
1065 use starnix_uapi::errors::Errno;
1066 use starnix_uapi::signals::SigSet;
1067 use starnix_uapi::user_address::UserRef;
1068
1069 pub fn sys_arch32_signalfd(
1084 current_task: &CurrentTask,
1085 fd: FdNumber,
1086 mask_addr: UserRef<SigSet>,
1087 mask_size: usize,
1088 ) -> Result<FdNumber, Errno> {
1089 super::sys_signalfd4(current_task, fd, mask_addr, mask_size, 0)
1090 }
1091
1092 pub use super::{
1093 sys_pidfd_send_signal as sys_arch32_pidfd_send_signal,
1094 sys_rt_sigaction as sys_arch32_rt_sigaction,
1095 sys_rt_sigqueueinfo as sys_arch32_rt_sigqueueinfo,
1096 sys_rt_sigtimedwait as sys_arch32_rt_sigtimedwait,
1097 sys_rt_tgsigqueueinfo as sys_arch32_rt_tgsigqueueinfo,
1098 sys_sigaltstack as sys_arch32_sigaltstack, sys_signalfd4 as sys_arch32_signalfd4,
1099 sys_waitid as sys_arch32_waitid,
1100 };
1101}
1102
1103#[cfg(target_arch = "aarch64")]
1104pub use arch32::*;
1105
1106#[cfg(test)]
1107mod tests {
1108 use super::*;
1109 use crate::mm::{MemoryAccessor, PAGE_SIZE};
1110 use crate::signals::testing::dequeue_signal_for_test;
1111 use crate::signals::{
1112 SI_HEADER_SIZE, SI_MAX_SIZE_AS_USIZE, SignalInfoHeader, send_standard_signal,
1113 };
1114 use crate::task::dynamic_thread_spawner::SpawnRequestBuilder;
1115 use crate::task::{EventHandler, ExitStatus, ZombieState};
1116 use crate::testing::*;
1117 use starnix_sync::{EventHandlerReadyQueueLock, LockDepMutex};
1118 use starnix_types::math::round_up_to_system_page_size;
1119 use starnix_uapi::auth::Credentials;
1120 use starnix_uapi::errors::ERESTARTSYS;
1121 use starnix_uapi::signals::{
1122 SIGCHLD, SIGHUP, SIGINT, SIGIO, SIGKILL, SIGRTMIN, SIGSEGV, SIGSTOP, SIGTERM, SIGTRAP,
1123 SIGUSR1, SIGWINCH,
1124 };
1125 use starnix_uapi::vfs::FdEvents;
1126 use starnix_uapi::{SI_QUEUE, sigaction_t, uaddr, uid_t};
1127 use std::collections::VecDeque;
1128 use std::sync::Arc;
1129 use zerocopy::IntoBytes;
1130
1131 #[cfg(target_arch = "x86_64")]
1132 #[::fuchsia::test]
1133 async fn test_sigaltstack() {
1134 spawn_kernel_and_run(async |current_task| {
1135 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1136
1137 let user_ss = UserRef::<sigaltstack>::new(addr);
1138 let nullptr = UserRef::<sigaltstack>::default();
1139
1140 sys_sigaltstack(¤t_task, nullptr.into(), user_ss.into())
1142 .expect("failed to call sigaltstack");
1143 let mut ss = current_task.read_object(user_ss).expect("failed to read struct");
1144 assert!(ss.ss_flags & (SS_DISABLE as i32) != 0);
1145
1146 ss.ss_sp = uaddr { addr: 0x7FFFF };
1148 ss.ss_size = 0x1000;
1149 ss.ss_flags = SS_AUTODISARM as i32;
1150 current_task.write_object(user_ss, &ss).expect("failed to write struct");
1151 sys_sigaltstack(¤t_task, user_ss.into(), nullptr.into())
1152 .expect("failed to call sigaltstack");
1153 current_task
1154 .write_memory(addr, &[0u8; std::mem::size_of::<sigaltstack>()])
1155 .expect("failed to clear struct");
1156 sys_sigaltstack(¤t_task, nullptr.into(), user_ss.into())
1157 .expect("failed to call sigaltstack");
1158 let another_ss = current_task.read_object(user_ss).expect("failed to read struct");
1159 assert_eq!(ss.as_bytes(), another_ss.as_bytes());
1160
1161 let ss = sigaltstack { ss_flags: SS_DISABLE as i32, ..sigaltstack::default() };
1163 current_task.write_object(user_ss, &ss).expect("failed to write struct");
1164 sys_sigaltstack(¤t_task, user_ss.into(), nullptr.into())
1165 .expect("failed to call sigaltstack");
1166 current_task
1167 .write_memory(addr, &[0u8; std::mem::size_of::<sigaltstack>()])
1168 .expect("failed to clear struct");
1169 sys_sigaltstack(¤t_task, nullptr.into(), user_ss.into())
1170 .expect("failed to call sigaltstack");
1171 let ss = current_task.read_object(user_ss).expect("failed to read struct");
1172 assert!(ss.ss_flags & (SS_DISABLE as i32) != 0);
1173 })
1174 .await;
1175 }
1176
1177 #[::fuchsia::test]
1178 async fn test_sigaltstack_invalid_size() {
1179 spawn_kernel_and_run(async |current_task| {
1180 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1181
1182 let user_ss = UserRef::<sigaltstack>::new(addr);
1183 let nullptr = UserRef::<sigaltstack>::default();
1184
1185 sys_sigaltstack(¤t_task, nullptr.into(), user_ss.into())
1187 .expect("failed to call sigaltstack");
1188 let mut ss = current_task.read_object(user_ss).expect("failed to read struct");
1189 assert!(ss.ss_flags & (SS_DISABLE as i32) != 0);
1190
1191 let sigaltstack_addr_size = round_up_to_system_page_size(uapi::MINSIGSTKSZ as usize)
1193 .expect("failed to round up");
1194 let sigaltstack_addr =
1195 map_memory(¤t_task, UserAddress::default(), sigaltstack_addr_size as u64);
1196 ss.ss_sp = sigaltstack_addr.into();
1197 ss.ss_flags = 0;
1198 ss.ss_size = uapi::MINSIGSTKSZ as u64 - 1;
1199 current_task.write_object(user_ss, &ss).expect("failed to write struct");
1200 assert_eq!(
1201 sys_sigaltstack(¤t_task, user_ss.into(), nullptr.into()),
1202 error!(ENOMEM)
1203 );
1204 })
1205 .await;
1206 }
1207
1208 #[cfg(target_arch = "x86_64")]
1209 #[::fuchsia::test]
1210 async fn test_sigaltstack_active_stack() {
1211 spawn_kernel_and_run(async |current_task| {
1212 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1213
1214 let user_ss = UserRef::<sigaltstack>::new(addr);
1215 let nullptr = UserRef::<sigaltstack>::default();
1216
1217 sys_sigaltstack(¤t_task, nullptr.into(), user_ss.into())
1219 .expect("failed to call sigaltstack");
1220 let mut ss = current_task.read_object(user_ss).expect("failed to read struct");
1221 assert!(ss.ss_flags & (SS_DISABLE as i32) != 0);
1222
1223 let sigaltstack_addr_size = round_up_to_system_page_size(uapi::MINSIGSTKSZ as usize)
1225 .expect("failed to round up");
1226 let sigaltstack_addr =
1227 map_memory(¤t_task, UserAddress::default(), sigaltstack_addr_size as u64);
1228 ss.ss_sp = sigaltstack_addr.into();
1229 ss.ss_flags = 0;
1230 ss.ss_size = sigaltstack_addr_size as u64;
1231 current_task.write_object(user_ss, &ss).expect("failed to write struct");
1232 sys_sigaltstack(¤t_task, user_ss.into(), nullptr.into())
1233 .expect("failed to call sigaltstack");
1234
1235 let next_addr = (sigaltstack_addr + sigaltstack_addr_size).unwrap();
1237 current_task.thread_state.registers.rsp = next_addr.ptr() as u64;
1238 ss.ss_flags = SS_DISABLE as i32;
1239 current_task.write_object(user_ss, &ss).expect("failed to write struct");
1240 assert_eq!(
1241 sys_sigaltstack(¤t_task, user_ss.into(), nullptr.into()),
1242 error!(EPERM)
1243 );
1244
1245 let next_ss_addr = sigaltstack_addr
1248 .checked_add(sigaltstack_addr_size)
1249 .unwrap()
1250 .checked_add(0x1000usize)
1251 .unwrap();
1252 current_task.thread_state.registers.rsp = next_ss_addr.ptr() as u64;
1253 let ss = sigaltstack { ss_flags: SS_DISABLE as i32, ..sigaltstack::default() };
1254 current_task.write_object(user_ss, &ss).expect("failed to write struct");
1255 sys_sigaltstack(¤t_task, user_ss.into(), nullptr.into())
1256 .expect("failed to call sigaltstack");
1257 })
1258 .await;
1259 }
1260
1261 #[cfg(target_arch = "x86_64")]
1262 #[::fuchsia::test]
1263 async fn test_sigaltstack_active_stack_saturates() {
1264 spawn_kernel_and_run(async |current_task| {
1265 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1266
1267 let user_ss = UserRef::<sigaltstack>::new(addr);
1268 let nullptr = UserRef::<sigaltstack>::default();
1269
1270 sys_sigaltstack(¤t_task, nullptr.into(), user_ss.into())
1272 .expect("failed to call sigaltstack");
1273 let mut ss = current_task.read_object(user_ss).expect("failed to read struct");
1274 assert!(ss.ss_flags & (SS_DISABLE as i32) != 0);
1275
1276 let sigaltstack_addr_size = round_up_to_system_page_size(uapi::MINSIGSTKSZ as usize)
1278 .expect("failed to round up");
1279 let sigaltstack_addr =
1280 map_memory(¤t_task, UserAddress::default(), sigaltstack_addr_size as u64);
1281 ss.ss_sp = sigaltstack_addr.into();
1282 ss.ss_flags = 0;
1283 ss.ss_size = u64::MAX;
1284 current_task.write_object(user_ss, &ss).expect("failed to write struct");
1285 sys_sigaltstack(¤t_task, user_ss.into(), nullptr.into())
1286 .expect("failed to call sigaltstack");
1287
1288 current_task.thread_state.registers.rsp =
1290 (sigaltstack_addr + sigaltstack_addr_size).unwrap().ptr() as u64;
1291 ss.ss_flags = SS_DISABLE as i32;
1292 current_task.write_object(user_ss, &ss).expect("failed to write struct");
1293 assert_eq!(
1294 sys_sigaltstack(¤t_task, user_ss.into(), nullptr.into()),
1295 error!(EPERM)
1296 );
1297
1298 current_task.thread_state.registers.rsp = 0u64;
1300 let ss = sigaltstack { ss_flags: SS_DISABLE as i32, ..sigaltstack::default() };
1301 current_task.write_object(user_ss, &ss).expect("failed to write struct");
1302 sys_sigaltstack(¤t_task, user_ss.into(), nullptr.into())
1303 .expect("failed to call sigaltstack");
1304 })
1305 .await;
1306 }
1307
1308 #[::fuchsia::test]
1311 async fn test_sigprocmask_invalid_size() {
1312 spawn_kernel_and_run(async |current_task| {
1313 let set = UserRef::<SigSet>::default();
1314 let old_set = UserRef::<SigSet>::default();
1315 let how = 0;
1316
1317 assert_eq!(
1318 sys_rt_sigprocmask(
1319 ¤t_task,
1320 how,
1321 set,
1322 old_set,
1323 std::mem::size_of::<SigSet>() * 2
1324 ),
1325 error!(EINVAL)
1326 );
1327 assert_eq!(
1328 sys_rt_sigprocmask(
1329 ¤t_task,
1330 how,
1331 set,
1332 old_set,
1333 std::mem::size_of::<SigSet>() / 2
1334 ),
1335 error!(EINVAL)
1336 );
1337 })
1338 .await;
1339 }
1340
1341 #[::fuchsia::test]
1343 async fn test_sigprocmask_invalid_how() {
1344 spawn_kernel_and_run(async |current_task| {
1345 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1346
1347 let set = UserRef::<SigSet>::new(addr);
1348 let old_set = UserRef::<SigSet>::default();
1349 let how = SIG_SETMASK | SIG_UNBLOCK | SIG_BLOCK;
1350
1351 assert_eq!(
1352 sys_rt_sigprocmask(¤t_task, how, set, old_set, std::mem::size_of::<SigSet>()),
1353 error!(EINVAL)
1354 );
1355 })
1356 .await;
1357 }
1358
1359 #[::fuchsia::test]
1362 async fn test_sigprocmask_null_set() {
1363 spawn_kernel_and_run(async |current_task| {
1364 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1365 let original_mask = SigSet::from(SIGTRAP);
1366 {
1367 current_task.write().set_signal_mask(original_mask);
1368 }
1369
1370 let set = UserRef::<SigSet>::default();
1371 let old_set = UserRef::<SigSet>::new(addr);
1372 let how = SIG_SETMASK;
1373
1374 current_task
1375 .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>()])
1376 .expect("failed to clear struct");
1377
1378 assert_eq!(
1379 sys_rt_sigprocmask(¤t_task, how, set, old_set, std::mem::size_of::<SigSet>()),
1380 Ok(())
1381 );
1382
1383 let old_mask = current_task.read_object(old_set).expect("failed to read mask");
1384 assert_eq!(old_mask, original_mask);
1385 })
1386 .await;
1387 }
1388
1389 #[::fuchsia::test]
1392 async fn test_sigprocmask_null_set_and_old_set() {
1393 spawn_kernel_and_run(async |current_task| {
1394 let original_mask = SigSet::from(SIGTRAP);
1395 {
1396 current_task.write().set_signal_mask(original_mask);
1397 }
1398
1399 let set = UserRef::<SigSet>::default();
1400 let old_set = UserRef::<SigSet>::default();
1401 let how = SIG_SETMASK;
1402
1403 assert_eq!(
1404 sys_rt_sigprocmask(¤t_task, how, set, old_set, std::mem::size_of::<SigSet>()),
1405 Ok(())
1406 );
1407 assert_eq!(current_task.read().signal_mask(), original_mask);
1408 })
1409 .await;
1410 }
1411
1412 #[::fuchsia::test]
1414 async fn test_sigprocmask_setmask() {
1415 spawn_kernel_and_run(async |current_task| {
1416 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1417 current_task
1418 .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1419 .expect("failed to clear struct");
1420
1421 let original_mask = SigSet::from(SIGTRAP);
1422 {
1423 current_task.write().set_signal_mask(original_mask);
1424 }
1425
1426 let new_mask = SigSet::from(SIGIO);
1427 let set = UserRef::<SigSet>::new(addr);
1428 current_task.write_object(set, &new_mask).expect("failed to set mask");
1429
1430 let old_addr_range = (addr + std::mem::size_of::<SigSet>()).unwrap();
1431 let old_set = UserRef::<SigSet>::new(old_addr_range);
1432 let how = SIG_SETMASK;
1433
1434 assert_eq!(
1435 sys_rt_sigprocmask(¤t_task, how, set, old_set, std::mem::size_of::<SigSet>()),
1436 Ok(())
1437 );
1438
1439 let old_mask = current_task.read_object(old_set).expect("failed to read mask");
1440 assert_eq!(old_mask, original_mask);
1441 assert_eq!(current_task.read().signal_mask(), new_mask);
1442 })
1443 .await;
1444 }
1445
1446 #[::fuchsia::test]
1448 async fn test_sigprocmask_block() {
1449 spawn_kernel_and_run(async |current_task| {
1450 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1451 current_task
1452 .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1453 .expect("failed to clear struct");
1454
1455 let original_mask = SigSet::from(SIGTRAP);
1456 {
1457 current_task.write().set_signal_mask(original_mask);
1458 }
1459
1460 let new_mask = SigSet::from(SIGIO);
1461 let set = UserRef::<SigSet>::new(addr);
1462 current_task.write_object(set, &new_mask).expect("failed to set mask");
1463
1464 let old_addr_range = (addr + std::mem::size_of::<SigSet>()).unwrap();
1465 let old_set = UserRef::<SigSet>::new(old_addr_range);
1466 let how = SIG_BLOCK;
1467
1468 assert_eq!(
1469 sys_rt_sigprocmask(¤t_task, how, set, old_set, std::mem::size_of::<SigSet>()),
1470 Ok(())
1471 );
1472
1473 let old_mask = current_task.read_object(old_set).expect("failed to read mask");
1474 assert_eq!(old_mask, original_mask);
1475 assert_eq!(current_task.read().signal_mask(), new_mask | original_mask);
1476 })
1477 .await;
1478 }
1479
1480 #[::fuchsia::test]
1482 async fn test_sigprocmask_unblock() {
1483 spawn_kernel_and_run(async |current_task| {
1484 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1485 current_task
1486 .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1487 .expect("failed to clear struct");
1488
1489 let original_mask = SigSet::from(SIGTRAP) | SigSet::from(SIGIO);
1490 {
1491 current_task.write().set_signal_mask(original_mask);
1492 }
1493
1494 let new_mask = SigSet::from(SIGTRAP);
1495 let set = UserRef::<SigSet>::new(addr);
1496 current_task.write_object(set, &new_mask).expect("failed to set mask");
1497
1498 let old_addr_range = (addr + std::mem::size_of::<SigSet>()).unwrap();
1499 let old_set = UserRef::<SigSet>::new(old_addr_range);
1500 let how = SIG_UNBLOCK;
1501
1502 assert_eq!(
1503 sys_rt_sigprocmask(¤t_task, how, set, old_set, std::mem::size_of::<SigSet>()),
1504 Ok(())
1505 );
1506
1507 let old_mask = current_task.read_object(old_set).expect("failed to read mask");
1508 assert_eq!(old_mask, original_mask);
1509 assert_eq!(current_task.read().signal_mask(), SIGIO.into());
1510 })
1511 .await;
1512 }
1513
1514 #[::fuchsia::test]
1516 async fn test_sigprocmask_unblock_not_set() {
1517 spawn_kernel_and_run(async |current_task| {
1518 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1519 current_task
1520 .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1521 .expect("failed to clear struct");
1522
1523 let original_mask = SigSet::from(SIGIO);
1524 {
1525 current_task.write().set_signal_mask(original_mask);
1526 }
1527
1528 let new_mask = SigSet::from(SIGTRAP);
1529 let set = UserRef::<SigSet>::new(addr);
1530 current_task.write_object(set, &new_mask).expect("failed to set mask");
1531
1532 let old_addr_range = (addr + std::mem::size_of::<SigSet>()).unwrap();
1533 let old_set = UserRef::<SigSet>::new(old_addr_range);
1534 let how = SIG_UNBLOCK;
1535
1536 assert_eq!(
1537 sys_rt_sigprocmask(¤t_task, how, set, old_set, std::mem::size_of::<SigSet>()),
1538 Ok(())
1539 );
1540
1541 let old_mask = current_task.read_object(old_set).expect("failed to read mask");
1542 assert_eq!(old_mask, original_mask);
1543 assert_eq!(current_task.read().signal_mask(), original_mask);
1544 })
1545 .await;
1546 }
1547
1548 #[::fuchsia::test]
1550 async fn test_sigprocmask_kill_stop() {
1551 spawn_kernel_and_run(async |current_task| {
1552 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1553 current_task
1554 .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1555 .expect("failed to clear struct");
1556
1557 let original_mask = SigSet::from(SIGIO);
1558 {
1559 current_task.write().set_signal_mask(original_mask);
1560 }
1561
1562 let new_mask = UNBLOCKABLE_SIGNALS;
1563 let set = UserRef::<SigSet>::new(addr);
1564 current_task.write_object(set, &new_mask).expect("failed to set mask");
1565
1566 let old_addr_range = (addr + std::mem::size_of::<SigSet>()).unwrap();
1567 let old_set = UserRef::<SigSet>::new(old_addr_range);
1568 let how = SIG_BLOCK;
1569
1570 assert_eq!(
1571 sys_rt_sigprocmask(¤t_task, how, set, old_set, std::mem::size_of::<SigSet>()),
1572 Ok(())
1573 );
1574
1575 let old_mask = current_task.read_object(old_set).expect("failed to read mask");
1576 assert_eq!(old_mask, original_mask);
1577 assert_eq!(current_task.read().signal_mask(), original_mask);
1578 })
1579 .await;
1580 }
1581
1582 #[::fuchsia::test]
1583 async fn test_sigaction_invalid_signal() {
1584 spawn_kernel_and_run(async |current_task| {
1585 assert_eq!(
1586 sys_rt_sigaction(
1587 ¤t_task,
1588 UncheckedSignal::from(SIGKILL),
1589 UserRef::<sigaction_t>::new(UserAddress::from(10)).into(),
1591 UserRef::<sigaction_t>::default().into(),
1592 std::mem::size_of::<SigSet>(),
1593 ),
1594 error!(EINVAL)
1595 );
1596 assert_eq!(
1597 sys_rt_sigaction(
1598 ¤t_task,
1599 UncheckedSignal::from(SIGSTOP),
1600 UserRef::<sigaction_t>::new(UserAddress::from(10)).into(),
1602 UserRef::<sigaction_t>::default().into(),
1603 std::mem::size_of::<SigSet>(),
1604 ),
1605 error!(EINVAL)
1606 );
1607 assert_eq!(
1608 sys_rt_sigaction(
1609 ¤t_task,
1610 UncheckedSignal::from(Signal::NUM_SIGNALS + 1),
1611 UserRef::<sigaction_t>::new(UserAddress::from(10)).into(),
1613 UserRef::<sigaction_t>::default().into(),
1614 std::mem::size_of::<SigSet>(),
1615 ),
1616 error!(EINVAL)
1617 );
1618 })
1619 .await;
1620 }
1621
1622 #[::fuchsia::test]
1623 async fn test_sigaction_old_value_set() {
1624 spawn_kernel_and_run(async |current_task| {
1625 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1626 current_task
1627 .write_memory(addr, &[0u8; std::mem::size_of::<sigaction_t>()])
1628 .expect("failed to clear struct");
1629
1630 let org_mask = SigSet::from(SIGHUP) | SigSet::from(SIGINT);
1631 let original_action =
1632 sigaction_t { sa_mask: org_mask.into(), ..sigaction_t::default() };
1633
1634 {
1635 current_task.thread_group().signal_actions.set(SIGHUP, original_action);
1636 }
1637
1638 let old_action_ref = UserRef::<sigaction_t>::new(addr);
1639 assert_eq!(
1640 sys_rt_sigaction(
1641 ¤t_task,
1642 UncheckedSignal::from(SIGHUP),
1643 UserRef::<sigaction_t>::default().into(),
1644 old_action_ref.into(),
1645 std::mem::size_of::<SigSet>()
1646 ),
1647 Ok(())
1648 );
1649
1650 let old_action =
1651 current_task.read_object(old_action_ref).expect("failed to read action");
1652 assert_eq!(old_action.as_bytes(), original_action.as_bytes());
1653 })
1654 .await;
1655 }
1656
1657 #[::fuchsia::test]
1658 async fn test_sigaction_new_value_set() {
1659 spawn_kernel_and_run(async |current_task| {
1660 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1661 current_task
1662 .write_memory(addr, &[0u8; std::mem::size_of::<sigaction_t>()])
1663 .expect("failed to clear struct");
1664
1665 let org_mask = SigSet::from(SIGHUP) | SigSet::from(SIGINT);
1666 let original_action =
1667 sigaction_t { sa_mask: org_mask.into(), ..sigaction_t::default() };
1668 let set_action_ref = UserRef::<sigaction_t>::new(addr);
1669 current_task
1670 .write_object(set_action_ref, &original_action)
1671 .expect("failed to set action");
1672
1673 assert_eq!(
1674 sys_rt_sigaction(
1675 ¤t_task,
1676 UncheckedSignal::from(SIGINT),
1677 set_action_ref.into(),
1678 UserRef::<sigaction_t>::default().into(),
1679 std::mem::size_of::<SigSet>(),
1680 ),
1681 Ok(())
1682 );
1683
1684 assert_eq!(
1685 current_task.thread_group().signal_actions.get(SIGINT).as_bytes(),
1686 original_action.as_bytes()
1687 );
1688 })
1689 .await;
1690 }
1691
1692 #[::fuchsia::test]
1694 async fn test_kill_same_task() {
1695 spawn_kernel_and_run(async |current_task| {
1696 assert_eq!(sys_kill(¤t_task, current_task.tid.id, SIGINT.into()), Ok(()));
1697 })
1698 .await;
1699 }
1700
1701 #[::fuchsia::test]
1703 async fn test_kill_own_thread_group() {
1704 spawn_kernel_and_run(async |init_task| {
1705 let task1 = init_task.clone_task_for_test(0, Some(SIGCHLD));
1706 task1.thread_group().setsid().expect("setsid");
1707 let task2 = task1.clone_task_for_test(0, Some(SIGCHLD));
1708
1709 assert_eq!(sys_kill(&task1, 0, SIGINT.into()), Ok(()));
1710 assert_eq!(task1.read().queued_signal_count(SIGINT), 1);
1711 assert_eq!(task2.read().queued_signal_count(SIGINT), 1);
1712 assert_eq!(init_task.read().queued_signal_count(SIGINT), 0);
1713 })
1714 .await;
1715 }
1716
1717 #[::fuchsia::test]
1720 async fn test_kill_thread_group_ignored_signal() {
1721 spawn_kernel_and_run(async |init_task| {
1722 let task = init_task.clone_task_for_test(0, Some(SIGCHLD));
1723 task.thread_group().setsid().expect("setsid");
1724
1725 assert_eq!(sys_kill(&task, 0, SIGWINCH.into()), Ok(()));
1727 assert_eq!(task.read().queued_signal_count(SIGWINCH), 0);
1728
1729 task.write().set_signal_mask(SIGWINCH.into());
1730 assert_eq!(sys_kill(&task, 0, SIGWINCH.into()), Ok(()));
1731 assert_eq!(task.read().queued_signal_count(SIGWINCH), 1);
1732 })
1733 .await;
1734 }
1735
1736 #[::fuchsia::test]
1738 async fn test_kill_thread_group() {
1739 spawn_kernel_and_run(async |init_task| {
1740 let task1 = init_task.clone_task_for_test(0, Some(SIGCHLD));
1741 task1.thread_group().setsid().expect("setsid");
1742 let task2 = task1.clone_task_for_test(0, Some(SIGCHLD));
1743
1744 assert_eq!(sys_kill(&task1, -task1.tid.id, SIGINT.into()), Ok(()));
1745 assert_eq!(task1.read().queued_signal_count(SIGINT), 1);
1746 assert_eq!(task2.read().queued_signal_count(SIGINT), 1);
1747 assert_eq!(init_task.read().queued_signal_count(SIGINT), 0);
1748 })
1749 .await;
1750 }
1751
1752 #[::fuchsia::test]
1754 async fn test_kill_all() {
1755 spawn_kernel_and_run(async |init_task| {
1756 let task1 = init_task.clone_task_for_test(0, Some(SIGCHLD));
1757 task1.thread_group().setsid().expect("setsid");
1758 let task2 = task1.clone_task_for_test(0, Some(SIGCHLD));
1759
1760 assert_eq!(sys_kill(&task1, -1, SIGINT.into()), Ok(()));
1761 assert_eq!(task1.read().queued_signal_count(SIGINT), 0);
1762 assert_eq!(task2.read().queued_signal_count(SIGINT), 1);
1763 assert_eq!(init_task.read().queued_signal_count(SIGINT), 0);
1764 })
1765 .await;
1766 }
1767
1768 #[::fuchsia::test]
1770 async fn test_kill_inexistant_task() {
1771 spawn_kernel_and_run(async |current_task| {
1772 assert_eq!(sys_kill(¤t_task, 9, SIGINT.into()), error!(ESRCH));
1773 })
1774 .await;
1775 }
1776
1777 #[::fuchsia::test]
1779 async fn test_kill_invalid_task() {
1780 spawn_kernel_and_run(async |task1| {
1781 task1.set_creds(Credentials::with_ids(1, 1));
1783 let task2 = task1.clone_task_for_test(0, Some(SIGCHLD));
1784 task2.set_creds(Credentials::with_ids(2, 2));
1785
1786 assert!(task1.can_signal(&task2, SIGINT.into()).is_err());
1787 assert_eq!(sys_kill(&task2, task1.tid.id, SIGINT.into()), error!(EPERM));
1788 assert_eq!(task1.read().queued_signal_count(SIGINT), 0);
1789 })
1790 .await;
1791 }
1792
1793 #[::fuchsia::test]
1795 async fn test_kill_invalid_task_in_thread_group() {
1796 spawn_kernel_and_run(async |init_task| {
1797 let task1 = init_task.clone_task_for_test(0, Some(SIGCHLD));
1798 task1.thread_group().setsid().expect("setsid");
1799 let task2 = task1.clone_task_for_test(0, Some(SIGCHLD));
1800 task2.thread_group().setsid().expect("setsid");
1801 task2.set_creds(Credentials::with_ids(2, 2));
1802
1803 assert!(task2.can_signal(&task1, SIGINT.into()).is_err());
1804 assert_eq!(sys_kill(&task2, -task1.tid.id, SIGINT.into()), error!(EPERM));
1805 assert_eq!(task1.read().queued_signal_count(SIGINT), 0);
1806 })
1807 .await;
1808 }
1809
1810 #[::fuchsia::test]
1812 async fn test_kill_invalid_signal() {
1813 spawn_kernel_and_run(async |current_task| {
1814 assert_eq!(
1815 sys_kill(¤t_task, current_task.tid.id, UncheckedSignal::from(75)),
1816 error!(EINVAL)
1817 );
1818 })
1819 .await;
1820 }
1821
1822 #[::fuchsia::test]
1824 async fn test_blocked_signal_pending() {
1825 spawn_kernel_and_run(async |current_task| {
1826 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1827 current_task
1828 .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1829 .expect("failed to clear struct");
1830
1831 let new_mask = SigSet::from(SIGIO);
1832 let set = UserRef::<SigSet>::new(addr);
1833 current_task.write_object(set, &new_mask).expect("failed to set mask");
1834
1835 assert_eq!(
1836 sys_rt_sigprocmask(
1837 ¤t_task,
1838 SIG_BLOCK,
1839 set,
1840 UserRef::default(),
1841 std::mem::size_of::<SigSet>()
1842 ),
1843 Ok(())
1844 );
1845 assert_eq!(sys_kill(¤t_task, current_task.tid.id, SIGIO.into()), Ok(()));
1846 assert_eq!(current_task.read().queued_signal_count(SIGIO), 1);
1847
1848 assert_eq!(sys_kill(¤t_task, current_task.tid.id, SIGIO.into()), Ok(()));
1850 assert_eq!(current_task.read().queued_signal_count(SIGIO), 1);
1851 })
1852 .await;
1853 }
1854
1855 #[::fuchsia::test]
1857 async fn test_blocked_real_time_signal_pending() {
1858 spawn_kernel_and_run(async |current_task| {
1859 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1860 current_task
1861 .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1862 .expect("failed to clear struct");
1863
1864 let new_mask = SigSet::from(starnix_uapi::signals::SIGRTMIN);
1865 let set = UserRef::<SigSet>::new(addr);
1866 current_task.write_object(set, &new_mask).expect("failed to set mask");
1867
1868 assert_eq!(
1869 sys_rt_sigprocmask(
1870 ¤t_task,
1871 SIG_BLOCK,
1872 set,
1873 UserRef::default(),
1874 std::mem::size_of::<SigSet>()
1875 ),
1876 Ok(())
1877 );
1878 assert_eq!(sys_kill(¤t_task, current_task.tid.id, SIGRTMIN.into()), Ok(()));
1879 assert_eq!(current_task.read().queued_signal_count(starnix_uapi::signals::SIGRTMIN), 1);
1880
1881 assert_eq!(sys_kill(¤t_task, current_task.tid.id, SIGRTMIN.into()), Ok(()));
1883 assert_eq!(current_task.read().queued_signal_count(starnix_uapi::signals::SIGRTMIN), 2);
1884 })
1885 .await;
1886 }
1887
1888 #[::fuchsia::test]
1889 async fn test_suspend() {
1890 spawn_kernel_and_run(async |current_task| {
1891 let init_task_weak = current_task.weak_task();
1892 let (tx, rx) = std::sync::mpsc::sync_channel::<()>(0);
1893
1894 let closure = move |current_task: &CurrentTask| {
1895 let init_task_temp = init_task_weak.upgrade().expect("Task must be alive");
1896
1897 let mut suspended = false;
1899 while !suspended {
1900 suspended = init_task_temp.read().is_blocked();
1901 std::thread::sleep(std::time::Duration::from_millis(10));
1902 }
1903
1904 let _ =
1906 sys_kill(current_task, init_task_temp.tid.id, UncheckedSignal::from(SIGHUP));
1907
1908 rx.recv().expect("receive");
1910 assert!(!init_task_temp.read().is_blocked());
1911 };
1912 let (thread, req) =
1913 SpawnRequestBuilder::new().with_sync_closure(closure).build_with_async_result();
1914 current_task.kernel().kthreads.spawner().spawn_from_request(req);
1915
1916 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
1917 let user_ref = UserRef::<SigSet>::new(addr);
1918
1919 let sigset = !SigSet::from(SIGHUP);
1920 current_task.write_object(user_ref, &sigset).expect("failed to set action");
1921
1922 assert_eq!(
1923 sys_rt_sigsuspend(current_task, user_ref, std::mem::size_of::<SigSet>()),
1924 error!(ERESTARTNOHAND)
1925 );
1926 tx.send(()).expect("send");
1927 futures::executor::block_on(thread).expect("join");
1928 })
1929 .await;
1930 }
1931
1932 #[::fuchsia::test]
1934 async fn test_waitid_options() {
1935 spawn_kernel_and_run(async |current_task| {
1936 let id = 1;
1937 assert_eq!(
1938 sys_waitid(
1939 ¤t_task,
1940 P_PID,
1941 id,
1942 MultiArchUserRef::null(current_task),
1943 0,
1944 UserRef::default().into()
1945 ),
1946 error!(EINVAL)
1947 );
1948 assert_eq!(
1949 sys_waitid(
1950 ¤t_task,
1951 P_PID,
1952 id,
1953 MultiArchUserRef::null(current_task),
1954 0xffff,
1955 UserRef::default().into()
1956 ),
1957 error!(EINVAL)
1958 );
1959 })
1960 .await;
1961 }
1962
1963 #[::fuchsia::test]
1965 async fn test_wait4_options() {
1966 spawn_kernel_and_run(async |current_task| {
1967 let id = 1;
1968 assert_eq!(
1969 sys_wait4(
1970 ¤t_task,
1971 id,
1972 UserRef::default(),
1973 WEXITED,
1974 RUsagePtr::null(current_task)
1975 ),
1976 error!(EINVAL)
1977 );
1978 assert_eq!(
1979 sys_wait4(
1980 ¤t_task,
1981 id,
1982 UserRef::default(),
1983 WNOWAIT,
1984 RUsagePtr::null(current_task)
1985 ),
1986 error!(EINVAL)
1987 );
1988 assert_eq!(
1989 sys_wait4(
1990 ¤t_task,
1991 id,
1992 UserRef::default(),
1993 0xffff,
1994 RUsagePtr::null(current_task)
1995 ),
1996 error!(EINVAL)
1997 );
1998 })
1999 .await;
2000 }
2001
2002 #[::fuchsia::test]
2003 async fn test_echild_when_no_zombie() {
2004 spawn_kernel_and_run(async |current_task| {
2005 assert!(
2007 sys_kill(¤t_task, current_task.get_pid(), UncheckedSignal::from(SIGCHLD))
2008 .is_ok()
2009 );
2010 assert_eq!(
2013 wait_on_pid(
2014 ¤t_task,
2015 &ProcessSelector::Any,
2016 &WaitingOptions::new_for_wait4(0).expect("WaitingOptions")
2017 ),
2018 error!(ECHILD)
2019 );
2020 })
2021 .await;
2022 }
2023
2024 #[::fuchsia::test]
2025 async fn test_no_error_when_zombie() {
2026 spawn_kernel_and_run(async |current_task| {
2027 let child = current_task.clone_task_for_test(0, Some(SIGCHLD));
2028 let expected_result = WaitResult {
2029 pid: child.tid.clone(),
2030 uid: 0,
2031 zombie_state: ZombieState {
2032 exit_status: ExitStatus::Exit(1),
2033 time_stats: Default::default(),
2034 },
2035 exit_signal: Some(SIGCHLD),
2036 };
2037 child.thread_group().kill(ExitStatus::Exit(1), None);
2038 std::mem::drop(child);
2039
2040 assert_eq!(
2041 wait_on_pid(
2042 ¤t_task,
2043 &ProcessSelector::Any,
2044 &WaitingOptions::new_for_wait4(0).expect("WaitingOptions")
2045 ),
2046 Ok(Some(expected_result))
2047 );
2048 })
2049 .await;
2050 }
2051
2052 #[::fuchsia::test]
2053 async fn test_waiting_for_child() {
2054 spawn_kernel_and_run(async |task| {
2055 let child = task.clone_task_builder_for_test(0, Some(SIGCHLD));
2056
2057 assert_eq!(
2059 wait_on_pid(
2060 &task,
2061 &ProcessSelector::Any,
2062 &WaitingOptions::new_for_wait4(WNOHANG).expect("WaitingOptions")
2063 ),
2064 Ok(None)
2065 );
2066
2067 let thread = std::thread::spawn({
2068 let task = task.weak_task();
2069 move || {
2070 let task = task.upgrade().expect("task must be alive");
2072 let child: AutoReleasableTask = child.into();
2073 while !task.read().is_blocked() {
2075 std::thread::sleep(std::time::Duration::from_millis(10));
2076 }
2077 child.thread_group().kill(ExitStatus::Exit(0), None);
2078 child.tid.clone()
2079 }
2080 });
2081
2082 let waited_child = wait_on_pid(
2084 &task,
2085 &ProcessSelector::Any,
2086 &WaitingOptions::new_for_wait4(0).expect("WaitingOptions"),
2087 )
2088 .expect("wait_on_pid")
2089 .unwrap();
2090
2091 let child_id = thread.join().expect("join");
2093 assert_eq!(waited_child.pid, child_id);
2094 })
2095 .await;
2096 }
2097
2098 #[::fuchsia::test]
2099 async fn test_waiting_for_child_with_signal_pending() {
2100 spawn_kernel_and_run(async |task| {
2101 task.thread_group().signal_actions.set(
2103 SIGUSR1,
2104 sigaction_t { sa_handler: uaddr { addr: 0xDEADBEEF }, ..sigaction_t::default() },
2105 );
2106
2107 let _child = task.clone_task_for_test(0, Some(SIGCHLD));
2109
2110 send_standard_signal(&task, SignalInfo::kernel(SIGUSR1));
2113
2114 let errno = wait_on_pid(
2115 &task,
2116 &ProcessSelector::Any,
2117 &WaitingOptions::new_for_wait4(0).expect("WaitingOptions"),
2118 )
2119 .expect_err("wait_on_pid");
2120 assert_eq!(errno, ERESTARTSYS);
2121 })
2122 .await;
2123 }
2124
2125 #[::fuchsia::test]
2126 async fn test_sigkill() {
2127 spawn_kernel_and_run(async |current_task| {
2128 let mut child = current_task.clone_task_for_test(0, Some(SIGCHLD));
2129
2130 send_standard_signal(&child, SignalInfo::kernel(SIGKILL));
2132 dequeue_signal_for_test(&mut child);
2133 std::mem::drop(child);
2134
2135 let address = map_memory(
2137 ¤t_task,
2138 UserAddress::default(),
2139 std::mem::size_of::<i32>() as u64,
2140 );
2141 let address_ref = UserRef::<i32>::new(address);
2142 sys_wait4(¤t_task, -1, address_ref, 0, RUsagePtr::null(current_task))
2143 .expect("wait4");
2144 let wstatus = current_task.read_object(address_ref).expect("read memory");
2145 assert_eq!(wstatus, SIGKILL.number() as i32);
2146 })
2147 .await;
2148 }
2149
2150 async fn test_exit_status_for_signal(
2151 sig: Signal,
2152 wait_status: i32,
2153 exit_signal: Option<Signal>,
2154 ) {
2155 spawn_kernel_and_run(async move |current_task| {
2156 let mut child = current_task.clone_task_for_test(0, exit_signal);
2157
2158 send_standard_signal(&child, SignalInfo::kernel(sig));
2160 dequeue_signal_for_test(&mut child);
2161 std::mem::drop(child);
2162
2163 let address = map_memory(
2165 ¤t_task,
2166 UserAddress::default(),
2167 std::mem::size_of::<i32>() as u64,
2168 );
2169 let address_ref = UserRef::<i32>::new(address);
2170 sys_wait4(¤t_task, -1, address_ref, 0, RUsagePtr::null(current_task))
2171 .expect("wait4");
2172 let wstatus = current_task.read_object(address_ref).expect("read memory");
2173 assert_eq!(wstatus, wait_status);
2174 })
2175 .await;
2176 }
2177
2178 #[::fuchsia::test]
2179 async fn test_exit_status() {
2180 test_exit_status_for_signal(SIGTERM, SIGTERM.number() as i32, Some(SIGCHLD)).await;
2182 test_exit_status_for_signal(SIGSEGV, (SIGSEGV.number() as i32) | 0x80, Some(SIGCHLD)).await;
2184 }
2185
2186 #[::fuchsia::test]
2187 async fn test_wait4_by_pgid() {
2188 spawn_kernel_and_run(async |current_task| {
2189 let child1 = current_task.clone_task_for_test(0, Some(SIGCHLD));
2190 let child1_pid = child1.tid.id;
2191 child1.thread_group().kill(ExitStatus::Exit(42), None);
2192 std::mem::drop(child1);
2193 let child2 = current_task.clone_task_for_test(0, Some(SIGCHLD));
2194 child2.thread_group().setsid().expect("setsid");
2195 let child2_pid = child2.tid.id;
2196 child2.thread_group().kill(ExitStatus::Exit(42), None);
2197 std::mem::drop(child2);
2198
2199 assert_eq!(
2200 sys_wait4(
2201 ¤t_task,
2202 -child2_pid,
2203 UserRef::default(),
2204 0,
2205 RUsagePtr::null(current_task)
2206 ),
2207 Ok(child2_pid)
2208 );
2209 assert_eq!(
2210 sys_wait4(¤t_task, 0, UserRef::default(), 0, RUsagePtr::null(current_task)),
2211 Ok(child1_pid)
2212 );
2213 })
2214 .await;
2215 }
2216
2217 #[::fuchsia::test]
2218 async fn test_waitid_by_pgid() {
2219 spawn_kernel_and_run(async |current_task| {
2220 let child1 = current_task.clone_task_for_test(0, Some(SIGCHLD));
2221 let child1_pid = child1.tid.id;
2222 child1.thread_group().kill(ExitStatus::Exit(42), None);
2223 std::mem::drop(child1);
2224 let child2 = current_task.clone_task_for_test(0, Some(SIGCHLD));
2225 child2.thread_group().setsid().expect("setsid");
2226 let child2_pid = child2.tid.id;
2227 child2.thread_group().kill(ExitStatus::Exit(42), None);
2228 std::mem::drop(child2);
2229
2230 let address: UserRef<uapi::siginfo_t> =
2231 map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE).into();
2232 assert_eq!(
2233 sys_waitid(
2234 ¤t_task,
2235 P_PGID,
2236 child2_pid,
2237 address.into(),
2238 WEXITED,
2239 UserRef::default().into()
2240 ),
2241 Ok(())
2242 );
2243 assert_eq!(
2245 current_task.thread_group().read().zombie_children[0].task.get_pid(),
2246 child1_pid
2247 );
2248
2249 assert_eq!(
2250 sys_waitid(
2251 ¤t_task,
2252 P_PGID,
2253 0,
2254 address.into(),
2255 WEXITED,
2256 UserRef::default().into()
2257 ),
2258 Ok(())
2259 );
2260 })
2261 .await;
2262 }
2263
2264 #[::fuchsia::test]
2265 async fn test_sigqueue() {
2266 spawn_kernel_and_run(async |current_task| {
2267 let current_uid = current_task.current_creds().uid;
2268 let current_pid = current_task.get_pid();
2269
2270 const TEST_VALUE: u64 = 101;
2271
2272 const ARCH64_SI_HEADER_SIZE: usize = SI_HEADER_SIZE + 4;
2274 const PID_DATA_OFFSET: usize = ARCH64_SI_HEADER_SIZE;
2276 const UID_DATA_OFFSET: usize = ARCH64_SI_HEADER_SIZE + 4;
2277 const VALUE_DATA_OFFSET: usize = ARCH64_SI_HEADER_SIZE + 8;
2278
2279 let mut data = vec![0u8; SI_MAX_SIZE_AS_USIZE];
2280 let header = SignalInfoHeader {
2281 signo: SIGIO.number(),
2282 code: SI_QUEUE,
2283 ..SignalInfoHeader::default()
2284 };
2285 let _ = header.write_to(&mut data[..SI_HEADER_SIZE]);
2286 data[PID_DATA_OFFSET..PID_DATA_OFFSET + 4].copy_from_slice(¤t_pid.to_ne_bytes());
2287 data[UID_DATA_OFFSET..UID_DATA_OFFSET + 4].copy_from_slice(¤t_uid.to_ne_bytes());
2288 data[VALUE_DATA_OFFSET..VALUE_DATA_OFFSET + 8]
2289 .copy_from_slice(&TEST_VALUE.to_ne_bytes());
2290
2291 let addr = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
2292 current_task.write_memory(addr, &data).unwrap();
2293 let second_current = create_task(current_task.kernel(), "second task");
2294 let second_pid = second_current.get_pid();
2295 let second_tid = second_current.get_tid();
2296 assert_eq!(second_current.read().queued_signal_count(SIGIO), 0);
2297
2298 assert_eq!(
2299 sys_rt_tgsigqueueinfo(
2300 ¤t_task,
2301 second_pid,
2302 second_tid,
2303 UncheckedSignal::from(SIGIO),
2304 addr
2305 ),
2306 Ok(())
2307 );
2308 assert_eq!(second_current.read().queued_signal_count(SIGIO), 1);
2309
2310 let signal = SignalInfo::with_detail(
2311 SIGIO,
2312 SI_QUEUE,
2313 SignalDetail::Kill {
2314 pid: current_task.pid.clone(),
2315 uid: current_task.current_creds().uid,
2316 },
2317 );
2318 let queued_signal = second_current.write().take_specific_signal(signal);
2319 if let Some(sig) = queued_signal {
2320 assert_eq!(sig.signal, SIGIO);
2321 assert_eq!(sig.errno, 0);
2322 assert_eq!(sig.code, SI_QUEUE);
2323 if let SignalDetail::Raw { data } = sig.detail {
2324 let offset_pid = PID_DATA_OFFSET - ARCH64_SI_HEADER_SIZE;
2326 let offset_uid = UID_DATA_OFFSET - ARCH64_SI_HEADER_SIZE;
2327 let offset_value = VALUE_DATA_OFFSET - ARCH64_SI_HEADER_SIZE;
2328 let pid =
2329 pid_t::from_ne_bytes(data[offset_pid..offset_pid + 4].try_into().unwrap());
2330 let uid =
2331 uid_t::from_ne_bytes(data[offset_uid..offset_uid + 4].try_into().unwrap());
2332 let value = u64::from_ne_bytes(
2333 data[offset_value..offset_value + 8].try_into().unwrap(),
2334 );
2335 assert_eq!(pid, current_pid);
2336 assert_eq!(uid, current_uid);
2337 assert_eq!(value, TEST_VALUE);
2338 } else {
2339 panic!("incorrect signal detail");
2340 }
2341 } else {
2342 panic!("expected a queued signal");
2343 }
2344 })
2345 .await;
2346 }
2347
2348 #[::fuchsia::test]
2349 async fn test_signalfd_filters_signals() {
2350 spawn_kernel_and_run(async |current_task| {
2351 let memory_for_masks = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
2352
2353 let term_int_mask = SigSet::from(SIGTERM) | SigSet::from(SIGINT);
2355 let term_int_mask_addr = UserRef::<SigSet>::new(memory_for_masks);
2356 current_task
2357 .write_object(term_int_mask_addr, &term_int_mask)
2358 .expect("failed to write mask");
2359 let sfd_term_int = sys_signalfd4(
2360 ¤t_task,
2361 FdNumber::from_raw(-1),
2362 term_int_mask_addr,
2363 std::mem::size_of::<SigSet>(),
2364 0,
2365 )
2366 .expect("failed to create SIGTERM/SIGINT signalfd");
2367
2368 let sigchld_mask = SigSet::from(SIGCHLD);
2370 let sigchld_mask_addr =
2371 UserRef::<SigSet>::new((memory_for_masks + std::mem::size_of::<SigSet>()).unwrap());
2372 current_task
2373 .write_object(sigchld_mask_addr, &sigchld_mask)
2374 .expect("failed to write mask");
2375 let sfd_chld = sys_signalfd4(
2376 ¤t_task,
2377 FdNumber::from_raw(-1),
2378 sigchld_mask_addr,
2379 std::mem::size_of::<SigSet>(),
2380 0,
2381 )
2382 .expect("failed to create SIGCHLD signalfd");
2383
2384 sys_rt_sigprocmask(
2386 ¤t_task,
2387 SIG_BLOCK,
2388 sigchld_mask_addr,
2389 UserRef::default(),
2390 std::mem::size_of::<SigSet>(),
2391 )
2392 .expect("failed to block SIGCHLD");
2393
2394 let child = current_task.clone_task_for_test(0, Some(SIGCHLD));
2396 child.thread_group().kill(ExitStatus::Exit(1), None);
2397 std::mem::drop(child);
2398
2399 let sfd_term_int_file =
2401 current_task.files().get(sfd_term_int).expect("failed to get sfd_term_int file");
2402 let sfd_chld_file =
2403 current_task.files().get(sfd_chld).expect("failed to get sfd_chld file");
2404
2405 let term_int_events = sfd_term_int_file
2406 .query_events(¤t_task)
2407 .expect("failed to query sfd_term_int events");
2408 let chld_events =
2409 sfd_chld_file.query_events(¤t_task).expect("failed to query sfd_chld events");
2410
2411 assert!(!term_int_events.contains(FdEvents::POLLIN));
2412 assert!(chld_events.contains(FdEvents::POLLIN));
2413 })
2414 .await;
2415 }
2416
2417 #[::fuchsia::test]
2418 async fn test_signalfd_filters_signals_async() {
2419 spawn_kernel_and_run(async |current_task| {
2420 let memory_for_masks = map_memory(¤t_task, UserAddress::default(), *PAGE_SIZE);
2421
2422 let term_int_mask = SigSet::from(SIGTERM) | SigSet::from(SIGINT);
2424 let term_int_mask_addr = UserRef::<SigSet>::new(memory_for_masks);
2425 current_task
2426 .write_object(term_int_mask_addr, &term_int_mask)
2427 .expect("failed to write mask");
2428 let sfd_term_int = sys_signalfd4(
2429 ¤t_task,
2430 FdNumber::from_raw(-1),
2431 term_int_mask_addr,
2432 std::mem::size_of::<SigSet>(),
2433 0,
2434 )
2435 .expect("failed to create SIGTERM/SIGINT signalfd");
2436
2437 let sigchld_mask = SigSet::from(SIGCHLD);
2439 let sigchld_mask_addr =
2440 UserRef::<SigSet>::new((memory_for_masks + std::mem::size_of::<SigSet>()).unwrap());
2441 current_task
2442 .write_object(sigchld_mask_addr, &sigchld_mask)
2443 .expect("failed to write mask");
2444 let sfd_chld = sys_signalfd4(
2445 ¤t_task,
2446 FdNumber::from_raw(-1),
2447 sigchld_mask_addr,
2448 std::mem::size_of::<SigSet>(),
2449 0,
2450 )
2451 .expect("failed to create SIGCHLD signalfd");
2452
2453 let waiter = Waiter::new();
2455 let ready_items =
2456 Arc::new(LockDepMutex::<_, EventHandlerReadyQueueLock>::new(VecDeque::new()));
2457
2458 let sfd_term_int_file =
2459 current_task.files().get(sfd_term_int).expect("failed to get sfd_term_int file");
2460 let sfd_chld_file =
2461 current_task.files().get(sfd_chld).expect("failed to get sfd_chld file");
2462
2463 sfd_term_int_file
2464 .wait_async(
2465 ¤t_task,
2466 &waiter,
2467 FdEvents::POLLIN,
2468 EventHandler::Enqueue {
2469 key: sfd_term_int.into(),
2470 queue: ready_items.clone(),
2471 sought_events: FdEvents::POLLIN,
2472 },
2473 )
2474 .expect("failed to wait on sfd_term_int");
2475
2476 sfd_chld_file
2477 .wait_async(
2478 ¤t_task,
2479 &waiter,
2480 FdEvents::POLLIN,
2481 EventHandler::Enqueue {
2482 key: sfd_chld.into(),
2483 queue: ready_items.clone(),
2484 sought_events: FdEvents::POLLIN,
2485 },
2486 )
2487 .expect("failed to wait on sfd_chld");
2488
2489 let sigchld_mask_ref = UserRef::<SigSet>::new(memory_for_masks);
2491 current_task
2492 .write_object(sigchld_mask_ref, &sigchld_mask)
2493 .expect("failed to write mask");
2494 sys_rt_sigprocmask(
2495 ¤t_task,
2496 SIG_BLOCK,
2497 sigchld_mask_ref,
2498 UserRef::default(),
2499 std::mem::size_of::<SigSet>(),
2500 )
2501 .expect("failed to block SIGCHLD");
2502
2503 let child = current_task.clone_task_for_test(0, Some(SIGCHLD));
2505 child.thread_group().kill(ExitStatus::Exit(1), None);
2506 std::mem::drop(child);
2507
2508 waiter.wait(¤t_task).expect("failed to wait");
2510
2511 let ready_items = ready_items.lock();
2513 assert_eq!(ready_items.len(), 1);
2514 assert_eq!(ready_items[0].key, sfd_chld.into());
2515 })
2516 .await;
2517 }
2518}