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