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