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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  arch/s390/kernel/signal.c
  3.  *
  4.  *  S390 version
  5.  *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  6.  *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
  7.  *
  8.  *    Based on Intel version
  9.  * 
  10.  *  Copyright (C) 1991, 1992  Linus Torvalds
  11.  *
  12.  *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson
  13.  */
  14. #include <linux/config.h>
  15. #include <linux/sched.h>
  16. #include <linux/mm.h>
  17. #include <linux/smp.h>
  18. #include <linux/smp_lock.h>
  19. #include <linux/kernel.h>
  20. #include <linux/signal.h>
  21. #include <linux/errno.h>
  22. #include <linux/wait.h>
  23. #include <linux/ptrace.h>
  24. #include <linux/unistd.h>
  25. #include <linux/stddef.h>
  26. #include <linux/personality.h>
  27. #include <asm/ucontext.h>
  28. #include <asm/uaccess.h>
  29. #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
  30. typedef struct 
  31. {
  32. __u8 callee_used_stack[__SIGNAL_FRAMESIZE];
  33. struct sigcontext sc;
  34. _sigregs sregs;
  35. __u8 retcode[S390_SYSCALL_SIZE];
  36. } sigframe;
  37. typedef struct 
  38. {
  39. __u8 callee_used_stack[__SIGNAL_FRAMESIZE];
  40. __u8 retcode[S390_SYSCALL_SIZE];
  41. struct siginfo info;
  42. struct ucontext uc;
  43. } rt_sigframe;
  44. asmlinkage int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
  45. int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
  46. {
  47. if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
  48. return -EFAULT;
  49. if (from->si_code < 0)
  50. return __copy_to_user(to, from, sizeof(siginfo_t));
  51. else {
  52. int err;
  53. /* If you change siginfo_t structure, please be sure
  54.    this code is fixed accordingly.
  55.    It should never copy any pad contained in the structure
  56.    to avoid security leaks, but must copy the generic
  57.    3 ints plus the relevant union member.  */
  58. err = __put_user(from->si_signo, &to->si_signo);
  59. err |= __put_user(from->si_errno, &to->si_errno);
  60. err |= __put_user((short)from->si_code, &to->si_code);
  61. /* First 64bits of unions are always present.  */
  62. err |= __put_user(from->si_pid, &to->si_pid);
  63. err |= __put_user(from->si_uid, &to->si_uid);
  64. switch (from->si_code >> 16) {
  65. case __SI_CHLD >> 16:
  66. err |= __put_user(from->si_utime, &to->si_utime);
  67. err |= __put_user(from->si_stime, &to->si_stime);
  68. err |= __put_user(from->si_status, &to->si_status);
  69. default:
  70. break;
  71. /* case __SI_RT: This is not generated by the kernel as of now.  */
  72. }
  73. return err;
  74. }
  75. }
  76. /*
  77.  * Atomically swap in the new signal mask, and wait for a signal.
  78.  */
  79. asmlinkage int
  80. sys_sigsuspend(struct pt_regs * regs,int history0, int history1, old_sigset_t mask)
  81. {
  82. sigset_t saveset;
  83. mask &= _BLOCKABLE;
  84. spin_lock_irq(&current->sigmask_lock);
  85. saveset = current->blocked;
  86. siginitset(&current->blocked, mask);
  87. recalc_sigpending(current);
  88. spin_unlock_irq(&current->sigmask_lock);
  89. regs->gprs[2] = -EINTR;
  90. while (1) {
  91. set_current_state(TASK_INTERRUPTIBLE);
  92. schedule();
  93. if (do_signal(regs, &saveset))
  94. return -EINTR;
  95. }
  96. }
  97. asmlinkage int
  98. sys_rt_sigsuspend(struct pt_regs * regs,sigset_t *unewset, size_t sigsetsize)
  99. {
  100. sigset_t saveset, newset;
  101. /* XXX: Don't preclude handling different sized sigset_t's.  */
  102. if (sigsetsize != sizeof(sigset_t))
  103. return -EINVAL;
  104. if (copy_from_user(&newset, unewset, sizeof(newset)))
  105. return -EFAULT;
  106. sigdelsetmask(&newset, ~_BLOCKABLE);
  107. spin_lock_irq(&current->sigmask_lock);
  108. saveset = current->blocked;
  109. current->blocked = newset;
  110. recalc_sigpending(current);
  111. spin_unlock_irq(&current->sigmask_lock);
  112. regs->gprs[2] = -EINTR;
  113. while (1) {
  114. set_current_state(TASK_INTERRUPTIBLE);
  115. schedule();
  116. if (do_signal(regs, &saveset))
  117. return -EINTR;
  118. }
  119. }
  120. asmlinkage int 
  121. sys_sigaction(int sig, const struct old_sigaction *act,
  122.       struct old_sigaction *oact)
  123. {
  124. struct k_sigaction new_ka, old_ka;
  125. int ret;
  126. if (act) {
  127. old_sigset_t mask;
  128. if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
  129.     __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
  130.     __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
  131. return -EFAULT;
  132. __get_user(new_ka.sa.sa_flags, &act->sa_flags);
  133. __get_user(mask, &act->sa_mask);
  134. siginitset(&new_ka.sa.sa_mask, mask);
  135. }
  136. ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
  137. if (!ret && oact) {
  138. if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
  139.     __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
  140.     __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
  141. return -EFAULT;
  142. __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
  143. __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
  144. }
  145. return ret;
  146. }
  147. asmlinkage int
  148. sys_sigaltstack(const stack_t *uss, stack_t *uoss, struct pt_regs *regs)
  149. {
  150. return do_sigaltstack(uss, uoss, regs->gprs[15]);
  151. }
  152. static int save_sigregs(struct pt_regs *regs,_sigregs *sregs)
  153. {
  154. int err;
  155. s390_fp_regs fpregs;
  156.   
  157. err = __copy_to_user(&sregs->regs,regs,sizeof(_s390_regs_common));
  158. if(!err)
  159. {
  160. save_fp_regs(&fpregs);
  161. err=__copy_to_user(&sregs->fpregs,&fpregs,sizeof(fpregs));
  162. }
  163. return(err);
  164. }
  165. static int restore_sigregs(struct pt_regs *regs,_sigregs *sregs)
  166. {
  167. int err;
  168. s390_fp_regs fpregs;
  169. psw_t saved_psw=regs->psw;
  170. err=__copy_from_user(regs,&sregs->regs,sizeof(_s390_regs_common));
  171. if(!err)
  172. {
  173. regs->trap = -1; /* disable syscall checks */
  174. regs->psw.mask=(saved_psw.mask&~PSW_MASK_DEBUGCHANGE)|
  175. (regs->psw.mask&PSW_MASK_DEBUGCHANGE);
  176. regs->psw.addr=(saved_psw.addr&~PSW_ADDR_DEBUGCHANGE)|
  177. (regs->psw.addr&PSW_ADDR_DEBUGCHANGE);
  178. err=__copy_from_user(&fpregs,&sregs->fpregs,sizeof(fpregs));
  179. if(!err)
  180. restore_fp_regs(&fpregs);
  181. }
  182. return(err);
  183. }
  184. asmlinkage long sys_sigreturn(struct pt_regs *regs)
  185. {
  186. sigframe *frame = (sigframe *)regs->gprs[15];
  187. sigset_t set;
  188. if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
  189. goto badframe;
  190. if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE))
  191. goto badframe;
  192. sigdelsetmask(&set, ~_BLOCKABLE);
  193. spin_lock_irq(&current->sigmask_lock);
  194. current->blocked = set;
  195. recalc_sigpending(current);
  196. spin_unlock_irq(&current->sigmask_lock);
  197. if (restore_sigregs(regs, &frame->sregs))
  198. goto badframe;
  199. return regs->gprs[2];
  200. badframe:
  201. force_sig(SIGSEGV, current);
  202. return 0;
  203. }
  204. asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
  205. {
  206. rt_sigframe *frame = (rt_sigframe *)regs->gprs[15];
  207. sigset_t set;
  208. if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
  209. goto badframe;
  210. if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
  211. goto badframe;
  212. sigdelsetmask(&set, ~_BLOCKABLE);
  213. spin_lock_irq(&current->sigmask_lock);
  214. current->blocked = set;
  215. recalc_sigpending(current);
  216. spin_unlock_irq(&current->sigmask_lock);
  217. if (restore_sigregs(regs, &frame->uc.uc_mcontext))
  218. goto badframe;
  219. /* It is more difficult to avoid calling this function than to
  220.    call it and ignore errors.  */
  221. do_sigaltstack(&frame->uc.uc_stack, NULL, regs->gprs[15]);
  222. return regs->gprs[2];
  223. badframe:
  224. force_sig(SIGSEGV, current);
  225. return 0;
  226. }
  227. /*
  228.  * Set up a signal frame.
  229.  */
  230. /*
  231.  * Determine which stack to use..
  232.  */
  233. static inline void *
  234. get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
  235. {
  236. unsigned long sp;
  237. /* Default to using normal stack */
  238. sp = regs->gprs[15];
  239. /* This is the X/Open sanctioned signal stack switching.  */
  240. if (ka->sa.sa_flags & SA_ONSTACK) {
  241. if (! on_sig_stack(sp))
  242. sp = current->sas_ss_sp + current->sas_ss_size;
  243. }
  244. /* This is the legacy signal stack switching. */
  245. else if (!user_mode(regs) &&
  246.  !(ka->sa.sa_flags & SA_RESTORER) &&
  247.  ka->sa.sa_restorer) {
  248. sp = (unsigned long) ka->sa.sa_restorer;
  249. }
  250. return (void *)((sp - frame_size) & -8ul);
  251. }
  252. static inline int map_signal(int sig)
  253. {
  254. if (current->exec_domain
  255.     && current->exec_domain->signal_invmap
  256.     && sig < 32)
  257. return current->exec_domain->signal_invmap[sig];
  258. else
  259. return sig;
  260. }
  261. static void setup_frame(int sig, struct k_sigaction *ka,
  262. sigset_t *set, struct pt_regs * regs)
  263. {
  264. sigframe *frame = get_sigframe(ka, regs, sizeof(sigframe));
  265. if (!access_ok(VERIFY_WRITE, frame, sizeof(sigframe)))
  266. goto give_sigsegv;
  267. if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE))
  268. goto give_sigsegv;
  269. if (save_sigregs(regs, &frame->sregs))
  270. goto give_sigsegv;
  271. if (__put_user(&frame->sregs, &frame->sc.sregs))
  272. goto give_sigsegv;
  273. /* Set up to return from userspace.  If provided, use a stub
  274.    already in userspace.  */
  275. if (ka->sa.sa_flags & SA_RESTORER) {
  276.                 regs->gprs[14] = FIX_PSW(ka->sa.sa_restorer);
  277. } else {
  278.                 regs->gprs[14] = FIX_PSW(frame->retcode);
  279. if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn, 
  280.                        (u16 *)(frame->retcode)))
  281. goto give_sigsegv;
  282. }
  283. /* Set up backchain. */
  284. if (__put_user(regs->gprs[15], (addr_t *) frame))
  285. goto give_sigsegv;
  286. /* Set up registers for signal handler */
  287. regs->gprs[15] = (addr_t)frame;
  288. regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
  289. regs->psw.mask = _USER_PSW_MASK;
  290. regs->gprs[2] = map_signal(sig);
  291. regs->gprs[3] = (addr_t)&frame->sc;
  292. /* We forgot to include these in the sigcontext.
  293.    To avoid breaking binary compatibility, they are passed as args. */
  294. regs->gprs[4] = current->thread.trap_no;
  295. regs->gprs[5] = current->thread.prot_addr;
  296. return;
  297. give_sigsegv:
  298. if (sig == SIGSEGV)
  299. ka->sa.sa_handler = SIG_DFL;
  300. force_sig(SIGSEGV, current);
  301. }
  302. static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
  303.    sigset_t *set, struct pt_regs * regs)
  304. {
  305. int err = 0;
  306. rt_sigframe *frame = get_sigframe(ka, regs, sizeof(rt_sigframe));
  307. if (!access_ok(VERIFY_WRITE, frame, sizeof(rt_sigframe)))
  308. goto give_sigsegv;
  309. if (copy_siginfo_to_user(&frame->info, info))
  310. goto give_sigsegv;
  311. /* Create the ucontext.  */
  312. err |= __put_user(0, &frame->uc.uc_flags);
  313. err |= __put_user(0, &frame->uc.uc_link);
  314. err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
  315. err |= __put_user(sas_ss_flags(regs->gprs[15]),
  316.   &frame->uc.uc_stack.ss_flags);
  317. err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
  318. err |= save_sigregs(regs, &frame->uc.uc_mcontext);
  319. err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
  320. if (err)
  321. goto give_sigsegv;
  322. /* Set up to return from userspace.  If provided, use a stub
  323.    already in userspace.  */
  324. if (ka->sa.sa_flags & SA_RESTORER) {
  325.                 regs->gprs[14] = FIX_PSW(ka->sa.sa_restorer);
  326. } else {
  327.                 regs->gprs[14] = FIX_PSW(frame->retcode);
  328. err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn, 
  329.                           (u16 *)(frame->retcode));
  330. }
  331. /* Set up backchain. */
  332. if (__put_user(regs->gprs[15], (addr_t *) frame))
  333. goto give_sigsegv;
  334. /* Set up registers for signal handler */
  335. regs->gprs[15] = (addr_t)frame;
  336. regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
  337. regs->psw.mask = _USER_PSW_MASK;
  338. regs->gprs[2] = map_signal(sig);
  339. regs->gprs[3] = (addr_t)&frame->info;
  340. regs->gprs[4] = (addr_t)&frame->uc;
  341. return;
  342. give_sigsegv:
  343. if (sig == SIGSEGV)
  344. ka->sa.sa_handler = SIG_DFL;
  345. force_sig(SIGSEGV, current);
  346. }
  347. /*
  348.  * OK, we're invoking a handler
  349.  */
  350. static void
  351. handle_signal(unsigned long sig, struct k_sigaction *ka,
  352.       siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
  353. {
  354. /* Are we from a system call? */
  355. if (regs->trap == __LC_SVC_OLD_PSW) {
  356. /* If so, check system call restarting.. */
  357. switch (regs->gprs[2]) {
  358. case -ERESTARTNOHAND:
  359. regs->gprs[2] = -EINTR;
  360. break;
  361. case -ERESTARTSYS:
  362. if (!(ka->sa.sa_flags & SA_RESTART)) {
  363. regs->gprs[2] = -EINTR;
  364. break;
  365. }
  366. /* fallthrough */
  367. case -ERESTARTNOINTR:
  368. regs->gprs[2] = regs->orig_gpr2;
  369. regs->psw.addr -= 2;
  370. }
  371. }
  372. /* Set up the stack frame */
  373. if (ka->sa.sa_flags & SA_SIGINFO)
  374. setup_rt_frame(sig, ka, info, oldset, regs);
  375. else
  376. setup_frame(sig, ka, oldset, regs);
  377. if (ka->sa.sa_flags & SA_ONESHOT)
  378. ka->sa.sa_handler = SIG_DFL;
  379. if (!(ka->sa.sa_flags & SA_NODEFER)) {
  380. spin_lock_irq(&current->sigmask_lock);
  381. sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
  382. sigaddset(&current->blocked,sig);
  383. recalc_sigpending(current);
  384. spin_unlock_irq(&current->sigmask_lock);
  385. }
  386. }
  387. /*
  388.  * Note that 'init' is a special process: it doesn't get signals it doesn't
  389.  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  390.  * mistake.
  391.  *
  392.  * Note that we go through the signals twice: once to check the signals that
  393.  * the kernel can handle, and then we build all the user-level signal handling
  394.  * stack-frames in one go after that.
  395.  */
  396. int do_signal(struct pt_regs *regs, sigset_t *oldset)
  397. {
  398. siginfo_t info;
  399. struct k_sigaction *ka;
  400. /*
  401.  * We want the common case to go fast, which
  402.  * is why we may in certain cases get here from
  403.  * kernel mode. Just return without doing anything
  404.  * if so.
  405.  */
  406. if (!user_mode(regs))
  407. return 1;
  408. if (!oldset)
  409. oldset = &current->blocked;
  410. #ifdef CONFIG_S390_SUPPORT 
  411. if (current->thread.flags & S390_FLAG_31BIT) {
  412. extern asmlinkage int do_signal32(struct pt_regs *regs, sigset_t *oldset); 
  413. return do_signal32(regs, oldset);
  414.         }
  415. #endif 
  416. for (;;) {
  417. unsigned long signr;
  418. spin_lock_irq(&current->sigmask_lock);
  419. signr = dequeue_signal(&current->blocked, &info);
  420. spin_unlock_irq(&current->sigmask_lock);
  421. if (!signr)
  422. break;
  423. if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
  424. /* Let the debugger run.  */
  425. current->exit_code = signr;
  426. set_current_state(TASK_STOPPED);
  427. notify_parent(current, SIGCHLD);
  428. schedule();
  429. /* We're back.  Did the debugger cancel the sig?  */
  430. if (!(signr = current->exit_code))
  431. continue;
  432. current->exit_code = 0;
  433. /* The debugger continued.  Ignore SIGSTOP.  */
  434. if (signr == SIGSTOP)
  435. continue;
  436. /* Update the siginfo structure.  Is this good?  */
  437. if (signr != info.si_signo) {
  438. info.si_signo = signr;
  439. info.si_errno = 0;
  440. info.si_code = SI_USER;
  441. info.si_pid = current->p_pptr->pid;
  442. info.si_uid = current->p_pptr->uid;
  443. }
  444. /* If the (new) signal is now blocked, requeue it.  */
  445. if (sigismember(&current->blocked, signr)) {
  446. send_sig_info(signr, &info, current);
  447. continue;
  448. }
  449. }
  450. ka = &current->sig->action[signr-1];
  451. if (ka->sa.sa_handler == SIG_IGN) {
  452. if (signr != SIGCHLD)
  453. continue;
  454. /* Check for SIGCHLD: it's special.  */
  455. while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
  456. /* nothing */;
  457. continue;
  458. }
  459. if (ka->sa.sa_handler == SIG_DFL) {
  460. int exit_code = signr;
  461. /* Init gets no signals it doesn't want.  */
  462. if (current->pid == 1)
  463. continue;
  464. switch (signr) {
  465. case SIGCONT: case SIGCHLD: case SIGWINCH:
  466. continue;
  467. case SIGTSTP: case SIGTTIN: case SIGTTOU:
  468. if (is_orphaned_pgrp(current->pgrp))
  469. continue;
  470. /* FALLTHRU */
  471. case SIGSTOP: {
  472. struct signal_struct *sig;
  473. set_current_state(TASK_STOPPED);
  474. current->exit_code = signr;
  475. sig = current->p_pptr->sig;
  476. if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
  477. notify_parent(current, SIGCHLD);
  478. schedule();
  479. continue;
  480. }
  481. case SIGQUIT: case SIGILL: case SIGTRAP:
  482. case SIGABRT: case SIGFPE: case SIGSEGV:
  483. case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
  484.                                 if (do_coredump(signr, regs))
  485.                                         exit_code |= 0x80;
  486.                                 /* FALLTHRU */
  487. default:
  488. sigaddset(&current->pending.signal, signr);
  489. recalc_sigpending(current);
  490. current->flags |= PF_SIGNALED;
  491. do_exit(exit_code);
  492. /* NOTREACHED */
  493. }
  494. }
  495. /* Whee!  Actually deliver the signal.  */
  496. handle_signal(signr, ka, &info, oldset, regs);
  497. return 1;
  498. }
  499. /* Did we come from a system call? */
  500. if ( regs->trap == __LC_SVC_OLD_PSW /* System Call! */ ) {
  501. /* Restart the system call - no handlers present */
  502. if (regs->gprs[2] == -ERESTARTNOHAND ||
  503.     regs->gprs[2] == -ERESTARTSYS ||
  504.     regs->gprs[2] == -ERESTARTNOINTR) {
  505. regs->gprs[2] = regs->orig_gpr2;
  506. regs->psw.addr -= 2;
  507. }
  508. }
  509. return 0;
  510. }