Skip to main content

starnix_core/signals/
syscalls.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5pub use super::signal_handling::sys_restart_syscall;
6use super::signalfd::SignalFd;
7use crate::mm::MemoryAccessorExt;
8use crate::security;
9use crate::signals::{
10    IntoSignalInfoOptions, SignalDetail, SignalInfo, UncheckedSignalInfo,
11    restore_from_signal_handler, send_signal,
12};
13use crate::task::{
14    CurrentTask, Pid, ProcessEntryRef, ProcessSelector, Task, TaskMutableState, ThreadGroup,
15    ThreadGroupLifecycleWaitValue, WaitResult, WaitableChildResult, Waiter,
16};
17use crate::vfs::{FdFlags, FdNumber};
18use fuchsia_rcu::RcuReadScope;
19use starnix_uapi::user_address::{ArchSpecific, MultiArchUserRef};
20use starnix_uapi::{tid_t, uapi};
21
22use starnix_logging::track_stub;
23use starnix_sync::InterruptibleEvent;
24use starnix_syscalls::SyscallResult;
25use starnix_types::time::{duration_from_timespec, timeval_from_duration};
26use starnix_uapi::errors::{EINTR, ETIMEDOUT, Errno, ErrnoResultExt};
27use starnix_uapi::open_flags::OpenFlags;
28use starnix_uapi::signals::{SigSet, Signal, UNBLOCKABLE_SIGNALS, UncheckedSignal};
29use starnix_uapi::user_address::{UserAddress, UserRef};
30use starnix_uapi::{
31    __WALL, __WCLONE, __WNOTHREAD, P_ALL, P_PGID, P_PID, P_PIDFD, SFD_CLOEXEC, SFD_NONBLOCK,
32    SI_TKILL, SIG_BLOCK, SIG_SETMASK, SIG_UNBLOCK, SS_AUTODISARM, SS_DISABLE, SS_ONSTACK,
33    WCONTINUED, WEXITED, WNOHANG, WNOWAIT, WSTOPPED, WUNTRACED, errno, error, pid_t, rusage,
34    sigaltstack,
35};
36use static_assertions::const_assert_eq;
37use zerocopy::{FromBytes, Immutable, IntoBytes};
38
39pub type RUsagePtr = MultiArchUserRef<uapi::rusage, uapi::arch32::rusage>;
40type SigAction64Ptr = MultiArchUserRef<uapi::sigaction_t, uapi::arch32::sigaction64_t>;
41type SigActionPtr = MultiArchUserRef<uapi::sigaction_t, uapi::arch32::sigaction_t>;
42
43/// The `rt_sigaction` syscall allows the calling process to examine and change the action
44/// associated with a specific signal.
45///
46/// # Args
47/// * `signum`: The signal number to examine or change. It can be any valid signal except
48///   `SIGKILL` and `SIGSTOP`.
49/// * `user_action`: A pointer to a `sigaction` structure. If it is not null, the new action
50///   for signal `signum` is installed from it.
51/// * `user_old_action`: A pointer to a `sigaction` structure. If it is not null, the previous
52///   action is saved in it.
53/// * `sigset_size`: The size in bytes of the signal sets in `user_action` and `user_old_action`.
54///
55/// # Returns
56/// `Ok(())` on success. Otherwise, returns an `Errno` with the error code.
57pub 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        // Actions can't be set for SIGKILL and SIGSTOP, but the actions for these signals can
90        // still be returned in `user_old_action`, so only return early if the intention is to
91        // set an action (i.e., the user_action is non-null).
92        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 = &current_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
116/// The `rt_sigpending` syscall returns the set of signals that are pending for delivery to the
117/// calling thread.
118///
119/// # Args
120/// * `set`: A pointer to a `sigset_t` where the set of pending signals is stored.
121/// * `sigset_size`: The size of the signal set, in bytes.
122///
123/// # Returns
124/// `Ok(())` on success. Otherwise, returns an `Errno` with the error code.
125pub 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
139/// The `rt_sigprocmask` syscall is used to fetch and/or change the signal mask of the calling
140/// thread.
141///
142/// # Args
143/// * `how`: Specifies how the signal mask should be changed. Can be `SIG_BLOCK`, `SIG_UNBLOCK`,
144///   or `SIG_SETMASK`.
145/// * `user_set`: A pointer to a signal set. The interpretation of this set depends on `how`.
146/// * `user_old_set`: If not null, the previous signal mask is stored here.
147/// * `sigset_size`: The size of the signal set, in bytes.
148///
149/// # Returns
150/// `Ok(())` on success. Otherwise, returns an `Errno` with the error code.
151pub 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    // Read the new mask. This must be done before the old mask is written to `user_old_set`
167    // since it might point to the same location as `user_set`.
168    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 old_set is not null, store the previous value in old_set.
176    if !user_old_set.is_null() {
177        current_task.write_object(user_old_set, &signal_mask)?;
178    }
179
180    // If set is null, how is ignored and the mask is not updated.
181    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        // Arguments have already been verified, this should never match.
190        _ => 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
199/// The `sigaltstack` syscall allows a process to define an alternate signal stack.
200///
201/// # Args
202/// * `user_ss`: A pointer to a `sigaltstack` structure specifying the new alternate signal stack.
203/// * `user_old_ss`: If not null, the previous alternate signal stack is stored here.
204///
205/// # Returns
206/// `Ok(())` on success. Otherwise, returns an `Errno` with the error code.
207pub 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
254/// The `rt_sigsuspend` syscall temporarily replaces the signal mask of the calling thread with
255/// the mask given by `user_mask` and then suspends the thread until delivery of a signal whose
256/// action is to invoke a signal handler or to terminate a process.
257///
258/// # Args
259/// * `user_mask`: A pointer to a signal set that will temporarily replace the thread's signal mask.
260/// * `sigset_size`: The size of the signal set, in bytes.
261///
262/// # Returns
263/// This function never returns `Ok(())`. It always returns an `Errno`, typically `EINTR` (or a
264/// restart equivalent).
265pub 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    // ERESTARTNOHAND indicates that the error should be EINTR if
277    // interrupted by a signal delivered to a user handler, and the syscall
278    // should be restarted otherwise.
279    current_task
280        .wait_with_temporary_mask(mask, |current_task| waiter.wait(current_task))
281        .map_eintr(|| errno!(ERESTARTNOHAND))
282}
283
284/// The `rt_sigtimedwait` syscall waits for one of the signals in `set_addr` to become pending
285/// for the calling thread. The call will block until a signal is pending or the timeout expires.
286///
287/// # Args
288/// * `set_addr`: A pointer to a signal set specifying the signals to wait for.
289/// * `siginfo_addr`: If not null, a `siginfo_t` structure for the received signal is stored here.
290/// * `timeout_addr`: If not null, specifies a timeout for the wait.
291/// * `sigset_size`: The size of the signal set, in bytes.
292///
293/// # Returns
294/// On success, returns `Ok(Signal)` containing the signal that was caught. On failure, returns
295/// an `Errno`.
296pub 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    // Signals in `set_addr` are what we are waiting for.
308    let set = current_task.read_object(set_addr)?;
309    // Attempts to wait for `UNBLOCKABLE_SIGNALS` will be ignored.
310    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 one of the signals in set is already pending for the calling thread,
324            // sigwaitinfo() will return immediately.
325            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        // A new signal is enqueued when it's masked in the SignalState. So we need to invert
334        // the SigSet to block them.
335        let tmp_mask = current_task.read().signal_mask() & !unblock;
336
337        // Wait for a timeout or a new signal.
338        let waiter_result = current_task.wait_with_temporary_mask(tmp_mask, |current_task| {
339            waiter.wait_until(current_task, deadline)
340        });
341
342        // Restore mask after timeout or get a new signal.
343        current_task.write().restore_signal_mask();
344
345        if let Err(e) = waiter_result {
346            if e == EINTR {
347                // Check if EINTR was returned for a signal we were waiting for.
348                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
366/// The `signalfd4` syscall creates a file descriptor that can be used to accept signals targeted
367/// at the caller.
368///
369/// # Args
370/// * `fd`: A file descriptor. If -1, a new file descriptor is created. Otherwise, the mask of the
371///   existing signalfd is modified.
372/// * `mask_addr`: A pointer to a signal set specifying the signals to handle with this signalfd.
373/// * `mask_size`: The size of the signal set, in bytes.
374/// * `flags`: Flags to control the behavior of the file descriptor.
375///
376/// # Returns
377/// On success, returns `Ok(FdNumber)` containing the file descriptor number. On failure, returns
378/// an `Errno`.
379pub 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    // 0 is a sentinel value used to do permission checks.
417    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/// Sends `siginfo` to `target`, a single task.
439///
440/// The caller must have already validated `siginfo` with `UncheckedSignalInfo::check_code`.
441#[track_caller]
442fn send_unchecked_signal_info(
443    current_task: &CurrentTask,
444    target: &Task,
445    unchecked_signal: UncheckedSignal,
446    siginfo: UncheckedSignalInfo,
447) -> Result<(), Errno> {
448    current_task.can_signal(&target, unchecked_signal)?;
449
450    // 0 is a sentinel value used to do permission checks.
451    if unchecked_signal.is_zero() {
452        return Ok(());
453    }
454
455    let signal = Signal::try_from(unchecked_signal)?;
456    security::check_signal_access(current_task, &target, signal)?;
457
458    send_signal(&target, siginfo.into_signal_info(signal, IntoSignalInfoOptions::None)?)
459}
460
461/// The `kill` syscall can be used to send any signal to any process group or process.
462///
463/// # Args
464/// * `pid`: Specifies the target process or process group. See `kill(2)` for details.
465/// * `unchecked_signal`: The signal to send.
466///
467/// # Returns
468/// `Ok(())` on success. Otherwise, returns an `Errno` with the error code.
469pub fn sys_kill(
470    current_task: &CurrentTask,
471    pid: pid_t,
472    unchecked_signal: UncheckedSignal,
473) -> Result<(), Errno> {
474    let pids = &current_task.kernel().pids;
475    match pid {
476        pid if pid > 0 => {
477            // "If pid is positive, then signal sig is sent to the process with
478            // the ID specified by pid."
479            let target_thread_group = {
480                let pid_entry = pids.get(pid)?;
481                match pid_entry.get_process() {
482                    Some(ProcessEntryRef::Process(process)) => process,
483
484                    // Zombies cannot receive signals. Just ignore it.
485                    Some(ProcessEntryRef::Zombie) => return Ok(()),
486
487                    // If there is no process with `pid`, check if there is a task with
488                    // the `pid`.
489                    None => {
490                        let task = pid_entry.get_task()?;
491                        task.thread_group().clone()
492                    }
493                }
494            };
495
496            target_thread_group.send_signal_unchecked(current_task, unchecked_signal)?;
497        }
498        pid if pid == -1 => {
499            // "If pid equals -1, then sig is sent to every process for which
500            // the calling process has permission to send signals, except for
501            // process 1 (init), but ... POSIX.1-2001 requires that kill(-1,sig)
502            // send sig to all processes that the calling process may send
503            // signals to, except possibly for some implementation-defined
504            // system processes. Linux allows a process to signal itself, but on
505            // Linux the call kill(-1,sig) does not signal the calling process."
506
507            let thread_groups: Vec<_> = pids
508                .get_thread_groups(&RcuReadScope::new())
509                .filter(|thread_group| {
510                    if *current_task.thread_group() == *thread_group {
511                        return false;
512                    }
513                    if thread_group.leader.id == 1 {
514                        return false;
515                    }
516                    true
517                })
518                .collect();
519            signal_thread_groups(current_task, unchecked_signal, thread_groups)?;
520        }
521        _ => {
522            // "If pid equals 0, then sig is sent to every process in the
523            // process group of the calling process."
524            //
525            // "If pid is less than -1, then sig is sent to every process in the
526            // process group whose ID is -pid."
527            let pid = match pid {
528                0 => current_task.thread_group().pgid(),
529                _ => pids.get(negate_pid(pid)?)?,
530            };
531
532            let scope = RcuReadScope::new();
533            signal_thread_groups(current_task, unchecked_signal, pid.pgid_thread_groups(&scope))?;
534        }
535    };
536
537    Ok(())
538}
539
540fn verify_tgid_for_task(task: &Task, tgid: &Pid) -> Result<(), Errno> {
541    if &task.pid != tgid {
542        return error!(EINVAL);
543    } else {
544        Ok(())
545    }
546}
547
548/// The `tkill` syscall sends the signal `unchecked_signal` to the thread with the thread ID
549/// `tid`.
550///
551/// This is an obsolete and non-standard syscall that is replaced by `tgkill`.
552///
553/// # Args
554/// * `tid`: The thread ID of the thread to send the signal to.
555/// * `unchecked_signal`: The signal to send.
556///
557/// # Returns
558/// `Ok(())` on success. Otherwise, returns an `Errno` with the error code.
559pub fn sys_tkill(
560    current_task: &CurrentTask,
561    tid: tid_t,
562    unchecked_signal: UncheckedSignal,
563) -> Result<(), Errno> {
564    // Linux returns EINVAL when the tgid or tid <= 0.
565    if tid <= 0 {
566        return error!(EINVAL);
567    }
568    let thread = current_task.get_task(tid)?;
569    send_unchecked_signal(current_task, &thread, unchecked_signal, SI_TKILL)
570}
571
572/// The `tgkill` syscall sends the signal `unchecked_signal` to the thread with thread ID `tid`
573/// in the thread group `tgid`.
574///
575/// # Args
576/// * `tgid`: The thread group ID of the target thread.
577/// * `tid`: The thread ID of the target thread.
578/// * `unchecked_signal`: The signal to send.
579///
580/// # Returns
581/// `Ok(())` on success. Otherwise, returns an `Errno` with the error code.
582pub fn sys_tgkill(
583    current_task: &CurrentTask,
584    tgid: pid_t,
585    tid: tid_t,
586    unchecked_signal: UncheckedSignal,
587) -> Result<(), Errno> {
588    // Linux returns EINVAL when the tgid or tid <= 0.
589    if tgid <= 0 || tid <= 0 {
590        return error!(EINVAL);
591    }
592    let pids = &current_task.kernel().pids;
593    let tid = pids.get(tid)?;
594    let tgid = pids.get(tgid)?;
595    let thread = tid.get_task()?;
596    verify_tgid_for_task(&thread, &tgid)?;
597    send_unchecked_signal(current_task, &thread, unchecked_signal, SI_TKILL)
598}
599
600/// The `rt_sigreturn` syscall returns from a signal handler and restores the process's context.
601///
602/// This function is not intended to be called directly by user code, but is instead part of the
603/// signal handling trampoline that is set up by the kernel.
604///
605/// # Returns
606/// A `SyscallResult` with the value that should be returned to userspace. This function
607/// does not return to the caller in the kernel on success.
608pub fn sys_rt_sigreturn(current_task: &mut CurrentTask) -> Result<SyscallResult, Errno> {
609    restore_from_signal_handler(current_task)?;
610    Ok(current_task.thread_state.registers.return_register().into())
611}
612
613/// The `rt_sigqueueinfo` syscall sends a signal with a payload to a process.
614///
615/// # Args
616/// * `tgid`: The thread group ID of the process to send the signal to.
617/// * `unchecked_signal`: The signal to send.
618/// * `siginfo_ref`: A pointer to a `siginfo_t` structure that contains the signal payload.
619///
620/// # Returns
621/// `Ok(())` on success. Otherwise, returns an `Errno` with the error code.
622pub fn sys_rt_sigqueueinfo(
623    current_task: &CurrentTask,
624    tgid: pid_t,
625    unchecked_signal: UncheckedSignal,
626    siginfo_ref: UserAddress,
627) -> Result<(), Errno> {
628    let siginfo = UncheckedSignalInfo::read_from_siginfo(current_task, siginfo_ref)?;
629    if tgid != current_task.get_pid() {
630        siginfo.check_code()?;
631    }
632
633    let target_thread_group = {
634        let pid_entry = current_task.kernel().pids.get(tgid)?;
635        match pid_entry.get_process() {
636            Some(ProcessEntryRef::Process(process)) => process,
637            Some(ProcessEntryRef::Zombie) => return Ok(()),
638            None => {
639                let task = pid_entry.get_task()?;
640                task.thread_group().clone()
641            }
642        }
643    };
644    target_thread_group.send_signal_unchecked_with_info(
645        current_task,
646        unchecked_signal,
647        siginfo,
648        IntoSignalInfoOptions::None,
649    )
650}
651
652/// The `rt_tgsigqueueinfo` syscall sends a signal with a payload to a specific thread.
653///
654/// # Args
655/// * `tgid`: The thread group ID of the process to send the signal to.
656/// * `tid`: The thread ID of the thread to send the signal to.
657/// * `unchecked_signal`: The signal to send.
658/// * `siginfo_ref`: A pointer to a `siginfo_t` structure that contains the signal payload.
659///
660/// # Returns
661/// `Ok(())` on success. Otherwise, returns an `Errno` with the error code.
662pub fn sys_rt_tgsigqueueinfo(
663    current_task: &CurrentTask,
664    tgid: pid_t,
665    tid: tid_t,
666    unchecked_signal: UncheckedSignal,
667    siginfo_ref: UserAddress,
668) -> Result<(), Errno> {
669    let siginfo = UncheckedSignalInfo::read_from_siginfo(current_task, siginfo_ref)?;
670    // Linux returns EINVAL when the tgid or tid <= 0.
671    if tgid <= 0 || tid <= 0 {
672        return error!(EINVAL);
673    }
674    // Unlike `rt_sigqueueinfo`, the target must be the calling thread, not merely the calling
675    // process.
676    if tid != current_task.get_tid() {
677        siginfo.check_code()?;
678    }
679
680    let pids = &current_task.kernel().pids;
681
682    let task = pids.get(tid)?.get_task()?;
683    let tgid_entry = pids.get(tgid)?;
684    verify_tgid_for_task(&task, &tgid_entry)?;
685    send_unchecked_signal_info(current_task, &task, unchecked_signal, siginfo)
686}
687
688/// The `pause` syscall causes the calling process sleep until it receives a signal or terminates.
689///
690/// # Returns
691/// This function never returns `Ok(())` under normal circumstances. It always returns `Err(EINTR)`.
692pub fn sys_pause(current_task: &CurrentTask) -> Result<(), Errno> {
693    let event = InterruptibleEvent::default();
694    let guard = event.begin_wait();
695    let result = current_task.block_until(guard, zx::MonotonicInstant::INFINITE);
696    // ERESTARTNOHAND is mapped to EINTR if interrupted by signal delivery.
697    result.map_eintr(|| errno!(ERESTARTNOHAND))
698}
699
700/// The `pidfd_send_signal` syscall sends a signal to a process specified by a PID file
701/// descriptor.
702///
703/// # Args
704/// * `pidfd`: The PID file descriptor of the process to send the signal to.
705/// * `unchecked_signal`: The signal to send.
706/// * `siginfo_ref`: An optional pointer to a `siginfo_t` structure that contains the signal
707///   payload.
708/// * `flags`: Must be 0.
709///
710/// # Returns
711/// `Ok(())` on success. Otherwise, returns an `Errno` with the error code.
712pub fn sys_pidfd_send_signal(
713    current_task: &CurrentTask,
714    pidfd: FdNumber,
715    unchecked_signal: UncheckedSignal,
716    siginfo_ref: UserAddress,
717    flags: u32,
718) -> Result<(), Errno> {
719    if flags != 0 {
720        return error!(EINVAL);
721    }
722
723    let file = current_task.files().get(pidfd)?;
724    let target = file.as_pid()?.get_thread_group()?;
725
726    if siginfo_ref.is_null() {
727        target.send_signal_unchecked(current_task, unchecked_signal)
728    } else {
729        let siginfo = UncheckedSignalInfo::read_from_siginfo(current_task, siginfo_ref)?;
730        if target.leader.id != current_task.get_pid() {
731            siginfo.check_code()?;
732        }
733        target.send_signal_unchecked_with_info(
734            current_task,
735            unchecked_signal,
736            siginfo,
737            IntoSignalInfoOptions::CheckSigno,
738        )
739    }
740}
741
742/// Sends a signal to all thread groups in `thread_groups`.
743///
744/// # Parameters
745/// - `task`: The task that is sending the signal.
746/// - `unchecked_signal`: The signal that is to be sent. Unchecked, since `0` is a sentinel value
747/// where rights are to be checked but no signal is actually sent.
748/// - `thread_groups`: The thread groups to signal.
749///
750/// # Returns
751/// Returns Ok(()) if at least one signal was sent, otherwise the last error that was encountered.
752#[track_caller]
753fn signal_thread_groups<F>(
754    current_task: &CurrentTask,
755    unchecked_signal: UncheckedSignal,
756    thread_groups: F,
757) -> Result<(), Errno>
758where
759    F: IntoIterator<Item: AsRef<ThreadGroup>>,
760{
761    let mut last_error = None;
762    let mut sent_signal = false;
763
764    // This loop keeps track of whether a signal was sent, so that "on
765    // success (at least one signal was sent), zero is returned."
766    for thread_group in thread_groups.into_iter() {
767        match thread_group.as_ref().send_signal_unchecked(current_task, unchecked_signal) {
768            Ok(_) => sent_signal = true,
769            Err(errno) => last_error = Some(errno),
770        }
771    }
772
773    if sent_signal { Ok(()) } else { Err(last_error.unwrap_or_else(|| errno!(ESRCH))) }
774}
775
776/// The generic options for both waitid and wait4.
777#[derive(Debug)]
778pub struct WaitingOptions {
779    /// Wait for a process that has exited.
780    pub wait_for_exited: bool,
781    /// Wait for a process in the stop state.
782    pub wait_for_stopped: bool,
783    /// Wait for a process that was continued.
784    pub wait_for_continued: bool,
785    /// Do not block if no child has exited.
786    pub wnohang: bool,
787    /// Block the wait until a process matches.
788    pub block: bool,
789    /// Do not clear the waitable state.
790    pub keep_waitable_state: bool,
791    /// Wait for all children processes.
792    pub wait_for_all: bool,
793    /// Wait for children who deliver no signal or a signal other than SIGCHLD, ignored if wait_for_all is true
794    pub wait_for_clone: bool,
795}
796
797impl WaitingOptions {
798    fn new(options: u32) -> Self {
799        const_assert_eq!(WUNTRACED, WSTOPPED);
800        if options & __WNOTHREAD != 0 {
801            track_stub!(TODO("https://fxbug.dev/509926462"), "wait options wnothread");
802        }
803        Self {
804            wait_for_exited: options & WEXITED > 0,
805            wait_for_stopped: options & WSTOPPED > 0,
806            wait_for_continued: options & WCONTINUED > 0,
807            wnohang: options & WNOHANG > 0,
808            block: options & WNOHANG == 0,
809            keep_waitable_state: options & WNOWAIT > 0,
810            wait_for_all: options & __WALL > 0,
811            wait_for_clone: options & __WCLONE > 0,
812        }
813    }
814
815    /// Build a `WaitingOptions` from the waiting flags of waitid.
816    pub fn new_for_waitid(options: u32) -> Result<Self, Errno> {
817        if options & !(__WCLONE | __WALL | WNOHANG | WNOWAIT | WSTOPPED | WEXITED | WCONTINUED) != 0
818        {
819            track_stub!(TODO("https://fxbug.dev/322874788"), "waitid options", options);
820            return error!(EINVAL);
821        }
822        if options & (WEXITED | WSTOPPED | WCONTINUED) == 0 {
823            return error!(EINVAL);
824        }
825        Ok(Self::new(options))
826    }
827
828    /// Build a `WaitingOptions` from the waiting flags of wait4.
829    pub fn new_for_wait4(options: u32) -> Result<Self, Errno> {
830        if options & !(__WCLONE | __WNOTHREAD | __WALL | WNOHANG | WUNTRACED | WCONTINUED) != 0 {
831            track_stub!(TODO("https://fxbug.dev/322874017"), "wait4 options", options);
832            return error!(EINVAL);
833        }
834        Ok(Self::new(options | WEXITED))
835    }
836}
837
838/// Waits on the task with `pid` to exit or change state.
839///
840/// - `current_task`: The current task.
841/// - `pid`: The id of the task to wait on.
842/// - `options`: The options passed to the wait syscall.
843fn wait_on_pid(
844    current_task: &CurrentTask,
845    selector: &ProcessSelector,
846    options: &WaitingOptions,
847) -> Result<Option<WaitResult>, Errno> {
848    let waiter = Waiter::new();
849    loop {
850        {
851            let mut pids = current_task.kernel().pids.lock();
852            // Waits and notifies on a given task need to be done atomically
853            // with respect to changes to the task's waitable state; otherwise,
854            // we see missing notifications. We do that by holding the task lock.
855            // This next line checks for waitable traces without holding the
856            // task lock, because constructing WaitResult objects requires
857            // holding all sorts of locks that are incompatible with holding the
858            // task lock.  We therefore have to check to see if a tracee has
859            // become waitable again, after we acquire the lock.
860            if let Some(tracee) =
861                current_task.thread_group().get_waitable_ptracee(selector, options, &mut pids)
862            {
863                return Ok(Some(tracee));
864            }
865            let mut has_waitable_tracee = false;
866            let mut has_any_tracee = false;
867            current_task.thread_group().get_ptracees_and(
868                selector,
869                &mut |task: &Task, task_state: &TaskMutableState| {
870                    if let Some(ptrace) = &task_state.ptrace {
871                        has_any_tracee = true;
872                        ptrace.tracer_waiters().wait_async(&waiter);
873                        if ptrace.is_waitable(task.load_stopped(), options) {
874                            has_waitable_tracee = true;
875                        }
876                    }
877                },
878            );
879            if has_waitable_tracee {
880                continue;
881            }
882
883            {
884                let mut thread_group = current_task.thread_group().write();
885
886                if thread_group.zombie_ptracees.has_zombie_matching(&selector) {
887                    continue;
888                }
889                match thread_group.get_waitable_child(selector, options, &mut pids) {
890                    WaitableChildResult::ReadyNow(child) => {
891                        return Ok(Some(*child));
892                    }
893                    WaitableChildResult::ShouldWait => (),
894                    WaitableChildResult::NoneFound => {
895                        if !has_any_tracee {
896                            return error!(ECHILD);
897                        }
898                    }
899                }
900                thread_group
901                    .lifecycle_waiters
902                    .wait_async_value(&waiter, ThreadGroupLifecycleWaitValue::ChildStatus);
903            }
904        }
905
906        if !options.block {
907            return Ok(None);
908        }
909        waiter.wait(current_task).map_eintr(|| errno!(ERESTARTSYS))?;
910    }
911}
912
913/// The `waitid` syscall waits for a child process to change state.
914///
915/// # Args
916/// * `id_type`: The type of ID to wait for.
917/// * `id`: The ID to wait for.
918/// * `user_info`: A pointer to a `siginfo_t` structure that will be filled with information
919///   about the state change.
920/// * `options`: A bitmask of flags that control the behavior of the syscall.
921/// * `user_rusage`: An optional pointer to a `rusage` structure that will be filled with
922///   resource usage information.
923///
924/// # Returns
925/// `Ok(())` on success. Otherwise, returns an `Errno` with the error code.
926pub fn sys_waitid(
927    current_task: &CurrentTask,
928    id_type: u32,
929    id: i32,
930    user_info: MultiArchUserRef<uapi::siginfo_t, uapi::arch32::siginfo_t>,
931    options: u32,
932    user_rusage: RUsagePtr,
933) -> Result<(), Errno> {
934    let mut waiting_options = WaitingOptions::new_for_waitid(options)?;
935
936    let task_selector = match id_type {
937        P_PID => {
938            let pid = current_task.kernel().pids.get(id).map_err(|_| errno!(ECHILD))?;
939            ProcessSelector::Pid(pid)
940        }
941        P_ALL => ProcessSelector::Any,
942        P_PGID => {
943            let pid = if id == 0 {
944                current_task.thread_group().pgid()
945            } else {
946                current_task.kernel().pids.get(id).map_err(|_| errno!(ECHILD))?
947            };
948            ProcessSelector::Pgid(pid)
949        }
950        P_PIDFD => {
951            let fd = FdNumber::from_raw(id);
952            let file = current_task.files().get(fd)?;
953            if file.flags().contains(OpenFlags::NONBLOCK) {
954                waiting_options.block = false;
955            }
956            ProcessSelector::Pid(file.as_pid()?)
957        }
958        _ => return error!(EINVAL),
959    };
960
961    // wait_on_pid returns None if no child changed state.
962    if let Some(waitable_process) = wait_on_pid(current_task, &task_selector, &waiting_options)? {
963        if !user_rusage.is_null() {
964            let usage = rusage {
965                ru_utime: timeval_from_duration(waitable_process.zombie_state.time_stats.user_time),
966                ru_stime: timeval_from_duration(
967                    waitable_process.zombie_state.time_stats.system_time,
968                ),
969                ..Default::default()
970            };
971
972            track_stub!(TODO("https://fxbug.dev/322874712"), "real rusage from waitid");
973            current_task.write_multi_arch_object(user_rusage, usage)?;
974        }
975
976        if !user_info.is_null() {
977            let siginfo = waitable_process.as_signal_info();
978            siginfo.write(current_task, user_info)?;
979        }
980    } else if id_type == P_PIDFD && !waiting_options.wnohang {
981        // From <https://man7.org/linux/man-pages/man2/pidfd_open.2.html>:
982        //
983        //   PIDFD_NONBLOCK
984        //     Return a nonblocking file descriptor.  If the process
985        //     referred to by the file descriptor has not yet terminated,
986        //     then an attempt to wait on the file descriptor using
987        //     waitid(2) will immediately return the error EAGAIN rather
988        //     than blocking.
989        return error!(EAGAIN);
990    } else {
991        // Under Linux, when WNOHANG is specified and no child changed state,
992        // waitid returns 0 and zeroes the siginfo_t structure (and rusage if provided).
993        if !user_rusage.is_null() {
994            current_task.write_multi_arch_object(user_rusage, rusage::default())?;
995        }
996
997        if !user_info.is_null() {
998            SignalInfo::zero(current_task, user_info)?;
999        }
1000    }
1001
1002    Ok(())
1003}
1004
1005/// The `wait4` syscall waits for a child process to change state.
1006///
1007/// # Args
1008/// * `raw_selector`: The PID of the process to wait for. See `wait4(2)` for more details.
1009/// * `user_wstatus`: A pointer to an integer that will be filled with the exit status of the
1010///   process.
1011/// * `options`: A bitmask of flags that control the behavior of the syscall.
1012/// * `user_rusage`: An optional pointer to a `rusage` structure that will be filled with
1013///   resource usage information.
1014///
1015/// # Returns
1016/// On success, returns the PID of the process that changed state, or 0 if `WNOHANG` was
1017/// specified and no child has changed state. On error, returns an `Errno`.
1018pub fn sys_wait4(
1019    current_task: &CurrentTask,
1020    raw_selector: pid_t,
1021    user_wstatus: UserRef<i32>,
1022    options: u32,
1023    user_rusage: RUsagePtr,
1024) -> Result<pid_t, Errno> {
1025    let waiting_options = WaitingOptions::new_for_wait4(options)?;
1026
1027    let selector = if raw_selector == 0 {
1028        ProcessSelector::Pgid(current_task.thread_group().pgid())
1029    } else if raw_selector == -1 {
1030        ProcessSelector::Any
1031    } else if raw_selector > 0 {
1032        let pid = current_task.kernel().pids.get(raw_selector).map_err(|_| errno!(ECHILD))?;
1033        ProcessSelector::Pid(pid)
1034    } else if raw_selector < -1 {
1035        let pid = current_task
1036            .kernel()
1037            .pids
1038            .get(negate_pid(raw_selector)?)
1039            .map_err(|_| errno!(ECHILD))?;
1040        ProcessSelector::Pgid(pid)
1041    } else {
1042        track_stub!(
1043            TODO("https://fxbug.dev/322874213"),
1044            "wait4 with selector",
1045            raw_selector as u64
1046        );
1047        return error!(ENOSYS);
1048    };
1049
1050    if let Some(waitable_process) = wait_on_pid(current_task, &selector, &waiting_options)? {
1051        let status = waitable_process.zombie_state.exit_status.wait_status();
1052
1053        if !user_rusage.is_null() {
1054            track_stub!(TODO("https://fxbug.dev/322874768"), "real rusage from wait4");
1055            let usage = rusage {
1056                ru_utime: timeval_from_duration(waitable_process.zombie_state.time_stats.user_time),
1057                ru_stime: timeval_from_duration(
1058                    waitable_process.zombie_state.time_stats.system_time,
1059                ),
1060                ..Default::default()
1061            };
1062            current_task.write_multi_arch_object(user_rusage, usage)?;
1063        }
1064
1065        if !user_wstatus.is_null() {
1066            current_task.write_object(user_wstatus, &status)?;
1067        }
1068
1069        Ok(waitable_process.pid.id)
1070    } else {
1071        Ok(0)
1072    }
1073}
1074
1075// Negates the `pid` safely or fails with `ESRCH` (negation operation panics for `i32::MIN`).
1076fn negate_pid(pid: pid_t) -> Result<pid_t, Errno> {
1077    pid.checked_neg().ok_or_else(|| errno!(ESRCH))
1078}
1079
1080// Syscalls for arch32 usage
1081#[cfg(target_arch = "aarch64")]
1082mod arch32 {
1083    use crate::task::CurrentTask;
1084    use crate::vfs::FdNumber;
1085    use starnix_uapi::errors::Errno;
1086    use starnix_uapi::signals::SigSet;
1087    use starnix_uapi::user_address::UserRef;
1088
1089    /// The `signalfd` syscall creates a file descriptor that can be used to accept signals targeted
1090    /// at the caller.
1091    ///
1092    /// This is the 32-bit compatibility version of `signalfd4`.
1093    ///
1094    /// # Args
1095    /// * `fd`: A file descriptor. If -1, a new file descriptor is created. Otherwise, the mask of the
1096    ///   existing signalfd is modified.
1097    /// * `mask_addr`: A pointer to a signal set specifying the signals to handle with this signalfd.
1098    /// * `mask_size`: The size of the signal set, in bytes.
1099    ///
1100    /// # Returns
1101    /// On success, returns `Ok(FdNumber)` containing the file descriptor number. On failure, returns
1102    /// an `Errno`.
1103    pub fn sys_arch32_signalfd(
1104        current_task: &CurrentTask,
1105        fd: FdNumber,
1106        mask_addr: UserRef<SigSet>,
1107        mask_size: usize,
1108    ) -> Result<FdNumber, Errno> {
1109        super::sys_signalfd4(current_task, fd, mask_addr, mask_size, 0)
1110    }
1111
1112    pub use super::{
1113        sys_pidfd_send_signal as sys_arch32_pidfd_send_signal,
1114        sys_rt_sigaction as sys_arch32_rt_sigaction,
1115        sys_rt_sigqueueinfo as sys_arch32_rt_sigqueueinfo,
1116        sys_rt_sigtimedwait as sys_arch32_rt_sigtimedwait,
1117        sys_rt_tgsigqueueinfo as sys_arch32_rt_tgsigqueueinfo,
1118        sys_sigaltstack as sys_arch32_sigaltstack, sys_signalfd4 as sys_arch32_signalfd4,
1119        sys_waitid as sys_arch32_waitid,
1120    };
1121}
1122
1123#[cfg(target_arch = "aarch64")]
1124pub use arch32::*;
1125
1126#[cfg(test)]
1127mod tests {
1128    use super::*;
1129    use crate::mm::{MemoryAccessor, PAGE_SIZE};
1130    use crate::signals::testing::dequeue_signal_for_test;
1131    use crate::signals::{
1132        SI_HEADER_SIZE, SI_MAX_SIZE_AS_USIZE, SignalInfoHeader, send_standard_signal,
1133    };
1134    use crate::task::dynamic_thread_spawner::SpawnRequestBuilder;
1135    use crate::task::{EventHandler, ExitStatus, ZombieState};
1136    use crate::testing::*;
1137    use starnix_sync::{EventHandlerReadyQueueLock, LockDepMutex};
1138    use starnix_types::math::round_up_to_system_page_size;
1139    use starnix_uapi::auth::Credentials;
1140    use starnix_uapi::errors::ERESTARTSYS;
1141    use starnix_uapi::signals::{
1142        SIGCHLD, SIGHUP, SIGINT, SIGIO, SIGKILL, SIGRTMIN, SIGSEGV, SIGSTOP, SIGTERM, SIGTRAP,
1143        SIGUSR1, SIGWINCH,
1144    };
1145    use starnix_uapi::vfs::FdEvents;
1146    use starnix_uapi::{SI_QUEUE, sigaction_t, uaddr, uid_t};
1147    use std::collections::VecDeque;
1148    use std::sync::Arc;
1149    use zerocopy::IntoBytes;
1150
1151    #[cfg(target_arch = "x86_64")]
1152    #[::fuchsia::test]
1153    async fn test_sigaltstack() {
1154        spawn_kernel_and_run(async |current_task| {
1155            let addr = map_memory(&current_task, UserAddress::default(), *PAGE_SIZE);
1156
1157            let user_ss = UserRef::<sigaltstack>::new(addr);
1158            let nullptr = UserRef::<sigaltstack>::default();
1159
1160            // Check that the initial state is disabled.
1161            sys_sigaltstack(&current_task, nullptr.into(), user_ss.into())
1162                .expect("failed to call sigaltstack");
1163            let mut ss = current_task.read_object(user_ss).expect("failed to read struct");
1164            assert!(ss.ss_flags & (SS_DISABLE as i32) != 0);
1165
1166            // Install a sigaltstack and read it back out.
1167            ss.ss_sp = uaddr { addr: 0x7FFFF };
1168            ss.ss_size = 0x1000;
1169            ss.ss_flags = SS_AUTODISARM as i32;
1170            current_task.write_object(user_ss, &ss).expect("failed to write struct");
1171            sys_sigaltstack(&current_task, user_ss.into(), nullptr.into())
1172                .expect("failed to call sigaltstack");
1173            current_task
1174                .write_memory(addr, &[0u8; std::mem::size_of::<sigaltstack>()])
1175                .expect("failed to clear struct");
1176            sys_sigaltstack(&current_task, nullptr.into(), user_ss.into())
1177                .expect("failed to call sigaltstack");
1178            let another_ss = current_task.read_object(user_ss).expect("failed to read struct");
1179            assert_eq!(ss.as_bytes(), another_ss.as_bytes());
1180
1181            // Disable the sigaltstack and read it back out.
1182            let ss = sigaltstack { ss_flags: SS_DISABLE as i32, ..sigaltstack::default() };
1183            current_task.write_object(user_ss, &ss).expect("failed to write struct");
1184            sys_sigaltstack(&current_task, user_ss.into(), nullptr.into())
1185                .expect("failed to call sigaltstack");
1186            current_task
1187                .write_memory(addr, &[0u8; std::mem::size_of::<sigaltstack>()])
1188                .expect("failed to clear struct");
1189            sys_sigaltstack(&current_task, nullptr.into(), user_ss.into())
1190                .expect("failed to call sigaltstack");
1191            let ss = current_task.read_object(user_ss).expect("failed to read struct");
1192            assert!(ss.ss_flags & (SS_DISABLE as i32) != 0);
1193        })
1194        .await;
1195    }
1196
1197    #[::fuchsia::test]
1198    async fn test_sigaltstack_invalid_size() {
1199        spawn_kernel_and_run(async |current_task| {
1200            let addr = map_memory(&current_task, UserAddress::default(), *PAGE_SIZE);
1201
1202            let user_ss = UserRef::<sigaltstack>::new(addr);
1203            let nullptr = UserRef::<sigaltstack>::default();
1204
1205            // Check that the initial state is disabled.
1206            sys_sigaltstack(&current_task, nullptr.into(), user_ss.into())
1207                .expect("failed to call sigaltstack");
1208            let mut ss = current_task.read_object(user_ss).expect("failed to read struct");
1209            assert!(ss.ss_flags & (SS_DISABLE as i32) != 0);
1210
1211            // Try to install a sigaltstack with an invalid size.
1212            let sigaltstack_addr_size = round_up_to_system_page_size(uapi::MINSIGSTKSZ as usize)
1213                .expect("failed to round up");
1214            let sigaltstack_addr =
1215                map_memory(&current_task, UserAddress::default(), sigaltstack_addr_size as u64);
1216            ss.ss_sp = sigaltstack_addr.into();
1217            ss.ss_flags = 0;
1218            ss.ss_size = uapi::MINSIGSTKSZ as u64 - 1;
1219            current_task.write_object(user_ss, &ss).expect("failed to write struct");
1220            assert_eq!(
1221                sys_sigaltstack(&current_task, user_ss.into(), nullptr.into()),
1222                error!(ENOMEM)
1223            );
1224        })
1225        .await;
1226    }
1227
1228    #[cfg(target_arch = "x86_64")]
1229    #[::fuchsia::test]
1230    async fn test_sigaltstack_active_stack() {
1231        spawn_kernel_and_run(async |current_task| {
1232            let addr = map_memory(&current_task, UserAddress::default(), *PAGE_SIZE);
1233
1234            let user_ss = UserRef::<sigaltstack>::new(addr);
1235            let nullptr = UserRef::<sigaltstack>::default();
1236
1237            // Check that the initial state is disabled.
1238            sys_sigaltstack(&current_task, nullptr.into(), user_ss.into())
1239                .expect("failed to call sigaltstack");
1240            let mut ss = current_task.read_object(user_ss).expect("failed to read struct");
1241            assert!(ss.ss_flags & (SS_DISABLE as i32) != 0);
1242
1243            // Try to install a sigaltstack.
1244            let sigaltstack_addr_size = round_up_to_system_page_size(uapi::MINSIGSTKSZ as usize)
1245                .expect("failed to round up");
1246            let sigaltstack_addr =
1247                map_memory(&current_task, UserAddress::default(), sigaltstack_addr_size as u64);
1248            ss.ss_sp = sigaltstack_addr.into();
1249            ss.ss_flags = 0;
1250            ss.ss_size = sigaltstack_addr_size as u64;
1251            current_task.write_object(user_ss, &ss).expect("failed to write struct");
1252            sys_sigaltstack(&current_task, user_ss.into(), nullptr.into())
1253                .expect("failed to call sigaltstack");
1254
1255            // Changing the sigaltstack while we are there should be an error.
1256            let next_addr = (sigaltstack_addr + sigaltstack_addr_size).unwrap();
1257            current_task.thread_state.registers.rsp = next_addr.ptr() as u64;
1258            ss.ss_flags = SS_DISABLE as i32;
1259            current_task.write_object(user_ss, &ss).expect("failed to write struct");
1260            assert_eq!(
1261                sys_sigaltstack(&current_task, user_ss.into(), nullptr.into()),
1262                error!(EPERM)
1263            );
1264
1265            // However, setting the rsp to a different value outside the alt stack should allow us to
1266            // disable it.
1267            let next_ss_addr = sigaltstack_addr
1268                .checked_add(sigaltstack_addr_size)
1269                .unwrap()
1270                .checked_add(0x1000usize)
1271                .unwrap();
1272            current_task.thread_state.registers.rsp = next_ss_addr.ptr() as u64;
1273            let ss = sigaltstack { ss_flags: SS_DISABLE as i32, ..sigaltstack::default() };
1274            current_task.write_object(user_ss, &ss).expect("failed to write struct");
1275            sys_sigaltstack(&current_task, user_ss.into(), nullptr.into())
1276                .expect("failed to call sigaltstack");
1277        })
1278        .await;
1279    }
1280
1281    #[cfg(target_arch = "x86_64")]
1282    #[::fuchsia::test]
1283    async fn test_sigaltstack_active_stack_saturates() {
1284        spawn_kernel_and_run(async |current_task| {
1285            let addr = map_memory(&current_task, UserAddress::default(), *PAGE_SIZE);
1286
1287            let user_ss = UserRef::<sigaltstack>::new(addr);
1288            let nullptr = UserRef::<sigaltstack>::default();
1289
1290            // Check that the initial state is disabled.
1291            sys_sigaltstack(&current_task, nullptr.into(), user_ss.into())
1292                .expect("failed to call sigaltstack");
1293            let mut ss = current_task.read_object(user_ss).expect("failed to read struct");
1294            assert!(ss.ss_flags & (SS_DISABLE as i32) != 0);
1295
1296            // Try to install a sigaltstack that takes the whole memory.
1297            let sigaltstack_addr_size = round_up_to_system_page_size(uapi::MINSIGSTKSZ as usize)
1298                .expect("failed to round up");
1299            let sigaltstack_addr =
1300                map_memory(&current_task, UserAddress::default(), sigaltstack_addr_size as u64);
1301            ss.ss_sp = sigaltstack_addr.into();
1302            ss.ss_flags = 0;
1303            ss.ss_size = u64::MAX;
1304            current_task.write_object(user_ss, &ss).expect("failed to write struct");
1305            sys_sigaltstack(&current_task, user_ss.into(), nullptr.into())
1306                .expect("failed to call sigaltstack");
1307
1308            // Changing the sigaltstack while we are there should be an error.
1309            current_task.thread_state.registers.rsp =
1310                (sigaltstack_addr + sigaltstack_addr_size).unwrap().ptr() as u64;
1311            ss.ss_flags = SS_DISABLE as i32;
1312            current_task.write_object(user_ss, &ss).expect("failed to write struct");
1313            assert_eq!(
1314                sys_sigaltstack(&current_task, user_ss.into(), nullptr.into()),
1315                error!(EPERM)
1316            );
1317
1318            // However, setting the rsp to a low value should work (it doesn't wrap-around).
1319            current_task.thread_state.registers.rsp = 0u64;
1320            let ss = sigaltstack { ss_flags: SS_DISABLE as i32, ..sigaltstack::default() };
1321            current_task.write_object(user_ss, &ss).expect("failed to write struct");
1322            sys_sigaltstack(&current_task, user_ss.into(), nullptr.into())
1323                .expect("failed to call sigaltstack");
1324        })
1325        .await;
1326    }
1327
1328    /// It is invalid to call rt_sigprocmask with a sigsetsize that does not match the size of
1329    /// SigSet.
1330    #[::fuchsia::test]
1331    async fn test_sigprocmask_invalid_size() {
1332        spawn_kernel_and_run(async |current_task| {
1333            let set = UserRef::<SigSet>::default();
1334            let old_set = UserRef::<SigSet>::default();
1335            let how = 0;
1336
1337            assert_eq!(
1338                sys_rt_sigprocmask(
1339                    &current_task,
1340                    how,
1341                    set,
1342                    old_set,
1343                    std::mem::size_of::<SigSet>() * 2
1344                ),
1345                error!(EINVAL)
1346            );
1347            assert_eq!(
1348                sys_rt_sigprocmask(
1349                    &current_task,
1350                    how,
1351                    set,
1352                    old_set,
1353                    std::mem::size_of::<SigSet>() / 2
1354                ),
1355                error!(EINVAL)
1356            );
1357        })
1358        .await;
1359    }
1360
1361    /// It is invalid to call rt_sigprocmask with a bad `how`.
1362    #[::fuchsia::test]
1363    async fn test_sigprocmask_invalid_how() {
1364        spawn_kernel_and_run(async |current_task| {
1365            let addr = map_memory(&current_task, UserAddress::default(), *PAGE_SIZE);
1366
1367            let set = UserRef::<SigSet>::new(addr);
1368            let old_set = UserRef::<SigSet>::default();
1369            let how = SIG_SETMASK | SIG_UNBLOCK | SIG_BLOCK;
1370
1371            assert_eq!(
1372                sys_rt_sigprocmask(&current_task, how, set, old_set, std::mem::size_of::<SigSet>()),
1373                error!(EINVAL)
1374            );
1375        })
1376        .await;
1377    }
1378
1379    /// It is valid to call rt_sigprocmask with a null value for set. In that case, old_set should
1380    /// contain the current signal mask.
1381    #[::fuchsia::test]
1382    async fn test_sigprocmask_null_set() {
1383        spawn_kernel_and_run(async |current_task| {
1384            let addr = map_memory(&current_task, UserAddress::default(), *PAGE_SIZE);
1385            let original_mask = SigSet::from(SIGTRAP);
1386            {
1387                current_task.write().set_signal_mask(original_mask);
1388            }
1389
1390            let set = UserRef::<SigSet>::default();
1391            let old_set = UserRef::<SigSet>::new(addr);
1392            let how = SIG_SETMASK;
1393
1394            current_task
1395                .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>()])
1396                .expect("failed to clear struct");
1397
1398            assert_eq!(
1399                sys_rt_sigprocmask(&current_task, how, set, old_set, std::mem::size_of::<SigSet>()),
1400                Ok(())
1401            );
1402
1403            let old_mask = current_task.read_object(old_set).expect("failed to read mask");
1404            assert_eq!(old_mask, original_mask);
1405        })
1406        .await;
1407    }
1408
1409    /// It is valid to call rt_sigprocmask with null values for both set and old_set.
1410    /// In this case, how should be ignored and the set remains the same.
1411    #[::fuchsia::test]
1412    async fn test_sigprocmask_null_set_and_old_set() {
1413        spawn_kernel_and_run(async |current_task| {
1414            let original_mask = SigSet::from(SIGTRAP);
1415            {
1416                current_task.write().set_signal_mask(original_mask);
1417            }
1418
1419            let set = UserRef::<SigSet>::default();
1420            let old_set = UserRef::<SigSet>::default();
1421            let how = SIG_SETMASK;
1422
1423            assert_eq!(
1424                sys_rt_sigprocmask(&current_task, how, set, old_set, std::mem::size_of::<SigSet>()),
1425                Ok(())
1426            );
1427            assert_eq!(current_task.read().signal_mask(), original_mask);
1428        })
1429        .await;
1430    }
1431
1432    /// Calling rt_sigprocmask with SIG_SETMASK should set the mask to the provided set.
1433    #[::fuchsia::test]
1434    async fn test_sigprocmask_setmask() {
1435        spawn_kernel_and_run(async |current_task| {
1436            let addr = map_memory(&current_task, UserAddress::default(), *PAGE_SIZE);
1437            current_task
1438                .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1439                .expect("failed to clear struct");
1440
1441            let original_mask = SigSet::from(SIGTRAP);
1442            {
1443                current_task.write().set_signal_mask(original_mask);
1444            }
1445
1446            let new_mask = SigSet::from(SIGIO);
1447            let set = UserRef::<SigSet>::new(addr);
1448            current_task.write_object(set, &new_mask).expect("failed to set mask");
1449
1450            let old_addr_range = (addr + std::mem::size_of::<SigSet>()).unwrap();
1451            let old_set = UserRef::<SigSet>::new(old_addr_range);
1452            let how = SIG_SETMASK;
1453
1454            assert_eq!(
1455                sys_rt_sigprocmask(&current_task, how, set, old_set, std::mem::size_of::<SigSet>()),
1456                Ok(())
1457            );
1458
1459            let old_mask = current_task.read_object(old_set).expect("failed to read mask");
1460            assert_eq!(old_mask, original_mask);
1461            assert_eq!(current_task.read().signal_mask(), new_mask);
1462        })
1463        .await;
1464    }
1465
1466    /// Calling st_sigprocmask with a how of SIG_BLOCK should add to the existing set.
1467    #[::fuchsia::test]
1468    async fn test_sigprocmask_block() {
1469        spawn_kernel_and_run(async |current_task| {
1470            let addr = map_memory(&current_task, UserAddress::default(), *PAGE_SIZE);
1471            current_task
1472                .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1473                .expect("failed to clear struct");
1474
1475            let original_mask = SigSet::from(SIGTRAP);
1476            {
1477                current_task.write().set_signal_mask(original_mask);
1478            }
1479
1480            let new_mask = SigSet::from(SIGIO);
1481            let set = UserRef::<SigSet>::new(addr);
1482            current_task.write_object(set, &new_mask).expect("failed to set mask");
1483
1484            let old_addr_range = (addr + std::mem::size_of::<SigSet>()).unwrap();
1485            let old_set = UserRef::<SigSet>::new(old_addr_range);
1486            let how = SIG_BLOCK;
1487
1488            assert_eq!(
1489                sys_rt_sigprocmask(&current_task, how, set, old_set, std::mem::size_of::<SigSet>()),
1490                Ok(())
1491            );
1492
1493            let old_mask = current_task.read_object(old_set).expect("failed to read mask");
1494            assert_eq!(old_mask, original_mask);
1495            assert_eq!(current_task.read().signal_mask(), new_mask | original_mask);
1496        })
1497        .await;
1498    }
1499
1500    /// Calling st_sigprocmask with a how of SIG_UNBLOCK should remove from the existing set.
1501    #[::fuchsia::test]
1502    async fn test_sigprocmask_unblock() {
1503        spawn_kernel_and_run(async |current_task| {
1504            let addr = map_memory(&current_task, UserAddress::default(), *PAGE_SIZE);
1505            current_task
1506                .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1507                .expect("failed to clear struct");
1508
1509            let original_mask = SigSet::from(SIGTRAP) | SigSet::from(SIGIO);
1510            {
1511                current_task.write().set_signal_mask(original_mask);
1512            }
1513
1514            let new_mask = SigSet::from(SIGTRAP);
1515            let set = UserRef::<SigSet>::new(addr);
1516            current_task.write_object(set, &new_mask).expect("failed to set mask");
1517
1518            let old_addr_range = (addr + std::mem::size_of::<SigSet>()).unwrap();
1519            let old_set = UserRef::<SigSet>::new(old_addr_range);
1520            let how = SIG_UNBLOCK;
1521
1522            assert_eq!(
1523                sys_rt_sigprocmask(&current_task, how, set, old_set, std::mem::size_of::<SigSet>()),
1524                Ok(())
1525            );
1526
1527            let old_mask = current_task.read_object(old_set).expect("failed to read mask");
1528            assert_eq!(old_mask, original_mask);
1529            assert_eq!(current_task.read().signal_mask(), SIGIO.into());
1530        })
1531        .await;
1532    }
1533
1534    /// It's ok to call sigprocmask to unblock a signal that is not set.
1535    #[::fuchsia::test]
1536    async fn test_sigprocmask_unblock_not_set() {
1537        spawn_kernel_and_run(async |current_task| {
1538            let addr = map_memory(&current_task, UserAddress::default(), *PAGE_SIZE);
1539            current_task
1540                .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1541                .expect("failed to clear struct");
1542
1543            let original_mask = SigSet::from(SIGIO);
1544            {
1545                current_task.write().set_signal_mask(original_mask);
1546            }
1547
1548            let new_mask = SigSet::from(SIGTRAP);
1549            let set = UserRef::<SigSet>::new(addr);
1550            current_task.write_object(set, &new_mask).expect("failed to set mask");
1551
1552            let old_addr_range = (addr + std::mem::size_of::<SigSet>()).unwrap();
1553            let old_set = UserRef::<SigSet>::new(old_addr_range);
1554            let how = SIG_UNBLOCK;
1555
1556            assert_eq!(
1557                sys_rt_sigprocmask(&current_task, how, set, old_set, std::mem::size_of::<SigSet>()),
1558                Ok(())
1559            );
1560
1561            let old_mask = current_task.read_object(old_set).expect("failed to read mask");
1562            assert_eq!(old_mask, original_mask);
1563            assert_eq!(current_task.read().signal_mask(), original_mask);
1564        })
1565        .await;
1566    }
1567
1568    /// It's not possible to block SIGKILL or SIGSTOP.
1569    #[::fuchsia::test]
1570    async fn test_sigprocmask_kill_stop() {
1571        spawn_kernel_and_run(async |current_task| {
1572            let addr = map_memory(&current_task, UserAddress::default(), *PAGE_SIZE);
1573            current_task
1574                .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1575                .expect("failed to clear struct");
1576
1577            let original_mask = SigSet::from(SIGIO);
1578            {
1579                current_task.write().set_signal_mask(original_mask);
1580            }
1581
1582            let new_mask = UNBLOCKABLE_SIGNALS;
1583            let set = UserRef::<SigSet>::new(addr);
1584            current_task.write_object(set, &new_mask).expect("failed to set mask");
1585
1586            let old_addr_range = (addr + std::mem::size_of::<SigSet>()).unwrap();
1587            let old_set = UserRef::<SigSet>::new(old_addr_range);
1588            let how = SIG_BLOCK;
1589
1590            assert_eq!(
1591                sys_rt_sigprocmask(&current_task, how, set, old_set, std::mem::size_of::<SigSet>()),
1592                Ok(())
1593            );
1594
1595            let old_mask = current_task.read_object(old_set).expect("failed to read mask");
1596            assert_eq!(old_mask, original_mask);
1597            assert_eq!(current_task.read().signal_mask(), original_mask);
1598        })
1599        .await;
1600    }
1601
1602    #[::fuchsia::test]
1603    async fn test_sigaction_invalid_signal() {
1604        spawn_kernel_and_run(async |current_task| {
1605            assert_eq!(
1606                sys_rt_sigaction(
1607                    &current_task,
1608                    UncheckedSignal::from(SIGKILL),
1609                    // The signal is only checked when the action is set (i.e., action is non-null).
1610                    UserRef::<sigaction_t>::new(UserAddress::from(10)).into(),
1611                    UserRef::<sigaction_t>::default().into(),
1612                    std::mem::size_of::<SigSet>(),
1613                ),
1614                error!(EINVAL)
1615            );
1616            assert_eq!(
1617                sys_rt_sigaction(
1618                    &current_task,
1619                    UncheckedSignal::from(SIGSTOP),
1620                    // The signal is only checked when the action is set (i.e., action is non-null).
1621                    UserRef::<sigaction_t>::new(UserAddress::from(10)).into(),
1622                    UserRef::<sigaction_t>::default().into(),
1623                    std::mem::size_of::<SigSet>(),
1624                ),
1625                error!(EINVAL)
1626            );
1627            assert_eq!(
1628                sys_rt_sigaction(
1629                    &current_task,
1630                    UncheckedSignal::from(Signal::NUM_SIGNALS + 1),
1631                    // The signal is only checked when the action is set (i.e., action is non-null).
1632                    UserRef::<sigaction_t>::new(UserAddress::from(10)).into(),
1633                    UserRef::<sigaction_t>::default().into(),
1634                    std::mem::size_of::<SigSet>(),
1635                ),
1636                error!(EINVAL)
1637            );
1638        })
1639        .await;
1640    }
1641
1642    #[::fuchsia::test]
1643    async fn test_sigaction_old_value_set() {
1644        spawn_kernel_and_run(async |current_task| {
1645            let addr = map_memory(&current_task, UserAddress::default(), *PAGE_SIZE);
1646            current_task
1647                .write_memory(addr, &[0u8; std::mem::size_of::<sigaction_t>()])
1648                .expect("failed to clear struct");
1649
1650            let org_mask = SigSet::from(SIGHUP) | SigSet::from(SIGINT);
1651            let original_action =
1652                sigaction_t { sa_mask: org_mask.into(), ..sigaction_t::default() };
1653
1654            {
1655                current_task.thread_group().signal_actions.set(SIGHUP, original_action);
1656            }
1657
1658            let old_action_ref = UserRef::<sigaction_t>::new(addr);
1659            assert_eq!(
1660                sys_rt_sigaction(
1661                    &current_task,
1662                    UncheckedSignal::from(SIGHUP),
1663                    UserRef::<sigaction_t>::default().into(),
1664                    old_action_ref.into(),
1665                    std::mem::size_of::<SigSet>()
1666                ),
1667                Ok(())
1668            );
1669
1670            let old_action =
1671                current_task.read_object(old_action_ref).expect("failed to read action");
1672            assert_eq!(old_action.as_bytes(), original_action.as_bytes());
1673        })
1674        .await;
1675    }
1676
1677    #[::fuchsia::test]
1678    async fn test_sigaction_new_value_set() {
1679        spawn_kernel_and_run(async |current_task| {
1680            let addr = map_memory(&current_task, UserAddress::default(), *PAGE_SIZE);
1681            current_task
1682                .write_memory(addr, &[0u8; std::mem::size_of::<sigaction_t>()])
1683                .expect("failed to clear struct");
1684
1685            let org_mask = SigSet::from(SIGHUP) | SigSet::from(SIGINT);
1686            let original_action =
1687                sigaction_t { sa_mask: org_mask.into(), ..sigaction_t::default() };
1688            let set_action_ref = UserRef::<sigaction_t>::new(addr);
1689            current_task
1690                .write_object(set_action_ref, &original_action)
1691                .expect("failed to set action");
1692
1693            assert_eq!(
1694                sys_rt_sigaction(
1695                    &current_task,
1696                    UncheckedSignal::from(SIGINT),
1697                    set_action_ref.into(),
1698                    UserRef::<sigaction_t>::default().into(),
1699                    std::mem::size_of::<SigSet>(),
1700                ),
1701                Ok(())
1702            );
1703
1704            assert_eq!(
1705                current_task.thread_group().signal_actions.get(SIGINT).as_bytes(),
1706                original_action.as_bytes()
1707            );
1708        })
1709        .await;
1710    }
1711
1712    /// A task should be able to signal itself.
1713    #[::fuchsia::test]
1714    async fn test_kill_same_task() {
1715        spawn_kernel_and_run(async |current_task| {
1716            assert_eq!(sys_kill(&current_task, current_task.tid.id, SIGINT.into()), Ok(()));
1717        })
1718        .await;
1719    }
1720
1721    /// A task should be able to signal its own thread group.
1722    #[::fuchsia::test]
1723    async fn test_kill_own_thread_group() {
1724        spawn_kernel_and_run(async |init_task| {
1725            let task1 = init_task.clone_task_for_test(0, Some(SIGCHLD));
1726            task1.thread_group().setsid().expect("setsid");
1727            let task2 = task1.clone_task_for_test(0, Some(SIGCHLD));
1728
1729            assert_eq!(sys_kill(&task1, 0, SIGINT.into()), Ok(()));
1730            assert_eq!(task1.read().queued_signal_count(SIGINT), 1);
1731            assert_eq!(task2.read().queued_signal_count(SIGINT), 1);
1732            assert_eq!(init_task.read().queued_signal_count(SIGINT), 0);
1733        })
1734        .await;
1735    }
1736
1737    /// A signal whose action is to ignore it is dropped rather than queued on the thread group,
1738    /// unless a task blocks it.
1739    #[::fuchsia::test]
1740    async fn test_kill_thread_group_ignored_signal() {
1741        spawn_kernel_and_run(async |init_task| {
1742            let task = init_task.clone_task_for_test(0, Some(SIGCHLD));
1743            task.thread_group().setsid().expect("setsid");
1744
1745            // SIGWINCH is ignored by default.
1746            assert_eq!(sys_kill(&task, 0, SIGWINCH.into()), Ok(()));
1747            assert_eq!(task.read().queued_signal_count(SIGWINCH), 0);
1748
1749            task.write().set_signal_mask(SIGWINCH.into());
1750            assert_eq!(sys_kill(&task, 0, SIGWINCH.into()), Ok(()));
1751            assert_eq!(task.read().queued_signal_count(SIGWINCH), 1);
1752        })
1753        .await;
1754    }
1755
1756    /// A task should be able to signal a thread group.
1757    #[::fuchsia::test]
1758    async fn test_kill_thread_group() {
1759        spawn_kernel_and_run(async |init_task| {
1760            let task1 = init_task.clone_task_for_test(0, Some(SIGCHLD));
1761            task1.thread_group().setsid().expect("setsid");
1762            let task2 = task1.clone_task_for_test(0, Some(SIGCHLD));
1763
1764            assert_eq!(sys_kill(&task1, -task1.tid.id, SIGINT.into()), Ok(()));
1765            assert_eq!(task1.read().queued_signal_count(SIGINT), 1);
1766            assert_eq!(task2.read().queued_signal_count(SIGINT), 1);
1767            assert_eq!(init_task.read().queued_signal_count(SIGINT), 0);
1768        })
1769        .await;
1770    }
1771
1772    /// A task should be able to signal everything but init and itself.
1773    #[::fuchsia::test]
1774    async fn test_kill_all() {
1775        spawn_kernel_and_run(async |init_task| {
1776            let task1 = init_task.clone_task_for_test(0, Some(SIGCHLD));
1777            task1.thread_group().setsid().expect("setsid");
1778            let task2 = task1.clone_task_for_test(0, Some(SIGCHLD));
1779
1780            assert_eq!(sys_kill(&task1, -1, SIGINT.into()), Ok(()));
1781            assert_eq!(task1.read().queued_signal_count(SIGINT), 0);
1782            assert_eq!(task2.read().queued_signal_count(SIGINT), 1);
1783            assert_eq!(init_task.read().queued_signal_count(SIGINT), 0);
1784        })
1785        .await;
1786    }
1787
1788    /// A task should not be able to signal a nonexistent task.
1789    #[::fuchsia::test]
1790    async fn test_kill_inexistant_task() {
1791        spawn_kernel_and_run(async |current_task| {
1792            assert_eq!(sys_kill(&current_task, 9, SIGINT.into()), error!(ESRCH));
1793        })
1794        .await;
1795    }
1796
1797    /// A task should not be able to signal a task owned by another uid.
1798    #[::fuchsia::test]
1799    async fn test_kill_invalid_task() {
1800        spawn_kernel_and_run(async |task1| {
1801            // Task must not have the kill capability.
1802            task1.set_creds(Credentials::with_ids(1, 1));
1803            let task2 = task1.clone_task_for_test(0, Some(SIGCHLD));
1804            task2.set_creds(Credentials::with_ids(2, 2));
1805
1806            assert!(task1.can_signal(&task2, SIGINT.into()).is_err());
1807            assert_eq!(sys_kill(&task2, task1.tid.id, SIGINT.into()), error!(EPERM));
1808            assert_eq!(task1.read().queued_signal_count(SIGINT), 0);
1809        })
1810        .await;
1811    }
1812
1813    /// A task should not be able to signal a task owned by another uid in a thead group.
1814    #[::fuchsia::test]
1815    async fn test_kill_invalid_task_in_thread_group() {
1816        spawn_kernel_and_run(async |init_task| {
1817            let task1 = init_task.clone_task_for_test(0, Some(SIGCHLD));
1818            task1.thread_group().setsid().expect("setsid");
1819            let task2 = task1.clone_task_for_test(0, Some(SIGCHLD));
1820            task2.thread_group().setsid().expect("setsid");
1821            task2.set_creds(Credentials::with_ids(2, 2));
1822
1823            assert!(task2.can_signal(&task1, SIGINT.into()).is_err());
1824            assert_eq!(sys_kill(&task2, -task1.tid.id, SIGINT.into()), error!(EPERM));
1825            assert_eq!(task1.read().queued_signal_count(SIGINT), 0);
1826        })
1827        .await;
1828    }
1829
1830    /// A task should not be able to send an invalid signal.
1831    #[::fuchsia::test]
1832    async fn test_kill_invalid_signal() {
1833        spawn_kernel_and_run(async |current_task| {
1834            assert_eq!(
1835                sys_kill(&current_task, current_task.tid.id, UncheckedSignal::from(75)),
1836                error!(EINVAL)
1837            );
1838        })
1839        .await;
1840    }
1841
1842    /// Sending a blocked signal should result in a pending signal.
1843    #[::fuchsia::test]
1844    async fn test_blocked_signal_pending() {
1845        spawn_kernel_and_run(async |current_task| {
1846            let addr = map_memory(&current_task, UserAddress::default(), *PAGE_SIZE);
1847            current_task
1848                .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1849                .expect("failed to clear struct");
1850
1851            let new_mask = SigSet::from(SIGIO);
1852            let set = UserRef::<SigSet>::new(addr);
1853            current_task.write_object(set, &new_mask).expect("failed to set mask");
1854
1855            assert_eq!(
1856                sys_rt_sigprocmask(
1857                    &current_task,
1858                    SIG_BLOCK,
1859                    set,
1860                    UserRef::default(),
1861                    std::mem::size_of::<SigSet>()
1862                ),
1863                Ok(())
1864            );
1865            assert_eq!(sys_kill(&current_task, current_task.tid.id, SIGIO.into()), Ok(()));
1866            assert_eq!(current_task.read().queued_signal_count(SIGIO), 1);
1867
1868            // A second signal should not increment the number of pending signals.
1869            assert_eq!(sys_kill(&current_task, current_task.tid.id, SIGIO.into()), Ok(()));
1870            assert_eq!(current_task.read().queued_signal_count(SIGIO), 1);
1871        })
1872        .await;
1873    }
1874
1875    /// More than one instance of a real-time signal can be blocked.
1876    #[::fuchsia::test]
1877    async fn test_blocked_real_time_signal_pending() {
1878        spawn_kernel_and_run(async |current_task| {
1879            let addr = map_memory(&current_task, UserAddress::default(), *PAGE_SIZE);
1880            current_task
1881                .write_memory(addr, &[0u8; std::mem::size_of::<SigSet>() * 2])
1882                .expect("failed to clear struct");
1883
1884            let new_mask = SigSet::from(starnix_uapi::signals::SIGRTMIN);
1885            let set = UserRef::<SigSet>::new(addr);
1886            current_task.write_object(set, &new_mask).expect("failed to set mask");
1887
1888            assert_eq!(
1889                sys_rt_sigprocmask(
1890                    &current_task,
1891                    SIG_BLOCK,
1892                    set,
1893                    UserRef::default(),
1894                    std::mem::size_of::<SigSet>()
1895                ),
1896                Ok(())
1897            );
1898            assert_eq!(sys_kill(&current_task, current_task.tid.id, SIGRTMIN.into()), Ok(()));
1899            assert_eq!(current_task.read().queued_signal_count(starnix_uapi::signals::SIGRTMIN), 1);
1900
1901            // A second signal should increment the number of pending signals.
1902            assert_eq!(sys_kill(&current_task, current_task.tid.id, SIGRTMIN.into()), Ok(()));
1903            assert_eq!(current_task.read().queued_signal_count(starnix_uapi::signals::SIGRTMIN), 2);
1904        })
1905        .await;
1906    }
1907
1908    #[::fuchsia::test]
1909    async fn test_suspend() {
1910        spawn_kernel_and_run(async |current_task| {
1911            let init_task_weak = current_task.weak_task();
1912            let (tx, rx) = std::sync::mpsc::sync_channel::<()>(0);
1913
1914            let closure = move |current_task: &CurrentTask| {
1915                let init_task_temp = init_task_weak.upgrade().expect("Task must be alive");
1916
1917                // Wait for the init task to be suspended.
1918                let mut suspended = false;
1919                while !suspended {
1920                    suspended = init_task_temp.read().is_blocked();
1921                    std::thread::sleep(std::time::Duration::from_millis(10));
1922                }
1923
1924                // Signal the suspended task with a signal that is not blocked (only SIGHUP in this test).
1925                let _ =
1926                    sys_kill(current_task, init_task_temp.tid.id, UncheckedSignal::from(SIGHUP));
1927
1928                // Wait for the sigsuspend to complete.
1929                rx.recv().expect("receive");
1930                assert!(!init_task_temp.read().is_blocked());
1931            };
1932            let (thread, req) =
1933                SpawnRequestBuilder::new().with_sync_closure(closure).build_with_async_result();
1934            current_task.kernel().kthreads.spawner().spawn_from_request(req);
1935
1936            let addr = map_memory(&current_task, UserAddress::default(), *PAGE_SIZE);
1937            let user_ref = UserRef::<SigSet>::new(addr);
1938
1939            let sigset = !SigSet::from(SIGHUP);
1940            current_task.write_object(user_ref, &sigset).expect("failed to set action");
1941
1942            assert_eq!(
1943                sys_rt_sigsuspend(current_task, user_ref, std::mem::size_of::<SigSet>()),
1944                error!(ERESTARTNOHAND)
1945            );
1946            tx.send(()).expect("send");
1947            futures::executor::block_on(thread).expect("join");
1948        })
1949        .await;
1950    }
1951
1952    /// Waitid does not support all options.
1953    #[::fuchsia::test]
1954    async fn test_waitid_options() {
1955        spawn_kernel_and_run(async |current_task| {
1956            let id = 1;
1957            assert_eq!(
1958                sys_waitid(
1959                    &current_task,
1960                    P_PID,
1961                    id,
1962                    MultiArchUserRef::null(current_task),
1963                    0,
1964                    UserRef::default().into()
1965                ),
1966                error!(EINVAL)
1967            );
1968            assert_eq!(
1969                sys_waitid(
1970                    &current_task,
1971                    P_PID,
1972                    id,
1973                    MultiArchUserRef::null(current_task),
1974                    0xffff,
1975                    UserRef::default().into()
1976                ),
1977                error!(EINVAL)
1978            );
1979        })
1980        .await;
1981    }
1982
1983    /// Wait4 does not support all options.
1984    #[::fuchsia::test]
1985    async fn test_wait4_options() {
1986        spawn_kernel_and_run(async |current_task| {
1987            let id = 1;
1988            assert_eq!(
1989                sys_wait4(
1990                    &current_task,
1991                    id,
1992                    UserRef::default(),
1993                    WEXITED,
1994                    RUsagePtr::null(current_task)
1995                ),
1996                error!(EINVAL)
1997            );
1998            assert_eq!(
1999                sys_wait4(
2000                    &current_task,
2001                    id,
2002                    UserRef::default(),
2003                    WNOWAIT,
2004                    RUsagePtr::null(current_task)
2005                ),
2006                error!(EINVAL)
2007            );
2008            assert_eq!(
2009                sys_wait4(
2010                    &current_task,
2011                    id,
2012                    UserRef::default(),
2013                    0xffff,
2014                    RUsagePtr::null(current_task)
2015                ),
2016                error!(EINVAL)
2017            );
2018        })
2019        .await;
2020    }
2021
2022    #[::fuchsia::test]
2023    async fn test_echild_when_no_zombie() {
2024        spawn_kernel_and_run(async |current_task| {
2025            // Send the signal to the task.
2026            assert!(
2027                sys_kill(&current_task, current_task.get_pid(), UncheckedSignal::from(SIGCHLD))
2028                    .is_ok()
2029            );
2030            // Verify that ECHILD is returned because there is no zombie process and no children to
2031            // block waiting for.
2032            assert_eq!(
2033                wait_on_pid(
2034                    &current_task,
2035                    &ProcessSelector::Any,
2036                    &WaitingOptions::new_for_wait4(0).expect("WaitingOptions")
2037                ),
2038                error!(ECHILD)
2039            );
2040        })
2041        .await;
2042    }
2043
2044    #[::fuchsia::test]
2045    async fn test_no_error_when_zombie() {
2046        spawn_kernel_and_run(async |current_task| {
2047            let child = current_task.clone_task_for_test(0, Some(SIGCHLD));
2048            let expected_result = WaitResult {
2049                pid: child.tid.clone(),
2050                uid: 0,
2051                zombie_state: ZombieState {
2052                    exit_status: ExitStatus::Exit(1),
2053                    time_stats: Default::default(),
2054                },
2055                exit_signal: Some(SIGCHLD),
2056            };
2057            child.thread_group().kill(ExitStatus::Exit(1), None);
2058            std::mem::drop(child);
2059
2060            assert_eq!(
2061                wait_on_pid(
2062                    &current_task,
2063                    &ProcessSelector::Any,
2064                    &WaitingOptions::new_for_wait4(0).expect("WaitingOptions")
2065                ),
2066                Ok(Some(expected_result))
2067            );
2068        })
2069        .await;
2070    }
2071
2072    #[::fuchsia::test]
2073    async fn test_waiting_for_child() {
2074        spawn_kernel_and_run(async |task| {
2075            let child = task.clone_task_builder_for_test(0, Some(SIGCHLD));
2076
2077            // No child is currently terminated.
2078            assert_eq!(
2079                wait_on_pid(
2080                    &task,
2081                    &ProcessSelector::Any,
2082                    &WaitingOptions::new_for_wait4(WNOHANG).expect("WaitingOptions")
2083                ),
2084                Ok(None)
2085            );
2086
2087            let thread = std::thread::spawn({
2088                let task = task.weak_task();
2089                move || {
2090                    // Create child
2091                    let task = task.upgrade().expect("task must be alive");
2092                    let child: AutoReleasableTask = child.into();
2093                    // Wait for the main thread to be blocked on waiting for a child.
2094                    while !task.read().is_blocked() {
2095                        std::thread::sleep(std::time::Duration::from_millis(10));
2096                    }
2097                    child.thread_group().kill(ExitStatus::Exit(0), None);
2098                    child.tid.clone()
2099                }
2100            });
2101
2102            // Block until child is terminated.
2103            let waited_child = wait_on_pid(
2104                &task,
2105                &ProcessSelector::Any,
2106                &WaitingOptions::new_for_wait4(0).expect("WaitingOptions"),
2107            )
2108            .expect("wait_on_pid")
2109            .unwrap();
2110
2111            // Child is deleted, the thread must be able to terminate.
2112            let child_id = thread.join().expect("join");
2113            assert_eq!(waited_child.pid, child_id);
2114        })
2115        .await;
2116    }
2117
2118    #[::fuchsia::test]
2119    async fn test_waiting_for_child_with_signal_pending() {
2120        spawn_kernel_and_run(async |task| {
2121            // Register a signal action to ensure that the `SIGUSR1` signal interrupts the task.
2122            task.thread_group().signal_actions.set(
2123                SIGUSR1,
2124                sigaction_t { sa_handler: uaddr { addr: 0xDEADBEEF }, ..sigaction_t::default() },
2125            );
2126
2127            // Start a child task. This will ensure that `wait_on_pid` tries to wait for the child.
2128            let _child = task.clone_task_for_test(0, Some(SIGCHLD));
2129
2130            // Send a signal to the task. `wait_on_pid` should realize there is a signal pending when
2131            // entering a wait and return with `EINTR`.
2132            send_standard_signal(&task, SignalInfo::kernel(SIGUSR1));
2133
2134            let errno = wait_on_pid(
2135                &task,
2136                &ProcessSelector::Any,
2137                &WaitingOptions::new_for_wait4(0).expect("WaitingOptions"),
2138            )
2139            .expect_err("wait_on_pid");
2140            assert_eq!(errno, ERESTARTSYS);
2141        })
2142        .await;
2143    }
2144
2145    #[::fuchsia::test]
2146    async fn test_sigkill() {
2147        spawn_kernel_and_run(async |current_task| {
2148            let mut child = current_task.clone_task_for_test(0, Some(SIGCHLD));
2149
2150            // Send SIGKILL to the child. As kill is handled immediately, no need to dequeue signals.
2151            send_standard_signal(&child, SignalInfo::kernel(SIGKILL));
2152            dequeue_signal_for_test(&mut child);
2153            std::mem::drop(child);
2154
2155            // Retrieve the exit status.
2156            let address = map_memory(
2157                &current_task,
2158                UserAddress::default(),
2159                std::mem::size_of::<i32>() as u64,
2160            );
2161            let address_ref = UserRef::<i32>::new(address);
2162            sys_wait4(&current_task, -1, address_ref, 0, RUsagePtr::null(current_task))
2163                .expect("wait4");
2164            let wstatus = current_task.read_object(address_ref).expect("read memory");
2165            assert_eq!(wstatus, SIGKILL.number() as i32);
2166        })
2167        .await;
2168    }
2169
2170    async fn test_exit_status_for_signal(
2171        sig: Signal,
2172        wait_status: i32,
2173        exit_signal: Option<Signal>,
2174    ) {
2175        spawn_kernel_and_run(async move |current_task| {
2176            let mut child = current_task.clone_task_for_test(0, exit_signal);
2177
2178            // Send the signal to the child.
2179            send_standard_signal(&child, SignalInfo::kernel(sig));
2180            dequeue_signal_for_test(&mut child);
2181            std::mem::drop(child);
2182
2183            // Retrieve the exit status.
2184            let address = map_memory(
2185                &current_task,
2186                UserAddress::default(),
2187                std::mem::size_of::<i32>() as u64,
2188            );
2189            let address_ref = UserRef::<i32>::new(address);
2190            sys_wait4(&current_task, -1, address_ref, 0, RUsagePtr::null(current_task))
2191                .expect("wait4");
2192            let wstatus = current_task.read_object(address_ref).expect("read memory");
2193            assert_eq!(wstatus, wait_status);
2194        })
2195        .await;
2196    }
2197
2198    #[::fuchsia::test]
2199    async fn test_exit_status() {
2200        // Default action is Terminate
2201        test_exit_status_for_signal(SIGTERM, SIGTERM.number() as i32, Some(SIGCHLD)).await;
2202        // Default action is CoreDump
2203        test_exit_status_for_signal(SIGSEGV, (SIGSEGV.number() as i32) | 0x80, Some(SIGCHLD)).await;
2204    }
2205
2206    #[::fuchsia::test]
2207    async fn test_wait4_by_pgid() {
2208        spawn_kernel_and_run(async |current_task| {
2209            let child1 = current_task.clone_task_for_test(0, Some(SIGCHLD));
2210            let child1_pid = child1.tid.id;
2211            child1.thread_group().kill(ExitStatus::Exit(42), None);
2212            std::mem::drop(child1);
2213            let child2 = current_task.clone_task_for_test(0, Some(SIGCHLD));
2214            child2.thread_group().setsid().expect("setsid");
2215            let child2_pid = child2.tid.id;
2216            child2.thread_group().kill(ExitStatus::Exit(42), None);
2217            std::mem::drop(child2);
2218
2219            assert_eq!(
2220                sys_wait4(
2221                    &current_task,
2222                    -child2_pid,
2223                    UserRef::default(),
2224                    0,
2225                    RUsagePtr::null(current_task)
2226                ),
2227                Ok(child2_pid)
2228            );
2229            assert_eq!(
2230                sys_wait4(&current_task, 0, UserRef::default(), 0, RUsagePtr::null(current_task)),
2231                Ok(child1_pid)
2232            );
2233        })
2234        .await;
2235    }
2236
2237    #[::fuchsia::test]
2238    async fn test_waitid_by_pgid() {
2239        spawn_kernel_and_run(async |current_task| {
2240            let child1 = current_task.clone_task_for_test(0, Some(SIGCHLD));
2241            let child1_pid = child1.tid.id;
2242            child1.thread_group().kill(ExitStatus::Exit(42), None);
2243            std::mem::drop(child1);
2244            let child2 = current_task.clone_task_for_test(0, Some(SIGCHLD));
2245            child2.thread_group().setsid().expect("setsid");
2246            let child2_pid = child2.tid.id;
2247            child2.thread_group().kill(ExitStatus::Exit(42), None);
2248            std::mem::drop(child2);
2249
2250            let address: UserRef<uapi::siginfo_t> =
2251                map_memory(&current_task, UserAddress::default(), *PAGE_SIZE).into();
2252            assert_eq!(
2253                sys_waitid(
2254                    &current_task,
2255                    P_PGID,
2256                    child2_pid,
2257                    address.into(),
2258                    WEXITED,
2259                    UserRef::default().into()
2260                ),
2261                Ok(())
2262            );
2263            // The previous wait matched child2, only child1 should be in the available zombies.
2264            assert_eq!(
2265                current_task.thread_group().read().zombie_children[0].task.get_pid(),
2266                child1_pid
2267            );
2268
2269            assert_eq!(
2270                sys_waitid(
2271                    &current_task,
2272                    P_PGID,
2273                    0,
2274                    address.into(),
2275                    WEXITED,
2276                    UserRef::default().into()
2277                ),
2278                Ok(())
2279            );
2280        })
2281        .await;
2282    }
2283
2284    #[::fuchsia::test]
2285    async fn test_sigqueue() {
2286        spawn_kernel_and_run(async |current_task| {
2287            let current_uid = current_task.current_creds().uid;
2288            let current_pid = current_task.get_pid();
2289
2290            const TEST_VALUE: u64 = 101;
2291
2292            // Add the padding int for arch64
2293            const ARCH64_SI_HEADER_SIZE: usize = SI_HEADER_SIZE + 4;
2294            // Taken from gVisor of SignalInfo in  //pkg/abi/linux/signal.go
2295            const PID_DATA_OFFSET: usize = ARCH64_SI_HEADER_SIZE;
2296            const UID_DATA_OFFSET: usize = ARCH64_SI_HEADER_SIZE + 4;
2297            const VALUE_DATA_OFFSET: usize = ARCH64_SI_HEADER_SIZE + 8;
2298
2299            let mut data = vec![0u8; SI_MAX_SIZE_AS_USIZE];
2300            let header = SignalInfoHeader {
2301                signo: SIGIO.number(),
2302                code: SI_QUEUE,
2303                ..SignalInfoHeader::default()
2304            };
2305            let _ = header.write_to(&mut data[..SI_HEADER_SIZE]);
2306            data[PID_DATA_OFFSET..PID_DATA_OFFSET + 4].copy_from_slice(&current_pid.to_ne_bytes());
2307            data[UID_DATA_OFFSET..UID_DATA_OFFSET + 4].copy_from_slice(&current_uid.to_ne_bytes());
2308            data[VALUE_DATA_OFFSET..VALUE_DATA_OFFSET + 8]
2309                .copy_from_slice(&TEST_VALUE.to_ne_bytes());
2310
2311            let addr = map_memory(&current_task, UserAddress::default(), *PAGE_SIZE);
2312            current_task.write_memory(addr, &data).unwrap();
2313            let second_current = create_task(current_task.kernel(), "second task");
2314            let second_pid = second_current.get_pid();
2315            let second_tid = second_current.get_tid();
2316            assert_eq!(second_current.read().queued_signal_count(SIGIO), 0);
2317
2318            assert_eq!(
2319                sys_rt_tgsigqueueinfo(
2320                    &current_task,
2321                    second_pid,
2322                    second_tid,
2323                    UncheckedSignal::from(SIGIO),
2324                    addr
2325                ),
2326                Ok(())
2327            );
2328            assert_eq!(second_current.read().queued_signal_count(SIGIO), 1);
2329
2330            let signal = SignalInfo::with_detail(
2331                SIGIO,
2332                SI_QUEUE,
2333                SignalDetail::Kill {
2334                    pid: current_task.pid.clone(),
2335                    uid: current_task.current_creds().uid,
2336                },
2337            );
2338            let queued_signal = second_current.write().take_specific_signal(signal);
2339            if let Some(sig) = queued_signal {
2340                assert_eq!(sig.signal, SIGIO);
2341                assert_eq!(sig.errno, 0);
2342                assert_eq!(sig.code, SI_QUEUE);
2343                if let SignalDetail::Raw { data } = sig.detail {
2344                    // offsets into the raw portion of the signal info
2345                    let offset_pid = PID_DATA_OFFSET - ARCH64_SI_HEADER_SIZE;
2346                    let offset_uid = UID_DATA_OFFSET - ARCH64_SI_HEADER_SIZE;
2347                    let offset_value = VALUE_DATA_OFFSET - ARCH64_SI_HEADER_SIZE;
2348                    let pid =
2349                        pid_t::from_ne_bytes(data[offset_pid..offset_pid + 4].try_into().unwrap());
2350                    let uid =
2351                        uid_t::from_ne_bytes(data[offset_uid..offset_uid + 4].try_into().unwrap());
2352                    let value = u64::from_ne_bytes(
2353                        data[offset_value..offset_value + 8].try_into().unwrap(),
2354                    );
2355                    assert_eq!(pid, current_pid);
2356                    assert_eq!(uid, current_uid);
2357                    assert_eq!(value, TEST_VALUE);
2358                } else {
2359                    panic!("incorrect signal detail");
2360                }
2361            } else {
2362                panic!("expected a queued signal");
2363            }
2364        })
2365        .await;
2366    }
2367
2368    #[::fuchsia::test]
2369    async fn test_signalfd_filters_signals() {
2370        spawn_kernel_and_run(async |current_task| {
2371            let memory_for_masks = map_memory(&current_task, UserAddress::default(), *PAGE_SIZE);
2372
2373            // Create a signalfd for SIGTERM and SIGINT.
2374            let term_int_mask = SigSet::from(SIGTERM) | SigSet::from(SIGINT);
2375            let term_int_mask_addr = UserRef::<SigSet>::new(memory_for_masks);
2376            current_task
2377                .write_object(term_int_mask_addr, &term_int_mask)
2378                .expect("failed to write mask");
2379            let sfd_term_int = sys_signalfd4(
2380                &current_task,
2381                FdNumber::from_raw(-1),
2382                term_int_mask_addr,
2383                std::mem::size_of::<SigSet>(),
2384                0,
2385            )
2386            .expect("failed to create SIGTERM/SIGINT signalfd");
2387
2388            // Create a signalfd for SIGCHLD.
2389            let sigchld_mask = SigSet::from(SIGCHLD);
2390            let sigchld_mask_addr =
2391                UserRef::<SigSet>::new((memory_for_masks + std::mem::size_of::<SigSet>()).unwrap());
2392            current_task
2393                .write_object(sigchld_mask_addr, &sigchld_mask)
2394                .expect("failed to write mask");
2395            let sfd_chld = sys_signalfd4(
2396                &current_task,
2397                FdNumber::from_raw(-1),
2398                sigchld_mask_addr,
2399                std::mem::size_of::<SigSet>(),
2400                0,
2401            )
2402            .expect("failed to create SIGCHLD signalfd");
2403
2404            // Block SIGCHLD so it can be received by the signalfd.
2405            sys_rt_sigprocmask(
2406                &current_task,
2407                SIG_BLOCK,
2408                sigchld_mask_addr,
2409                UserRef::default(),
2410                std::mem::size_of::<SigSet>(),
2411            )
2412            .expect("failed to block SIGCHLD");
2413
2414            // Create and exit a child process, which should generate a SIGCHLD.
2415            let child = current_task.clone_task_for_test(0, Some(SIGCHLD));
2416            child.thread_group().kill(ExitStatus::Exit(1), None);
2417            std::mem::drop(child);
2418
2419            // Check which signalfds are readable.
2420            let sfd_term_int_file =
2421                current_task.files().get(sfd_term_int).expect("failed to get sfd_term_int file");
2422            let sfd_chld_file =
2423                current_task.files().get(sfd_chld).expect("failed to get sfd_chld file");
2424
2425            let term_int_events = sfd_term_int_file
2426                .query_events(&current_task)
2427                .expect("failed to query sfd_term_int events");
2428            let chld_events =
2429                sfd_chld_file.query_events(&current_task).expect("failed to query sfd_chld events");
2430
2431            assert!(!term_int_events.contains(FdEvents::POLLIN));
2432            assert!(chld_events.contains(FdEvents::POLLIN));
2433        })
2434        .await;
2435    }
2436
2437    #[::fuchsia::test]
2438    async fn test_signalfd_filters_signals_async() {
2439        spawn_kernel_and_run(async |current_task| {
2440            let memory_for_masks = map_memory(&current_task, UserAddress::default(), *PAGE_SIZE);
2441
2442            // Create a signalfd for SIGTERM and SIGINT.
2443            let term_int_mask = SigSet::from(SIGTERM) | SigSet::from(SIGINT);
2444            let term_int_mask_addr = UserRef::<SigSet>::new(memory_for_masks);
2445            current_task
2446                .write_object(term_int_mask_addr, &term_int_mask)
2447                .expect("failed to write mask");
2448            let sfd_term_int = sys_signalfd4(
2449                &current_task,
2450                FdNumber::from_raw(-1),
2451                term_int_mask_addr,
2452                std::mem::size_of::<SigSet>(),
2453                0,
2454            )
2455            .expect("failed to create SIGTERM/SIGINT signalfd");
2456
2457            // Create a signalfd for SIGCHLD.
2458            let sigchld_mask = SigSet::from(SIGCHLD);
2459            let sigchld_mask_addr =
2460                UserRef::<SigSet>::new((memory_for_masks + std::mem::size_of::<SigSet>()).unwrap());
2461            current_task
2462                .write_object(sigchld_mask_addr, &sigchld_mask)
2463                .expect("failed to write mask");
2464            let sfd_chld = sys_signalfd4(
2465                &current_task,
2466                FdNumber::from_raw(-1),
2467                sigchld_mask_addr,
2468                std::mem::size_of::<SigSet>(),
2469                0,
2470            )
2471            .expect("failed to create SIGCHLD signalfd");
2472
2473            // Set up the async wait.
2474            let waiter = Waiter::new();
2475            let ready_items =
2476                Arc::new(LockDepMutex::<_, EventHandlerReadyQueueLock>::new(VecDeque::new()));
2477
2478            let sfd_term_int_file =
2479                current_task.files().get(sfd_term_int).expect("failed to get sfd_term_int file");
2480            let sfd_chld_file =
2481                current_task.files().get(sfd_chld).expect("failed to get sfd_chld file");
2482
2483            sfd_term_int_file
2484                .wait_async(
2485                    &current_task,
2486                    &waiter,
2487                    FdEvents::POLLIN,
2488                    EventHandler::Enqueue {
2489                        key: sfd_term_int.into(),
2490                        queue: ready_items.clone(),
2491                        sought_events: FdEvents::POLLIN,
2492                    },
2493                )
2494                .expect("failed to wait on sfd_term_int");
2495
2496            sfd_chld_file
2497                .wait_async(
2498                    &current_task,
2499                    &waiter,
2500                    FdEvents::POLLIN,
2501                    EventHandler::Enqueue {
2502                        key: sfd_chld.into(),
2503                        queue: ready_items.clone(),
2504                        sought_events: FdEvents::POLLIN,
2505                    },
2506                )
2507                .expect("failed to wait on sfd_chld");
2508
2509            // Block SIGCHLD so it can be received by the signalfd.
2510            let sigchld_mask_ref = UserRef::<SigSet>::new(memory_for_masks);
2511            current_task
2512                .write_object(sigchld_mask_ref, &sigchld_mask)
2513                .expect("failed to write mask");
2514            sys_rt_sigprocmask(
2515                &current_task,
2516                SIG_BLOCK,
2517                sigchld_mask_ref,
2518                UserRef::default(),
2519                std::mem::size_of::<SigSet>(),
2520            )
2521            .expect("failed to block SIGCHLD");
2522
2523            // Create and exit a child process, which should generate a SIGCHLD.
2524            let child = current_task.clone_task_for_test(0, Some(SIGCHLD));
2525            child.thread_group().kill(ExitStatus::Exit(1), None);
2526            std::mem::drop(child);
2527
2528            // Wait for the signal to be processed.
2529            waiter.wait(&current_task).expect("failed to wait");
2530
2531            // Check that only the correct signalfd was woken up.
2532            let ready_items = ready_items.lock();
2533            assert_eq!(ready_items.len(), 1);
2534            assert_eq!(ready_items[0].key, sfd_chld.into());
2535        })
2536        .await;
2537    }
2538}