From 6398b287b632394deb3deb043d41c93f738d08a8 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 3 Oct 2010 01:36:58 -0400 Subject: [PATCH] --- yaml --- r: 227840 b: refs/heads/master c: 90731d7537317ad5d9672187f7a1dff90b29bb12 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/arch/m68k/kernel/signal.c | 44 ++++++++++++++++++++++----------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/[refs] b/[refs] index ae82969d6bc4..adc43a9c9f6a 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: f85741eb5fb2653fd9138b4bef68396615c720f7 +refs/heads/master: 90731d7537317ad5d9672187f7a1dff90b29bb12 diff --git a/trunk/arch/m68k/kernel/signal.c b/trunk/arch/m68k/kernel/signal.c index a6dd61418e76..16ea319d1ed5 100644 --- a/trunk/arch/m68k/kernel/signal.c +++ b/trunk/arch/m68k/kernel/signal.c @@ -761,10 +761,8 @@ static int setup_frame (int sig, struct k_sigaction *ka, frame = get_sigframe(ka, regs, sizeof(*frame) + fsize); - if (fsize) { + if (fsize) err |= copy_to_user (frame + 1, regs + 1, fsize); - regs->stkadj = fsize; - } err |= __put_user((current_thread_info()->exec_domain && current_thread_info()->exec_domain->signal_invmap @@ -794,11 +792,21 @@ static int setup_frame (int sig, struct k_sigaction *ka, push_cache ((unsigned long) &frame->retcode); - /* Set up registers for signal handler */ + /* + * Set up registers for signal handler. All the state we are about + * to destroy is successfully copied to sigframe. + */ wrusp ((unsigned long) frame); regs->pc = (unsigned long) ka->sa.sa_handler; -adjust_stack: + /* + * This is subtle; if we build more than one sigframe, all but the + * first one will see frame format 0 and have fsize == 0, so we won't + * screw stkadj. + */ + if (fsize) + regs->stkadj = fsize; + /* Prepare to skip over the extra stuff in the exception frame. */ if (regs->stkadj) { struct pt_regs *tregs = @@ -813,11 +821,11 @@ static int setup_frame (int sig, struct k_sigaction *ka, tregs->pc = regs->pc; tregs->sr = regs->sr; } - return err; + return 0; give_sigsegv: force_sigsegv(sig, current); - goto adjust_stack; + return err; } static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, @@ -837,10 +845,8 @@ static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, frame = get_sigframe(ka, regs, sizeof(*frame)); - if (fsize) { + if (fsize) err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize); - regs->stkadj = fsize; - } err |= __put_user((current_thread_info()->exec_domain && current_thread_info()->exec_domain->signal_invmap @@ -882,11 +888,21 @@ static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, push_cache ((unsigned long) &frame->retcode); - /* Set up registers for signal handler */ + /* + * Set up registers for signal handler. All the state we are about + * to destroy is successfully copied to sigframe. + */ wrusp ((unsigned long) frame); regs->pc = (unsigned long) ka->sa.sa_handler; -adjust_stack: + /* + * This is subtle; if we build more than one sigframe, all but the + * first one will see frame format 0 and have fsize == 0, so we won't + * screw stkadj. + */ + if (fsize) + regs->stkadj = fsize; + /* Prepare to skip over the extra stuff in the exception frame. */ if (regs->stkadj) { struct pt_regs *tregs = @@ -901,11 +917,11 @@ static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, tregs->pc = regs->pc; tregs->sr = regs->sr; } - return err; + return 0; give_sigsegv: force_sigsegv(sig, current); - goto adjust_stack; + return err; } static inline void