1use core::sync::atomic::{AtomicU64, Ordering};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12#[repr(u32)]
13pub enum Signal {
14 SIGHUP = 1,
16 SIGINT = 2,
18 SIGQUIT = 3,
20 SIGILL = 4,
22 SIGTRAP = 5,
24 SIGABRT = 6,
26 SIGBUS = 7,
28 SIGFPE = 8,
30 SIGKILL = 9,
32 SIGUSR1 = 10,
34 SIGSEGV = 11,
36 SIGUSR2 = 12,
38 SIGPIPE = 13,
40 SIGALRM = 14,
42 SIGTERM = 15,
44 SIGCHLD = 17,
46 SIGCONT = 18,
48 SIGSTOP = 19,
50 SIGTSTP = 20,
52 SIGTTIN = 21,
54 SIGTTOU = 22,
56 SIGURG = 23,
58 SIGXCPU = 24,
60 SIGXFSZ = 25,
62 SIGVTALRM = 26,
64 SIGPROF = 27,
66 SIGWINCH = 28,
68 SIGIO = 29,
70 SIGPWR = 30,
72 SIGSYS = 31,
74}
75
76impl Signal {
77 pub fn from_u32(num: u32) -> Option<Self> {
79 match num {
80 1 => Some(Signal::SIGHUP),
81 2 => Some(Signal::SIGINT),
82 3 => Some(Signal::SIGQUIT),
83 4 => Some(Signal::SIGILL),
84 5 => Some(Signal::SIGTRAP),
85 6 => Some(Signal::SIGABRT),
86 7 => Some(Signal::SIGBUS),
87 8 => Some(Signal::SIGFPE),
88 9 => Some(Signal::SIGKILL),
89 10 => Some(Signal::SIGUSR1),
90 11 => Some(Signal::SIGSEGV),
91 12 => Some(Signal::SIGUSR2),
92 13 => Some(Signal::SIGPIPE),
93 14 => Some(Signal::SIGALRM),
94 15 => Some(Signal::SIGTERM),
95 17 => Some(Signal::SIGCHLD),
96 18 => Some(Signal::SIGCONT),
97 19 => Some(Signal::SIGSTOP),
98 20 => Some(Signal::SIGTSTP),
99 21 => Some(Signal::SIGTTIN),
100 22 => Some(Signal::SIGTTOU),
101 23 => Some(Signal::SIGURG),
102 24 => Some(Signal::SIGXCPU),
103 25 => Some(Signal::SIGXFSZ),
104 26 => Some(Signal::SIGVTALRM),
105 27 => Some(Signal::SIGPROF),
106 28 => Some(Signal::SIGWINCH),
107 29 => Some(Signal::SIGIO),
108 30 => Some(Signal::SIGPWR),
109 31 => Some(Signal::SIGSYS),
110 _ => None,
111 }
112 }
113
114 pub fn as_u32(self) -> u32 {
116 self as u32
117 }
118
119 pub fn is_uncatchable(self) -> bool {
121 matches!(self, Signal::SIGKILL | Signal::SIGSTOP)
122 }
123
124 pub fn bit(self) -> u64 {
126 1u64 << (self.as_u32() - 1)
127 }
128}
129
130pub const SIGNAL_MASK_SIZE: usize = 8; pub const SIGNAL_MAX: u32 = 64;
133
134pub const SIG_BLOCK: i32 = 0;
136pub const SIG_UNBLOCK: i32 = 1;
137pub const SIG_SETMASK: i32 = 2;
138
139#[derive(Debug)]
143pub struct SignalSet {
144 mask: AtomicU64,
145}
146
147impl Clone for SignalSet {
148 fn clone(&self) -> Self {
150 Self::from_mask(self.get_mask())
151 }
152}
153
154impl SignalSet {
155 pub const fn new() -> Self {
157 Self {
158 mask: AtomicU64::new(0),
159 }
160 }
161
162 pub const fn from_mask(mask: u64) -> Self {
164 Self {
165 mask: AtomicU64::new(mask),
166 }
167 }
168
169 pub fn add(&self, signal: Signal) {
171 let bit = signal.bit();
172 self.mask.fetch_or(bit, Ordering::Release);
173 }
174
175 pub fn remove(&self, signal: Signal) {
177 let bit = !signal.bit();
178 self.mask.fetch_and(bit, Ordering::AcqRel);
179 }
180
181 pub fn contains(&self, signal: Signal) -> bool {
183 let bit = signal.bit();
184 (self.mask.load(Ordering::Acquire) & bit) != 0
185 }
186
187 pub fn is_empty(&self) -> bool {
189 self.mask.load(Ordering::Acquire) == 0
190 }
191
192 pub fn get_mask(&self) -> u64 {
194 self.mask.load(Ordering::Acquire)
195 }
196
197 pub fn set_mask(&self, mask: u64) {
199 self.mask.store(mask, Ordering::Release);
200 }
201
202 pub fn clear(&self) {
204 self.mask.store(0, Ordering::Release);
205 }
206
207 pub fn next_pending(&self) -> Option<Signal> {
209 let pending = self.mask.load(Ordering::Acquire);
210 if pending == 0 {
211 return None;
212 }
213 let signal_num = pending.trailing_zeros() + 1;
214 Signal::from_u32(signal_num)
215 }
216
217 pub fn unblocked(&self, blocked: &SignalSet) -> u64 {
219 let pending = self.mask.load(Ordering::Acquire);
220 let blocked_mask = blocked.mask.load(Ordering::Acquire);
221 pending & !blocked_mask
222 }
223
224 pub fn consume_one_unblocked(&self, blocked: &SignalSet) -> Option<Signal> {
226 loop {
227 let pending = self.mask.load(Ordering::Acquire);
228 let blocked_mask = blocked.mask.load(Ordering::Acquire);
229 let unblocked = pending & !blocked_mask;
230 if unblocked == 0 {
231 return None;
232 }
233 let lowest_bit = unblocked & unblocked.wrapping_neg();
234 let new_pending = pending & !lowest_bit;
235 match self.mask.compare_exchange_weak(
236 pending,
237 new_pending,
238 Ordering::AcqRel,
239 Ordering::Acquire,
240 ) {
241 Ok(_) => {
242 let signal_num = lowest_bit.trailing_zeros() + 1;
243 return Signal::from_u32(signal_num);
244 }
245 Err(_) => continue,
246 }
247 }
248 }
249}
250
251pub const SA_NOCLDSTOP: u32 = 1 << 0;
253pub const SA_NOCLDWAIT: u32 = 1 << 1;
254pub const SA_SIGINFO: u32 = 1 << 2;
255pub const SA_RESTORER: u32 = 1 << 3;
256pub const SA_ONSTACK: u32 = 1 << 4;
257pub const SA_RESTART: u32 = 1 << 5;
258pub const SA_NODEFER: u32 = 1 << 6;
259pub const SA_RESETHAND: u32 = 1 << 7;
260
261pub const SIG_DFL: u64 = 0;
262pub const SIG_IGN: u64 = 1;
263
264#[derive(Debug, Clone, Copy)]
265#[repr(C)]
266pub struct SigActionData {
267 pub handler: u64,
268 pub flags: u64,
269 pub restorer: u64,
270 pub mask: u64,
271}
272
273impl SigActionData {
274 pub const fn default() -> Self {
276 Self {
277 handler: SIG_DFL,
278 flags: 0,
279 restorer: 0,
280 mask: 0,
281 }
282 }
283
284 pub fn is_default(&self) -> bool {
286 self.handler == SIG_DFL
287 }
288 pub fn is_ignore(&self) -> bool {
290 self.handler == SIG_IGN
291 }
292 pub fn is_user_handler(&self) -> bool {
294 self.handler > 1
295 }
296}
297
298impl Default for SigActionData {
299 fn default() -> Self {
301 Self::default()
302 }
303}
304
305#[derive(Debug, Clone, Copy, PartialEq, Eq)]
306pub enum DefaultAction {
307 Term,
308 Core,
309 Stop,
310 Cont,
311 Ign,
312}
313
314impl Signal {
315 pub fn default_action(self) -> DefaultAction {
317 match self {
318 Signal::SIGHUP
319 | Signal::SIGINT
320 | Signal::SIGPIPE
321 | Signal::SIGALRM
322 | Signal::SIGTERM
323 | Signal::SIGUSR1
324 | Signal::SIGUSR2
325 | Signal::SIGPROF
326 | Signal::SIGVTALRM
327 | Signal::SIGIO
328 | Signal::SIGPWR
329 | Signal::SIGSYS => DefaultAction::Term,
330
331 Signal::SIGQUIT
332 | Signal::SIGILL
333 | Signal::SIGABRT
334 | Signal::SIGFPE
335 | Signal::SIGSEGV
336 | Signal::SIGBUS
337 | Signal::SIGTRAP
338 | Signal::SIGXCPU
339 | Signal::SIGXFSZ => DefaultAction::Core,
340
341 Signal::SIGSTOP | Signal::SIGTSTP | Signal::SIGTTIN | Signal::SIGTTOU => {
342 DefaultAction::Stop
343 }
344
345 Signal::SIGCONT => DefaultAction::Cont,
346
347 Signal::SIGCHLD | Signal::SIGURG | Signal::SIGWINCH => DefaultAction::Ign,
348
349 Signal::SIGKILL => DefaultAction::Term,
350 }
351 }
352}
353
354pub const SIGNAL_FRAME_MAGIC: u64 = 0x5354_5239_5349_4700;
355
356#[derive(Debug, Clone, Copy)]
357#[repr(C)]
358pub struct SignalFrame {
359 pub restorer: u64,
360 pub signo: u64,
361 pub saved_mask: u64,
362 pub rip: u64,
363 pub rsp: u64,
364 pub rflags: u64,
365 pub rax: u64,
366 pub rcx: u64,
367 pub rdx: u64,
368 pub rbx: u64,
369 pub rbp: u64,
370 pub rsi: u64,
371 pub rdi: u64,
372 pub r8: u64,
373 pub r9: u64,
374 pub r10: u64,
375 pub r11: u64,
376 pub r12: u64,
377 pub r13: u64,
378 pub r14: u64,
379 pub r15: u64,
380 pub magic: u64,
381}
382
383pub fn deliver_pending_signal(frame: &mut crate::syscall::SyscallFrame) -> bool {
385 let task = match crate::process::current_task_clone() {
386 Some(t) => t,
387 None => return false,
388 };
389
390 if task.is_kernel() {
391 return false;
392 }
393
394 let signal = match task
395 .pending_signals
396 .consume_one_unblocked(&task.blocked_signals)
397 {
398 Some(s) => s,
399 None => return false,
400 };
401
402 let action = unsafe {
403 let actions = &*task.process.signal_actions.get();
404 actions[signal.as_u32() as usize]
405 };
406
407 if action.is_ignore() {
408 return true;
409 }
410
411 if action.is_default() {
412 match signal.default_action() {
413 DefaultAction::Ign => return true,
414 DefaultAction::Cont => return true,
415 DefaultAction::Stop => {
416 return true;
417 }
418 DefaultAction::Term | DefaultAction::Core => {
419 log::info!(
420 "[signal] killing pid {} on SIG{}",
421 task.pid,
422 signal.as_u32()
423 );
424 crate::process::kill_task(task.id);
425 return true;
426 }
427 }
428 }
429
430 let handler = action.handler;
431 let restorer = action.restorer;
432 let sig_mask = action.mask;
433 let flags = action.flags;
434
435 if restorer == 0 {
436 log::warn!("[signal] no restorer for SIG{}, killing", signal.as_u32());
437 crate::process::kill_task(task.id);
438 return true;
439 }
440
441 let user_rsp = frame.iret_rsp;
442 let frame_size = core::mem::size_of::<SignalFrame>() as u64;
443 let new_rsp = ((user_rsp - frame_size) & !0xF) - 8;
444
445 let sig_frame = SignalFrame {
446 restorer,
447 signo: signal.as_u32() as u64,
448 saved_mask: task.blocked_signals.get_mask(),
449 rip: frame.iret_rip,
450 rsp: frame.iret_rsp,
451 rflags: frame.iret_rflags,
452 rax: frame.rax,
453 rcx: frame.rcx,
454 rdx: frame.rdx,
455 rbx: frame.rbx,
456 rbp: frame.rbp,
457 rsi: frame.rsi,
458 rdi: frame.rdi,
459 r8: frame.r8,
460 r9: frame.r9,
461 r10: frame.r10,
462 r11: frame.r11,
463 r12: frame.r12,
464 r13: frame.r13,
465 r14: frame.r14,
466 r15: frame.r15,
467 magic: SIGNAL_FRAME_MAGIC,
468 };
469
470 let bytes: &[u8] = unsafe {
471 core::slice::from_raw_parts(
472 &sig_frame as *const SignalFrame as *const u8,
473 core::mem::size_of::<SignalFrame>(),
474 )
475 };
476
477 match crate::memory::UserSliceWrite::new(new_rsp, bytes.len()) {
478 Ok(slice) => {
479 slice.copy_from(bytes);
480 }
481 Err(_) => {
482 log::warn!("[signal] fault writing signal frame, killing");
483 crate::process::kill_task(task.id);
484 return true;
485 }
486 }
487
488 let mut new_mask = task.blocked_signals.get_mask() | sig_mask;
490 if flags & (SA_NODEFER as u64) == 0 {
491 new_mask |= signal.bit();
492 }
493 task.blocked_signals.set_mask(new_mask);
494
495 if flags & (SA_RESETHAND as u64) != 0 {
497 unsafe {
498 let actions = &mut *task.process.signal_actions.get();
499 actions[signal.as_u32() as usize] = SigActionData::default();
500 }
501 }
502
503 frame.iret_rip = handler;
504 frame.iret_rsp = new_rsp;
505 frame.rdi = signal.as_u32() as u64;
506 frame.rsi = 0;
507 frame.rdx = 0;
508
509 true
510}
511
512#[derive(Debug, Clone, Copy, Default)]
514#[repr(C)]
515pub struct SigStack {
516 pub ss_sp: u64,
518 pub ss_flags: i32,
520 pub ss_size: usize,
522}
523
524pub fn send_signal(
536 target: crate::process::TaskId,
537 signal: Signal,
538) -> Result<(), crate::syscall::error::SyscallError> {
539 use crate::{process::get_task_by_id, syscall::error::SyscallError};
540
541 if signal.is_uncatchable() {
543 }
545
546 let task = get_task_by_id(target).ok_or(SyscallError::InvalidArgument)?;
547
548 let pending = &task.pending_signals;
551 pending.add(signal);
552
553 unsafe {
559 let state = &*task.state.get();
560 if *state == crate::process::TaskState::Blocked {
561 let blocked = &task.blocked_signals;
562 if !blocked.contains(signal) {
563 crate::process::wake_task(target);
565 }
566 }
567 }
568
569 Ok(())
570}
571
572pub fn has_pending_signals() -> bool {
576 use crate::process::current_task_clone;
577
578 if let Some(task) = current_task_clone() {
579 let pending = &task.pending_signals;
580 let blocked = &task.blocked_signals;
581 pending.unblocked(blocked) != 0
582 } else {
583 false
584 }
585}
586
587pub fn consume_next_signal() -> Option<Signal> {
591 use crate::process::current_task_clone;
592
593 if let Some(task) = current_task_clone() {
594 task.pending_signals
595 .consume_one_unblocked(&task.blocked_signals)
596 } else {
597 None
598 }
599}