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