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) 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 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] 110 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 信号的接收者 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: u64 = 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的可变引用 154 fn lock_process_sighand<'a>( 155 pcb: &'a mut process_control_block, 156 flags: &mut u64, 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寄存器中 178 fn unlock_process_sighand(pcb: &mut process_control_block, flags: u64) { 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 错误码 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 错误码 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字段代表的含义 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] 310 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] 339 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] 358 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] 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 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] 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结构体 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 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,则无效 520 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位 540 fn recalc_sigpending() { 541 // todo: 542 } 543 544 /// @brief 收集信号的信息 545 /// 546 /// @param sig 要收集的信号的信息 547 /// @param pending 信号的排队等待标志 548 /// @return siginfo 信号的信息 549 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) 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要弹出的内核栈栈帧 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)] 691 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结构体拷贝到用户栈 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要弹出的内核栈栈帧 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 -> 执行失败 746 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恢复成默认状态 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 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中对应的位进行置位 865 pub fn sigmask(sig: SignalNumber) -> u64 { 866 // 减1的原因是,sigset的第0位表示信号1 867 return 1u64 << ((sig as i32) - 1); 868 } 869 870 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 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