ia32_signal.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:14k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/arch/x86_64/ia32/ia32_signal.c
  3.  *
  4.  *  Copyright (C) 1991, 1992  Linus Torvalds
  5.  *
  6.  *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson
  7.  *  2000-06-20  Pentium III FXSR, SSE support by Gareth Hughes
  8.  *  2000-12-*   x86-64 compatibility mode signal handling by Andi Kleen
  9.  * 
  10.  *  $Id: ia32_signal.c,v 1.22 2002/07/29 10:34:03 ak Exp $
  11.  */
  12. #include <linux/sched.h>
  13. #include <linux/mm.h>
  14. #include <linux/smp.h>
  15. #include <linux/smp_lock.h>
  16. #include <linux/kernel.h>
  17. #include <linux/signal.h>
  18. #include <linux/errno.h>
  19. #include <linux/wait.h>
  20. #include <linux/ptrace.h>
  21. #include <linux/unistd.h>
  22. #include <linux/stddef.h>
  23. #include <linux/personality.h>
  24. #include <asm/ucontext.h>
  25. #include <asm/uaccess.h>
  26. #include <asm/i387.h>
  27. #include <asm/ia32.h>
  28. #include <asm/ptrace.h>
  29. #include <asm/ia32_unistd.h>
  30. #include <asm/user32.h>
  31. #include <asm/sigcontext32.h>
  32. #include <asm/fpu32.h>
  33. #define ptr_to_u32(x) ((u32)(u64)(x)) /* avoid gcc warning */ 
  34. #define DEBUG_SIG 0
  35. #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
  36. asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
  37. void signal_fault(struct pt_regs *regs, void *frame, char *where);
  38. static int ia32_copy_siginfo_to_user(siginfo_t32 *to, siginfo_t *from)
  39. {
  40. if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
  41. return -EFAULT;
  42. if (from->si_code < 0)
  43. return __copy_to_user(to, from, sizeof(siginfo_t));
  44. else {
  45. int err;
  46. /* If you change siginfo_t structure, please be sure
  47.    this code is fixed accordingly.
  48.    It should never copy any pad contained in the structure
  49.    to avoid security leaks, but must copy the generic
  50.    3 ints plus the relevant union member.  */
  51. err = __put_user(from->si_signo, &to->si_signo);
  52. err |= __put_user(from->si_errno, &to->si_errno);
  53. err |= __put_user((short)from->si_code, &to->si_code);
  54. /* First 32bits of unions are always present.  */
  55. err |= __put_user(from->si_pid, &to->si_pid);
  56. switch (from->si_code >> 16) {
  57. case __SI_FAULT >> 16:
  58. break;
  59. case __SI_CHLD >> 16:
  60. err |= __put_user(from->si_utime, &to->si_utime);
  61. err |= __put_user(from->si_stime, &to->si_stime);
  62. err |= __put_user(from->si_status, &to->si_status);
  63. default:
  64. err |= __put_user(from->si_uid, &to->si_uid);
  65. break;
  66. /* case __SI_RT: This is not generated by the kernel as of now.  */
  67. }
  68. return err;
  69. }
  70. }
  71. asmlinkage int
  72. sys32_sigsuspend(int history0, int history1, old_sigset_t mask, struct pt_regs regs)
  73. {
  74. sigset_t saveset;
  75. mask &= _BLOCKABLE;
  76. spin_lock_irq(&current->sigmask_lock);
  77. saveset = current->blocked;
  78. siginitset(&current->blocked, mask);
  79. recalc_sigpending(current);
  80. spin_unlock_irq(&current->sigmask_lock);
  81. regs.rax = -EINTR;
  82. while (1) {
  83. current->state = TASK_INTERRUPTIBLE;
  84. schedule();
  85. if (do_signal(&regs, &saveset))
  86. return -EINTR;
  87. }
  88. }
  89. asmlinkage int
  90. sys32_sigaltstack(const stack_ia32_t *uss_ptr, stack_ia32_t *uoss_ptr, 
  91.   struct pt_regs regs)
  92. {
  93. stack_t uss,uoss; 
  94. int ret;
  95. mm_segment_t seg; 
  96. if (!access_ok(VERIFY_READ,uss_ptr,sizeof(stack_ia32_t)) ||
  97.     __get_user(ptr_to_u32(uss.ss_sp), &uss_ptr->ss_sp) ||
  98.     __get_user((u32)uss.ss_flags, &uss_ptr->ss_flags) ||
  99.     __get_user((u32)uss.ss_size, &uss_ptr->ss_size))
  100. return -EFAULT;
  101. seg = get_fs(); 
  102. set_fs(KERNEL_DS); 
  103. ret = do_sigaltstack(&uss, &uoss, regs.rsp);
  104. set_fs(seg); 
  105. if (ret >= 0 && uoss_ptr)  {
  106. if (!access_ok(VERIFY_WRITE,uss_ptr,sizeof(stack_ia32_t)) ||
  107.     __put_user(ptr_to_u32(uss.ss_sp), &uss_ptr->ss_sp) ||
  108.     __put_user((u32)uss.ss_flags, &uss_ptr->ss_flags) ||
  109.     __put_user((u32)uss.ss_size, &uss_ptr->ss_size))
  110. ret = -EFAULT;
  111. return ret;
  112. }
  113. /*
  114.  * Do a signal return; undo the signal stack.
  115.  */
  116. struct sigframe
  117. {
  118. u32 pretcode;
  119. int sig;
  120. struct sigcontext_ia32 sc;
  121. struct _fpstate_ia32 fpstate;
  122. unsigned int extramask[_IA32_NSIG_WORDS-1];
  123. char retcode[8];
  124. };
  125. struct rt_sigframe
  126. {
  127. u32 pretcode;
  128. int sig;
  129. u32 pinfo;
  130. u32 puc;
  131. struct siginfo32 info;
  132. struct ucontext_ia32 uc;
  133. struct _fpstate_ia32 fpstate;
  134. char retcode[8];
  135. };
  136. static int
  137. ia32_restore_sigcontext(struct pt_regs *regs, struct sigcontext_ia32 *sc, unsigned int *peax)
  138. {
  139. unsigned int err = 0;
  140. #if DEBUG_SIG
  141. printk("SIG restore_sigcontext: sc=%p err(%x) eip(%x) cs(%x) flg(%x)n",
  142. sc, sc->err, sc->eip, sc->cs, sc->eflags);
  143. #endif
  144. #define COPY(x) { 
  145. unsigned int reg;
  146. err |= __get_user(reg, &sc->e ##x);
  147. regs->r ## x = reg;
  148. }
  149. #define RELOAD_SEG(seg,mask)
  150. { unsigned int cur; 
  151.   unsigned short pre;
  152.   err |= __get_user(pre, &sc->seg);
  153.        asm volatile("movl %%" #seg ",%0" : "=r" (cur));
  154.   pre |= mask; 
  155.   if (pre != cur) loadsegment(seg,pre); }
  156. /* Reload fs and gs if they have changed in the signal handler.
  157.    This does not handle long fs/gs base changes in the handler, but 
  158.    does not clobber them at least in the normal case. */ 
  159. {
  160. unsigned short gs; 
  161. err |= __get_user(gs, &sc->gs);
  162. load_gs_index(gs); 
  163. RELOAD_SEG(fs,0);
  164. RELOAD_SEG(ds,0);
  165. RELOAD_SEG(es,0);
  166. COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
  167. COPY(dx); COPY(cx); COPY(ip);
  168. /* Don't touch extended registers */ 
  169. #if 1 /* not ready for this yet */ 
  170. err |= __get_user(regs->cs, &sc->cs); 
  171. regs->cs |= 2; 
  172. err |= __get_user(regs->ss, &sc->ss); 
  173. regs->ss |= 2; 
  174. #else
  175. regs->cs = __USER32_CS;
  176. regs->ss = __USER32_DS; 
  177. #endif
  178. {
  179. unsigned int tmpflags;
  180. err |= __get_user(tmpflags, &sc->eflags);
  181. regs->eflags = (regs->eflags & ~0x40DD5) | (tmpflags & 0x40DD5);
  182. regs->orig_rax = -1; /* disable syscall checks */
  183. }
  184. {
  185. u32 tmp;
  186. struct _fpstate_ia32 * buf;
  187. err |= __get_user(tmp, &sc->fpstate);
  188. buf = (struct _fpstate_ia32 *) (u64)tmp;
  189. if (buf) {
  190. if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
  191. goto badframe;
  192. err |= restore_i387_ia32(current, buf, 0);
  193. }
  194. }
  195. u32 tmp;
  196. err |= __get_user(tmp, &sc->eax);
  197. *peax = tmp;
  198. }
  199. return err;
  200. badframe:
  201. return 1;
  202. }
  203. asmlinkage int sys32_sigreturn(struct pt_regs regs)
  204. {
  205. struct sigframe *frame = (struct sigframe *)(regs.rsp - 8);
  206. sigset_t set;
  207. unsigned int eax;
  208. if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
  209. goto badframe;
  210. if (__get_user(set.sig[0], &frame->sc.oldmask)
  211.     || (_IA32_NSIG_WORDS > 1
  212. && __copy_from_user((((char *) &set.sig) + 4), &frame->extramask,
  213.     sizeof(frame->extramask))))
  214. goto badframe;
  215. sigdelsetmask(&set, ~_BLOCKABLE);
  216. spin_lock_irq(&current->sigmask_lock);
  217. current->blocked = set;
  218. recalc_sigpending(current);
  219. spin_unlock_irq(&current->sigmask_lock);
  220. if (ia32_restore_sigcontext(&regs, &frame->sc, &eax))
  221. goto badframe;
  222. return eax;
  223. badframe:
  224. signal_fault(&regs,frame,"32bit sigreturn");
  225. return 0;
  226. }
  227. asmlinkage int sys32_rt_sigreturn(struct pt_regs regs)
  228. {
  229. struct rt_sigframe *frame = (struct rt_sigframe *)(regs.rsp - 4);
  230. sigset_t set;
  231. stack_t st;
  232. unsigned int eax;
  233. if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
  234. goto badframe;
  235. if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
  236. goto badframe;
  237. sigdelsetmask(&set, ~_BLOCKABLE);
  238. spin_lock_irq(&current->sigmask_lock);
  239. current->blocked = set;
  240. recalc_sigpending(current);
  241. spin_unlock_irq(&current->sigmask_lock);
  242. if (ia32_restore_sigcontext(&regs, &frame->uc.uc_mcontext, &eax))
  243. goto badframe;
  244. if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
  245. goto badframe;
  246. /* It is more difficult to avoid calling this function than to
  247.    call it and ignore errors.  */
  248. {
  249. mm_segment_t oldds = get_fs(); 
  250. set_fs(KERNEL_DS); 
  251. do_sigaltstack(&st, NULL, regs.rsp);
  252. set_fs(oldds);  
  253. }
  254. return eax;
  255. badframe:
  256. signal_fault(&regs,frame,"32bit rt sigreturn");
  257. return 0;
  258. }
  259. /*
  260.  * Set up a signal frame.
  261.  */
  262. static int
  263. ia32_setup_sigcontext(struct sigcontext_ia32 *sc, struct _fpstate_ia32 *fpstate,
  264.  struct pt_regs *regs, unsigned int mask)
  265. {
  266. int tmp, err = 0;
  267. tmp = 0;
  268. __asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp));
  269. err |= __put_user(tmp, (unsigned int *)&sc->gs);
  270. __asm__("movl %%fs,%0" : "=r"(tmp): "0"(tmp));
  271. err |= __put_user(tmp, (unsigned int *)&sc->fs);
  272. __asm__("movl %%ds,%0" : "=r"(tmp): "0"(tmp));
  273. err |= __put_user(tmp, (unsigned int *)&sc->ds);
  274. __asm__("movl %%es,%0" : "=r"(tmp): "0"(tmp));
  275. err |= __put_user(tmp, (unsigned int *)&sc->es);
  276. err |= __put_user((u32)regs->rdi, &sc->edi);
  277. err |= __put_user((u32)regs->rsi, &sc->esi);
  278. err |= __put_user((u32)regs->rbp, &sc->ebp);
  279. err |= __put_user((u32)regs->rsp, &sc->esp);
  280. err |= __put_user((u32)regs->rbx, &sc->ebx);
  281. err |= __put_user((u32)regs->rdx, &sc->edx);
  282. err |= __put_user((u32)regs->rcx, &sc->ecx);
  283. err |= __put_user((u32)regs->rax, &sc->eax);
  284. err |= __put_user((u32)regs->cs, &sc->cs); 
  285. err |= __put_user((u32)regs->ss, &sc->ss); 
  286. err |= __put_user(current->thread.trap_no, &sc->trapno);
  287. err |= __put_user(current->thread.error_code, &sc->err);
  288. err |= __put_user((u32)regs->rip, &sc->eip);
  289. err |= __put_user((u32)regs->eflags, &sc->eflags);
  290. err |= __put_user((u32)regs->rsp, &sc->esp_at_signal);
  291. tmp = save_i387_ia32(current, fpstate, regs, 0);
  292. if (tmp < 0)
  293.   err = -EFAULT;
  294. else
  295.   err |= __put_user((u32)(u64)(tmp ? fpstate : NULL), &sc->fpstate);
  296. /* non-iBCS2 extensions.. */
  297. err |= __put_user(mask, &sc->oldmask);
  298. err |= __put_user(current->thread.cr2, &sc->cr2);
  299. return err;
  300. }
  301. /*
  302.  * Determine which stack to use..
  303.  */
  304. static inline void *
  305. get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
  306. {
  307. unsigned long rsp;
  308. /* Default to using normal stack */
  309. rsp = regs->rsp;
  310. /* This is the X/Open sanctioned signal stack switching.  */
  311. if (ka->sa.sa_flags & SA_ONSTACK) {
  312. if (! on_sig_stack(rsp))
  313. rsp = current->sas_ss_sp + current->sas_ss_size;
  314. }
  315. /* This is the legacy signal stack switching. */
  316. else if ((regs->ss & 0xffff) != __USER_DS &&
  317. !(ka->sa.sa_flags & SA_RESTORER) &&
  318.  ka->sa.sa_restorer) {
  319. rsp = (unsigned long) ka->sa.sa_restorer;
  320. }
  321. return (void *)((rsp - frame_size) & -8UL);
  322. }
  323. void ia32_setup_frame(int sig, struct k_sigaction *ka,
  324. sigset32_t *set, struct pt_regs * regs)
  325. {
  326. struct sigframe *frame;
  327. int err = 0;
  328. frame = get_sigframe(ka, regs, sizeof(*frame));
  329. if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
  330. goto give_sigsegv;
  331. err |= __put_user((current->exec_domain
  332.            && current->exec_domain->signal_invmap
  333.            && sig < 32
  334.            ? current->exec_domain->signal_invmap[sig]
  335.            : sig),
  336.           &frame->sig);
  337. if (err)
  338. goto give_sigsegv;
  339. err |= ia32_setup_sigcontext(&frame->sc, &frame->fpstate, regs, set->sig[0]);
  340. if (err)
  341. goto give_sigsegv;
  342. if (_IA32_NSIG_WORDS > 1) {
  343. err |= __copy_to_user(frame->extramask, &set->sig[1],
  344.       sizeof(frame->extramask));
  345. }
  346. if (err)
  347. goto give_sigsegv;
  348. /* Set up to return from userspace.  If provided, use a stub
  349.    already in userspace.  */
  350. if (ka->sa.sa_flags & SA_RESTORER) {
  351. err |= __put_user((u32)(u64)ka->sa.sa_restorer, &frame->pretcode);
  352. } else {
  353. err |= __put_user((u32)(u64)frame->retcode, &frame->pretcode);
  354. /* This is popl %eax ; movl $,%eax ; int $0x80 */
  355. err |= __put_user((u16)0xb858, (short *)(frame->retcode+0));
  356. err |= __put_user((u32)__NR_ia32_sigreturn, (int *)(frame->retcode+2));
  357. err |= __put_user((u16)0x80cd, (short *)(frame->retcode+6));
  358. }
  359. if (err)
  360. goto give_sigsegv;
  361. /* Set up registers for signal handler */
  362. regs->rsp = (unsigned long) frame;
  363. regs->rip = (unsigned long) ka->sa.sa_handler;
  364. asm volatile("movl %0,%%ds" :: "r" (__USER32_DS)); 
  365. asm volatile("movl %0,%%es" :: "r" (__USER32_DS)); 
  366. regs->cs = __USER32_CS; 
  367. regs->ss = __USER32_DS; 
  368. set_fs(USER_DS);
  369. regs->eflags &= ~TF_MASK;
  370. #if DEBUG_SIG
  371. printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%pn",
  372. current->comm, current->pid, frame, regs->rip, frame->pretcode);
  373. #endif
  374. return;
  375. give_sigsegv:
  376. if (sig == SIGSEGV)
  377. ka->sa.sa_handler = SIG_DFL;
  378. signal_fault(regs,frame,"32bit signal deliver");
  379. }
  380. void ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
  381.    sigset32_t *set, struct pt_regs * regs)
  382. {
  383. struct rt_sigframe *frame;
  384. int err = 0;
  385. frame = get_sigframe(ka, regs, sizeof(*frame));
  386. if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
  387. goto give_sigsegv;
  388. err |= __put_user((current->exec_domain
  389.         && current->exec_domain->signal_invmap
  390.         && sig < 32
  391.         ? current->exec_domain->signal_invmap[sig]
  392.    : sig),
  393.   &frame->sig);
  394. err |= __put_user((u32)(u64)&frame->info, &frame->pinfo);
  395. err |= __put_user((u32)(u64)&frame->uc, &frame->puc);
  396. err |= ia32_copy_siginfo_to_user(&frame->info, info);
  397. if (err)
  398. goto give_sigsegv;
  399. /* Create the ucontext.  */
  400. err |= __put_user(0, &frame->uc.uc_flags);
  401. err |= __put_user(0, &frame->uc.uc_link);
  402. err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
  403. err |= __put_user(sas_ss_flags(regs->rsp),
  404.   &frame->uc.uc_stack.ss_flags);
  405. err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
  406. err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, &frame->fpstate,
  407.         regs, set->sig[0]);
  408. err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
  409. if (err)
  410. goto give_sigsegv;
  411. /* Set up to return from userspace.  If provided, use a stub
  412.    already in userspace.  */
  413. if (ka->sa.sa_flags & SA_RESTORER) {
  414. err |= __put_user((u32)(u64)ka->sa.sa_restorer, &frame->pretcode);
  415. } else {
  416. err |= __put_user(ptr_to_u32(frame->retcode), &frame->pretcode);
  417. /* This is movl $,%eax ; int $0x80 */
  418. err |= __put_user(0xb8, (char *)(frame->retcode+0));
  419. err |= __put_user((u32)__NR_ia32_rt_sigreturn, (int *)(frame->retcode+1));
  420. err |= __put_user(0x80cd, (short *)(frame->retcode+5));
  421. }
  422. if (err)
  423. goto give_sigsegv;
  424. /* Set up registers for signal handler */
  425. regs->rsp = (unsigned long) frame;
  426. regs->rip = (unsigned long) ka->sa.sa_handler;
  427. asm volatile("movl %0,%%ds" :: "r" (__USER32_DS)); 
  428. asm volatile("movl %0,%%es" :: "r" (__USER32_DS)); 
  429. regs->cs = __USER32_CS; 
  430. regs->ss = __USER32_DS; 
  431. set_fs(USER_DS);
  432. regs->eflags &= ~TF_MASK;
  433. #if DEBUG_SIG
  434. printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%pn",
  435. current->comm, current->pid, frame, regs->rip, frame->pretcode);
  436. #endif
  437. return;
  438. give_sigsegv:
  439. if (sig == SIGSEGV)
  440. ka->sa.sa_handler = SIG_DFL;
  441. signal_fault(regs,frame,"32bit rt signal deliver");
  442. }