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] 64 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) 99 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 110 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] 134 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 信号的接收者 146 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的可变引用 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寄存器中 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 错误码 212 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 错误码 241 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字段代表的含义 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] 320 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] 349 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] 368 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] 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 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] 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结构体 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 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,则无效 531 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位 551 fn recalc_sigpending() { 552 // todo: 553 } 554 555 /// @brief 收集信号的信息 556 /// 557 /// @param sig 要收集的信号的信息 558 /// @param pending 信号的排队等待标志 559 /// @return siginfo 信号的信息 560 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) 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要弹出的内核栈栈帧 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)] 684 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结构体拷贝到用户栈 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要弹出的内核栈栈帧 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 -> 执行失败 735 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恢复成默认状态 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] 778 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 881 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中对应的位进行置位 962 pub fn sigmask(sig: SignalNumber) -> u64 { 963 // 减1的原因是,sigset的第0位表示信号1 964 return 1u64 << ((sig as i32) - 1); 965 } 966 967 #[no_mangle] 968 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 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