linux_api/
signal.rs

1use bytemuck::TransparentWrapper;
2use linux_syscall::Result as LinuxSyscallResult;
3use linux_syscall::syscall;
4use num_enum::{IntoPrimitive, TryFromPrimitive};
5use shadow_pod::Pod;
6use vasi::VirtualAddressSpaceIndependent;
7
8use crate::bindings::{self, linux_sigval};
9use crate::const_conversions;
10use crate::const_conversions::i32_from_u32_allowing_wraparound;
11use crate::errno::Errno;
12use crate::posix_types::Pid;
13use crate::posix_types::kernel_pid_t;
14
15// signal names. This is a `struct` instead of an `enum` to support
16// realtime signals.
17#[derive(Debug, Copy, Clone, Eq, PartialEq)]
18#[repr(transparent)]
19pub struct Signal(i32);
20
21#[derive(Debug, Copy, Clone)]
22pub struct SignalFromI32Error(pub i32);
23
24impl TryFrom<i32> for Signal {
25    type Error = SignalFromI32Error;
26
27    fn try_from(value: i32) -> Result<Self, Self::Error> {
28        if (1..=i32::from(Signal::SIGRT_MAX)).contains(&value) {
29            Ok(Self(value))
30        } else {
31            Err(SignalFromI32Error(value))
32        }
33    }
34}
35
36impl From<Signal> for i32 {
37    fn from(value: Signal) -> Self {
38        value.as_i32()
39    }
40}
41
42impl Signal {
43    pub const SIGHUP: Self = Self::std_from_u32_const(bindings::LINUX_SIGHUP);
44    pub const SIGINT: Self = Self::std_from_u32_const(bindings::LINUX_SIGINT);
45    pub const SIGQUIT: Self = Self::std_from_u32_const(bindings::LINUX_SIGQUIT);
46    pub const SIGILL: Self = Self::std_from_u32_const(bindings::LINUX_SIGILL);
47    pub const SIGTRAP: Self = Self::std_from_u32_const(bindings::LINUX_SIGTRAP);
48    pub const SIGABRT: Self = Self::std_from_u32_const(bindings::LINUX_SIGABRT);
49    pub const SIGBUS: Self = Self::std_from_u32_const(bindings::LINUX_SIGBUS);
50    pub const SIGFPE: Self = Self::std_from_u32_const(bindings::LINUX_SIGFPE);
51    pub const SIGKILL: Self = Self::std_from_u32_const(bindings::LINUX_SIGKILL);
52    pub const SIGUSR1: Self = Self::std_from_u32_const(bindings::LINUX_SIGUSR1);
53    pub const SIGSEGV: Self = Self::std_from_u32_const(bindings::LINUX_SIGSEGV);
54    pub const SIGUSR2: Self = Self::std_from_u32_const(bindings::LINUX_SIGUSR2);
55    pub const SIGPIPE: Self = Self::std_from_u32_const(bindings::LINUX_SIGPIPE);
56    pub const SIGALRM: Self = Self::std_from_u32_const(bindings::LINUX_SIGALRM);
57    pub const SIGTERM: Self = Self::std_from_u32_const(bindings::LINUX_SIGTERM);
58    pub const SIGSTKFLT: Self = Self::std_from_u32_const(bindings::LINUX_SIGSTKFLT);
59    pub const SIGCHLD: Self = Self::std_from_u32_const(bindings::LINUX_SIGCHLD);
60    pub const SIGCONT: Self = Self::std_from_u32_const(bindings::LINUX_SIGCONT);
61    pub const SIGSTOP: Self = Self::std_from_u32_const(bindings::LINUX_SIGSTOP);
62    pub const SIGTSTP: Self = Self::std_from_u32_const(bindings::LINUX_SIGTSTP);
63    pub const SIGTTIN: Self = Self::std_from_u32_const(bindings::LINUX_SIGTTIN);
64    pub const SIGTTOU: Self = Self::std_from_u32_const(bindings::LINUX_SIGTTOU);
65    pub const SIGURG: Self = Self::std_from_u32_const(bindings::LINUX_SIGURG);
66    pub const SIGXCPU: Self = Self::std_from_u32_const(bindings::LINUX_SIGXCPU);
67    pub const SIGXFSZ: Self = Self::std_from_u32_const(bindings::LINUX_SIGXFSZ);
68    pub const SIGVTALRM: Self = Self::std_from_u32_const(bindings::LINUX_SIGVTALRM);
69    pub const SIGPROF: Self = Self::std_from_u32_const(bindings::LINUX_SIGPROF);
70    pub const SIGWINCH: Self = Self::std_from_u32_const(bindings::LINUX_SIGWINCH);
71    pub const SIGIO: Self = Self::std_from_u32_const(bindings::LINUX_SIGIO);
72    pub const SIGPWR: Self = Self::std_from_u32_const(bindings::LINUX_SIGPWR);
73    pub const SIGSYS: Self = Self::std_from_u32_const(bindings::LINUX_SIGSYS);
74
75    pub const STANDARD_MAX: Self = Self(31);
76
77    pub const SIGRT_MIN: Self = Self::rt_from_u32_const(bindings::LINUX_SIGRTMIN);
78    // According to signal(7). bindgen fails to bind this one.
79    pub const SIGRT_MAX: Self = Self::rt_from_u32_const(64);
80
81    pub const MIN: Self = Self(1);
82    pub const MAX: Self = Self::SIGRT_MAX;
83
84    // Aliases
85    pub const SIGIOT: Self = Self::std_from_u32_const(bindings::LINUX_SIGIOT);
86    pub const SIGPOLL: Self = Self::std_from_u32_const(bindings::LINUX_SIGPOLL);
87    pub const SIGUNUSED: Self = Self::std_from_u32_const(bindings::LINUX_SIGUNUSED);
88
89    pub fn is_realtime(&self) -> bool {
90        (i32::from(Self::SIGRT_MIN)..=i32::from(Self::SIGRT_MAX)).contains(&self.0)
91    }
92
93    pub const fn as_i32(&self) -> i32 {
94        self.0
95    }
96
97    pub fn standard_signals() -> impl Iterator<Item = Signal> {
98        (i32::from(Self::MIN)..=i32::from(Self::STANDARD_MAX)).map(|i| Self::try_from(i).unwrap())
99    }
100
101    // Checked conversion from bindings
102    const fn std_from_u32_const(val: u32) -> Self {
103        let rv = Self(const_conversions::i32_from_u32(val));
104        assert!(rv.0 as u32 == val);
105        assert!(rv.0 <= Self::STANDARD_MAX.0);
106        rv
107    }
108
109    const fn rt_from_u32_const(val: u32) -> Self {
110        let rv = Self(const_conversions::i32_from_u32(val));
111        assert!(rv.0 as u32 == val);
112        assert!(rv.0 > Self::STANDARD_MAX.0);
113        rv
114    }
115
116    /// Returns the raw signal integer or 0.
117    pub fn as_raw(this: Option<Self>) -> i32 {
118        this.map(|s| s.as_i32()).unwrap_or(0)
119    }
120}
121
122bitflags::bitflags! {
123    #[repr(transparent)]
124    #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
125    pub struct SigActionFlags: u64 {
126        const SA_NOCLDSTOP = const_conversions::u64_from_u32(bindings::LINUX_SA_NOCLDSTOP);
127        const SA_NOCLDWAIT = const_conversions::u64_from_u32(bindings::LINUX_SA_NOCLDWAIT);
128        const SA_NODEFER = const_conversions::u64_from_u32(bindings::LINUX_SA_NODEFER);
129        const SA_ONSTACK = const_conversions::u64_from_u32(bindings::LINUX_SA_ONSTACK);
130        const SA_RESETHAND = const_conversions::u64_from_u32(bindings::LINUX_SA_RESETHAND);
131        const SA_RESTART = const_conversions::u64_from_u32(bindings::LINUX_SA_RESTART);
132        const SA_RESTORER = const_conversions::u64_from_u32(bindings::LINUX_SA_RESTORER);
133        const SA_SIGINFO = const_conversions::u64_from_u32(bindings::LINUX_SA_SIGINFO);
134    }
135}
136// SAFETY: bitflags guarantees the internal representation is effectively a u64.
137unsafe impl VirtualAddressSpaceIndependent for SigActionFlags {}
138
139/// Describes how a signal was sent.
140#[derive(Copy, Clone, Debug, Eq, PartialEq)]
141pub enum SigInfoCode {
142    Si(SigInfoCodeSi),
143    Ill(SigInfoCodeIll),
144    Fpe(SigInfoCodeFpe),
145    Segv(SigInfoCodeSegv),
146    Bus(SigInfoCodeBus),
147    Trap(SigInfoCodeTrap),
148    Cld(SigInfoCodeCld),
149    Poll(SigInfoCodePoll),
150    Sys(SigInfoCodeSys),
151}
152
153#[derive(Debug, Copy, Clone)]
154pub struct SigInfoCodeFromRawError {
155    pub code: i32,
156    pub signo: i32,
157}
158
159impl SigInfoCode {
160    /// The interpretation of the `si_code` field `sigaction` can depend on the `si_signo`
161    /// field. Tries to determine the correct interpretation.
162    fn try_from_raw(raw_code: i32, raw_signo: i32) -> Result<Self, SigInfoCodeFromRawError> {
163        // These codes always take precedence, e.g. covering the case where
164        // a SIGCHLD is sent via `kill`. The code values are mutually exclusive
165        // from the other sets below.
166        if let Ok(si_code) = SigInfoCodeSi::try_from(raw_code) {
167            return Ok(SigInfoCode::Si(si_code));
168        }
169
170        let err = SigInfoCodeFromRawError {
171            code: raw_code,
172            signo: raw_signo,
173        };
174
175        let Ok(signal) = Signal::try_from(raw_signo) else {
176            return Err(err);
177        };
178
179        // Remaining sets of codes are *not* mutually exclusive, and depend on the signal.
180        match signal {
181            Signal::SIGCHLD => SigInfoCodeCld::try_from(raw_code)
182                .map(SigInfoCode::Cld)
183                .or(Err(err)),
184            Signal::SIGILL => SigInfoCodeIll::try_from(raw_code)
185                .map(SigInfoCode::Ill)
186                .or(Err(err)),
187            Signal::SIGFPE => SigInfoCodeFpe::try_from(raw_code)
188                .map(SigInfoCode::Fpe)
189                .or(Err(err)),
190            Signal::SIGSEGV => SigInfoCodeSegv::try_from(raw_code)
191                .map(SigInfoCode::Segv)
192                .or(Err(err)),
193            Signal::SIGBUS => SigInfoCodeBus::try_from(raw_code)
194                .map(SigInfoCode::Bus)
195                .or(Err(err)),
196            Signal::SIGTRAP => SigInfoCodeTrap::try_from(raw_code)
197                .map(SigInfoCode::Trap)
198                .or(Err(err)),
199            Signal::SIGPOLL => SigInfoCodePoll::try_from(raw_code)
200                .map(SigInfoCode::Poll)
201                .or(Err(err)),
202            Signal::SIGSYS => SigInfoCodeSys::try_from(raw_code)
203                .map(SigInfoCode::Sys)
204                .or(Err(err)),
205            _ => Err(err),
206        }
207    }
208}
209
210#[allow(non_camel_case_types)]
211#[repr(i32)]
212#[derive(Copy, Clone, Debug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)]
213pub enum SigInfoCodeSi {
214    // sigaction(2): kill(2)
215    SI_USER = const_conversions::i32_from_u32(bindings::LINUX_SI_USER),
216    // sigaction(2): Sent by the kernel.
217    SI_KERNEL = const_conversions::i32_from_u32(bindings::LINUX_SI_KERNEL),
218    // sigaction(2): sigqueue(3)
219    SI_QUEUE = bindings::LINUX_SI_QUEUE,
220    // sigaction(2): POSIX timer expired.
221    SI_TIMER = bindings::LINUX_SI_TIMER,
222    // sigaction(2): POSIX message queue state changed; see mq_notify(3)
223    SI_MESGQ = bindings::LINUX_SI_MESGQ,
224    // sigaction(2): AIO completed
225    SI_ASYNCIO = bindings::LINUX_SI_ASYNCIO,
226    // sigaction(2): tkill(2) or tgkill(2).
227    SI_TKILL = bindings::LINUX_SI_TKILL,
228}
229
230/// Codes for SIGCHLD
231#[allow(non_camel_case_types)]
232#[repr(i32)]
233#[derive(Copy, Clone, Debug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)]
234pub enum SigInfoCodeCld {
235    // Child has exited.
236    CLD_EXITED = const_conversions::i32_from_u32(bindings::LINUX_CLD_EXITED),
237    // Child was killed.
238    CLD_KILLED = const_conversions::i32_from_u32(bindings::LINUX_CLD_KILLED),
239    // Child terminated abnormally.
240    CLD_DUMPED = const_conversions::i32_from_u32(bindings::LINUX_CLD_DUMPED),
241    // Traced child has trapped.
242    CLD_TRAPPED = const_conversions::i32_from_u32(bindings::LINUX_CLD_TRAPPED),
243    // Child has stopped.
244    CLD_STOPPED = const_conversions::i32_from_u32(bindings::LINUX_CLD_STOPPED),
245    // Stopped child has continued.
246    CLD_CONTINUED = const_conversions::i32_from_u32(bindings::LINUX_CLD_CONTINUED),
247}
248
249/// Codes for SIGILL
250#[allow(non_camel_case_types)]
251#[repr(i32)]
252#[derive(Copy, Clone, Debug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)]
253pub enum SigInfoCodeIll {
254    ILL_ILLOPC = const_conversions::i32_from_u32(bindings::LINUX_ILL_ILLOPC),
255    ILL_ILLOPN = const_conversions::i32_from_u32(bindings::LINUX_ILL_ILLOPN),
256    ILL_ILLADR = const_conversions::i32_from_u32(bindings::LINUX_ILL_ILLADR),
257    ILL_ILLTRP = const_conversions::i32_from_u32(bindings::LINUX_ILL_ILLTRP),
258    ILL_PRVOPC = const_conversions::i32_from_u32(bindings::LINUX_ILL_PRVOPC),
259    ILL_PRVREG = const_conversions::i32_from_u32(bindings::LINUX_ILL_PRVREG),
260    ILL_COPROC = const_conversions::i32_from_u32(bindings::LINUX_ILL_COPROC),
261    ILL_BADSTK = const_conversions::i32_from_u32(bindings::LINUX_ILL_BADSTK),
262    ILL_BADIADDR = const_conversions::i32_from_u32(bindings::LINUX_ILL_BADIADDR),
263}
264
265/// Codes for SIGFPE
266#[allow(non_camel_case_types)]
267#[repr(i32)]
268#[derive(Copy, Clone, Debug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)]
269pub enum SigInfoCodeFpe {
270    FPE_INTDIV = const_conversions::i32_from_u32(bindings::LINUX_FPE_INTDIV),
271    FPE_INTOVF = const_conversions::i32_from_u32(bindings::LINUX_FPE_INTOVF),
272    FPE_FLTDIV = const_conversions::i32_from_u32(bindings::LINUX_FPE_FLTDIV),
273    FPE_FLTOVF = const_conversions::i32_from_u32(bindings::LINUX_FPE_FLTOVF),
274    FPE_FLTUND = const_conversions::i32_from_u32(bindings::LINUX_FPE_FLTUND),
275    FPE_FLTRES = const_conversions::i32_from_u32(bindings::LINUX_FPE_FLTRES),
276    FPE_FLTINV = const_conversions::i32_from_u32(bindings::LINUX_FPE_FLTINV),
277    FPE_FLTSUB = const_conversions::i32_from_u32(bindings::LINUX_FPE_FLTSUB),
278    FPE_FLTUNK = const_conversions::i32_from_u32(bindings::LINUX_FPE_FLTUNK),
279    FPE_CONDTRAP = const_conversions::i32_from_u32(bindings::LINUX_FPE_CONDTRAP),
280}
281
282/// Codes for SIGSEGV
283#[allow(non_camel_case_types)]
284#[repr(i32)]
285#[derive(Copy, Clone, Debug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)]
286pub enum SigInfoCodeSegv {
287    SEGV_MAPERR = const_conversions::i32_from_u32(bindings::LINUX_SEGV_MAPERR),
288    SEGV_ACCERR = const_conversions::i32_from_u32(bindings::LINUX_SEGV_ACCERR),
289    SEGV_BNDERR = const_conversions::i32_from_u32(bindings::LINUX_SEGV_BNDERR),
290    SEGV_PKUERR = const_conversions::i32_from_u32(bindings::LINUX_SEGV_PKUERR),
291    SEGV_ACCADI = const_conversions::i32_from_u32(bindings::LINUX_SEGV_ACCADI),
292    SEGV_ADIDERR = const_conversions::i32_from_u32(bindings::LINUX_SEGV_ADIDERR),
293    SEGV_ADIPERR = const_conversions::i32_from_u32(bindings::LINUX_SEGV_ADIPERR),
294    SEGV_MTEAERR = const_conversions::i32_from_u32(bindings::LINUX_SEGV_MTEAERR),
295    SEGV_MTESERR = const_conversions::i32_from_u32(bindings::LINUX_SEGV_MTESERR),
296}
297
298/// Codes for SIGBUS
299#[allow(non_camel_case_types)]
300#[repr(i32)]
301#[derive(Copy, Clone, Debug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)]
302pub enum SigInfoCodeBus {
303    BUS_ADRALN = const_conversions::i32_from_u32(bindings::LINUX_BUS_ADRALN),
304    BUS_ADRERR = const_conversions::i32_from_u32(bindings::LINUX_BUS_ADRERR),
305    BUS_OBJERR = const_conversions::i32_from_u32(bindings::LINUX_BUS_OBJERR),
306    BUS_MCEERR_AR = const_conversions::i32_from_u32(bindings::LINUX_BUS_MCEERR_AR),
307    BUS_MCEERR_AO = const_conversions::i32_from_u32(bindings::LINUX_BUS_MCEERR_AO),
308}
309
310/// Codes for SIGTRAP
311#[allow(non_camel_case_types)]
312#[repr(i32)]
313#[derive(Copy, Clone, Debug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)]
314pub enum SigInfoCodeTrap {
315    TRAP_BRKPT = const_conversions::i32_from_u32(bindings::LINUX_TRAP_BRKPT),
316    TRAP_TRACE = const_conversions::i32_from_u32(bindings::LINUX_TRAP_TRACE),
317    TRAP_BRANCH = const_conversions::i32_from_u32(bindings::LINUX_TRAP_BRANCH),
318    TRAP_HWBKPT = const_conversions::i32_from_u32(bindings::LINUX_TRAP_HWBKPT),
319    TRAP_UNK = const_conversions::i32_from_u32(bindings::LINUX_TRAP_UNK),
320    TRAP_PERF = const_conversions::i32_from_u32(bindings::LINUX_TRAP_PERF),
321}
322
323/// Codes for SIGIO/SIGPOLL
324#[allow(non_camel_case_types)]
325#[repr(i32)]
326#[derive(Copy, Clone, Debug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)]
327pub enum SigInfoCodePoll {
328    POLL_IN = const_conversions::i32_from_u32(bindings::LINUX_POLL_IN),
329    POLL_OUT = const_conversions::i32_from_u32(bindings::LINUX_POLL_OUT),
330    POLL_MSG = const_conversions::i32_from_u32(bindings::LINUX_POLL_MSG),
331    POLL_ERR = const_conversions::i32_from_u32(bindings::LINUX_POLL_ERR),
332    POLL_PRI = const_conversions::i32_from_u32(bindings::LINUX_POLL_PRI),
333    POLL_HUP = const_conversions::i32_from_u32(bindings::LINUX_POLL_HUP),
334}
335
336/// Codes for SIGSYS
337#[allow(non_camel_case_types)]
338#[repr(i32)]
339#[derive(Copy, Clone, Debug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)]
340pub enum SigInfoCodeSys {
341    SYS_SECCOMP = const_conversions::i32_from_u32(bindings::LINUX_SYS_SECCOMP),
342}
343
344#[allow(non_camel_case_types)]
345pub type linux_siginfo_t = bindings::linux_siginfo_t;
346
347type SigInfoDetailsFields = bindings::linux___sifields;
348
349// The fields of `linux___sifields` in the original Linux source are anonymous
350// unions, which aren't supported in Rust.  bindgen generates names for these
351// union types. We create aliases here so that we only have to name them in one
352// place, and fix them in one place if the names change due to field insertion
353// or reordering in some later version of the Linux source.
354//
355// e.g. in the current version of the generated and mangled kernel bindings, this
356// is the declaration of `linux___sifields`:
357//
358// pub union linux___sifields {
359//     pub l_kill: linux___sifields__bindgen_ty_1,
360//     pub l_timer: linux___sifields__bindgen_ty_2,
361//     pub l_rt: linux___sifields__bindgen_ty_3,
362//     pub l_sigchld: linux___sifields__bindgen_ty_4,
363//     pub l_sigfault: linux___sifields__bindgen_ty_5,
364//     pub l_sigpoll: linux___sifields__bindgen_ty_6,
365//     pub l_sigsys: linux___sifields__bindgen_ty_7,
366// }
367pub type SigInfoDetailsKill = bindings::linux___sifields__bindgen_ty_1;
368pub type SigInfoDetailsTimer = bindings::linux___sifields__bindgen_ty_2;
369pub type SigInfoDetailsRt = bindings::linux___sifields__bindgen_ty_3;
370pub type SigInfoDetailsSigChld = bindings::linux___sifields__bindgen_ty_4;
371pub type SigInfoDetailsSigFault = bindings::linux___sifields__bindgen_ty_5;
372pub type SigInfoDetailsSigPoll = bindings::linux___sifields__bindgen_ty_6;
373pub type SigInfoDetailsSigSys = bindings::linux___sifields__bindgen_ty_7;
374
375pub enum SigInfoDetails {
376    Kill(SigInfoDetailsKill),
377    Timer(SigInfoDetailsTimer),
378    Rt(SigInfoDetailsRt),
379    SigChld(SigInfoDetailsSigChld),
380    SigFault(SigInfoDetailsSigFault),
381    SigPoll(SigInfoDetailsSigPoll),
382    SigSys(SigInfoDetailsSigSys),
383}
384
385/// Wrapper around `linux_siginfo_t`.
386///
387/// # Invariants
388///
389/// The following invariants in the internal `linux_siginfo_t` are ensured when
390/// constructed through safe constructors:
391///
392/// * `lsi_code`, `lsi_signo`, and `lsi_errno` are initialized.
393/// * The parts of the `l_sifields` union are initialized that `sigaction(2)`
394///   specifies are initialized for the given `lsi_code` and `lsi_signo`.
395///
396/// When constructing via one of the unsafe constructors that takes some form of
397/// `linux_siginfo_t` or the pieces of one, the above must also hold. However,
398/// it is sufficient for all bytes to be initialized; any bit pattern is
399/// acceptable as long as it is an initialized one. (Initializing from garbage data
400/// may result in garbage pointers, but the safe methods of this type will never
401/// dereference those itself). For example, `unsafe {
402/// SigInfo::wrap_assume_initd(core::mem::zeroed()) }` is sound.
403#[derive(Copy, Clone, Debug)]
404#[repr(transparent)]
405#[allow(non_camel_case_types)]
406pub struct siginfo_t(linux_siginfo_t);
407// Contains pointers, but they are understood to not necessarily be valid in the
408// current address space.
409unsafe impl Send for siginfo_t {}
410unsafe impl Pod for siginfo_t {}
411
412impl siginfo_t {
413    /// The bindings end up with a couple extra outer layers of unions.
414    /// The outermost only has a single member; the next one has a data
415    /// field and a padding field.
416    fn inner(&self) -> &bindings::linux_siginfo__bindgen_ty_1__bindgen_ty_1 {
417        // SAFETY: Guaranteed initialized by [`SigInfo`] invariants.
418        unsafe { &self.0.l__bindgen_anon_1.l__bindgen_anon_1 }
419    }
420
421    /// Analogous to `bytemuck::TransparentWrapper::wrap`, but `unsafe`.
422    ///
423    /// # Safety
424    ///
425    /// See [`siginfo_t`] `Invariants`.
426    pub unsafe fn wrap_assume_initd(si: linux_siginfo_t) -> Self {
427        Self(si)
428    }
429
430    /// Analogous to `bytemuck::TransparentWrapper::wrap_ref`, but `unsafe`.
431    ///
432    /// # Safety
433    ///
434    /// See [`siginfo_t`] `Invariants`.
435    pub unsafe fn wrap_ref_assume_initd(si: &linux_siginfo_t) -> &Self {
436        unsafe { &*(core::ptr::from_ref(si) as *const Self) }
437    }
438
439    /// Analogous to `bytemuck::TransparentWrapper::wrap_mut`, but `unsafe`.
440    ///
441    /// # Safety
442    ///
443    /// See [`siginfo_t`] `Invariants`.
444    pub unsafe fn wrap_mut_assume_initd(si: &mut linux_siginfo_t) -> &mut Self {
445        unsafe { &mut *(core::ptr::from_mut(si) as *mut Self) }
446    }
447
448    /// # Safety
449    ///
450    /// Pointers are safe to dereference iff those used to construct `si` are.
451    pub unsafe fn peel(si: Self) -> linux_siginfo_t {
452        si.0
453    }
454
455    #[inline]
456    pub fn signal(&self) -> Result<Signal, SignalFromI32Error> {
457        Signal::try_from(self.inner().lsi_signo)
458    }
459
460    #[inline]
461    pub fn code(&self) -> Result<SigInfoCode, SigInfoCodeFromRawError> {
462        SigInfoCode::try_from_raw(self.inner().lsi_code, self.inner().lsi_signo)
463    }
464
465    /// # Safety
466    ///
467    /// Pointers are safe to dereference iff those used to construct `self` (or set
468    /// via mutable methods) are.
469    pub unsafe fn details(&self) -> Option<SigInfoDetails> {
470        let Ok(code) = self.code() else {
471            return None;
472        };
473        match code {
474            SigInfoCode::Si(SigInfoCodeSi::SI_USER) => Some(SigInfoDetails::Kill(unsafe {
475                self.inner().l_sifields.l_kill
476            })),
477            SigInfoCode::Si(SigInfoCodeSi::SI_KERNEL) => Some(SigInfoDetails::SigFault(unsafe {
478                self.inner().l_sifields.l_sigfault
479            })),
480            SigInfoCode::Si(SigInfoCodeSi::SI_QUEUE) => {
481                Some(SigInfoDetails::Rt(unsafe { self.inner().l_sifields.l_rt }))
482            }
483            SigInfoCode::Si(SigInfoCodeSi::SI_TIMER) => Some(SigInfoDetails::Timer(unsafe {
484                self.inner().l_sifields.l_timer
485            })),
486            SigInfoCode::Si(SigInfoCodeSi::SI_MESGQ) => {
487                Some(SigInfoDetails::Rt(unsafe { self.inner().l_sifields.l_rt }))
488            }
489            SigInfoCode::Si(SigInfoCodeSi::SI_ASYNCIO) => Some(SigInfoDetails::SigPoll(unsafe {
490                self.inner().l_sifields.l_sigpoll
491            })),
492            SigInfoCode::Si(SigInfoCodeSi::SI_TKILL) => Some(SigInfoDetails::Kill(unsafe {
493                self.inner().l_sifields.l_kill
494            })),
495            SigInfoCode::Cld(_) => Some(SigInfoDetails::SigChld(unsafe {
496                self.inner().l_sifields.l_sigchld
497            })),
498            // TODO: `l_sigfault` contains another union. Would be nice
499            // to safely pick it apart further here.
500            SigInfoCode::Ill(_) => Some(SigInfoDetails::SigFault(unsafe {
501                self.inner().l_sifields.l_sigfault
502            })),
503            SigInfoCode::Fpe(_) => Some(SigInfoDetails::SigFault(unsafe {
504                self.inner().l_sifields.l_sigfault
505            })),
506            SigInfoCode::Segv(_) => Some(SigInfoDetails::SigFault(unsafe {
507                self.inner().l_sifields.l_sigfault
508            })),
509            SigInfoCode::Bus(_) => Some(SigInfoDetails::SigFault(unsafe {
510                self.inner().l_sifields.l_sigfault
511            })),
512            SigInfoCode::Trap(_) => Some(SigInfoDetails::SigFault(unsafe {
513                self.inner().l_sifields.l_sigfault
514            })),
515            SigInfoCode::Poll(_) => Some(SigInfoDetails::SigFault(unsafe {
516                self.inner().l_sifields.l_sigfault
517            })),
518            SigInfoCode::Sys(_) => Some(SigInfoDetails::SigSys(unsafe {
519                self.inner().l_sifields.l_sigsys
520            })),
521        }
522    }
523
524    // SAFETY: `fields` must be initialized consistently with [`SigInfo`] `Invariants`.
525    unsafe fn new(signal: Signal, errno: i32, code: i32, fields: SigInfoDetailsFields) -> Self {
526        Self(bindings::linux_siginfo_t {
527            l__bindgen_anon_1: bindings::linux_siginfo__bindgen_ty_1 {
528                l__bindgen_anon_1: bindings::linux_siginfo__bindgen_ty_1__bindgen_ty_1 {
529                    lsi_signo: signal.into(),
530                    lsi_errno: errno,
531                    lsi_code: code,
532                    l_sifields: fields,
533                },
534            },
535        })
536    }
537
538    // TODO: Should `sender_pid` actually be `sender_tid`?
539    pub fn new_for_kill(signal: Signal, sender_pid: i32, sender_uid: u32) -> Self {
540        // sigaction(2):
541        // > Signals  sent  with  kill(2) and sigqueue(3) fill in si_pid and si_uid.
542        // > In addition, signals sent with sigqueue(3) fill in si_int and si_ptr with
543        // > the values specified by the sender of the signal; see sigqueue(3) for
544        // > more details.
545        unsafe {
546            Self::new(
547                signal,
548                0,
549                SigInfoCodeSi::SI_USER.into(),
550                SigInfoDetailsFields {
551                    l_kill: SigInfoDetailsKill {
552                        l_pid: sender_pid,
553                        l_uid: sender_uid,
554                    },
555                },
556            )
557        }
558    }
559
560    // TODO: Should `sender_pid` actually be `sender_tid`?
561    pub fn new_for_tkill(signal: Signal, sender_pid: i32, sender_uid: u32) -> Self {
562        unsafe {
563            Self::new(
564                signal,
565                0,
566                SigInfoCodeSi::SI_TKILL.into(),
567                SigInfoDetailsFields {
568                    l_kill: SigInfoDetailsKill {
569                        l_pid: sender_pid,
570                        l_uid: sender_uid,
571                    },
572                },
573            )
574        }
575    }
576
577    pub fn new_for_timer(signal: Signal, timer_id: i32, overrun: i32) -> Self {
578        // sigaction(2):
579        // > Signals sent by POSIX.1b timers (since Linux 2.6) fill in si_overrun and
580        // > si_timerid.  The si_timerid field is  an  internal ID  used by the kernel
581        // > to identify the timer; it is not the same as the timer ID returned by
582        // > timer_create(2).  The si_overrun field is the timer overrun count; this
583        // > is the same information as is obtained by a call to timer_getoverrun(2).
584        // > These fields are nonstandard Linux extensions.
585        unsafe {
586            Self::new(
587                signal,
588                0,
589                SigInfoCodeSi::SI_TIMER.into(),
590                SigInfoDetailsFields {
591                    l_timer: SigInfoDetailsTimer {
592                        l_tid: timer_id,
593                        l_overrun: overrun,
594                        l_sigval: core::mem::zeroed(),
595                        l_sys_private: 0,
596                    },
597                },
598            )
599        }
600    }
601
602    // TODO: Should `sender_pid` actually be `sender_tid`?
603    pub fn new_for_mq(
604        signal: Signal,
605        sender_pid: i32,
606        sender_uid: u32,
607        sigval: linux_sigval,
608    ) -> Self {
609        // sigaction(2):
610        // > Signals  sent  for  message queue notification (see the description of
611        // > SIGEV_SIGNAL in mq_notify(3)) fill in si_int/si_ptr, with the sigev_value
612        // > supplied to mq_notify(3); si_pid, with the process ID of the message
613        // > sender; and si_uid, with the real user ID of the message sender.
614        unsafe {
615            Self::new(
616                signal,
617                0,
618                SigInfoCodeSi::SI_MESGQ.into(),
619                SigInfoDetailsFields {
620                    l_rt: SigInfoDetailsRt {
621                        l_pid: sender_pid,
622                        l_uid: sender_uid,
623                        l_sigval: sigval,
624                    },
625                },
626            )
627        }
628    }
629
630    pub fn new_for_sigchld_exited(
631        exit_signal: Signal,
632        child_pid: i32,
633        child_uid: u32,
634        child_exit_status: i32,
635        child_utime: i64,
636        child_stime: i64,
637    ) -> Self {
638        // sigaction(2):
639        // > SIGCHLD  fills  in  si_pid,  si_uid,  si_status, si_utime, and si_stime,
640        // > providing information about the child.  The si_pid field is the process
641        // > ID of the child; si_uid is the child's real user ID.  The si_status field
642        // > contains the exit status  of the  child  (if  si_code  is  CLD_EXITED),
643        // ...
644        // > The si_utime and si_stime contain the user and system CPU time used by the
645        // > child process; these fields do not  include  the  times  used  by
646        // > waited-for  children  (unlike  getrusage(2) and times(2)).
647        unsafe {
648            Self::new(
649                exit_signal,
650                0,
651                SigInfoCodeCld::CLD_EXITED.into(),
652                SigInfoDetailsFields {
653                    l_sigchld: SigInfoDetailsSigChld {
654                        l_pid: child_pid,
655                        l_uid: child_uid,
656                        l_status: child_exit_status,
657                        l_utime: child_utime,
658                        l_stime: child_stime,
659                    },
660                },
661            )
662        }
663    }
664
665    // sigaction(2):
666    // > SIGCHLD  fills  in  si_pid,  si_uid,  si_status, si_utime, and si_stime,
667    // > providing information about the child.  The si_pid field is the process
668    // > ID of the child; si_uid is the child's real user ID. The si_status field
669    // > contains
670    // ...
671    // > the signal number that caused the process to change state.  The
672    // > si_utime and si_stime contain the user and system CPU time used by the
673    // > child process; these fields do not  include  the  times  used  by
674    // > waited-for  children  (unlike  getrusage(2) and times(2)).
675    fn new_for_sigchld_signaled(
676        exit_signal: Signal,
677        code: SigInfoCodeCld,
678        child_pid: i32,
679        child_uid: u32,
680        signal: Signal,
681        child_utime: i64,
682        child_stime: i64,
683    ) -> Self {
684        unsafe {
685            Self::new(
686                exit_signal,
687                0,
688                code.into(),
689                SigInfoDetailsFields {
690                    l_sigchld: SigInfoDetailsSigChld {
691                        l_pid: child_pid,
692                        l_uid: child_uid,
693                        l_status: signal.into(),
694                        l_utime: child_utime,
695                        l_stime: child_stime,
696                    },
697                },
698            )
699        }
700    }
701
702    pub fn new_for_sigchld_killed(
703        exit_signal: Signal,
704        child_pid: i32,
705        child_uid: u32,
706        fatal_signal: Signal,
707        child_utime: i64,
708        child_stime: i64,
709    ) -> Self {
710        Self::new_for_sigchld_signaled(
711            exit_signal,
712            SigInfoCodeCld::CLD_KILLED,
713            child_pid,
714            child_uid,
715            fatal_signal,
716            child_utime,
717            child_stime,
718        )
719    }
720    pub fn new_for_sigchld_dumped(
721        exit_signal: Signal,
722        child_pid: i32,
723        child_uid: u32,
724        fatal_signal: Signal,
725        child_utime: i64,
726        child_stime: i64,
727    ) -> Self {
728        Self::new_for_sigchld_signaled(
729            exit_signal,
730            SigInfoCodeCld::CLD_DUMPED,
731            child_pid,
732            child_uid,
733            fatal_signal,
734            child_utime,
735            child_stime,
736        )
737    }
738    pub fn new_for_sigchld_trapped(
739        exit_signal: Signal,
740        child_pid: i32,
741        child_uid: u32,
742        child_utime: i64,
743        child_stime: i64,
744    ) -> Self {
745        Self::new_for_sigchld_signaled(
746            exit_signal,
747            SigInfoCodeCld::CLD_TRAPPED,
748            child_pid,
749            child_uid,
750            Signal::SIGTRAP,
751            child_utime,
752            child_stime,
753        )
754    }
755    pub fn new_for_sigchld_stopped(
756        exit_signal: Signal,
757        child_pid: i32,
758        child_uid: u32,
759        child_utime: i64,
760        child_stime: i64,
761    ) -> Self {
762        Self::new_for_sigchld_signaled(
763            exit_signal,
764            SigInfoCodeCld::CLD_STOPPED,
765            child_pid,
766            child_uid,
767            Signal::SIGSTOP,
768            child_utime,
769            child_stime,
770        )
771    }
772    pub fn new_for_sigchld_continued(
773        exit_signal: Signal,
774        child_pid: i32,
775        child_uid: u32,
776        child_utime: i64,
777        child_stime: i64,
778    ) -> Self {
779        Self::new_for_sigchld_signaled(
780            exit_signal,
781            SigInfoCodeCld::CLD_CONTINUED,
782            child_pid,
783            child_uid,
784            Signal::SIGCONT,
785            child_utime,
786            child_stime,
787        )
788    }
789
790    // TODO: (see sigaction(2))
791    // * new_for_sigill
792    // * new_for_sigfpe
793    // * new_for_sigsegv
794    // * new_for_sigtrap
795    // * new_for_poll
796    // * new_for_seccomp
797    // ...
798}
799
800impl Default for siginfo_t {
801    fn default() -> Self {
802        unsafe { core::mem::zeroed() }
803    }
804}
805
806#[allow(non_camel_case_types)]
807pub type linux_sigset_t = bindings::linux_sigset_t;
808
809/// Compatible with the Linux kernel's definition of sigset_t on x86_64.
810///
811/// This is analagous to, but typically smaller than, libc's sigset_t.
812#[derive(
813    Copy,
814    Clone,
815    Eq,
816    PartialEq,
817    Debug,
818    Default,
819    VirtualAddressSpaceIndependent,
820    bytemuck_derive::TransparentWrapper,
821)]
822#[repr(transparent)]
823#[allow(non_camel_case_types)]
824pub struct sigset_t(linux_sigset_t);
825unsafe impl shadow_pod::Pod for sigset_t {}
826
827impl sigset_t {
828    pub const EMPTY: Self = Self(0);
829    pub const FULL: Self = Self(!0);
830
831    pub fn has(&self, sig: Signal) -> bool {
832        (*self & sigset_t::from(sig)).0 != 0
833    }
834
835    pub fn lowest(&self) -> Option<Signal> {
836        if self.0 == 0 {
837            return None;
838        }
839        for i in i32::from(Signal::MIN)..=i32::from(Signal::MAX) {
840            let s = Signal::try_from(i).unwrap();
841            if self.has(s) {
842                return Some(s);
843            }
844        }
845        unreachable!();
846    }
847
848    pub fn is_empty(&self) -> bool {
849        *self == sigset_t::EMPTY
850    }
851
852    pub fn del(&mut self, sig: Signal) {
853        *self &= !sigset_t::from(sig);
854    }
855
856    pub fn add(&mut self, sig: Signal) {
857        *self |= sigset_t::from(sig);
858    }
859}
860
861impl From<Signal> for sigset_t {
862    #[inline]
863    fn from(value: Signal) -> Self {
864        let value = i32::from(value);
865        debug_assert!(value <= 64);
866        Self(1 << (value - 1))
867    }
868}
869
870#[test]
871fn test_from_signal() {
872    let sigset = sigset_t::from(Signal::SIGABRT);
873    assert!(sigset.has(Signal::SIGABRT));
874    assert!(!sigset.has(Signal::SIGSEGV));
875    assert_ne!(sigset, sigset_t::EMPTY);
876}
877
878impl core::ops::BitOr for sigset_t {
879    type Output = Self;
880
881    fn bitor(self, rhs: Self) -> Self::Output {
882        Self(self.0 | rhs.0)
883    }
884}
885
886#[test]
887fn test_bitor() {
888    let sigset = sigset_t::from(Signal::SIGABRT) | sigset_t::from(Signal::SIGSEGV);
889    assert!(sigset.has(Signal::SIGABRT));
890    assert!(sigset.has(Signal::SIGSEGV));
891    assert!(!sigset.has(Signal::SIGALRM));
892}
893
894impl core::ops::BitOrAssign for sigset_t {
895    fn bitor_assign(&mut self, rhs: Self) {
896        self.0 |= rhs.0
897    }
898}
899
900#[test]
901fn test_bitorassign() {
902    let mut sigset = sigset_t::from(Signal::SIGABRT);
903    sigset |= sigset_t::from(Signal::SIGSEGV);
904    assert!(sigset.has(Signal::SIGABRT));
905    assert!(sigset.has(Signal::SIGSEGV));
906    assert!(!sigset.has(Signal::SIGALRM));
907}
908
909impl core::ops::BitAnd for sigset_t {
910    type Output = Self;
911
912    fn bitand(self, rhs: Self) -> Self::Output {
913        Self(self.0 & rhs.0)
914    }
915}
916
917#[test]
918fn test_bitand() {
919    let lhs = sigset_t::from(Signal::SIGABRT) | sigset_t::from(Signal::SIGSEGV);
920    let rhs = sigset_t::from(Signal::SIGABRT) | sigset_t::from(Signal::SIGALRM);
921    let and = lhs & rhs;
922    assert!(and.has(Signal::SIGABRT));
923    assert!(!and.has(Signal::SIGSEGV));
924    assert!(!and.has(Signal::SIGALRM));
925}
926
927impl core::ops::BitAndAssign for sigset_t {
928    fn bitand_assign(&mut self, rhs: Self) {
929        self.0 &= rhs.0
930    }
931}
932
933#[test]
934fn test_bitand_assign() {
935    let mut set = sigset_t::from(Signal::SIGABRT) | sigset_t::from(Signal::SIGSEGV);
936    set &= sigset_t::from(Signal::SIGABRT) | sigset_t::from(Signal::SIGALRM);
937    assert!(set.has(Signal::SIGABRT));
938    assert!(!set.has(Signal::SIGSEGV));
939    assert!(!set.has(Signal::SIGALRM));
940}
941
942impl core::ops::Not for sigset_t {
943    type Output = Self;
944
945    fn not(self) -> Self::Output {
946        Self(!self.0)
947    }
948}
949
950#[test]
951fn test_not() {
952    let set = sigset_t::from(Signal::SIGABRT) | sigset_t::from(Signal::SIGSEGV);
953    let set = !set;
954    assert!(!set.has(Signal::SIGABRT));
955    assert!(!set.has(Signal::SIGSEGV));
956    assert!(set.has(Signal::SIGALRM));
957}
958
959pub type SignalHandlerFn = unsafe extern "C" fn(i32);
960pub type SignalActionFn = unsafe extern "C" fn(i32, *mut siginfo_t, *mut core::ffi::c_void);
961
962pub enum SignalHandler {
963    Handler(SignalHandlerFn),
964    Action(SignalActionFn),
965    SigIgn,
966    SigDfl,
967}
968
969/// Expose for cbindgen APIs
970#[allow(non_camel_case_types)]
971pub type linux_sigaction = bindings::linux_sigaction;
972
973/// Restorer suitable for use with `sigaction`.
974///
975/// Normally libc's implementation of the `sigaction` function injects a similar
976/// restorer function.
977///
978/// From `sigreturn(2)`:
979///
980/// > If the Linux kernel determines that an unblocked signal is pending for a
981/// > process, then, at the next transition back to user mode in that process
982/// > (e.g., upon return from a system call or when the process is rescheduled
983/// > onto the CPU), it creates a new frame on the user-space stack where it saves
984/// > various pieces of process context (processor status word, registers, signal
985/// > mask,  and  signal stack settings).
986/// >
987/// > The  kernel  also  arranges that, during the transition back to user mode,
988/// > the signal handler is called, and that, upon return from the handler,
989/// > control passes to a piece of user-space code com‐ monly called the "signal
990/// > trampoline".  The signal trampoline code in turn calls sigreturn().
991/// >
992/// > This sigreturn() call undoes everything that was done—changing the
993/// > process's signal mask, switching signal stacks (see sigaltstack(2))—in order
994/// > to invoke the signal handler.  Using the  informa‐ tion  that was earlier
995/// > saved on the user-space stack sigreturn() restores the process's signal
996/// > mask, switches stacks, and restores the process's context (processor flags
997/// > and registers, including the stack pointer and instruction pointer), so that
998/// > the process resumes execution at the point where it was interrupted by the
999/// > signal.
1000///
1001/// # Safety
1002///
1003/// This function is only intended for use as a `restorer` in `sigaction`.
1004/// Do not call this function directly.
1005//
1006// This has to be a `naked` function; the `rt_return` syscall assumes that the
1007// signal stack frame is at an exact offset from the current stack address; a
1008// non-naked function would manipulate the stack and break this assumption.
1009//
1010// TODO: use the language-provided `naked` attribute if and when one is provided.
1011// There's been a fair bit of discussion and issues about it, but the current state
1012// is unclear. See e.g.
1013// <https://github.com/rust-lang/rfcs/blob/master/text/1201-naked-fns.md>
1014#[cfg(target_arch = "x86_64")]
1015#[naked_function::naked]
1016pub unsafe extern "C" fn sigaction_restorer() {
1017    // 15 is rt_sigreturn; see static assertion below.
1018    // The `naked` macro doesn't support putting the assertion here in the
1019    // function body.
1020    //
1021    // The `rt_sigreturn` shouldn't return, but we use `ud2` (illegal
1022    // instruction) to ensure we don't unexpectedly return in case it does.
1023    // Strictly speaking the signature of this function could be `-> !`, but
1024    // that doesn't match the signature expected for the restorer.
1025    //
1026    // TODO: use a `const` operand to the asm template instead of inlining "15",
1027    // once `const` asm template operands are stabilized.
1028    asm!("mov rax, 15", "syscall", "ud2")
1029}
1030static_assertions::const_assert_eq!(bindings::LINUX___NR_rt_sigreturn, 15);
1031
1032/// # Invariants
1033///
1034/// `sigaction` does *not* require or guarantee that its internal function
1035/// pointers, if any, are safe to call/dereference.
1036#[derive(Copy, Clone)]
1037#[repr(C)]
1038#[allow(non_camel_case_types)]
1039pub struct sigaction(linux_sigaction);
1040unsafe impl shadow_pod::Pod for sigaction {}
1041
1042impl sigaction {
1043    // Bindgen doesn't succesfully bind these constants; maybe because
1044    // the macros defining them cast them to pointers.
1045    //
1046    // Copied from linux's include/uapi/asm-generic/signal-defs.h.
1047    const SIG_DFL: usize = 0;
1048    const SIG_IGN: usize = 1;
1049
1050    /// Consider [`sigaction::new_with_default_restorer`] instead, which takes
1051    /// care of setting up a restorer.
1052    ///
1053    /// panics if `handler` is inconsistent with the presence or absence of the
1054    /// `SA_SIGINFO` flag.
1055    pub fn new_raw(
1056        handler: SignalHandler,
1057        flags: SigActionFlags,
1058        mask: sigset_t,
1059        restorer: Option<unsafe extern "C" fn()>,
1060    ) -> Self {
1061        // The sigaction struct only has a field to hold a handler of type
1062        // `SignalHandlerFn`, but it can alternatively store a function of type
1063        // `SignalActionFn` or the integer `SIG_IGN`.
1064        //
1065        // We don't have much choice other than to `transmute` here.  We
1066        // validate the `SA_SIGINFO` flag to ensure we don't reinterpret as the
1067        // wrong type when extracting from the internal C structure again.
1068        let handler = match handler {
1069            SignalHandler::Handler(h) => {
1070                assert!(!flags.contains(SigActionFlags::SA_SIGINFO));
1071                Some(h)
1072            }
1073            SignalHandler::Action(a) => {
1074                assert!(flags.contains(SigActionFlags::SA_SIGINFO));
1075                Some(unsafe { core::mem::transmute::<SignalActionFn, SignalHandlerFn>(a) })
1076            }
1077            SignalHandler::SigIgn => {
1078                assert!(!flags.contains(SigActionFlags::SA_SIGINFO));
1079                Some(unsafe { core::mem::transmute::<usize, SignalHandlerFn>(Self::SIG_IGN) })
1080            }
1081            SignalHandler::SigDfl => {
1082                assert!(!flags.contains(SigActionFlags::SA_SIGINFO));
1083                static_assertions::const_assert_eq!(sigaction::SIG_DFL, 0);
1084                None
1085            }
1086        };
1087        sigaction(linux_sigaction {
1088            lsa_handler: handler,
1089            lsa_flags: flags.bits(),
1090            lsa_mask: mask.0,
1091            lsa_restorer: restorer,
1092        })
1093    }
1094
1095    /// Creates a `sigaction` with `SA_RESTORER` set, and the internal
1096    /// `restorer` field set to [`sigaction_restorer`]. The libc `sigaction`
1097    /// function normally makes these changes to the provided `struct
1098    /// sigaction`.
1099    pub fn new_with_default_restorer(
1100        handler: SignalHandler,
1101        flags: SigActionFlags,
1102        mask: sigset_t,
1103    ) -> Self {
1104        Self::new_raw(
1105            handler,
1106            flags | SigActionFlags::SA_RESTORER,
1107            mask,
1108            Some(sigaction_restorer),
1109        )
1110    }
1111
1112    pub fn wrap(si: linux_sigaction) -> Self {
1113        Self(si)
1114    }
1115
1116    pub fn wrap_ref(si: &linux_sigaction) -> &Self {
1117        unsafe { &*(core::ptr::from_ref(si) as *const Self) }
1118    }
1119
1120    pub fn wrap_mut(si: &mut linux_sigaction) -> &mut Self {
1121        unsafe { &mut *(core::ptr::from_mut(si) as *mut Self) }
1122    }
1123
1124    /// # Safety
1125    ///
1126    /// `lsa_handler` is safe to dereference iff the `lsa_handler` used to
1127    /// construct `Self` is.
1128    pub unsafe fn peel(si: Self) -> linux_sigaction {
1129        si.0
1130    }
1131
1132    pub fn flags(&self) -> Option<SigActionFlags> {
1133        SigActionFlags::from_bits(self.0.lsa_flags)
1134    }
1135
1136    pub fn flags_retain(&self) -> SigActionFlags {
1137        SigActionFlags::from_bits_retain(self.0.lsa_flags)
1138    }
1139
1140    pub fn mask(&self) -> sigset_t {
1141        sigset_t::wrap(self.0.lsa_mask)
1142    }
1143
1144    /// # Safety
1145    ///
1146    /// The functions in `SignalHandler::Action` or `SignalHandler::Handler` are
1147    /// safe to call iff the function pointer in the internal `lsa_handler` is,
1148    /// and is of the type specified in the internal `lsa_flags`.
1149    pub unsafe fn handler(&self) -> SignalHandler {
1150        let as_usize = self.as_usize();
1151        if as_usize == Self::SIG_IGN {
1152            SignalHandler::SigIgn
1153        } else if as_usize == Self::SIG_DFL {
1154            SignalHandler::SigDfl
1155        } else if self.flags_retain().contains(SigActionFlags::SA_SIGINFO) {
1156            // SIG_IGN is, not coincidentally, 0. If we get here, we know it's not 0/NULL.
1157            // Therefore the `Option` will be non-empty.
1158            let handler_fn: SignalHandlerFn = self.0.lsa_handler.unwrap();
1159            // The C bindings only store a single function pointer type, and cast it
1160            // when appropriate. In Rust this requires a `transmute`.
1161            //
1162            // We *don't* know whether the function is actually safe to call. The pointer
1163            // could be invalid in the current virtual address space, or invalid everywhere.
1164            // We *do* know it's not NULL.
1165            let action_fn: SignalActionFn =
1166                unsafe { core::mem::transmute::<SignalHandlerFn, SignalActionFn>(handler_fn) };
1167            SignalHandler::Action(action_fn)
1168        } else {
1169            SignalHandler::Handler(self.0.lsa_handler.unwrap())
1170        }
1171    }
1172
1173    fn as_usize(&self) -> usize {
1174        self.0.lsa_handler.map(|f| f as usize).unwrap_or(0)
1175    }
1176
1177    pub fn is_ignore(&self) -> bool {
1178        self.as_usize() == Self::SIG_IGN
1179    }
1180
1181    pub fn is_default(&self) -> bool {
1182        self.as_usize() == Self::SIG_DFL
1183    }
1184}
1185
1186impl Default for sigaction {
1187    fn default() -> Self {
1188        unsafe { core::mem::zeroed() }
1189    }
1190}
1191
1192// Corresponds to default actions documented in signal(7).
1193#[derive(Eq, PartialEq, Debug)]
1194#[repr(C)]
1195pub enum LinuxDefaultAction {
1196    TERM,
1197    IGN,
1198    CORE,
1199    STOP,
1200    CONT,
1201}
1202
1203pub fn defaultaction(sig: Signal) -> LinuxDefaultAction {
1204    use LinuxDefaultAction as Action;
1205    match sig  {
1206        Signal::SIGCONT => Action::CONT,
1207        // aka SIGIOT
1208        Signal::SIGABRT
1209        | Signal::SIGBUS
1210        | Signal::SIGFPE
1211        | Signal::SIGILL
1212        | Signal::SIGQUIT
1213        | Signal::SIGSEGV
1214        | Signal::SIGSYS
1215        | Signal::SIGTRAP
1216        | Signal::SIGXCPU
1217        | Signal::SIGXFSZ => Action::CORE,
1218        // aka SIGCLD
1219        Signal::SIGCHLD
1220        | Signal::SIGURG
1221        | Signal::SIGWINCH => Action::IGN,
1222        Signal::SIGSTOP
1223        | Signal::SIGTSTP
1224        | Signal::SIGTTIN
1225        | Signal::SIGTTOU => Action::STOP,
1226        Signal::SIGALRM
1227        //| SIGEMT
1228        | Signal::SIGHUP
1229        | Signal::SIGINT
1230        // aka SIGPOLL
1231        | Signal::SIGIO
1232        | Signal::SIGKILL
1233        //| SIGLOST
1234        | Signal::SIGPIPE
1235        | Signal::SIGPROF
1236        | Signal::SIGPWR
1237        | Signal::SIGSTKFLT
1238        | Signal::SIGTERM
1239        | Signal::SIGUSR1
1240        | Signal::SIGUSR2
1241        | Signal::SIGVTALRM => Action::TERM,
1242        //  realtime
1243        other => {
1244            assert!(other.is_realtime());
1245            // signal(7):
1246            // > The default action for an unhandled real-time signal is to
1247            // > terminate the receiving process.
1248            Action::TERM
1249        },
1250    }
1251}
1252
1253/// Execute the `kill` syscall.
1254pub fn kill_raw(pid: kernel_pid_t, sig: i32) -> Result<(), Errno> {
1255    unsafe { syscall!(linux_syscall::SYS_kill, pid, sig) }
1256        .check()
1257        .map_err(Errno::from)
1258}
1259
1260/// Execute the `kill` syscall, targeting a process.
1261pub fn kill_process(pid: Pid, sig: Option<Signal>) -> Result<(), Errno> {
1262    kill_raw(pid.as_raw_nonzero().into(), Signal::as_raw(sig))
1263}
1264
1265/// Execute the `kill` syscall, targeting a process group.
1266pub fn kill_process_group(pid: Pid, sig: Option<Signal>) -> Result<(), Errno> {
1267    kill_raw(-i32::from(pid.as_raw_nonzero()), Signal::as_raw(sig))
1268}
1269
1270/// Execute the `kill` syscall, targeting the current process group.
1271pub fn kill_current_process_group(sig: Option<Signal>) -> Result<(), Errno> {
1272    kill_raw(0, Signal::as_raw(sig))
1273}
1274
1275/// Calls the `rt_sigaction` syscall.
1276///
1277/// # Safety
1278///
1279/// * `new_action` must be safe to dereference.
1280/// * `old_action` must be safe to write to. (uninitd is ok).
1281/// * `new_action`'s handler must be safe to call as a signal handler.
1282///   See `signal-safety(7)`.
1283/// * Generally, `new_action` must have `SA_RESTORER` set and a suitable
1284///   `restorer`, such as [`sigaction_restorer`]. (There might be some esoteric
1285///   way to call this syscall without this property, but I'm not aware of one).
1286pub unsafe fn rt_sigaction_raw(
1287    signo: i32,
1288    new_action: *const sigaction,
1289    old_action: *mut sigaction,
1290    sigsetsize: usize,
1291) -> Result<(), Errno> {
1292    unsafe {
1293        syscall!(
1294            linux_syscall::SYS_rt_sigaction,
1295            signo,
1296            new_action,
1297            old_action,
1298            sigsetsize
1299        )
1300    }
1301    .check()
1302    .map_err(Errno::from)
1303}
1304
1305/// Calls the `rt_sigaction` syscall.
1306///
1307/// # Safety
1308///
1309/// * `new_action`'s handler must be safe to call as a signal handler.
1310///   See `signal-safety(7)`.
1311/// * Generally, `new_action` must have `SA_RESTORER` set and a suitable
1312///   `restorer`, such as [`sigaction_restorer`]. (There might be some esoteric
1313///   way to call this syscall without this property, but I'm not aware of one).
1314pub unsafe fn rt_sigaction(
1315    signal: Signal,
1316    new_action: &sigaction,
1317    old_action: Option<&mut sigaction>,
1318) -> Result<(), Errno> {
1319    unsafe {
1320        rt_sigaction_raw(
1321            signal.as_i32(),
1322            new_action,
1323            old_action
1324                .map(core::ptr::from_mut)
1325                .unwrap_or(core::ptr::null_mut()),
1326            core::mem::size_of::<sigset_t>(),
1327        )
1328    }
1329}
1330
1331/// For use with [`rt_sigprocmask`].
1332#[allow(non_camel_case_types)]
1333#[repr(i32)]
1334#[derive(Debug, Eq, PartialEq, TryFromPrimitive, IntoPrimitive)]
1335pub enum SigProcMaskAction {
1336    SIG_BLOCK = const_conversions::i32_from_u32(bindings::LINUX_SIG_BLOCK),
1337    SIG_UNBLOCK = const_conversions::i32_from_u32(bindings::LINUX_SIG_UNBLOCK),
1338    SIG_SETMASK = const_conversions::i32_from_u32(bindings::LINUX_SIG_SETMASK),
1339}
1340
1341/// Make the `rt_sigprocmask` syscall.
1342///
1343/// # Safety
1344///
1345/// * `sigset_in` must be safe to dereference
1346/// * `sigset_out` must be safe to write (uninit is ok)
1347pub unsafe fn rt_sigprocmask_raw(
1348    how: i32,
1349    sigset_in: *const sigset_t,
1350    sigset_out: *mut sigset_t,
1351    sigset_sz: usize,
1352) -> Result<(), Errno> {
1353    unsafe {
1354        syscall!(
1355            linux_syscall::SYS_rt_sigprocmask,
1356            how,
1357            sigset_in,
1358            sigset_out,
1359            sigset_sz,
1360        )
1361        .check()
1362        .map_err(Errno::from)
1363    }
1364}
1365
1366/// Make the `rt_sigprocmask` syscall.
1367pub fn rt_sigprocmask(
1368    how: SigProcMaskAction,
1369    sigset_in: &sigset_t,
1370    sigset_out: Option<&mut sigset_t>,
1371) -> Result<(), Errno> {
1372    unsafe {
1373        rt_sigprocmask_raw(
1374            how.into(),
1375            sigset_in,
1376            sigset_out
1377                .map(core::ptr::from_mut)
1378                .unwrap_or(core::ptr::null_mut()),
1379            core::mem::size_of::<sigset_t>(),
1380        )
1381    }
1382}
1383
1384#[cfg(test)]
1385mod rt_sigaction_tests {
1386    use core::sync::atomic::AtomicI32;
1387
1388    use shadow_pod::zeroed;
1389
1390    use super::*;
1391
1392    // This test calls `rt_sigaction` with `SIGUSR2`. `rt_sigaction` sets the
1393    // handler *process*-wide, so could interfere if other unit tests use
1394    // `SIGUSR2`. This is *probably* the only module in this crate that uses
1395    // signal handling, but we should be careful about creating other tests that
1396    // do signal handling. e.g. add those to this test to ensure they are
1397    // effectively serialized, or ensure they use different signals.
1398    #[cfg(not(miri))]
1399    #[test]
1400    fn test_rt_sigaction() {
1401        // Test signal handler
1402        static CALL_COUNTER: AtomicI32 = AtomicI32::new(0);
1403        extern "C" fn handler(_signo: i32) {
1404            CALL_COUNTER.fetch_add(1, core::sync::atomic::Ordering::Relaxed);
1405        }
1406
1407        // Test sigaction
1408        let action = sigaction::new_with_default_restorer(
1409            SignalHandler::Handler(handler),
1410            SigActionFlags::empty(),
1411            sigset_t::EMPTY,
1412        );
1413
1414        // Signal that we'll be using.
1415        let signal = Signal::SIGUSR2;
1416
1417        // Install our handler.
1418        let mut old_action = zeroed();
1419        unsafe { rt_sigaction(signal, &action, Some(&mut old_action)) }.unwrap();
1420
1421        // Ensure the signal isn't blocked.
1422        let mut old_mask: sigset_t = sigset_t::EMPTY;
1423        let mask = sigset_t::from(signal);
1424        rt_sigprocmask(SigProcMaskAction::SIG_UNBLOCK, &mask, Some(&mut old_mask)).unwrap();
1425
1426        // Send the signal to this thread. This should guarantee that the signal
1427        // is handled before returning from the `tgkill` syscall.
1428        let pid = rustix::process::getpid();
1429        let tid = rustix::thread::gettid();
1430        unsafe {
1431            linux_syscall::syscall!(
1432                linux_syscall::SYS_tgkill,
1433                pid.as_raw_nonzero().get(),
1434                tid.as_raw_nonzero().get(),
1435                signal.as_i32()
1436            )
1437        }
1438        .check()
1439        .unwrap();
1440
1441        // Validate that our signal handler was called.
1442        assert_eq!(CALL_COUNTER.load(core::sync::atomic::Ordering::Relaxed), 1);
1443
1444        // Restore previous signal action and mask.
1445        rt_sigprocmask(SigProcMaskAction::SIG_SETMASK, &old_mask, None).unwrap();
1446        unsafe { rt_sigaction(signal, &old_action, None) }.unwrap();
1447    }
1448}
1449
1450pub use bindings::linux_stack_t;
1451#[allow(non_camel_case_types)]
1452pub type stack_t = linux_stack_t;
1453
1454impl stack_t {
1455    pub fn new(sp: *mut core::ffi::c_void, flags: SigAltStackFlags, size: usize) -> Self {
1456        Self {
1457            ss_sp: sp,
1458            ss_flags: flags.bits(),
1459            ss_size: size.try_into().unwrap(),
1460        }
1461    }
1462
1463    pub fn flags_retain(&self) -> SigAltStackFlags {
1464        SigAltStackFlags::from_bits_retain(self.ss_flags)
1465    }
1466
1467    pub fn sp(&self) -> *mut core::ffi::c_void {
1468        self.ss_sp
1469    }
1470
1471    pub fn size(&self) -> usize {
1472        self.ss_size.try_into().unwrap()
1473    }
1474}
1475
1476// bindgen fails to bind this one.
1477// Copied from linux's include/uapi/linux/signal.h.
1478pub const LINUX_SS_AUTODISARM: u32 = 1 << 31;
1479bitflags::bitflags! {
1480    // While the Linux header defines the only current value of this flag as
1481    // u32, the field in `stack_t::ss_flags` where this type is used is i32.
1482    #[repr(transparent)]
1483    #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)]
1484    pub struct SigAltStackFlags: i32 {
1485        // The raw u32 value wraps around to a negative i32.
1486        const SS_AUTODISARM = i32_from_u32_allowing_wraparound(LINUX_SS_AUTODISARM);
1487        const SS_ONSTACK = const_conversions::i32_from_u32(bindings::LINUX_SS_ONSTACK);
1488        const SS_DISABLE= const_conversions::i32_from_u32(bindings::LINUX_SS_DISABLE);
1489    }
1490}
1491// SAFETY: bitflags guarantees the internal representation is effectively a i32.
1492unsafe impl VirtualAddressSpaceIndependent for SigAltStackFlags {}
1493
1494/// # Safety
1495///
1496/// * `new_stack` must be dereferenceable or NULL.
1497/// * `old_stack` must be dereferenceable or NULL.
1498/// * See sigaltstack(2).
1499pub unsafe fn sigaltstack_raw(
1500    new_stack: *const stack_t,
1501    old_stack: *mut stack_t,
1502) -> Result<(), Errno> {
1503    unsafe { syscall!(linux_syscall::SYS_sigaltstack, new_stack, old_stack) }
1504        .check()
1505        .map_err(Errno::from)
1506}
1507
1508/// # Safety
1509///
1510/// See sigaltstack(2)
1511pub unsafe fn sigaltstack(
1512    new_stack: Option<&stack_t>,
1513    old_stack: Option<&mut stack_t>,
1514) -> Result<(), Errno> {
1515    unsafe {
1516        sigaltstack_raw(
1517            new_stack
1518                .map(core::ptr::from_ref)
1519                .unwrap_or(core::ptr::null()),
1520            old_stack
1521                .map(core::ptr::from_mut)
1522                .unwrap_or(core::ptr::null_mut()),
1523        )
1524    }
1525}
1526
1527pub fn tgkill_raw(tgid: kernel_pid_t, tid: kernel_pid_t, signo: i32) -> Result<(), Errno> {
1528    unsafe { syscall!(linux_syscall::SYS_tgkill, tgid, tid, signo) }
1529        .check()
1530        .map_err(Errno::from)
1531}
1532
1533pub fn tgkill(tgid: Pid, tid: Pid, signal: Option<Signal>) -> Result<(), Errno> {
1534    tgkill_raw(
1535        Pid::as_raw(Some(tgid)),
1536        Pid::as_raw(Some(tid)),
1537        signal.map(i32::from).unwrap_or(0),
1538    )
1539}
1540
1541mod export {
1542    use crate::bindings::{linux_siginfo_t, linux_sigset_t};
1543
1544    use super::*;
1545
1546    #[unsafe(no_mangle)]
1547    pub extern "C-unwind" fn linux_signal_is_valid(signo: i32) -> bool {
1548        Signal::try_from(signo).is_ok()
1549    }
1550
1551    #[unsafe(no_mangle)]
1552    pub extern "C-unwind" fn linux_signal_is_realtime(signo: i32) -> bool {
1553        let Ok(signal) = Signal::try_from(signo) else {
1554            return false;
1555        };
1556        signal.is_realtime()
1557    }
1558
1559    #[unsafe(no_mangle)]
1560    pub extern "C-unwind" fn linux_sigemptyset() -> linux_sigset_t {
1561        sigset_t::EMPTY.0
1562    }
1563
1564    #[unsafe(no_mangle)]
1565    pub extern "C-unwind" fn linux_sigfullset() -> linux_sigset_t {
1566        sigset_t::FULL.0
1567    }
1568
1569    #[unsafe(no_mangle)]
1570    pub unsafe extern "C-unwind" fn linux_sigaddset(set: *mut linux_sigset_t, signo: i32) {
1571        let set = sigset_t::wrap_mut(unsafe { set.as_mut().unwrap() });
1572        let signo = Signal::try_from(signo).unwrap();
1573        set.add(signo);
1574    }
1575
1576    #[unsafe(no_mangle)]
1577    pub unsafe extern "C-unwind" fn linux_sigdelset(set: *mut linux_sigset_t, signo: i32) {
1578        let set = sigset_t::wrap_mut(unsafe { set.as_mut().unwrap() });
1579        let signo = Signal::try_from(signo).unwrap();
1580        set.del(signo);
1581    }
1582
1583    #[unsafe(no_mangle)]
1584    pub unsafe extern "C-unwind" fn linux_sigismember(
1585        set: *const linux_sigset_t,
1586        signo: i32,
1587    ) -> bool {
1588        let set = sigset_t::wrap_ref(unsafe { set.as_ref().unwrap() });
1589        set.has(signo.try_into().unwrap())
1590    }
1591
1592    #[unsafe(no_mangle)]
1593    pub unsafe extern "C-unwind" fn linux_sigisemptyset(set: *const linux_sigset_t) -> bool {
1594        let set = sigset_t::wrap_ref(unsafe { set.as_ref().unwrap() });
1595        set.is_empty()
1596    }
1597
1598    #[unsafe(no_mangle)]
1599    pub unsafe extern "C-unwind" fn linux_sigorset(
1600        lhs: *const linux_sigset_t,
1601        rhs: *const linux_sigset_t,
1602    ) -> linux_sigset_t {
1603        let lhs = unsafe { lhs.as_ref().unwrap() };
1604        let rhs = unsafe { rhs.as_ref().unwrap() };
1605        sigset_t(*lhs | *rhs).0
1606    }
1607
1608    #[unsafe(no_mangle)]
1609    pub unsafe extern "C-unwind" fn linux_sigandset(
1610        lhs: *const linux_sigset_t,
1611        rhs: *const linux_sigset_t,
1612    ) -> linux_sigset_t {
1613        let lhs = unsafe { lhs.as_ref().unwrap() };
1614        let rhs = unsafe { rhs.as_ref().unwrap() };
1615        sigset_t(*lhs & *rhs).0
1616    }
1617
1618    #[unsafe(no_mangle)]
1619    pub unsafe extern "C-unwind" fn linux_signotset(set: *const linux_sigset_t) -> linux_sigset_t {
1620        let set = unsafe { set.as_ref().unwrap() };
1621        sigset_t(!*set).0
1622    }
1623
1624    #[unsafe(no_mangle)]
1625    pub unsafe extern "C-unwind" fn linux_siglowest(set: *const linux_sigset_t) -> i32 {
1626        let set = sigset_t::wrap_ref(unsafe { set.as_ref().unwrap() });
1627        match set.lowest() {
1628            Some(s) => s.into(),
1629            None => 0,
1630        }
1631    }
1632
1633    #[unsafe(no_mangle)]
1634    pub extern "C-unwind" fn linux_defaultAction(signo: i32) -> LinuxDefaultAction {
1635        let sig = Signal::try_from(signo).unwrap();
1636        defaultaction(sig)
1637    }
1638
1639    #[unsafe(no_mangle)]
1640    pub unsafe extern "C-unwind" fn linux_kill(pid: i32, sig: i32) -> i32 {
1641        match kill_raw(pid, sig) {
1642            Ok(()) => 0,
1643            Err(e) => e.to_negated_i32(),
1644        }
1645    }
1646
1647    /// Returns the handler if there is one, or else NULL.
1648    #[unsafe(no_mangle)]
1649    pub unsafe extern "C-unwind" fn linux_sigaction_handler(
1650        sa: *const linux_sigaction,
1651    ) -> Option<unsafe extern "C" fn(i32)> {
1652        let sa = sigaction::wrap_ref(unsafe { sa.as_ref().unwrap() });
1653        match unsafe { sa.handler() } {
1654            SignalHandler::Handler(h) => Some(h),
1655            _ => None,
1656        }
1657    }
1658
1659    /// Returns the action if there is one, else NULL.
1660    #[unsafe(no_mangle)]
1661    pub unsafe extern "C-unwind" fn linux_sigaction_action(
1662        sa: *const linux_sigaction,
1663    ) -> Option<unsafe extern "C" fn(i32, *mut linux_siginfo_t, *mut core::ffi::c_void)> {
1664        let sa = sigaction::wrap_ref(unsafe { sa.as_ref().unwrap() });
1665        match unsafe { sa.handler() } {
1666            SignalHandler::Action(h) =>
1667            // We transmute the function pointer from one that takes SigAction
1668            // to one that takes linux_sigaction_t. These two types are safely
1669            // transmutable.
1670            {
1671                Some(unsafe {
1672                    core::mem::transmute::<
1673                        unsafe extern "C" fn(i32, *mut siginfo_t, *mut core::ffi::c_void),
1674                        unsafe extern "C" fn(i32, *mut linux_siginfo_t, *mut core::ffi::c_void),
1675                    >(h)
1676                })
1677            }
1678            _ => None,
1679        }
1680    }
1681
1682    #[unsafe(no_mangle)]
1683    pub unsafe extern "C-unwind" fn linux_sigaction_is_ign(sa: *const linux_sigaction) -> bool {
1684        let sa = sigaction::wrap_ref(unsafe { sa.as_ref().unwrap() });
1685        matches!(unsafe { sa.handler() }, SignalHandler::SigIgn)
1686    }
1687
1688    #[unsafe(no_mangle)]
1689    pub unsafe extern "C-unwind" fn linux_sigaction_is_dfl(sa: *const linux_sigaction) -> bool {
1690        let sa = sigaction::wrap_ref(unsafe { sa.as_ref().unwrap() });
1691        matches!(unsafe { sa.handler() }, SignalHandler::SigDfl)
1692    }
1693}