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