xref: /DragonOS/kernel/src/ipc/signal_types.rs (revision 24ff1faffb3d610cd55e3c658fd50ea0a0efedfb)
1 use core::{ffi::c_void, mem::size_of, sync::atomic::AtomicI64};
2 
3 use alloc::vec::Vec;
4 
5 use crate::{
6     arch::{
7         asm::bitops::ffz,
8         interrupt::TrapFrame,
9         ipc::signal::{SigCode, SigFlags, SigSet, Signal, MAX_SIG_NUM},
10     },
11     mm::VirtAddr,
12     process::Pid,
13     syscall::{user_access::UserBufferWriter, SystemError},
14 };
15 
16 /// 用户态程序传入的SIG_DFL的值
17 pub const USER_SIG_DFL: u64 = 0;
18 /// 用户态程序传入的SIG_IGN的值
19 pub const USER_SIG_IGN: u64 = 1;
20 /// 用户态程序传入的SIG_ERR的值
21 pub const USER_SIG_ERR: u64 = 2;
22 
23 // 因为 Rust 编译器不能在常量声明中正确识别级联的 "|" 运算符(experimental feature: https://github.com/rust-lang/rust/issues/67792),因此
24 // 暂时只能通过这种方法来声明这些常量,这些常量暂时没有全部用到,但是都出现在 linux 的判断逻辑中,所以都保留下来了
25 #[allow(dead_code)]
26 pub const SIG_KERNEL_ONLY_MASK: SigSet =
27     Signal::into_sigset(Signal::SIGSTOP).union(Signal::into_sigset(Signal::SIGKILL));
28 
29 pub const SIG_KERNEL_STOP_MASK: SigSet = Signal::into_sigset(Signal::SIGSTOP)
30     .union(Signal::into_sigset(Signal::SIGTSTP))
31     .union(Signal::into_sigset(Signal::SIGTTIN))
32     .union(Signal::into_sigset(Signal::SIGTTOU));
33 #[allow(dead_code)]
34 pub const SIG_KERNEL_COREDUMP_MASK: SigSet = Signal::into_sigset(Signal::SIGQUIT)
35     .union(Signal::into_sigset(Signal::SIGILL))
36     .union(Signal::into_sigset(Signal::SIGTRAP))
37     .union(Signal::into_sigset(Signal::SIGABRT_OR_IOT))
38     .union(Signal::into_sigset(Signal::SIGFPE))
39     .union(Signal::into_sigset(Signal::SIGSEGV))
40     .union(Signal::into_sigset(Signal::SIGBUS))
41     .union(Signal::into_sigset(Signal::SIGSYS))
42     .union(Signal::into_sigset(Signal::SIGXCPU))
43     .union(Signal::into_sigset(Signal::SIGXFSZ));
44 #[allow(dead_code)]
45 pub const SIG_KERNEL_IGNORE_MASK: SigSet = Signal::into_sigset(Signal::SIGCONT)
46     .union(Signal::into_sigset(Signal::SIGFPE))
47     .union(Signal::into_sigset(Signal::SIGSEGV))
48     .union(Signal::into_sigset(Signal::SIGBUS))
49     .union(Signal::into_sigset(Signal::SIGTRAP))
50     .union(Signal::into_sigset(Signal::SIGCHLD))
51     .union(Signal::into_sigset(Signal::SIGIO_OR_POLL))
52     .union(Signal::into_sigset(Signal::SIGSYS));
53 
54 /// SignalStruct 在 pcb 中加锁
55 #[derive(Debug)]
56 pub struct SignalStruct {
57     pub cnt: AtomicI64,
58     /// 如果对应linux,这部分会有一个引用计数,但是没发现在哪里有用到需要计算引用的地方,因此
59     /// 暂时删掉,不然这个Arc会导致其他地方的代码十分丑陋
60     pub handlers: [Sigaction; MAX_SIG_NUM as usize],
61 }
62 
63 impl Default for SignalStruct {
64     fn default() -> Self {
65         Self {
66             cnt: Default::default(),
67             handlers: [Sigaction::default(); MAX_SIG_NUM as usize],
68         }
69     }
70 }
71 
72 #[derive(Debug, Copy, Clone)]
73 #[allow(dead_code)]
74 pub enum SigactionType {
75     SaHandler(SaHandlerType),
76     SaSigaction(
77         Option<
78             unsafe extern "C" fn(
79                 sig: ::core::ffi::c_int,
80                 sinfo: *mut SigInfo,
81                 arg1: *mut ::core::ffi::c_void,
82             ),
83         >,
84     ), // 暂时没有用上
85 }
86 
87 impl SigactionType {
88     /// Returns `true` if the sa handler type is [`SaHandler(SaHandlerType::SigIgnore)`].
89     ///
90     /// [`SigIgnore`]: SaHandlerType::SigIgnore
91     pub fn is_ignore(&self) -> bool {
92         return matches!(self, Self::SaHandler(SaHandlerType::SigIgnore));
93     }
94     /// Returns `true` if the sa handler type is [`SaHandler(SaHandlerType::SigCustomized(_))`].
95     ///
96     /// [`SigCustomized`]: SaHandlerType::SigCustomized(_)
97     pub fn is_customized(&self) -> bool {
98         return matches!(self, Self::SaHandler(SaHandlerType::SigCustomized(_)));
99     }
100 }
101 
102 #[derive(Debug, Copy, Clone)]
103 #[allow(dead_code)]
104 pub enum SaHandlerType {
105     SigError, // 暂时没有用上
106     SigDefault,
107     SigIgnore,
108     SigCustomized(VirtAddr),
109 }
110 
111 impl Into<usize> for SaHandlerType {
112     fn into(self) -> usize {
113         match self {
114             Self::SigError => 2 as usize,
115             Self::SigIgnore => 1 as usize,
116             Self::SigDefault => 0 as usize,
117             Self::SigCustomized(handler) => handler.data(),
118         }
119     }
120 }
121 
122 impl SaHandlerType {
123     /// Returns `true` if the sa handler type is [`SigDefault`].
124     ///
125     /// [`SigDefault`]: SaHandlerType::SigDefault
126     pub fn is_sig_default(&self) -> bool {
127         matches!(self, Self::SigDefault)
128     }
129 
130     /// Returns `true` if the sa handler type is [`SigIgnore`].
131     ///
132     /// [`SigIgnore`]: SaHandlerType::SigIgnore
133     pub fn is_sig_ignore(&self) -> bool {
134         matches!(self, Self::SigIgnore)
135     }
136 
137     /// Returns `true` if the sa handler type is [`SigError`].
138     ///
139     /// [`SigError`]: SaHandlerType::SigError
140     pub fn is_sig_error(&self) -> bool {
141         matches!(self, Self::SigError)
142     }
143 }
144 
145 /// 信号处理结构体
146 ///
147 #[derive(Debug, Copy, Clone)]
148 pub struct Sigaction {
149     action: SigactionType,
150     flags: SigFlags,
151     mask: SigSet, // 为了可扩展性而设置的sa_mask
152     /// 信号处理函数执行结束后,将会跳转到这个函数内进行执行,然后执行sigreturn系统调用
153     restorer: Option<VirtAddr>,
154 }
155 
156 impl Default for Sigaction {
157     fn default() -> Self {
158         Self {
159             action: SigactionType::SaHandler(SaHandlerType::SigDefault),
160             flags: Default::default(),
161             mask: Default::default(),
162             restorer: Default::default(),
163         }
164     }
165 }
166 
167 impl Sigaction {
168     /// 判断传入的信号是否被忽略
169     ///
170     /// ## 参数
171     ///
172     /// - `sig` 传入的信号
173     ///
174     /// ## 返回值
175     ///
176     /// - `true` 被忽略
177     /// - `false`未被忽略
178     pub fn is_ignore(&self) -> bool {
179         return self.action.is_ignore();
180     }
181     pub fn new(
182         action: SigactionType,
183         flags: SigFlags,
184         mask: SigSet,
185         restorer: Option<VirtAddr>,
186     ) -> Self {
187         Self {
188             action,
189             flags,
190             mask,
191             restorer,
192         }
193     }
194 
195     pub fn action(&self) -> SigactionType {
196         self.action
197     }
198 
199     pub fn flags(&self) -> SigFlags {
200         self.flags
201     }
202 
203     pub fn restorer(&self) -> Option<VirtAddr> {
204         self.restorer
205     }
206 
207     pub fn flags_mut(&mut self) -> &mut SigFlags {
208         &mut self.flags
209     }
210 
211     pub fn set_action(&mut self, action: SigactionType) {
212         self.action = action;
213     }
214 
215     pub fn mask(&self) -> SigSet {
216         self.mask
217     }
218 
219     pub fn mask_mut(&mut self) -> &mut SigSet {
220         &mut self.mask
221     }
222 
223     pub fn set_restorer(&mut self, restorer: Option<VirtAddr>) {
224         self.restorer = restorer;
225     }
226 
227     /// 默认信号处理程序占位符(用于在sighand结构体中的action数组中占位)
228     pub const DEFAULT_SIGACTION: Sigaction = Sigaction {
229         action: SigactionType::SaHandler(SaHandlerType::SigDefault),
230         flags: SigFlags::empty(),
231         mask: SigSet::from_bits_truncate(0),
232         restorer: None,
233     };
234 
235     /// 默认的“忽略信号”的sigaction
236     pub const DEFAULT_SIGACTION_IGNORE: Sigaction = Sigaction {
237         action: SigactionType::SaHandler(SaHandlerType::SigIgnore),
238         flags: SigFlags::empty(),
239         mask: SigSet::from_bits_truncate(0),
240         restorer: None,
241     };
242 }
243 
244 /// 用户态传入的sigaction结构体(符合posix规范)
245 /// 请注意,我们会在sys_sigaction函数里面将其转换成内核使用的sigaction结构体
246 #[repr(C)]
247 #[derive(Debug, Clone, Copy)]
248 pub struct UserSigaction {
249     pub handler: *mut core::ffi::c_void,
250     pub flags: SigFlags,
251     pub restorer: *mut core::ffi::c_void,
252     pub mask: SigSet,
253 }
254 
255 /**
256  * siginfo中,根据signal的来源不同,该info中对应了不同的数据./=
257  * 请注意,该info最大占用16字节
258  */
259 
260 #[repr(C)]
261 #[derive(Copy, Clone, Debug)]
262 pub struct SigInfo {
263     sig_no: i32,
264     sig_code: SigCode,
265     errno: i32,
266     sig_type: SigType,
267 }
268 
269 impl SigInfo {
270     pub fn sig_code(&self) -> SigCode {
271         self.sig_code
272     }
273 
274     pub fn set_sig_type(&mut self, sig_type: SigType) {
275         self.sig_type = sig_type;
276     }
277     /// @brief 将siginfo结构体拷贝到用户栈
278     /// ## 参数
279     ///
280     /// `to` 用户空间指针
281     ///
282     /// ## 注意
283     ///
284     /// 该函数对应Linux中的https://opengrok.ringotek.cn/xref/linux-6.1.9/kernel/signal.c#3323
285     /// Linux还提供了 https://opengrok.ringotek.cn/xref/linux-6.1.9/kernel/signal.c#3383 用来实现
286     /// kernel_siginfo 保存到 用户的 compact_siginfo 的功能,但是我们系统内还暂时没有对这两种
287     /// siginfo做区分,因此暂时不需要第二个函数
288     pub fn copy_siginfo_to_user(&self, to: *mut SigInfo) -> Result<i32, SystemError> {
289         // 验证目标地址是否为用户空间
290         let mut user_buffer = UserBufferWriter::new(to, size_of::<SigInfo>(), true)?;
291 
292         let retval: Result<i32, SystemError> = Ok(0);
293 
294         user_buffer.copy_one_to_user(self, 0)?;
295         return retval;
296     }
297 }
298 
299 #[derive(Copy, Clone, Debug)]
300 pub enum SigType {
301     Kill(Pid),
302     // 后续完善下列中的具体字段
303     // Timer,
304     // Rt,
305     // SigChild,
306     // SigFault,
307     // SigPoll,
308     // SigSys,
309 }
310 
311 impl SigInfo {
312     pub fn new(sig: Signal, sig_errno: i32, sig_code: SigCode, sig_type: SigType) -> Self {
313         Self {
314             sig_no: sig as i32,
315             sig_code,
316             errno: sig_errno,
317             sig_type,
318         }
319     }
320 }
321 
322 #[derive(Debug)]
323 pub struct SigPending {
324     signal: SigSet,
325     queue: SigQueue,
326 }
327 
328 impl Default for SigPending {
329     fn default() -> Self {
330         SigPending {
331             signal: SigSet::default(),
332             queue: SigQueue::default(),
333         }
334     }
335 }
336 
337 impl SigPending {
338     /// 判断是否有待处理的信号
339     pub fn has_pending(&self) -> bool {
340         return !self.signal.is_empty();
341     }
342 
343     pub fn signal(&self) -> SigSet {
344         self.signal
345     }
346 
347     pub fn queue(&self) -> &SigQueue {
348         &self.queue
349     }
350 
351     pub fn queue_mut(&mut self) -> &mut SigQueue {
352         &mut self.queue
353     }
354 
355     pub fn signal_mut(&mut self) -> &mut SigSet {
356         &mut self.signal
357     }
358     /// @brief 获取下一个要处理的信号(sig number越小的信号,优先级越高)
359     ///
360     /// @param pending 等待处理的信号
361     /// @param sig_mask 屏蔽了的信号
362     /// @return i32 下一个要处理的信号的number. 如果为0,则无效
363     pub fn next_signal(&self, sig_mask: &SigSet) -> Signal {
364         let mut sig = Signal::INVALID;
365 
366         let s = self.signal();
367         let m = *sig_mask;
368         m.is_empty();
369         // 获取第一个待处理的信号的号码
370         let x = s & (!m);
371         if x.bits() != 0 {
372             sig = Signal::from(ffz(x.complement().bits()) + 1);
373             return sig;
374         }
375 
376         // 暂时只支持64种信号
377         assert_eq!(MAX_SIG_NUM, 64);
378 
379         return sig;
380     }
381     /// @brief 收集信号的信息
382     ///
383     /// @param sig 要收集的信号的信息
384     /// @param pending 信号的排队等待标志
385     /// @return SigInfo 信号的信息
386     pub fn collect_signal(&mut self, sig: Signal) -> SigInfo {
387         let (info, still_pending) = self.queue_mut().find_and_delete(sig);
388 
389         // 如果没有仍在等待的信号,则清除pending位
390         if !still_pending {
391             self.signal_mut().remove(sig.into());
392         }
393 
394         if info.is_some() {
395             return info.unwrap();
396         } else {
397             // 信号不在sigqueue中,这意味着当前信号是来自快速路径,因此直接把siginfo设置为0即可。
398             let mut ret = SigInfo::new(sig, 0, SigCode::User, SigType::Kill(Pid::from(0)));
399             ret.set_sig_type(SigType::Kill(Pid::new(0)));
400             return ret;
401         }
402     }
403 
404     /// @brief 从当前进程的sigpending中取出下一个待处理的signal,并返回给调用者。(调用者应当处理这个信号)
405     /// 请注意,进入本函数前,当前进程应当持有current_pcb().sighand.siglock
406     pub fn dequeue_signal(&mut self, sig_mask: &SigSet) -> (Signal, Option<SigInfo>) {
407         // kdebug!("dequeue signal");
408         // 获取下一个要处理的信号的编号
409         let sig = self.next_signal(sig_mask);
410 
411         let info: Option<SigInfo>;
412         if sig != Signal::INVALID {
413             // 如果下一个要处理的信号是合法的,则收集其siginfo
414             info = Some(self.collect_signal(sig));
415         } else {
416             info = None;
417         }
418 
419         // 当一个进程具有多个线程之后,在这里需要重新计算线程的flag中的TIF_SIGPENDING位
420         // recalc_sigpending();
421         return (sig, info);
422     }
423     /// @brief 从sigpending中删除mask中被置位的信号。也就是说,比如mask的第1位被置为1,那么就从sigqueue中删除所有signum为2的信号的信息。
424     pub fn flush_by_mask(&mut self, mask: &SigSet) {
425         // 定义过滤器,从sigqueue中删除mask中被置位的信号
426         let filter = |x: &SigInfo| !mask.contains(SigSet::from_bits_truncate(x.sig_no as u64));
427         self.queue.q.retain(filter);
428     }
429 }
430 
431 /// @brief 进程接收到的信号的队列
432 #[derive(Debug, Clone)]
433 pub struct SigQueue {
434     pub q: Vec<SigInfo>,
435 }
436 
437 #[allow(dead_code)]
438 impl SigQueue {
439     /// @brief 初始化一个新的信号队列
440     pub fn new(capacity: usize) -> Self {
441         SigQueue {
442             q: Vec::with_capacity(capacity),
443         }
444     }
445 
446     /// @brief 在信号队列中寻找第一个满足要求的siginfo, 并返回它的引用
447     ///
448     /// @return (第一个满足要求的siginfo的引用; 是否有多个满足条件的siginfo)
449     pub fn find(&self, sig: Signal) -> (Option<&SigInfo>, bool) {
450         // 是否存在多个满足条件的siginfo
451         let mut still_pending = false;
452         let mut info: Option<&SigInfo> = None;
453 
454         for x in self.q.iter() {
455             if x.sig_no == sig as i32 {
456                 if info.is_some() {
457                     still_pending = true;
458                     break;
459                 } else {
460                     info = Some(x);
461                 }
462             }
463         }
464         return (info, still_pending);
465     }
466 
467     /// @brief 在信号队列中寻找第一个满足要求的siginfo, 并将其从队列中删除,然后返回这个siginfo
468     ///
469     /// @return (第一个满足要求的siginfo; 从队列中删除前是否有多个满足条件的siginfo)
470     pub fn find_and_delete(&mut self, sig: Signal) -> (Option<SigInfo>, bool) {
471         // 是否存在多个满足条件的siginfo
472         let mut still_pending = false;
473         let mut first = true; // 标记变量,记录当前是否已经筛选出了一个元素
474 
475         let filter = |x: &mut SigInfo| {
476             if x.sig_no == sig as i32 {
477                 if !first {
478                     // 如果之前已经筛选出了一个元素,则不把当前元素删除
479                     still_pending = true;
480                     return false;
481                 } else {
482                     // 当前是第一个被筛选出来的元素
483                     first = false;
484                     return true;
485                 }
486             }
487             return false;
488         };
489         // 从sigqueue中过滤出结果
490         let mut filter_result: Vec<SigInfo> = self.q.extract_if(filter).collect();
491         // 筛选出的结果不能大于1个
492         assert!(filter_result.len() <= 1);
493 
494         return (filter_result.pop(), still_pending);
495     }
496 
497     /// @brief 从C的void*指针转换为static生命周期的可变引用
498     pub fn from_c_void(p: *mut c_void) -> &'static mut SigQueue {
499         let sq = p as *mut SigQueue;
500         let sq = unsafe { sq.as_mut::<'static>() }.unwrap();
501         return sq;
502     }
503 }
504 
505 impl Default for SigQueue {
506     fn default() -> Self {
507         Self {
508             q: Default::default(),
509         }
510     }
511 }
512 
513 ///
514 /// 定义了不同架构下实现 Signal 要实现的接口
515 ///
516 pub trait SignalArch {
517     /// 信号处理函数
518     ///
519     /// ## 参数
520     ///
521     /// - `frame` 中断栈帧
522     unsafe fn do_signal(frame: &mut TrapFrame);
523 
524     fn sys_rt_sigreturn(trap_frame: &mut TrapFrame) -> u64;
525 }
526