Commit 3a892a64 authored by Richard Henderson's avatar Richard Henderson

[ALPHA] Tidy buglets in sigreturn paths:

    Don't pretend support for _NSIG_WORDS > 1.
    Don't verify_area on more memory than we actually care about.
    Don't fiddle stack_t in do_rt_sigreturn.
parent 7883a18c
...@@ -201,10 +201,13 @@ sys_sigaltstack(const stack_t *uss, stack_t *uoss) ...@@ -201,10 +201,13 @@ sys_sigaltstack(const stack_t *uss, stack_t *uoss)
* Do a signal return; undo the signal stack. * Do a signal return; undo the signal stack.
*/ */
#if _NSIG_WORDS > 1
# error "Non SA_SIGINFO frame needs rearranging"
#endif
struct sigframe struct sigframe
{ {
struct sigcontext sc; struct sigcontext sc;
unsigned long extramask[_NSIG_WORDS-1];
unsigned int retcode[3]; unsigned int retcode[3];
}; };
...@@ -268,19 +271,20 @@ restore_sigcontext(struct sigcontext *sc, struct pt_regs *regs, ...@@ -268,19 +271,20 @@ restore_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
return err; return err;
} }
/* Note that this syscall is also used by setcontext(3) to install
a given sigcontext. This because it's impossible to set *all*
registers and transfer control from userland. */
asmlinkage void asmlinkage void
do_sigreturn(struct sigframe *frame, struct pt_regs *regs, do_sigreturn(struct sigcontext *sc, struct pt_regs *regs,
struct switch_stack *sw) struct switch_stack *sw)
{ {
sigset_t set; sigset_t set;
/* Verify that it's a good sigcontext before using it */ /* Verify that it's a good sigcontext before using it */
if (verify_area(VERIFY_READ, frame, sizeof(*frame))) if (verify_area(VERIFY_READ, sc, sizeof(*sc)))
goto give_sigsegv; goto give_sigsegv;
if (__get_user(set.sig[0], &frame->sc.sc_mask) if (__get_user(set.sig[0], &sc->sc_mask))
|| (_NSIG_WORDS > 1
&& __copy_from_user(&set.sig[1], &frame->extramask,
sizeof(frame->extramask))))
goto give_sigsegv; goto give_sigsegv;
sigdelsetmask(&set, ~_BLOCKABLE); sigdelsetmask(&set, ~_BLOCKABLE);
...@@ -289,7 +293,7 @@ do_sigreturn(struct sigframe *frame, struct pt_regs *regs, ...@@ -289,7 +293,7 @@ do_sigreturn(struct sigframe *frame, struct pt_regs *regs,
recalc_sigpending(); recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
if (restore_sigcontext(&frame->sc, regs, sw)) if (restore_sigcontext(sc, regs, sw))
goto give_sigsegv; goto give_sigsegv;
/* Send SIGTRAP if we're single-stepping: */ /* Send SIGTRAP if we're single-stepping: */
...@@ -314,10 +318,9 @@ do_rt_sigreturn(struct rt_sigframe *frame, struct pt_regs *regs, ...@@ -314,10 +318,9 @@ do_rt_sigreturn(struct rt_sigframe *frame, struct pt_regs *regs,
struct switch_stack *sw) struct switch_stack *sw)
{ {
sigset_t set; sigset_t set;
stack_t st;
/* Verify that it's a good sigcontext before using it */ /* Verify that it's a good ucontext_t before using it */
if (verify_area(VERIFY_READ, frame, sizeof(*frame))) if (verify_area(VERIFY_READ, &frame->uc, sizeof(frame->uc)))
goto give_sigsegv; goto give_sigsegv;
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto give_sigsegv; goto give_sigsegv;
...@@ -331,12 +334,6 @@ do_rt_sigreturn(struct rt_sigframe *frame, struct pt_regs *regs, ...@@ -331,12 +334,6 @@ do_rt_sigreturn(struct rt_sigframe *frame, struct pt_regs *regs,
if (restore_sigcontext(&frame->uc.uc_mcontext, regs, sw)) if (restore_sigcontext(&frame->uc.uc_mcontext, regs, sw))
goto give_sigsegv; goto give_sigsegv;
if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
goto give_sigsegv;
/* It is more difficult to avoid calling this function than to
call it and ignore errors. */
do_sigaltstack(&st, NULL, rdusp());
/* Send SIGTRAP if we're single-stepping: */ /* Send SIGTRAP if we're single-stepping: */
if (ptrace_cancel_bpt (current)) { if (ptrace_cancel_bpt (current)) {
siginfo_t info; siginfo_t info;
...@@ -437,10 +434,6 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, ...@@ -437,10 +434,6 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
goto give_sigsegv; goto give_sigsegv;
err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp); err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp);
if (_NSIG_WORDS > 1) {
err |= __copy_to_user(frame->extramask, &set->sig[1],
sizeof(frame->extramask));
}
if (err) if (err)
goto give_sigsegv; goto give_sigsegv;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment