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