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