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