]> git.hungrycats.org Git - linux/commitdiff
[PATCH] signal-race fixes for s390
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Wed, 25 Aug 2004 11:01:08 +0000 (04:01 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Wed, 25 Aug 2004 11:01:08 +0000 (04:01 -0700)
  Update s30 for the signal race fix

From: Mikael Pettersson <mikpe@csd.uu.se>

  The signal-race-fixes patch in 2.6.8-rc2-mm1 appears to be a bit broken on
  s390.

  When forcing a SIGSEGV the old code updated "*ka", where ka was a pointer
  to current's k_sigaction for SIGSEGV.  Now "ka_copy" points to a copy of
  that structure, so assigning "*ka_copy" doesn't do what we want.  Instead do
  the assignment via current->...  just like i386 and x86_64 do.

  Furthermore, the SA_ONESHOT handling wasn't deleted.  That is now handled
  by generic code in the kernel.

Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
arch/s390/kernel/compat_signal.c
arch/s390/kernel/signal.c

index 08ff15adfcc6fb045710fe1f496e1faf23e60e56..44a307caf0c90926fc4422b613bf5b72affd94df 100644 (file)
@@ -610,20 +610,15 @@ give_sigsegv:
  */    
 
 void
-handle_signal32(unsigned long sig, siginfo_t *info, sigset_t *oldset,
-       struct pt_regs * regs)
+handle_signal32(unsigned long sig, struct k_sigaction *ka,
+               siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
 {
-       struct k_sigaction *ka = &current->sighand->action[sig-1];
-
        /* Set up the stack frame */
        if (ka->sa.sa_flags & SA_SIGINFO)
                setup_rt_frame32(sig, ka, info, oldset, regs);
        else
                setup_frame32(sig, ka, oldset, regs);
 
-       if (ka->sa.sa_flags & SA_ONESHOT)
-               ka->sa.sa_handler = SIG_DFL;
-
        if (!(ka->sa.sa_flags & SA_NODEFER)) {
                spin_lock_irq(&current->sighand->siglock);
                sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
index 792d82b860a031494fcc0a16e4caafc06cf39a74..179db7e039d86dd8d7a006824e5b7e36eb9bac15 100644 (file)
@@ -420,20 +420,15 @@ give_sigsegv:
  */    
 
 static void
-handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
-       struct pt_regs * regs)
+handle_signal(unsigned long sig, struct k_sigaction *ka,
+             siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
 {
-       struct k_sigaction *ka = &current->sighand->action[sig-1];
-
        /* Set up the stack frame */
        if (ka->sa.sa_flags & SA_SIGINFO)
                setup_rt_frame(sig, ka, info, oldset, regs);
        else
                setup_frame(sig, ka, oldset, regs);
 
-       if (ka->sa.sa_flags & SA_ONESHOT)
-               ka->sa.sa_handler = SIG_DFL;
-
        if (!(ka->sa.sa_flags & SA_NODEFER)) {
                spin_lock_irq(&current->sighand->siglock);
                sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
@@ -457,6 +452,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
        unsigned long retval = 0, continue_addr = 0, restart_addr = 0;
        siginfo_t info;
        int signr;
+       struct k_sigaction ka;
 
        /*
         * We want the common case to go fast, which
@@ -490,7 +486,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
 
        /* Get signal to deliver.  When running under ptrace, at this point
           the debugger may change all our registers ... */
-       signr = get_signal_to_deliver(&info, regs, NULL);
+       signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 
        /* Depending on the signal settings we may need to revert the
           decision to restart the system call. */
@@ -509,14 +505,15 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
 #ifdef CONFIG_S390_SUPPORT
                if (test_thread_flag(TIF_31BIT)) {
                        extern void handle_signal32(unsigned long sig,
+                                                   struct k_sigaction *ka,
                                                    siginfo_t *info,
                                                    sigset_t *oldset,
                                                    struct pt_regs *regs);
-                       handle_signal32(signr, &info, oldset, regs);
+                       handle_signal32(signr, &ka, &info, oldset, regs);
                        return 1;
                }
 #endif
-               handle_signal(signr, &info, oldset, regs);
+               handle_signal(signr, &ka, &info, oldset, regs);
                return 1;
        }