1use crate::errors::{Errno, errno, error};
6use crate::sigset_t;
7use linux_uapi as uapi;
8use static_assertions::assert_eq_size;
9use std::fmt;
10use std::ops::{BitAnd, BitOr, Not};
11use zerocopy::{FromBytes, Immutable, IntoBytes, KnownLayout};
12
13pub const UNBLOCKABLE_SIGNALS: SigSet = SigSet(SIGKILL.mask() | SIGSTOP.mask());
14
15#[derive(Debug, Copy, Clone, Eq, PartialEq)]
18pub struct UncheckedSignal(u64);
19
20impl UncheckedSignal {
21 pub fn new(value: u64) -> UncheckedSignal {
22 UncheckedSignal(value)
23 }
24
25 pub fn is_zero(self) -> bool {
26 self.0 == 0
27 }
28}
29impl From<Signal> for UncheckedSignal {
30 fn from(signal: Signal) -> UncheckedSignal {
31 UncheckedSignal(signal.number as u64)
32 }
33}
34impl From<u32> for UncheckedSignal {
35 fn from(value: u32) -> UncheckedSignal {
36 UncheckedSignal(value as u64)
37 }
38}
39
40#[derive(Copy, Clone, PartialEq, Eq, Hash)]
42pub struct Signal {
43 number: u32,
44}
45
46impl Signal {
47 pub fn number(&self) -> u32 {
49 self.number
50 }
51
52 pub const fn mask(&self) -> u64 {
54 1 << (self.number - 1)
55 }
56
57 pub fn is_real_time(&self) -> bool {
59 self.number >= super::SIGRTMIN
60 }
61
62 pub fn is_unblockable(&self) -> bool {
64 UNBLOCKABLE_SIGNALS.has_signal(*self)
65 }
66
67 pub fn set_ptrace_syscall_bit(&mut self) {
69 self.number |= 0x80
70 }
71
72 pub const NUM_SIGNALS: u32 = 64;
74}
75
76pub const SIGHUP: Signal = Signal { number: uapi::SIGHUP };
77pub const SIGINT: Signal = Signal { number: uapi::SIGINT };
78pub const SIGQUIT: Signal = Signal { number: uapi::SIGQUIT };
79pub const SIGILL: Signal = Signal { number: uapi::SIGILL };
80pub const SIGTRAP: Signal = Signal { number: uapi::SIGTRAP };
81pub const SIGABRT: Signal = Signal { number: uapi::SIGABRT };
82#[allow(dead_code)]
83pub const SIGIOT: Signal = Signal { number: uapi::SIGIOT };
84pub const SIGBUS: Signal = Signal { number: uapi::SIGBUS };
85pub const SIGFPE: Signal = Signal { number: uapi::SIGFPE };
86pub const SIGKILL: Signal = Signal { number: uapi::SIGKILL };
87pub const SIGUSR1: Signal = Signal { number: uapi::SIGUSR1 };
88pub const SIGSEGV: Signal = Signal { number: uapi::SIGSEGV };
89pub const SIGUSR2: Signal = Signal { number: uapi::SIGUSR2 };
90pub const SIGPIPE: Signal = Signal { number: uapi::SIGPIPE };
91pub const SIGALRM: Signal = Signal { number: uapi::SIGALRM };
92pub const SIGTERM: Signal = Signal { number: uapi::SIGTERM };
93pub const SIGSTKFLT: Signal = Signal { number: uapi::SIGSTKFLT };
94pub const SIGCHLD: Signal = Signal { number: uapi::SIGCHLD };
95pub const SIGCONT: Signal = Signal { number: uapi::SIGCONT };
96pub const SIGSTOP: Signal = Signal { number: uapi::SIGSTOP };
97pub const SIGTSTP: Signal = Signal { number: uapi::SIGTSTP };
98pub const SIGTTIN: Signal = Signal { number: uapi::SIGTTIN };
99pub const SIGTTOU: Signal = Signal { number: uapi::SIGTTOU };
100pub const SIGURG: Signal = Signal { number: uapi::SIGURG };
101pub const SIGXCPU: Signal = Signal { number: uapi::SIGXCPU };
102pub const SIGXFSZ: Signal = Signal { number: uapi::SIGXFSZ };
103pub const SIGVTALRM: Signal = Signal { number: uapi::SIGVTALRM };
104pub const SIGPROF: Signal = Signal { number: uapi::SIGPROF };
105pub const SIGWINCH: Signal = Signal { number: uapi::SIGWINCH };
106pub const SIGIO: Signal = Signal { number: uapi::SIGIO };
107pub const SIGPWR: Signal = Signal { number: uapi::SIGPWR };
108pub const SIGSYS: Signal = Signal { number: uapi::SIGSYS };
109#[allow(dead_code)]
110pub const SIGRTMIN: Signal = Signal { number: super::SIGRTMIN };
111
112impl TryFrom<UncheckedSignal> for Signal {
113 type Error = Errno;
114
115 fn try_from(value: UncheckedSignal) -> Result<Self, Self::Error> {
116 let value = u32::try_from(value.0).map_err(|_| errno!(EINVAL))?;
117 if (1..=Signal::NUM_SIGNALS).contains(&value) {
118 Ok(Signal { number: value })
119 } else {
120 error!(EINVAL)
121 }
122 }
123}
124
125impl fmt::Debug for Signal {
126 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127 write!(f, "{self}")
128 }
129}
130
131impl fmt::Display for Signal {
132 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133 if !self.is_real_time() {
134 let name = match self.number {
135 uapi::SIGHUP => "SIGHUP",
136 uapi::SIGINT => "SIGINT",
137 uapi::SIGQUIT => "SIGQUIT",
138 uapi::SIGILL => "SIGILL",
139 uapi::SIGTRAP => "SIGTRAP",
140 uapi::SIGABRT => "SIGABRT",
141 uapi::SIGBUS => "SIGBUS",
142 uapi::SIGFPE => "SIGFPE",
143 uapi::SIGKILL => "SIGKILL",
144 uapi::SIGUSR1 => "SIGUSR1",
145 uapi::SIGSEGV => "SIGSEGV",
146 uapi::SIGUSR2 => "SIGUSR2",
147 uapi::SIGPIPE => "SIGPIPE",
148 uapi::SIGALRM => "SIGALRM",
149 uapi::SIGTERM => "SIGTERM",
150 uapi::SIGSTKFLT => "SIGSTKFLT",
151 uapi::SIGCHLD => "SIGCHLD",
152 uapi::SIGCONT => "SIGCONT",
153 uapi::SIGSTOP => "SIGSTOP",
154 uapi::SIGTSTP => "SIGTSTP",
155 uapi::SIGTTIN => "SIGTTIN",
156 uapi::SIGTTOU => "SIGTTOU",
157 uapi::SIGURG => "SIGURG",
158 uapi::SIGXCPU => "SIGXCPU",
159 uapi::SIGXFSZ => "SIGXFSZ",
160 uapi::SIGVTALRM => "SIGVTALRM",
161 uapi::SIGPROF => "SIGPROF",
162 uapi::SIGWINCH => "SIGWINCH",
163 uapi::SIGIO => "SIGIO",
164 uapi::SIGPWR => "SIGPWR",
165 uapi::SIGSYS => "SIGSYS",
166 _ => "unknown signal",
167 };
168 write!(f, "{}({})", name, self.number)
169 } else {
170 write!(f, "SIGRTMIN+{}({})", self.number - super::SIGRTMIN, self.number)
171 }
172 }
173}
174
175#[repr(transparent)]
189#[derive(
190 Debug, Copy, Clone, Default, IntoBytes, Eq, KnownLayout, FromBytes, Immutable, PartialEq,
191)]
192pub struct SigSet(pub std::os::raw::c_ulong);
193assert_eq_size!(SigSet, sigset_t);
194
195impl SigSet {
196 pub fn has_signal(&self, signal: Signal) -> bool {
198 (self.0 & (signal.mask() as std::os::raw::c_ulong)) != 0
199 }
200
201 pub fn intersects(&self, other: &Self) -> bool {
203 (self.0 & other.0) != 0
204 }
205}
206
207impl From<sigset_t> for SigSet {
208 fn from(value: sigset_t) -> Self {
209 #[allow(
212 clippy::undocumented_unsafe_blocks,
213 reason = "Force documented unsafe blocks in Starnix"
214 )]
215 SigSet(unsafe { std::mem::transmute(value) })
216 }
217}
218
219impl From<SigSet> for sigset_t {
220 fn from(val: SigSet) -> Self {
221 #[allow(
224 clippy::undocumented_unsafe_blocks,
225 reason = "Force documented unsafe blocks in Starnix"
226 )]
227 unsafe {
228 std::mem::transmute(val.0)
229 }
230 }
231}
232
233impl BitAnd for SigSet {
234 type Output = Self;
235
236 fn bitand(self, rhs: Self) -> Self::Output {
238 Self(self.0 & rhs.0)
239 }
240}
241
242impl BitOr for SigSet {
243 type Output = Self;
244
245 fn bitor(self, rhs: Self) -> Self::Output {
247 Self(self.0 | rhs.0)
248 }
249}
250
251impl Not for SigSet {
252 type Output = Self;
253
254 fn not(self) -> Self::Output {
255 SigSet(!self.0)
256 }
257}
258
259impl From<Signal> for SigSet {
260 fn from(value: Signal) -> Self {
262 SigSet(value.mask() as std::os::raw::c_ulong)
263 }
264}
265
266pub fn sigaltstack_contains_pointer(stack: &uapi::sigaltstack, ptr: u64) -> bool {
267 let min = stack.ss_sp.addr as u64;
268 let max = (stack.ss_sp.addr as u64).saturating_add(stack.ss_size as u64);
269 ptr >= min && ptr <= max
270}