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