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