signal.rs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. use core::{ffi::c_void, intrinsics::unlikely, mem::size_of};
  2. use defer::defer;
  3. use log::error;
  4. use system_error::SystemError;
  5. pub use crate::ipc::generic_signal::AtomicGenericSignal as AtomicSignal;
  6. pub use crate::ipc::generic_signal::GenericSigChildCode as SigChildCode;
  7. pub use crate::ipc::generic_signal::GenericSigSet as SigSet;
  8. pub use crate::ipc::generic_signal::GenericSignal as Signal;
  9. use crate::{
  10. arch::{
  11. fpu::FpState,
  12. interrupt::TrapFrame,
  13. process::table::{USER_CS, USER_DS},
  14. syscall::nr::SYS_RESTART_SYSCALL,
  15. CurrentIrqArch, MMArch,
  16. },
  17. exception::InterruptArch,
  18. ipc::{
  19. signal::{restore_saved_sigmask, set_current_blocked},
  20. signal_types::{SaHandlerType, SigInfo, Sigaction, SigactionType, SignalArch},
  21. },
  22. mm::MemoryManagementArch,
  23. process::ProcessManager,
  24. syscall::user_access::UserBufferWriter,
  25. };
  26. /// 信号处理的栈的栈指针的最小对齐数量
  27. pub const STACK_ALIGN: u64 = 16;
  28. /// 信号最大值
  29. pub const MAX_SIG_NUM: usize = 64;
  30. /// siginfo中的si_code的可选值
  31. /// 请注意,当这个值小于0时,表示siginfo来自用户态,否则来自内核态
  32. #[derive(Copy, Debug, Clone)]
  33. #[repr(i32)]
  34. pub enum SigCode {
  35. /// sent by kill, sigsend, raise
  36. User = 0,
  37. /// sent by kernel from somewhere
  38. Kernel = 0x80,
  39. /// 通过sigqueue发送
  40. Queue = -1,
  41. /// 定时器过期时发送
  42. Timer = -2,
  43. /// 当实时消息队列的状态发生改变时发送
  44. Mesgq = -3,
  45. /// 当异步IO完成时发送
  46. AsyncIO = -4,
  47. /// sent by queued SIGIO
  48. SigIO = -5,
  49. }
  50. impl SigCode {
  51. /// 为SigCode这个枚举类型实现从i32转换到枚举类型的转换函数
  52. #[allow(dead_code)]
  53. pub fn from_i32(x: i32) -> SigCode {
  54. match x {
  55. 0 => Self::User,
  56. 0x80 => Self::Kernel,
  57. -1 => Self::Queue,
  58. -2 => Self::Timer,
  59. -3 => Self::Mesgq,
  60. -4 => Self::AsyncIO,
  61. -5 => Self::SigIO,
  62. _ => panic!("signal code not valid"),
  63. }
  64. }
  65. }
  66. bitflags! {
  67. #[repr(C,align(8))]
  68. #[derive(Default)]
  69. pub struct SigFlags:u32{
  70. const SA_NOCLDSTOP = 1;
  71. const SA_NOCLDWAIT = 2;
  72. const SA_SIGINFO = 4;
  73. const SA_ONSTACK = 0x08000000;
  74. const SA_RESTART = 0x10000000;
  75. const SA_NODEFER = 0x40000000;
  76. const SA_RESETHAND = 0x80000000;
  77. const SA_RESTORER =0x04000000;
  78. const SA_ALL = Self::SA_NOCLDSTOP.bits()|Self::SA_NOCLDWAIT.bits()|Self::SA_NODEFER.bits()|Self::SA_ONSTACK.bits()|Self::SA_RESETHAND.bits()|Self::SA_RESTART.bits()|Self::SA_SIGINFO.bits()|Self::SA_RESTORER.bits();
  79. }
  80. }
  81. #[repr(C, align(16))]
  82. #[derive(Debug, Clone, Copy)]
  83. pub struct SigFrame {
  84. // pub pedding: u64,
  85. /// 指向restorer的地址的指针。(该变量必须放在sigframe的第一位,因为这样才能在handler返回的时候,跳转到对应的代码,执行sigreturn)
  86. pub ret_code_ptr: *mut core::ffi::c_void,
  87. pub handler: *mut c_void,
  88. pub info: SigInfo,
  89. pub context: SigContext,
  90. }
  91. #[repr(C, align(16))]
  92. #[derive(Debug, Clone, Copy)]
  93. pub struct SigContext {
  94. /// sigcontext的标志位
  95. pub sc_flags: u64,
  96. pub sc_stack: SigStack, // 信号处理程序备用栈信息
  97. pub frame: TrapFrame, // 暂存的系统调用/中断返回时,原本要弹出的内核栈帧
  98. // pub trap_num: u64, // 用来保存线程结构体中的trap_num字段
  99. pub oldmask: SigSet, // 暂存的执行信号处理函数之前的,被设置block的信号
  100. pub cr2: u64, // 用来保存线程结构体中的cr2字段
  101. // pub err_code: u64, // 用来保存线程结构体中的err_code字段
  102. pub reserved_for_x87_state: Option<FpState>,
  103. pub reserved: [u64; 8],
  104. }
  105. impl SigContext {
  106. /// 设置sigcontext
  107. ///
  108. /// ## 参数
  109. ///
  110. /// - `mask` 要被暂存的信号mask标志位
  111. /// - `regs` 进入信号处理流程前,Restore all要弹出的内核栈栈帧
  112. ///
  113. /// ## 返回值
  114. ///
  115. /// - `Ok(0)`
  116. /// - `Err(Systemerror)` (暂时不会返回错误)
  117. pub fn setup_sigcontext(
  118. &mut self,
  119. mask: &SigSet,
  120. frame: &TrapFrame,
  121. ) -> Result<i32, SystemError> {
  122. //TODO 引入线程后补上
  123. // let current_thread = ProcessManager::current_pcb().thread;
  124. let pcb = ProcessManager::current_pcb();
  125. let mut archinfo_guard = pcb.arch_info_irqsave();
  126. self.oldmask = *mask;
  127. self.frame = *frame;
  128. // context.trap_num = unsafe { (*current_thread).trap_num };
  129. // context.err_code = unsafe { (*current_thread).err_code };
  130. // context.cr2 = unsafe { (*current_thread).cr2 };
  131. self.reserved_for_x87_state = *archinfo_guard.fp_state();
  132. // 保存完毕后,清空fp_state,以免下次save的时候,出现SIMD exception
  133. archinfo_guard.clear_fp_state();
  134. return Ok(0);
  135. }
  136. /// 指定的sigcontext恢复到当前进程的内核栈帧中,并将当前线程结构体的几个参数进行恢复
  137. ///
  138. /// ## 参数
  139. /// - `frame` 目标栈帧(也就是把context恢复到这个栈帧中)
  140. ///
  141. /// ##返回值
  142. /// - `true` -> 成功恢复
  143. /// - `false` -> 执行失败
  144. pub fn restore_sigcontext(&mut self, frame: &mut TrapFrame) -> bool {
  145. let guard = ProcessManager::current_pcb();
  146. let mut arch_info = guard.arch_info_irqsave();
  147. (*frame) = self.frame;
  148. // (*current_thread).trap_num = (*context).trap_num;
  149. *arch_info.cr2_mut() = self.cr2 as usize;
  150. // (*current_thread).err_code = (*context).err_code;
  151. // 如果当前进程有fpstate,则将其恢复到pcb的fp_state中
  152. *arch_info.fp_state_mut() = self.reserved_for_x87_state;
  153. arch_info.restore_fp_state();
  154. return true;
  155. }
  156. }
  157. /// @brief 信号处理备用栈的信息
  158. #[allow(dead_code)]
  159. #[derive(Debug, Clone, Copy)]
  160. pub struct SigStack {
  161. pub sp: *mut c_void,
  162. pub flags: u32,
  163. pub size: u32,
  164. pub fpstate: FpState,
  165. }
  166. unsafe fn do_signal(frame: &mut TrapFrame, got_signal: &mut bool) {
  167. let pcb = ProcessManager::current_pcb();
  168. let siginfo = pcb.try_siginfo_irqsave(5);
  169. if unlikely(siginfo.is_none()) {
  170. return;
  171. }
  172. let siginfo_read_guard = siginfo.unwrap();
  173. // 检查sigpending是否为0
  174. if siginfo_read_guard.sig_pending().signal().bits() == 0 || !frame.is_from_user() {
  175. // 若没有正在等待处理的信号,或者将要返回到的是内核态,则返回
  176. return;
  177. }
  178. let mut sig_number: Signal;
  179. let mut info: Option<SigInfo>;
  180. let mut sigaction: Option<Sigaction>;
  181. let sig_block: SigSet = *siginfo_read_guard.sig_blocked();
  182. drop(siginfo_read_guard);
  183. let sig_guard = pcb.try_sig_struct_irqsave(5);
  184. if unlikely(sig_guard.is_none()) {
  185. return;
  186. }
  187. let siginfo_mut = pcb.try_siginfo_mut(5);
  188. if unlikely(siginfo_mut.is_none()) {
  189. return;
  190. }
  191. let sig_guard = sig_guard.unwrap();
  192. let mut siginfo_mut_guard = siginfo_mut.unwrap();
  193. loop {
  194. (sig_number, info) = siginfo_mut_guard.dequeue_signal(&sig_block, &pcb);
  195. // 如果信号非法,则直接返回
  196. if sig_number == Signal::INVALID {
  197. return;
  198. }
  199. let sa = sig_guard.handlers[sig_number as usize - 1];
  200. match sa.action() {
  201. SigactionType::SaHandler(action_type) => match action_type {
  202. SaHandlerType::Error => {
  203. error!("Trying to handle a Sigerror on Process:{:?}", pcb.pid());
  204. return;
  205. }
  206. SaHandlerType::Default => {
  207. sigaction = Some(sa);
  208. }
  209. SaHandlerType::Ignore => continue,
  210. SaHandlerType::Customized(_) => {
  211. sigaction = Some(sa);
  212. }
  213. },
  214. SigactionType::SaSigaction(_) => todo!(),
  215. }
  216. if sigaction.is_some() {
  217. break;
  218. }
  219. }
  220. let oldset = *siginfo_mut_guard.sig_blocked();
  221. //避免死锁
  222. drop(siginfo_mut_guard);
  223. drop(sig_guard);
  224. drop(pcb);
  225. // 做完上面的检查后,开中断
  226. CurrentIrqArch::interrupt_enable();
  227. if sigaction.is_none() {
  228. return;
  229. }
  230. *got_signal = true;
  231. let mut sigaction = sigaction.unwrap();
  232. // 注意!由于handle_signal里面可能会退出进程,
  233. // 因此这里需要检查清楚:上面所有的锁、arc指针都被释放了。否则会产生资源泄露的问题!
  234. let res: Result<i32, SystemError> =
  235. handle_signal(sig_number, &mut sigaction, &info.unwrap(), &oldset, frame);
  236. if res.is_err() {
  237. error!(
  238. "Error occurred when handling signal: {}, pid={:?}, errcode={:?}",
  239. sig_number as i32,
  240. ProcessManager::current_pcb().pid(),
  241. res.as_ref().unwrap_err()
  242. );
  243. }
  244. }
  245. fn try_restart_syscall(frame: &mut TrapFrame) {
  246. defer!({
  247. // 如果没有信号需要传递,我们只需恢复保存的信号掩码
  248. restore_saved_sigmask();
  249. });
  250. if unsafe { frame.syscall_nr() }.is_none() {
  251. return;
  252. }
  253. let syscall_err = unsafe { frame.syscall_error() };
  254. if syscall_err.is_none() {
  255. return;
  256. }
  257. let syscall_err = syscall_err.unwrap();
  258. let mut restart = false;
  259. match syscall_err {
  260. SystemError::ERESTARTSYS | SystemError::ERESTARTNOHAND | SystemError::ERESTARTNOINTR => {
  261. frame.rax = frame.errcode;
  262. frame.rip -= 2;
  263. restart = true;
  264. }
  265. SystemError::ERESTART_RESTARTBLOCK => {
  266. frame.rax = SYS_RESTART_SYSCALL as u64;
  267. frame.rip -= 2;
  268. restart = true;
  269. }
  270. _ => {}
  271. }
  272. log::debug!("try restart syscall: {:?}", restart);
  273. }
  274. pub struct X86_64SignalArch;
  275. impl SignalArch for X86_64SignalArch {
  276. /// 处理信号,并尝试重启系统调用
  277. ///
  278. /// 参考: https://code.dragonos.org.cn/xref/linux-6.1.9/arch/x86/kernel/signal.c#865
  279. unsafe fn do_signal_or_restart(frame: &mut TrapFrame) {
  280. let mut got_signal = false;
  281. do_signal(frame, &mut got_signal);
  282. if got_signal {
  283. return;
  284. }
  285. try_restart_syscall(frame);
  286. }
  287. fn sys_rt_sigreturn(trap_frame: &mut TrapFrame) -> u64 {
  288. let frame = (trap_frame.rsp as usize - size_of::<u64>()) as *mut SigFrame;
  289. // 如果当前的rsp不来自用户态,则认为产生了错误(或被SROP攻击)
  290. if UserBufferWriter::new(frame, size_of::<SigFrame>(), true).is_err() {
  291. error!("rsp doesn't from user level");
  292. let _r = crate::ipc::kill::kill_process(
  293. ProcessManager::current_pcb().pid(),
  294. Signal::SIGSEGV,
  295. )
  296. .map_err(|e| e.to_posix_errno());
  297. return trap_frame.rax;
  298. }
  299. let mut sigmask: SigSet = unsafe { (*frame).context.oldmask };
  300. set_current_blocked(&mut sigmask);
  301. // 从用户栈恢复sigcontext
  302. if !unsafe { &mut (*frame).context }.restore_sigcontext(trap_frame) {
  303. error!("unable to restore sigcontext");
  304. let _r = crate::ipc::kill::kill_process(
  305. ProcessManager::current_pcb().pid(),
  306. Signal::SIGSEGV,
  307. )
  308. .map_err(|e| e.to_posix_errno());
  309. // 如果这里返回 err 值的话会丢失上一个系统调用的返回值
  310. }
  311. // 由于系统调用的返回值会被系统调用模块被存放在rax寄存器,因此,为了还原原来的那个系统调用的返回值,我们需要在这里返回恢复后的rax的值
  312. return trap_frame.rax;
  313. }
  314. }
  315. /// @brief 真正发送signal,执行自定义的处理函数
  316. ///
  317. /// @param sig 信号number
  318. /// @param sigaction 信号响应动作
  319. /// @param info 信号信息
  320. /// @param oldset
  321. /// @param regs 之前的系统调用将要返回的时候,要弹出的栈帧的拷贝
  322. ///
  323. /// @return Result<0,SystemError> 若Error, 则返回错误码,否则返回Ok(0)
  324. ///
  325. /// 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/arch/x86/kernel/signal.c#787
  326. fn handle_signal(
  327. sig: Signal,
  328. sigaction: &mut Sigaction,
  329. info: &SigInfo,
  330. oldset: &SigSet,
  331. frame: &mut TrapFrame,
  332. ) -> Result<i32, SystemError> {
  333. if unsafe { frame.syscall_nr() }.is_some() {
  334. if let Some(syscall_err) = unsafe { frame.syscall_error() } {
  335. match syscall_err {
  336. SystemError::ERESTARTNOHAND | SystemError::ERESTART_RESTARTBLOCK => {
  337. frame.rax = SystemError::EINTR.to_posix_errno() as i64 as u64;
  338. }
  339. SystemError::ERESTARTSYS => {
  340. if !sigaction.flags().contains(SigFlags::SA_RESTART) {
  341. frame.rax = SystemError::EINTR.to_posix_errno() as i64 as u64;
  342. } else {
  343. frame.rax = frame.errcode;
  344. frame.rip -= 2;
  345. }
  346. }
  347. SystemError::ERESTARTNOINTR => {
  348. frame.rax = frame.errcode;
  349. frame.rip -= 2;
  350. }
  351. _ => {}
  352. }
  353. }
  354. }
  355. // 设置栈帧
  356. return setup_frame(sig, sigaction, info, oldset, frame);
  357. }
  358. /// @brief 在用户栈上开辟一块空间,并且把内核栈的栈帧以及需要在用户态执行的代码给保存进去。
  359. ///
  360. /// @param regs 进入信号处理流程前,Restore all要弹出的内核栈栈帧
  361. fn setup_frame(
  362. sig: Signal,
  363. sigaction: &mut Sigaction,
  364. info: &SigInfo,
  365. oldset: &SigSet,
  366. trap_frame: &mut TrapFrame,
  367. ) -> Result<i32, SystemError> {
  368. let ret_code_ptr: *mut c_void;
  369. let temp_handler: *mut c_void;
  370. match sigaction.action() {
  371. SigactionType::SaHandler(handler_type) => match handler_type {
  372. SaHandlerType::Default => {
  373. sig.handle_default();
  374. return Ok(0);
  375. }
  376. SaHandlerType::Customized(handler) => {
  377. // 如果handler位于内核空间
  378. if handler >= MMArch::USER_END_VADDR {
  379. // 如果当前是SIGSEGV,则采用默认函数处理
  380. if sig == Signal::SIGSEGV {
  381. sig.handle_default();
  382. return Ok(0);
  383. } else {
  384. error!("attempting to execute a signal handler from kernel");
  385. sig.handle_default();
  386. return Err(SystemError::EINVAL);
  387. }
  388. } else {
  389. // 为了与Linux的兼容性,64位程序必须由用户自行指定restorer
  390. if sigaction.flags().contains(SigFlags::SA_RESTORER) {
  391. ret_code_ptr = sigaction.restorer().unwrap().data() as *mut c_void;
  392. } else {
  393. error!(
  394. "pid-{:?} forgot to set SA_FLAG_RESTORER for signal {:?}",
  395. ProcessManager::current_pcb().pid(),
  396. sig as i32
  397. );
  398. let r = crate::ipc::kill::kill_process(
  399. ProcessManager::current_pcb().pid(),
  400. Signal::SIGSEGV,
  401. );
  402. if r.is_err() {
  403. error!("In setup_sigcontext: generate SIGSEGV signal failed");
  404. }
  405. return Err(SystemError::EINVAL);
  406. }
  407. if sigaction.restorer().is_none() {
  408. error!(
  409. "restorer in process:{:?} is not defined",
  410. ProcessManager::current_pcb().pid()
  411. );
  412. return Err(SystemError::EINVAL);
  413. }
  414. temp_handler = handler.data() as *mut c_void;
  415. }
  416. }
  417. SaHandlerType::Ignore => {
  418. return Ok(0);
  419. }
  420. _ => {
  421. return Err(SystemError::EINVAL);
  422. }
  423. },
  424. SigactionType::SaSigaction(_) => {
  425. //TODO 这里应该是可以恢复栈的,等后续来做
  426. error!("trying to recover from sigaction type instead of handler");
  427. return Err(SystemError::EINVAL);
  428. }
  429. }
  430. let frame: *mut SigFrame = get_stack(trap_frame, size_of::<SigFrame>());
  431. // debug!("frame=0x{:016x}", frame as usize);
  432. // 要求这个frame的地址位于用户空间,因此进行校验
  433. let r: Result<UserBufferWriter<'_>, SystemError> =
  434. UserBufferWriter::new(frame, size_of::<SigFrame>(), true);
  435. if r.is_err() {
  436. // 如果地址区域位于内核空间,则直接报错
  437. // todo: 生成一个sigsegv
  438. let r =
  439. crate::ipc::kill::kill_process(ProcessManager::current_pcb().pid(), Signal::SIGSEGV);
  440. if r.is_err() {
  441. error!("In setup frame: generate SIGSEGV signal failed");
  442. }
  443. error!("In setup frame: access check failed");
  444. return Err(SystemError::EFAULT);
  445. }
  446. // 将siginfo拷贝到用户栈
  447. info.copy_siginfo_to_user(unsafe { &mut ((*frame).info) as *mut SigInfo })
  448. .map_err(|e| -> SystemError {
  449. let r = crate::ipc::kill::kill_process(
  450. ProcessManager::current_pcb().pid(),
  451. Signal::SIGSEGV,
  452. );
  453. if r.is_err() {
  454. error!("In copy_siginfo_to_user: generate SIGSEGV signal failed");
  455. }
  456. return e;
  457. })?;
  458. // todo: 拷贝处理程序备用栈的地址、大小、ss_flags
  459. unsafe {
  460. (*frame)
  461. .context
  462. .setup_sigcontext(oldset, trap_frame)
  463. .map_err(|e: SystemError| -> SystemError {
  464. let r = crate::ipc::kill::kill_process(
  465. ProcessManager::current_pcb().pid(),
  466. Signal::SIGSEGV,
  467. );
  468. if r.is_err() {
  469. error!("In setup_sigcontext: generate SIGSEGV signal failed");
  470. }
  471. return e;
  472. })?
  473. };
  474. unsafe {
  475. // 在开头检验过sigaction.restorer是否为空了,实际上libc会保证 restorer始终不为空
  476. (*frame).ret_code_ptr = ret_code_ptr;
  477. }
  478. unsafe { (*frame).handler = temp_handler };
  479. // 传入信号处理函数的第一个参数
  480. trap_frame.rdi = sig as u64;
  481. trap_frame.rsi = unsafe { &(*frame).info as *const SigInfo as u64 };
  482. trap_frame.rsp = frame as u64;
  483. trap_frame.rip = unsafe { (*frame).handler as u64 };
  484. // 设置cs和ds寄存器
  485. trap_frame.cs = (USER_CS.bits() | 0x3) as u64;
  486. trap_frame.ds = (USER_DS.bits() | 0x3) as u64;
  487. // 禁用中断
  488. // trap_frame.rflags &= !(0x200);
  489. return Ok(0);
  490. }
  491. #[inline(always)]
  492. fn get_stack(frame: &TrapFrame, size: usize) -> *mut SigFrame {
  493. // TODO:在 linux 中会根据 Sigaction 中的一个flag 的值来确定是否使用pcb中的 signal 处理程序备用堆栈,现在的
  494. // pcb中也没有这个备用堆栈
  495. // 默认使用 用户栈的栈顶指针-128字节的红区-sigframe的大小 并且16字节对齐
  496. let mut rsp: usize = (frame.rsp as usize) - 128 - size;
  497. // 按照要求进行对齐,别问为什么减8,不减8就是错的,可以看
  498. // https://sourcegraph.com/github.com/torvalds/linux@dd72f9c7e512da377074d47d990564959b772643/-/blob/arch/x86/kernel/signal.c?L124
  499. // 我猜测是跟x86汇编的某些弹栈行为有关系,它可能会出于某种原因递增 rsp
  500. rsp &= (!(STACK_ALIGN - 1)) as usize - 8;
  501. // rsp &= (!(STACK_ALIGN - 1)) as usize;
  502. return rsp as *mut SigFrame;
  503. }