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