Loading arch/x86/kernel/signal_32.c +6 −0 Original line number Diff line number Diff line /* * Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 2000, 2001, 2002 Andi Kleen SuSE Labs * * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson * 2000-06-20 Pentium III FXSR, SSE support by Gareth Hughes * 2000-2002 x86-64 support by Andi Kleen */ #include <linux/sched.h> Loading Loading @@ -481,6 +483,7 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, } #endif /* CONFIG_X86_32 */ #ifdef CONFIG_X86_32 /* * Atomically swap in the new signal mask, and wait for a signal. */ Loading Loading @@ -535,6 +538,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, return ret; } #endif /* CONFIG_X86_32 */ #ifdef CONFIG_X86_32 asmlinkage int sys_sigaltstack(unsigned long bx) Loading @@ -561,6 +565,7 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, /* * Do a signal return; undo the signal stack. */ #ifdef CONFIG_X86_32 asmlinkage unsigned long sys_sigreturn(unsigned long __unused) { struct sigframe __user *frame; Loading Loading @@ -603,6 +608,7 @@ asmlinkage unsigned long sys_sigreturn(unsigned long __unused) return 0; } #endif /* CONFIG_X86_32 */ static long do_rt_sigreturn(struct pt_regs *regs) { Loading arch/x86/kernel/signal_64.c +115 −1 Original line number Diff line number Diff line Loading @@ -54,12 +54,24 @@ err |= __get_user(regs->x, &sc->x); \ } #define COPY_SEG(seg) { \ unsigned short tmp; \ err |= __get_user(tmp, &sc->seg); \ regs->seg = tmp; \ } #define COPY_SEG_CPL3(seg) { \ unsigned short tmp; \ err |= __get_user(tmp, &sc->seg); \ regs->seg = tmp | 3; \ } #define GET_SEG(seg) { \ unsigned short tmp; \ err |= __get_user(tmp, &sc->seg); \ loadsegment(seg, tmp); \ } static int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, unsigned long *pax) Loading Loading @@ -471,6 +483,63 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, } #endif /* CONFIG_X86_32 */ #ifdef CONFIG_X86_32 /* * Atomically swap in the new signal mask, and wait for a signal. */ asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask) { mask &= _BLOCKABLE; spin_lock_irq(¤t->sighand->siglock); current->saved_sigmask = current->blocked; siginitset(¤t->blocked, mask); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); current->state = TASK_INTERRUPTIBLE; schedule(); set_restore_sigmask(); return -ERESTARTNOHAND; } asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user *act, struct old_sigaction __user *oact) { struct k_sigaction new_ka, old_ka; int ret; if (act) { old_sigset_t mask; if (!access_ok(VERIFY_READ, act, sizeof(*act)) || __get_user(new_ka.sa.sa_handler, &act->sa_handler) || __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) return -EFAULT; __get_user(new_ka.sa.sa_flags, &act->sa_flags); __get_user(mask, &act->sa_mask); siginitset(&new_ka.sa.sa_mask, mask); } ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); if (!ret && oact) { if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) return -EFAULT; __put_user(old_ka.sa.sa_flags, &oact->sa_flags); __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); } return ret; } #endif /* CONFIG_X86_32 */ #ifdef CONFIG_X86_32 asmlinkage int sys_sigaltstack(unsigned long bx) { Loading @@ -496,6 +565,51 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, /* * Do a signal return; undo the signal stack. */ #ifdef CONFIG_X86_32 asmlinkage unsigned long sys_sigreturn(unsigned long __unused) { struct sigframe __user *frame; struct pt_regs *regs; unsigned long ax; sigset_t set; regs = (struct pt_regs *) &__unused; frame = (struct sigframe __user *)(regs->sp - 8); if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) goto badframe; if (__get_user(set.sig[0], &frame->sc.oldmask) || (_NSIG_WORDS > 1 && __copy_from_user(&set.sig[1], &frame->extramask, sizeof(frame->extramask)))) goto badframe; sigdelsetmask(&set, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); if (restore_sigcontext(regs, &frame->sc, &ax)) goto badframe; return ax; badframe: if (show_unhandled_signals && printk_ratelimit()) { printk("%s%s[%d] bad frame in sigreturn frame:" "%p ip:%lx sp:%lx oeax:%lx", task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG, current->comm, task_pid_nr(current), frame, regs->ip, regs->sp, regs->orig_ax); print_vma_addr(" in ", regs->ip); printk(KERN_CONT "\n"); } force_sig(SIGSEGV, current); return 0; } #endif /* CONFIG_X86_32 */ static long do_rt_sigreturn(struct pt_regs *regs) { struct rt_sigframe __user *frame; Loading Loading @@ -542,7 +656,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) #endif /* CONFIG_X86_32 */ /* * OK, we're invoking a handler * OK, we're invoking a handler: */ static int signr_convert(int sig) { Loading Loading
arch/x86/kernel/signal_32.c +6 −0 Original line number Diff line number Diff line /* * Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 2000, 2001, 2002 Andi Kleen SuSE Labs * * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson * 2000-06-20 Pentium III FXSR, SSE support by Gareth Hughes * 2000-2002 x86-64 support by Andi Kleen */ #include <linux/sched.h> Loading Loading @@ -481,6 +483,7 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, } #endif /* CONFIG_X86_32 */ #ifdef CONFIG_X86_32 /* * Atomically swap in the new signal mask, and wait for a signal. */ Loading Loading @@ -535,6 +538,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, return ret; } #endif /* CONFIG_X86_32 */ #ifdef CONFIG_X86_32 asmlinkage int sys_sigaltstack(unsigned long bx) Loading @@ -561,6 +565,7 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, /* * Do a signal return; undo the signal stack. */ #ifdef CONFIG_X86_32 asmlinkage unsigned long sys_sigreturn(unsigned long __unused) { struct sigframe __user *frame; Loading Loading @@ -603,6 +608,7 @@ asmlinkage unsigned long sys_sigreturn(unsigned long __unused) return 0; } #endif /* CONFIG_X86_32 */ static long do_rt_sigreturn(struct pt_regs *regs) { Loading
arch/x86/kernel/signal_64.c +115 −1 Original line number Diff line number Diff line Loading @@ -54,12 +54,24 @@ err |= __get_user(regs->x, &sc->x); \ } #define COPY_SEG(seg) { \ unsigned short tmp; \ err |= __get_user(tmp, &sc->seg); \ regs->seg = tmp; \ } #define COPY_SEG_CPL3(seg) { \ unsigned short tmp; \ err |= __get_user(tmp, &sc->seg); \ regs->seg = tmp | 3; \ } #define GET_SEG(seg) { \ unsigned short tmp; \ err |= __get_user(tmp, &sc->seg); \ loadsegment(seg, tmp); \ } static int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, unsigned long *pax) Loading Loading @@ -471,6 +483,63 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, } #endif /* CONFIG_X86_32 */ #ifdef CONFIG_X86_32 /* * Atomically swap in the new signal mask, and wait for a signal. */ asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask) { mask &= _BLOCKABLE; spin_lock_irq(¤t->sighand->siglock); current->saved_sigmask = current->blocked; siginitset(¤t->blocked, mask); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); current->state = TASK_INTERRUPTIBLE; schedule(); set_restore_sigmask(); return -ERESTARTNOHAND; } asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user *act, struct old_sigaction __user *oact) { struct k_sigaction new_ka, old_ka; int ret; if (act) { old_sigset_t mask; if (!access_ok(VERIFY_READ, act, sizeof(*act)) || __get_user(new_ka.sa.sa_handler, &act->sa_handler) || __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) return -EFAULT; __get_user(new_ka.sa.sa_flags, &act->sa_flags); __get_user(mask, &act->sa_mask); siginitset(&new_ka.sa.sa_mask, mask); } ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); if (!ret && oact) { if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) return -EFAULT; __put_user(old_ka.sa.sa_flags, &oact->sa_flags); __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); } return ret; } #endif /* CONFIG_X86_32 */ #ifdef CONFIG_X86_32 asmlinkage int sys_sigaltstack(unsigned long bx) { Loading @@ -496,6 +565,51 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, /* * Do a signal return; undo the signal stack. */ #ifdef CONFIG_X86_32 asmlinkage unsigned long sys_sigreturn(unsigned long __unused) { struct sigframe __user *frame; struct pt_regs *regs; unsigned long ax; sigset_t set; regs = (struct pt_regs *) &__unused; frame = (struct sigframe __user *)(regs->sp - 8); if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) goto badframe; if (__get_user(set.sig[0], &frame->sc.oldmask) || (_NSIG_WORDS > 1 && __copy_from_user(&set.sig[1], &frame->extramask, sizeof(frame->extramask)))) goto badframe; sigdelsetmask(&set, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); current->blocked = set; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); if (restore_sigcontext(regs, &frame->sc, &ax)) goto badframe; return ax; badframe: if (show_unhandled_signals && printk_ratelimit()) { printk("%s%s[%d] bad frame in sigreturn frame:" "%p ip:%lx sp:%lx oeax:%lx", task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG, current->comm, task_pid_nr(current), frame, regs->ip, regs->sp, regs->orig_ax); print_vma_addr(" in ", regs->ip); printk(KERN_CONT "\n"); } force_sig(SIGSEGV, current); return 0; } #endif /* CONFIG_X86_32 */ static long do_rt_sigreturn(struct pt_regs *regs) { struct rt_sigframe __user *frame; Loading Loading @@ -542,7 +656,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) #endif /* CONFIG_X86_32 */ /* * OK, we're invoking a handler * OK, we're invoking a handler: */ static int signr_convert(int sig) { Loading