xref: /DragonOS/kernel/src/ipc/signal.rs (revision ab5c8ca46db8e7d4793a9791292122b0b9684274)
1 use core::{
2     ffi::c_void,
3     intrinsics::size_of,
4     ptr::{null_mut, read_volatile},
5     sync::atomic::compiler_fence,
6 };
7 
8 use crate::{
9     arch::{
10         asm::{bitops::ffz, current::current_pcb, ptrace::user_mode},
11         fpu::FpState,
12         interrupt::sti,
13     },
14     include::bindings::bindings::{
15         pid_t, process_control_block, process_do_exit, process_find_pcb_by_pid, pt_regs,
16         spinlock_t, verify_area, NULL, PF_EXITING, PF_KTHREAD, PF_SIGNALED, PF_WAKEKILL,
17         PROC_INTERRUPTIBLE, USER_CS, USER_DS, USER_MAX_LINEAR_ADDR,
18     },
19     ipc::signal_types::sigset_add,
20     kBUG, kdebug, kerror, kwarn,
21     libs::{
22         ffi_convert::FFIBind2Rust,
23         spinlock::{
24             spin_is_locked, spin_lock_irq, spin_lock_irqsave, spin_unlock_irq,
25             spin_unlock_irqrestore,
26         },
27     },
28     process::{
29         pid::PidType,
30         process::{process_is_stopped, process_kick, process_wake_up_state},
31     },
32     syscall::SystemError,
33 };
34 
35 use super::signal_types::{
36     si_code_val, sig_is_member, sigaction, sigaction__union_u, sigcontext, sigframe,
37     sighand_struct, siginfo, signal_struct, sigpending, sigset_clear, sigset_del, sigset_delmask,
38     sigset_equal, sigset_t, SigQueue, SignalNumber, MAX_SIG_NUM, SA_ALL_FLAGS,
39     SA_FLAG_DFL, SA_FLAG_IGN, SA_FLAG_IMMUTABLE, SA_FLAG_RESTORER, STACK_ALIGN, _NSIG_U64_CNT,
40 };
41 
42 
43 
44 /// 默认信号处理程序占位符(用于在sighand结构体中的action数组中占位)
45 pub static DEFAULT_SIGACTION: sigaction = sigaction {
46     _u: sigaction__union_u {
47         _sa_handler: NULL as u64,
48     },
49     sa_flags: SA_FLAG_DFL,
50     sa_mask: 0,
51     sa_restorer: NULL as u64,
52 };
53 
54 /// 默认的“忽略信号”的sigaction
55 #[allow(dead_code)]
56 pub static DEFAULT_SIGACTION_IGNORE: sigaction = sigaction {
57     _u: sigaction__union_u {
58         _sa_handler: NULL as u64,
59     },
60     sa_flags: SA_FLAG_IGN,
61     sa_mask: 0,
62     sa_restorer: NULL as u64,
63 };
64 
65 /// 通过kill的方式向目标进程发送信号
66 /// @param sig 要发送的信号
67 /// @param info 要发送的信息
68 /// @param pid 进程id(目前只支持pid>0)
69 pub fn signal_kill_something_info(
70     sig: SignalNumber,
71     info: Option<&mut siginfo>,
72     pid: pid_t,
73 ) -> Result<i32, SystemError> {
74     // 暂时不支持特殊的kill操作
75     if pid <= 0 {
76         kwarn!("Kill operation not support: pid={}", pid);
77         return Err(SystemError::EOPNOTSUPP_OR_ENOTSUP);
78     }
79 
80     // kill单个进程
81     return signal_kill_proc_info(sig, info, pid);
82 }
83 
84 fn signal_kill_proc_info(
85     sig: SignalNumber,
86     info: Option<&mut siginfo>,
87     pid: pid_t,
88 ) -> Result<i32, SystemError> {
89     let mut retval = Err(SystemError::ESRCH);
90 
91     // step1: 当进程管理模块拥有pcblist_lock之后,对其加锁
92 
93     // step2: 根据pid找到pcb
94     let pcb = unsafe { process_find_pcb_by_pid(pid).as_mut() };
95 
96     if pcb.is_none() {
97         kwarn!("No such process.");
98         return retval;
99     }
100 
101     // println!("Target pcb = {:?}", pcb.as_ref().unwrap());
102     compiler_fence(core::sync::atomic::Ordering::SeqCst);
103     // step3: 调用signal_send_sig_info函数,发送信息
104     retval = signal_send_sig_info(sig, info, pcb.unwrap());
105     compiler_fence(core::sync::atomic::Ordering::SeqCst);
106     // step4: 解锁
107     return retval;
108 }
109 
110 /// @brief 验证信号的值是否在范围内
111 #[inline]
112 fn verify_signal(sig: SignalNumber) -> bool {
113     return if (sig as i32) <= MAX_SIG_NUM {
114         true
115     } else {
116         false
117     };
118 }
119 
120 /// @brief 在发送信号给指定的进程前,做一些权限检查. 检查是否有权限发送
121 /// @param sig 要发送的信号
122 /// @param info 要发送的信息
123 /// @param target_pcb 信号的接收者
124 fn signal_send_sig_info(
125     sig: SignalNumber,
126     info: Option<&mut siginfo>,
127     target_pcb: &mut process_control_block,
128 ) -> Result<i32, SystemError> {
129     // kdebug!("signal_send_sig_info");
130     // 检查sig是否符合要求,如果不符合要求,则退出。
131     if !verify_signal(sig) {
132         return Err(SystemError::EINVAL);
133     }
134 
135     // 信号符合要求,可以发送
136 
137     let mut retval = Err(SystemError::ESRCH);
138     let mut flags: u64 = 0;
139     // 如果上锁成功,则发送信号
140     if !lock_process_sighand(target_pcb, &mut flags).is_none() {
141         compiler_fence(core::sync::atomic::Ordering::SeqCst);
142         // 发送信号
143         retval = send_signal_locked(sig, info, target_pcb, PidType::PID);
144         compiler_fence(core::sync::atomic::Ordering::SeqCst);
145         // kdebug!("flags=0x{:016x}", flags);
146         // 对sighand放锁
147         unlock_process_sighand(target_pcb, flags);
148     }
149     return retval;
150 }
151 
152 /// @brief 对pcb的sighand结构体中的siglock进行加锁,并关闭中断
153 /// @param pcb 目标pcb
154 /// @param flags 用来保存rflags的变量
155 /// @return 指向sighand_struct的可变引用
156 fn lock_process_sighand<'a>(
157     pcb: &'a mut process_control_block,
158     flags: &mut u64,
159 ) -> Option<&'a mut sighand_struct> {
160     // kdebug!("lock_process_sighand");
161 
162     let sighand_ptr = sighand_struct::convert_mut(unsafe { &mut *pcb.sighand });
163     // kdebug!("sighand_ptr={:?}", &sighand_ptr);
164     if !sighand_ptr.is_some() {
165         kBUG!("Sighand ptr of process {pid} is NULL!", pid = pcb.pid);
166         return None;
167     }
168 
169     let lock = { &mut sighand_ptr.unwrap().siglock };
170 
171     spin_lock_irqsave(lock, flags);
172     let ret = unsafe { ((*pcb).sighand as *mut sighand_struct).as_mut() };
173 
174     return ret;
175 }
176 
177 /// @brief 对pcb的sighand结构体中的siglock进行放锁,并恢复之前存储的rflags
178 /// @param pcb 目标pcb
179 /// @param flags 用来保存rflags的变量,将这个值恢复到rflags寄存器中
180 fn unlock_process_sighand(pcb: &mut process_control_block, flags: u64) {
181     let lock = unsafe { &mut (*pcb.sighand).siglock };
182 
183     spin_unlock_irqrestore(lock, &flags);
184 }
185 
186 /// @brief 判断是否需要强制发送信号,然后发送信号
187 /// 注意,进入该函数前,我们应当对pcb.sighand.siglock加锁。
188 ///
189 /// @return SystemError 错误码
190 fn send_signal_locked(
191     sig: SignalNumber,
192     info: Option<&mut siginfo>,
193     pcb: &mut process_control_block,
194     pt: PidType,
195 ) -> Result<i32, SystemError> {
196     // 是否强制发送信号
197     let mut force_send = false;
198     // signal的信息为空
199     if info.is_none() {
200         // todo: 判断signal是否来自于一个祖先进程的namespace,如果是,则强制发送信号
201     } else {
202         force_send = unsafe { info.as_ref().unwrap()._sinfo.data.si_code }
203             == (si_code_val::SI_KERNEL as i32);
204     }
205 
206     // kdebug!("force send={}", force_send);
207 
208     return __send_signal_locked(sig, info, pcb, pt, force_send);
209 }
210 
211 /// @brief 发送信号
212 /// 注意,进入该函数前,我们应当对pcb.sighand.siglock加锁。
213 ///
214 /// @param sig 信号
215 /// @param _info 信号携带的信息
216 /// @param pcb 目标进程的pcb
217 /// @param pt siginfo结构体中,pid字段代表的含义
218 /// @return SystemError 错误码
219 fn __send_signal_locked(
220     sig: SignalNumber,
221     info: Option<&mut siginfo>,
222     pcb: &mut process_control_block,
223     pt: PidType,
224     _force_send: bool,
225 ) -> Result<i32, SystemError> {
226     // kdebug!("__send_signal_locked");
227 
228     // 判断该进入该函数时,是否已经持有了锁
229     assert!(spin_is_locked(unsafe { &(*pcb.sighand).siglock }));
230 
231     let _pending: Option<&mut sigpending> = sigpending::convert_mut(&mut pcb.sig_pending);
232     compiler_fence(core::sync::atomic::Ordering::SeqCst);
233     // 如果是kill或者目标pcb是内核线程,则无需获取sigqueue,直接发送信号即可
234     if sig == SignalNumber::SIGKILL || (pcb.flags & (PF_KTHREAD as u64)) != 0 {
235         complete_signal(sig, pcb, pt);
236     } else {
237         // 如果是其他信号,则加入到sigqueue内,然后complete_signal
238         let mut q: siginfo;
239         match info {
240             Some(x) => {
241                 // 已经显式指定了siginfo,则直接使用它。
242                 q = x.clone();
243             }
244             None => {
245                 // 不需要显示指定siginfo,因此设置为默认值
246                 q = siginfo::new(sig, 0, si_code_val::SI_USER);
247                 q._sinfo.data._sifields._kill._pid = current_pcb().pid;
248             }
249         }
250 
251         let sq: &mut SigQueue = SigQueue::from_c_void(current_pcb().sig_pending.sigqueue);
252         sq.q.push(q);
253         complete_signal(sig, pcb, pt);
254     }
255     compiler_fence(core::sync::atomic::Ordering::SeqCst);
256     return Ok(0);
257 }
258 
259 /// @brief 将信号添加到目标进程的sig_pending。在引入进程组后,本函数还将负责把信号传递给整个进程组。
260 ///
261 /// @param sig 信号
262 /// @param pcb 目标pcb
263 /// @param pt siginfo结构体中,pid字段代表的含义
264 fn complete_signal(sig: SignalNumber, pcb: &mut process_control_block, pt: PidType) {
265     // kdebug!("complete_signal");
266 
267     // todo: 将信号产生的消息通知到正在监听这个信号的进程(引入signalfd之后,在这里调用signalfd_notify)
268     // 将这个信号加到目标进程的sig_pending中
269     sigset_add(
270         sigset_t::convert_mut(&mut pcb.sig_pending.signal).unwrap(),
271         sig,
272     );
273     compiler_fence(core::sync::atomic::Ordering::SeqCst);
274     // ===== 寻找需要wakeup的目标进程 =====
275     // 备注:由于当前没有进程组的概念,每个进程只有1个对应的线程,因此不需要通知进程组内的每个进程。
276     //      todo: 当引入进程组的概念后,需要完善这里,使得它能寻找一个目标进程来唤醒,接着执行信号处理的操作。
277 
278     let _signal: Option<&mut signal_struct> = signal_struct::convert_mut(pcb.signal);
279 
280     let mut _target: Option<&mut process_control_block> = None;
281 
282     // 判断目标进程是否想接收这个信号
283     if wants_signal(sig, pcb) {
284         _target = Some(pcb);
285     } else if pt == PidType::PID {
286         /*
287          * There is just one thread and it does not need to be woken.
288          * It will dequeue unblocked signals before it runs again.
289          */
290         return;
291     } else {
292         /*
293          * Otherwise try to find a suitable thread.
294          * 由于目前每个进程只有1个线程,因此当前情况可以返回。信号队列的dequeue操作不需要考虑同步阻塞的问题。
295          */
296         return;
297     }
298 
299     // todo:引入进程组后,在这里挑选一个进程来唤醒,让它执行相应的操作。
300     // todo!();
301     compiler_fence(core::sync::atomic::Ordering::SeqCst);
302     // todo: 到这里,信号已经被放置在共享的pending队列中,我们在这里把目标进程唤醒。
303     if _target.is_some() {
304         signal_wake_up(pcb, sig == SignalNumber::SIGKILL);
305     }
306 }
307 
308 /// @brief 本函数用于检测指定的进程是否想要接收SIG这个信号。
309 /// 当我们对于进程组中的所有进程都运行了这个检查之后,我们将可以找到组内愿意接收信号的进程。
310 /// 这么做是为了防止我们把信号发送给了一个正在或已经退出的进程,或者是不响应该信号的进程。
311 #[inline]
312 fn wants_signal(sig: SignalNumber, pcb: &process_control_block) -> bool {
313     // 如果改进程屏蔽了这个signal,则不能接收
314     if sig_is_member(sigset_t::convert_ref(&pcb.sig_blocked).unwrap(), sig) {
315         return false;
316     }
317 
318     // 如果进程正在退出,则不能接收信号
319     if (pcb.flags & (PF_EXITING as u64)) > 0 {
320         return false;
321     }
322 
323     if sig == SignalNumber::SIGKILL {
324         return true;
325     }
326 
327     if process_is_stopped(pcb) {
328         return false;
329     }
330 
331     // todo: 检查目标进程是否正在一个cpu上执行,如果是,则返回true,否则继续检查下一项
332 
333     // 检查目标进程是否有信号正在等待处理,如果是,则返回false,否则返回true
334     return !has_sig_pending(pcb);
335 }
336 
337 /// @brief 判断signal的处理是否可能使得整个进程组退出
338 /// @return true 可能会导致退出(不一定)
339 #[allow(dead_code)]
340 #[inline]
341 fn sig_fatal(pcb: &process_control_block, sig: SignalNumber) -> bool {
342     let handler = unsafe {
343         sighand_struct::convert_ref(pcb.sighand).unwrap().action[(sig as usize) - 1]
344             ._u
345             ._sa_handler
346     };
347 
348     // 如果handler是空,采用默认函数,signal处理可能会导致进程退出。
349     if handler == NULL.into() {
350         return true;
351     } else {
352         return false;
353     }
354 
355     // todo: 参照linux的sig_fatal实现完整功能
356 }
357 
358 /// @brief 判断某个进程是否有信号正在等待处理
359 #[inline]
360 fn has_sig_pending(pcb: &process_control_block) -> bool {
361     let ptr = &sigpending::convert_ref(&(*pcb).sig_pending).unwrap().signal;
362     if unsafe { read_volatile(ptr) } != 0 {
363         return true;
364     } else {
365         return false;
366     }
367 }
368 
369 #[inline]
370 fn signal_wake_up(pcb: &mut process_control_block, fatal: bool) {
371     // kdebug!("signal_wake_up");
372     let mut state: u64 = 0;
373     if fatal {
374         state = PF_WAKEKILL as u64;
375     }
376     signal_wake_up_state(pcb, state);
377 }
378 
379 fn signal_wake_up_state(pcb: &mut process_control_block, state: u64) {
380     assert!(spin_is_locked(&unsafe { (*pcb.sighand).siglock }));
381     // todo: 设置线程结构体的标志位为TIF_SIGPENDING
382     compiler_fence(core::sync::atomic::Ordering::SeqCst);
383     // 如果目标进程已经在运行,则发起一个ipi,使得它陷入内核
384     if !process_wake_up_state(pcb, state | (PROC_INTERRUPTIBLE as u64)) {
385         process_kick(pcb);
386     }
387     compiler_fence(core::sync::atomic::Ordering::SeqCst);
388 }
389 
390 /// @brief 信号处理函数。该函数在进程退出内核态的时候会被调用,且调用前会关闭中断。
391 #[no_mangle]
392 pub extern "C" fn do_signal(regs: &mut pt_regs) {
393     // 检查sigpending是否为0
394     if current_pcb().sig_pending.signal == 0 || (!user_mode(regs)) {
395         // 若没有正在等待处理的信号,或者将要返回到的是内核态,则启用中断,然后返回
396         sti();
397         return;
398     }
399 
400     // 做完上面的检查后,开中断
401     sti();
402 
403     let oldset = current_pcb().sig_blocked;
404     loop {
405         let (sig_number, info, ka) = get_signal_to_deliver(regs.clone());
406         // 所有的信号都处理完了
407         if sig_number == SignalNumber::INVALID {
408             return;
409         }
410         kdebug!(
411             "To handle signal [{}] for pid:{}",
412             sig_number as i32,
413             current_pcb().pid
414         );
415         let res = handle_signal(sig_number, ka.unwrap(), &info.unwrap(), &oldset, regs);
416         if res.is_err() {
417             kerror!(
418                 "Error occurred when handling signal: {}, pid={}, errcode={:?}",
419                 sig_number as i32,
420                 current_pcb().pid,
421                 res.unwrap_err()
422             );
423         }
424     }
425 }
426 
427 /// @brief 获取要被发送的信号的signumber, siginfo, 以及对应的sigaction结构体
428 fn get_signal_to_deliver(
429     _regs: pt_regs,
430 ) -> (
431     SignalNumber,
432     Option<siginfo>,
433     Option<&'static mut sigaction>,
434 ) {
435     let mut info: Option<siginfo>;
436     let ka: Option<&mut sigaction>;
437     let mut sig_number;
438     let sighand: &mut sighand_struct;
439 
440     {
441         let _tmp = sighand_struct::convert_mut(current_pcb().sighand);
442         if let Some(i) = _tmp {
443             sighand = i;
444         } else {
445             panic!("Sighand is NULL! pid={}", current_pcb().pid);
446         }
447     }
448 
449     spin_lock_irq(&mut sighand.siglock);
450     loop {
451         (sig_number, info) =
452             dequeue_signal(sigset_t::convert_mut(&mut current_pcb().sig_blocked).unwrap());
453 
454         // 如果信号非法,则直接返回
455         if sig_number == SignalNumber::INVALID {
456             spin_unlock_irq(unsafe { (&mut (*current_pcb().sighand).siglock) as *mut spinlock_t });
457             return (sig_number, None, None);
458         }
459 
460         // 获取指向sigaction结构体的引用
461         let hand = sighand_struct::convert_mut(current_pcb().sighand).unwrap();
462         // kdebug!("hand=0x{:018x}", hand as *const sighand_struct as usize);
463         let tmp_ka = &mut hand.action[sig_number as usize - 1];
464 
465         // 如果当前动作是忽略这个信号,则不管它了。
466         if (tmp_ka.sa_flags & SA_FLAG_IGN) != 0 {
467             continue;
468         } else if (tmp_ka.sa_flags & SA_FLAG_DFL) == 0 {
469             // 当前不采用默认的信号处理函数
470             ka = Some(tmp_ka);
471             break;
472         }
473         kdebug!(
474             "Use default handler to handle signal [{}] for pid {}",
475             sig_number as i32,
476             current_pcb().pid
477         );
478         // ===== 经过上面的判断,如果能走到这一步,就意味着我们采用默认的信号处理函数来处理这个信号 =====
479         spin_unlock_irq(&mut sighand.siglock);
480         // 标记当前进程由于信号而退出
481         current_pcb().flags |= PF_SIGNALED as u64;
482 
483         // 执行进程的退出动作
484         unsafe { process_do_exit(info.unwrap()._sinfo.data.si_signo as u64) };
485         /* NOT REACHED 这部分代码将不会到达 */
486     }
487     spin_unlock_irq(&mut sighand.siglock);
488     return (sig_number, info, ka);
489 }
490 
491 /// @brief 从当前进程的sigpending中取出下一个待处理的signal,并返回给调用者。(调用者应当处理这个信号)
492 /// 请注意,进入本函数前,当前进程应当持有current_pcb().sighand.siglock
493 fn dequeue_signal(sig_mask: &mut sigset_t) -> (SignalNumber, Option<siginfo>) {
494     // kdebug!("dequeue signal");
495     // 获取下一个要处理的信号的编号
496     let sig = next_signal(
497         sigpending::convert_ref(&(current_pcb().sig_pending)).unwrap(),
498         sig_mask,
499     );
500 
501     let info: Option<siginfo>;
502     if sig != SignalNumber::INVALID {
503         // 如果下一个要处理的信号是合法的,则收集其siginfo
504         info = Some(collect_signal(
505             sig,
506             sigpending::convert_mut(&mut current_pcb().sig_pending).unwrap(),
507         ));
508     } else {
509         info = None;
510     }
511 
512     // 当一个进程具有多个线程之后,在这里需要重新计算线程的flag中的TIF_SIGPENDING位
513     recalc_sigpending();
514     return (sig, info);
515 }
516 
517 /// @brief 获取下一个要处理的信号(sig number越小的信号,优先级越高)
518 ///
519 /// @param pending 等待处理的信号
520 /// @param sig_mask 屏蔽了的信号
521 /// @return i32 下一个要处理的信号的number. 如果为0,则无效
522 fn next_signal(pending: &sigpending, sig_mask: &sigset_t) -> SignalNumber {
523     let mut sig = SignalNumber::INVALID;
524 
525     let s = pending.signal;
526     let m = *sig_mask;
527 
528     // 获取第一个待处理的信号的号码
529     let x = s & (!m);
530     if x != 0 {
531         sig = SignalNumber::from(ffz(!x) + 1);
532         return sig;
533     }
534 
535     // 暂时只支持64种信号信号
536     assert_eq!(_NSIG_U64_CNT, 1);
537 
538     return sig;
539 }
540 
541 /// @brief 当一个进程具有多个线程之后,在这里需要重新计算线程的flag中的TIF_SIGPENDING位
542 fn recalc_sigpending() {
543     // todo:
544 }
545 
546 /// @brief 收集信号的信息
547 ///
548 /// @param sig 要收集的信号的信息
549 /// @param pending 信号的排队等待标志
550 /// @return siginfo 信号的信息
551 fn collect_signal(sig: SignalNumber, pending: &mut sigpending) -> siginfo {
552     let (info, still_pending) = unsafe { pending.queue.as_mut() }
553         .unwrap()
554         .find_and_delete(sig);
555 
556     // 如果没有仍在等待的信号,则清除pending位
557     if !still_pending {
558         sigset_del(&mut pending.signal, sig);
559     }
560 
561     if info.is_some() {
562         return info.unwrap();
563     } else {
564         // 信号不在sigqueue中,这意味着当前信号是来自快速路径,因此直接把siginfo设置为0即可。
565         let mut ret = siginfo::new(sig, 0, si_code_val::SI_USER);
566         ret._sinfo.data._sifields._kill._pid = 0;
567         return ret;
568     }
569 }
570 
571 /// @brief 真正发送signal,执行自定义的处理函数
572 ///
573 /// @param sig 信号number
574 /// @param ka 信号响应动作
575 /// @param info 信号信息
576 /// @param oldset
577 /// @param regs 之前的系统调用将要返回的时候,要弹出的栈帧的拷贝
578 ///
579 /// @return Result<0,SystemError> 若Error, 则返回错误码,否则返回Ok(0)
580 fn handle_signal(
581     sig: SignalNumber,
582     ka: &mut sigaction,
583     info: &siginfo,
584     oldset: &sigset_t,
585     regs: &mut pt_regs,
586 ) -> Result<i32, SystemError> {
587     // 设置栈帧
588     let retval = setup_frame(sig, ka, info, oldset, regs);
589     if retval.is_err() {
590         return retval;
591     }
592     return Ok(0);
593 }
594 
595 /// @brief 在用户栈上开辟一块空间,并且把内核栈的栈帧以及需要在用户态执行的代码给保存进去。
596 ///
597 /// @param regs 进入信号处理流程前,Restore all要弹出的内核栈栈帧
598 fn setup_frame(
599     sig: SignalNumber,
600     ka: &mut sigaction,
601     info: &siginfo,
602     oldset: &sigset_t,
603     regs: &mut pt_regs,
604 ) -> Result<i32, SystemError> {
605     let mut err = 0;
606     let frame: *mut sigframe = get_stack(ka, &regs, size_of::<sigframe>());
607     // kdebug!("frame=0x{:016x}", frame as usize);
608     // 要求这个frame的地址位于用户空间,因此进行校验
609     let access_check_ok = unsafe { verify_area(frame as u64, size_of::<sigframe>() as u64) };
610     if !access_check_ok {
611         // 如果地址区域位于内核空间,则直接报错
612         // todo: 生成一个sigsegv
613         kerror!("In setup frame: access check failed");
614         return Err(SystemError::EPERM);
615     }
616 
617     unsafe {
618         (*frame).arg0 = sig as u64;
619         (*frame).arg1 = &((*frame).info) as *const siginfo as usize;
620         (*frame).arg2 = &((*frame).context) as *const sigcontext as usize;
621         (*frame).handler = ka._u._sa_handler as usize as *mut c_void;
622     }
623 
624     // 将当前进程的fp_state拷贝到用户栈
625     if current_pcb().fp_state != null_mut() {
626         unsafe {
627             let fp_state: &mut FpState = (current_pcb().fp_state as usize as *mut FpState)
628                 .as_mut()
629                 .unwrap();
630             (*frame).context.sc_stack.fpstate = *fp_state;
631             // 保存完毕后,清空fp_state,以免下次save的时候,出现SIMD exception
632             fp_state.clear();
633         }
634     }
635     // 将siginfo拷贝到用户栈
636     err |= copy_siginfo_to_user(unsafe { &mut (*frame).info }, info).unwrap_or(1);
637 
638     // todo: 拷贝处理程序备用栈的地址、大小、ss_flags
639 
640     err |= setup_sigcontext(unsafe { &mut (*frame).context }, oldset, &regs).unwrap_or(1);
641 
642     // 为了与Linux的兼容性,64位程序必须由用户自行指定restorer
643     if ka.sa_flags & SA_FLAG_RESTORER != 0 {
644         unsafe {
645             (*frame).ret_code_ptr = ka.sa_restorer as usize as *mut c_void;
646         }
647     } else {
648         kerror!(
649             "pid-{} forgot to set SA_FLAG_RESTORER for signal {}",
650             current_pcb().pid,
651             sig as i32
652         );
653         err = 1;
654     }
655     if err != 0 {
656         // todo: 在这里生成一个sigsegv,然后core dump
657         //临时解决方案:退出当前进程
658         unsafe {
659             process_do_exit(1);
660         }
661     }
662     // 传入信号处理函数的第一个参数
663     regs.rdi = sig as u64;
664     regs.rsi = unsafe { &(*frame).info as *const siginfo as u64 };
665     regs.rsp = frame as u64;
666     regs.rip = unsafe { ka._u._sa_handler };
667 
668     // todo: 传入新版的sa_sigaction的处理函数的第三个参数
669 
670     // 如果handler位于内核空间
671     if regs.rip >= USER_MAX_LINEAR_ADDR {
672         // 如果当前是SIGSEGV,则采用默认函数处理
673         if sig == SignalNumber::SIGSEGV {
674             ka.sa_flags |= SA_FLAG_DFL;
675         }
676 
677         // 将rip设置为0
678         regs.rip = 0;
679     }
680 
681     // 设置cs和ds寄存器
682     regs.cs = (USER_CS | 0x3) as u64;
683     regs.ds = (USER_DS | 0x3) as u64;
684 
685     return if err == 0 {
686         Ok(0)
687     } else {
688         Err(SystemError::EPERM)
689     };
690 }
691 
692 #[inline(always)]
693 fn get_stack(_ka: &sigaction, regs: &pt_regs, size: usize) -> *mut sigframe {
694     // 默认使用 用户栈的栈顶指针-128字节的红区-sigframe的大小
695     let mut rsp: usize = (regs.rsp as usize) - 128 - size;
696     // 按照要求进行对齐
697     rsp &= (-(STACK_ALIGN as i64)) as usize;
698     return rsp as *mut sigframe;
699 }
700 
701 /// @brief 将siginfo结构体拷贝到用户栈
702 fn copy_siginfo_to_user(to: *mut siginfo, from: &siginfo) -> Result<i32, SystemError> {
703     // 验证目标地址是否为用户空间
704     if unsafe { !verify_area(to as u64, size_of::<siginfo>() as u64) } {
705         // 如果目标地址空间不为用户空间,则直接返回错误码 -EPERM
706         return Err(SystemError::EPERM);
707     }
708 
709     let retval: Result<i32, SystemError> = Ok(0);
710 
711     // todo: 将这里按照si_code的类型来分别拷贝不同的信息。
712     // 这里参考linux-2.6.39  网址: http://opengrok.ringotek.cn/xref/linux-2.6.39/arch/ia64/kernel/signal.c#137
713 
714     unsafe {
715         (*to)._sinfo.data._sifields._kill._pid = from._sinfo.data._sifields._kill._pid;
716     }
717 
718     return retval;
719 }
720 
721 /// @brief 设置目标的sigcontext
722 ///
723 /// @param context 要被设置的目标sigcontext
724 /// @param mask 要被暂存的信号mask标志位
725 /// @param regs 进入信号处理流程前,Restore all要弹出的内核栈栈帧
726 fn setup_sigcontext(
727     context: &mut sigcontext,
728     mask: &sigset_t,
729     regs: &pt_regs,
730 ) -> Result<i32, SystemError> {
731     let current_thread = current_pcb().thread;
732 
733     context.oldmask = *mask;
734     context.regs = regs.clone();
735     context.trap_num = unsafe { (*current_thread).trap_num };
736     context.err_code = unsafe { (*current_thread).err_code };
737     context.cr2 = unsafe { (*current_thread).cr2 };
738     return Ok(0);
739 }
740 
741 /// @brief 将指定的sigcontext恢复到当前进程的内核栈帧中,并将当前线程结构体的几个参数进行恢复
742 ///
743 /// @param context 要被恢复的context
744 /// @param regs 目标栈帧(也就是把context恢复到这个栈帧中)
745 ///
746 /// @return bool true -> 成功恢复
747 ///              false -> 执行失败
748 fn restore_sigcontext(context: *const sigcontext, regs: &mut pt_regs) -> bool {
749     let mut current_thread = current_pcb().thread;
750     unsafe {
751         *regs = (*context).regs;
752 
753         (*current_thread).trap_num = (*context).trap_num;
754         (*current_thread).cr2 = (*context).cr2;
755         (*current_thread).err_code = (*context).err_code;
756 
757         // 如果当前进程有fpstate,则将其恢复到pcb的fp_state中
758         *(current_pcb().fp_state as usize as *mut FpState) = (*context).sc_stack.fpstate;
759     }
760 
761     return true;
762 }
763 
764 /// @brief 刷新指定进程的sighand的sigaction,将满足条件的sigaction恢复为Default
765 ///     除非某个信号被设置为ignore且force_default为false,否则都不会将其恢复
766 ///
767 /// @param pcb 要被刷新的pcb
768 /// @param force_default 是否强制将sigaction恢复成默认状态
769 pub fn flush_signal_handlers(pcb: *mut process_control_block, force_default: bool) {
770     compiler_fence(core::sync::atomic::Ordering::SeqCst);
771 
772     let action = unsafe { &mut (*(*pcb).sighand).action };
773     for ka in action.iter_mut() {
774         if force_default || (ka.sa_flags != SA_FLAG_IGN) {
775             ka.sa_flags = SA_FLAG_DFL;
776             ka._u._sa_handler = None;
777         }
778         // 清除flags中,除了DFL和IGN以外的所有标志
779         ka.sa_flags &= SA_FLAG_DFL | SA_FLAG_IGN;
780         ka.sa_restorer = None;
781         sigset_clear(&mut ka.sa_mask);
782         compiler_fence(core::sync::atomic::Ordering::SeqCst);
783     }
784     compiler_fence(core::sync::atomic::Ordering::SeqCst);
785 }
786 
787 pub fn do_sigaction(
788     sig: SignalNumber,
789     act: Option<&mut sigaction>,
790     old_act: Option<&mut sigaction>,
791 ) -> Result<(), SystemError> {
792     let pcb = current_pcb();
793 
794     // 指向当前信号的action的引用
795     let action =
796         sigaction::convert_mut(unsafe { &mut (*(pcb.sighand)).action[(sig as usize) - 1] })
797             .unwrap();
798 
799     spin_lock_irq(unsafe { &mut (*(pcb.sighand)).siglock });
800 
801     if (action.sa_flags & SA_FLAG_IMMUTABLE) != 0 {
802         spin_unlock_irq(unsafe { &mut (*(pcb.sighand)).siglock });
803         return Err(SystemError::EINVAL);
804     }
805 
806     // 如果需要保存原有的sigaction
807     // 写的这么恶心,还得感谢rust的所有权系统...old_act的所有权被传入了这个闭包之后,必须要把所有权返回给外面。(也许是我不会用才导致写的这么丑,但是它确实能跑)
808     let old_act: Option<&mut sigaction> = {
809         if old_act.is_some() {
810             let oa = old_act.unwrap();
811             *(oa) = *action;
812             Some(oa)
813         } else {
814             None
815         }
816     };
817 
818     // 清除所有的脏的sa_flags位(也就是清除那些未使用的)
819     let act = {
820         if act.is_some() {
821             let ac = act.unwrap();
822             ac.sa_flags &= SA_ALL_FLAGS;
823             Some(ac)
824         } else {
825             None
826         }
827     };
828 
829     if old_act.is_some() {
830         old_act.unwrap().sa_flags &= SA_ALL_FLAGS;
831     }
832 
833     if act.is_some() {
834         let ac = act.unwrap();
835         // 将act.sa_mask的SIGKILL SIGSTOP的屏蔽清除
836         sigset_delmask(
837             &mut ac.sa_mask,
838             sigmask(SignalNumber::SIGKILL) | sigmask(SignalNumber::SIGSTOP),
839         );
840 
841         // 将新的sigaction拷贝到进程的action中
842         *action = *ac;
843 
844         /*
845         * 根据POSIX 3.3.1.3规定:
846         * 1.不管一个信号是否被阻塞,只要将其设置SIG_IGN,如果当前已经存在了正在pending的信号,那么就把这个信号忽略。
847         *
848         * 2.不管一个信号是否被阻塞,只要将其设置SIG_DFL,如果当前已经存在了正在pending的信号,
849               并且对这个信号的默认处理方式是忽略它,那么就会把pending的信号忽略。
850         */
851         if action.ignored(sig) {
852             let mut mask: sigset_t = 0;
853             sigset_clear(&mut mask);
854             sigset_add(&mut mask, sig);
855             let sq: &mut SigQueue = SigQueue::from_c_void(pcb.sig_pending.sigqueue);
856             sq.flush_by_mask(&mask);
857 
858             // todo: 当有了多个线程后,在这里进行操作,把每个线程的sigqueue都进行刷新
859         }
860     }
861 
862     spin_unlock_irq(unsafe { &mut (*(pcb.sighand)).siglock });
863     return Ok(());
864 }
865 
866 /// @brief 对于给定的signal number,将u64中对应的位进行置位
867 pub fn sigmask(sig: SignalNumber) -> u64 {
868     // 减1的原因是,sigset的第0位表示信号1
869     return 1u64 << ((sig as i32) - 1);
870 }
871 
872 pub fn sys_rt_sigreturn(regs: &mut pt_regs) -> u64 {
873     let frame = regs.rsp as usize as *mut sigframe;
874 
875     // 如果当前的rsp不来自用户态,则认为产生了错误(或被SROP攻击)
876     if unsafe { !verify_area(frame as u64, size_of::<sigframe>() as u64) } {
877         // todo:这里改为生成一个sigsegv
878         // 退出进程
879         unsafe {
880             process_do_exit(SignalNumber::SIGSEGV as u64);
881         }
882     }
883 
884     let mut sigmask: sigset_t = unsafe { (*frame).context.oldmask };
885     set_current_sig_blocked(&mut sigmask);
886 
887     // 从用户栈恢复sigcontext
888     if restore_sigcontext(unsafe { &mut (*frame).context }, regs) == false {
889         // todo:这里改为生成一个sigsegv
890         // 退出进程
891         unsafe {
892             process_do_exit(SignalNumber::SIGSEGV as u64);
893         }
894     }
895 
896     // 由于系统调用的返回值会被系统调用模块被存放在rax寄存器,因此,为了还原原来的那个系统调用的返回值,我们需要在这里返回恢复后的rax的值
897     return regs.rax;
898 }
899 
900 fn set_current_sig_blocked(new_set: &mut sigset_t) {
901     sigset_delmask(
902         new_set,
903         sigmask(SignalNumber::SIGKILL) | sigmask(SignalNumber::SIGSTOP),
904     );
905 
906     let mut pcb = current_pcb();
907 
908     /*
909         如果当前pcb的sig_blocked和新的相等,那么就不用改变它。
910         请注意,一个进程的sig_blocked字段不能被其他进程修改!
911     */
912     if sigset_equal(&pcb.sig_blocked, new_set) {
913         return;
914     }
915 
916     let lock: &mut spinlock_t = &mut sighand_struct::convert_mut(pcb.sighand).unwrap().siglock;
917     spin_lock_irq(lock);
918     // todo: 当一个进程有多个线程后,在这里需要设置每个线程的block字段,并且 retarget_shared_pending(虽然我还没搞明白linux这部分是干啥的)
919 
920     // 设置当前进程的sig blocked
921     pcb.sig_blocked = *new_set;
922     recalc_sigpending();
923     spin_unlock_irq(lock);
924 }
925