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