]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/s390/kernel/signal.c
[S390] Cleanup kprobes printk messages.
[linux-2.6-omap-h63xx.git] / arch / s390 / kernel / signal.c
index d264671c1b71e996b38563a398e7109cb9946028..b976820402154a49b3792e7f8c07d7c803416358 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/lowcore.h>
+#include "entry.h"
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
@@ -235,6 +236,10 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
        /* Default to using normal stack */
        sp = regs->gprs[15];
 
+       /* Overflow on alternate signal stack gives SIGSEGV. */
+       if (on_sig_stack(sp) && !on_sig_stack((sp - frame_size) & -8UL))
+               return (void __user *) -1UL;
+
        /* This is the X/Open sanctioned signal stack switching.  */
        if (ka->sa.sa_flags & SA_ONSTACK) {
                if (! sas_ss_flags(sp))
@@ -270,6 +275,9 @@ static int setup_frame(int sig, struct k_sigaction *ka,
        if (!access_ok(VERIFY_WRITE, frame, sizeof(sigframe)))
                goto give_sigsegv;
 
+       if (frame == (void __user *) -1UL)
+               goto give_sigsegv;
+
        if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE))
                goto give_sigsegv;
 
@@ -327,6 +335,9 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        if (!access_ok(VERIFY_WRITE, frame, sizeof(rt_sigframe)))
                goto give_sigsegv;
 
+       if (frame == (void __user *) -1UL)
+               goto give_sigsegv;
+
        if (copy_siginfo_to_user(&frame->info, info))
                goto give_sigsegv;
 
@@ -471,22 +482,15 @@ void do_signal(struct pt_regs *regs)
 
        if (signr > 0) {
                /* Whee!  Actually deliver the signal.  */
+               int ret;
 #ifdef CONFIG_COMPAT
                if (test_thread_flag(TIF_31BIT)) {
-                       extern int handle_signal32(unsigned long sig,
-                                                  struct k_sigaction *ka,
-                                                  siginfo_t *info,
-                                                  sigset_t *oldset,
-                                                  struct pt_regs *regs);
-                       if (handle_signal32(
-                                   signr, &ka, &info, oldset, regs) == 0) {
-                               if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                                       clear_thread_flag(TIF_RESTORE_SIGMASK);
-                       }
-                       return;
+                       ret = handle_signal32(signr, &ka, &info, oldset, regs);
                }
+               else
 #endif
-               if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
+                       ret = handle_signal(signr, &ka, &info, oldset, regs);
+               if (!ret) {
                        /*
                         * A signal was successfully delivered; the saved
                         * sigmask will have been stored in the signal frame,
@@ -495,6 +499,14 @@ void do_signal(struct pt_regs *regs)
                         */
                        if (test_thread_flag(TIF_RESTORE_SIGMASK))
                                clear_thread_flag(TIF_RESTORE_SIGMASK);
+
+                       /*
+                        * If we would have taken a single-step trap
+                        * for a normal instruction, act like we took
+                        * one for the handler setup.
+                        */
+                       if (current->thread.per_info.single_step)
+                               set_thread_flag(TIF_SINGLE_STEP);
                }
                return;
        }