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