signal.rs 32 KB

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