aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/signal_64.c
diff options
context:
space:
mode:
authorHiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>2008-11-24 21:24:11 -0500
committerIngo Molnar <mingo@elte.hu>2008-11-25 23:11:54 -0500
commite5fa2d063cf2ca38eae5fb3469315db669d5c041 (patch)
treece3deacf11e47bed1066dfa8039a2aa38e117126 /arch/x86/kernel/signal_64.c
parentbfeb91a9435889ef4fe7bfbb4b673f625e69e790 (diff)
x86: signal: unify signal_{32|64}.c, prepare
Impact: cleanup Add #ifdef directive for 32-bit only code. Signed-off-by: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/signal_64.c')
-rw-r--r--arch/x86/kernel/signal_64.c116
1 files changed, 115 insertions, 1 deletions
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c
index 2da7e6e60807..b1f4d34e0a38 100644
--- a/arch/x86/kernel/signal_64.c
+++ b/arch/x86/kernel/signal_64.c
@@ -54,12 +54,24 @@
54 err |= __get_user(regs->x, &sc->x); \ 54 err |= __get_user(regs->x, &sc->x); \
55} 55}
56 56
57#define COPY_SEG(seg) { \
58 unsigned short tmp; \
59 err |= __get_user(tmp, &sc->seg); \
60 regs->seg = tmp; \
61}
62
57#define COPY_SEG_CPL3(seg) { \ 63#define COPY_SEG_CPL3(seg) { \
58 unsigned short tmp; \ 64 unsigned short tmp; \
59 err |= __get_user(tmp, &sc->seg); \ 65 err |= __get_user(tmp, &sc->seg); \
60 regs->seg = tmp | 3; \ 66 regs->seg = tmp | 3; \
61} 67}
62 68
69#define GET_SEG(seg) { \
70 unsigned short tmp; \
71 err |= __get_user(tmp, &sc->seg); \
72 loadsegment(seg, tmp); \
73}
74
63static int 75static int
64restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, 76restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
65 unsigned long *pax) 77 unsigned long *pax)
@@ -472,6 +484,63 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
472#endif /* CONFIG_X86_32 */ 484#endif /* CONFIG_X86_32 */
473 485
474#ifdef CONFIG_X86_32 486#ifdef CONFIG_X86_32
487/*
488 * Atomically swap in the new signal mask, and wait for a signal.
489 */
490asmlinkage int
491sys_sigsuspend(int history0, int history1, old_sigset_t mask)
492{
493 mask &= _BLOCKABLE;
494 spin_lock_irq(&current->sighand->siglock);
495 current->saved_sigmask = current->blocked;
496 siginitset(&current->blocked, mask);
497 recalc_sigpending();
498 spin_unlock_irq(&current->sighand->siglock);
499
500 current->state = TASK_INTERRUPTIBLE;
501 schedule();
502 set_restore_sigmask();
503
504 return -ERESTARTNOHAND;
505}
506
507asmlinkage int
508sys_sigaction(int sig, const struct old_sigaction __user *act,
509 struct old_sigaction __user *oact)
510{
511 struct k_sigaction new_ka, old_ka;
512 int ret;
513
514 if (act) {
515 old_sigset_t mask;
516
517 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
518 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
519 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
520 return -EFAULT;
521
522 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
523 __get_user(mask, &act->sa_mask);
524 siginitset(&new_ka.sa.sa_mask, mask);
525 }
526
527 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
528
529 if (!ret && oact) {
530 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
531 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
532 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
533 return -EFAULT;
534
535 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
536 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
537 }
538
539 return ret;
540}
541#endif /* CONFIG_X86_32 */
542
543#ifdef CONFIG_X86_32
475asmlinkage int sys_sigaltstack(unsigned long bx) 544asmlinkage int sys_sigaltstack(unsigned long bx)
476{ 545{
477 /* 546 /*
@@ -496,6 +565,51 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
496/* 565/*
497 * Do a signal return; undo the signal stack. 566 * Do a signal return; undo the signal stack.
498 */ 567 */
568#ifdef CONFIG_X86_32
569asmlinkage unsigned long sys_sigreturn(unsigned long __unused)
570{
571 struct sigframe __user *frame;
572 struct pt_regs *regs;
573 unsigned long ax;
574 sigset_t set;
575
576 regs = (struct pt_regs *) &__unused;
577 frame = (struct sigframe __user *)(regs->sp - 8);
578
579 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
580 goto badframe;
581 if (__get_user(set.sig[0], &frame->sc.oldmask) || (_NSIG_WORDS > 1
582 && __copy_from_user(&set.sig[1], &frame->extramask,
583 sizeof(frame->extramask))))
584 goto badframe;
585
586 sigdelsetmask(&set, ~_BLOCKABLE);
587 spin_lock_irq(&current->sighand->siglock);
588 current->blocked = set;
589 recalc_sigpending();
590 spin_unlock_irq(&current->sighand->siglock);
591
592 if (restore_sigcontext(regs, &frame->sc, &ax))
593 goto badframe;
594 return ax;
595
596badframe:
597 if (show_unhandled_signals && printk_ratelimit()) {
598 printk("%s%s[%d] bad frame in sigreturn frame:"
599 "%p ip:%lx sp:%lx oeax:%lx",
600 task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG,
601 current->comm, task_pid_nr(current), frame, regs->ip,
602 regs->sp, regs->orig_ax);
603 print_vma_addr(" in ", regs->ip);
604 printk(KERN_CONT "\n");
605 }
606
607 force_sig(SIGSEGV, current);
608
609 return 0;
610}
611#endif /* CONFIG_X86_32 */
612
499static long do_rt_sigreturn(struct pt_regs *regs) 613static long do_rt_sigreturn(struct pt_regs *regs)
500{ 614{
501 struct rt_sigframe __user *frame; 615 struct rt_sigframe __user *frame;
@@ -542,7 +656,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
542#endif /* CONFIG_X86_32 */ 656#endif /* CONFIG_X86_32 */
543 657
544/* 658/*
545 * OK, we're invoking a handler 659 * OK, we're invoking a handler:
546 */ 660 */
547static int signr_convert(int sig) 661static int signr_convert(int sig)
548{ 662{