OSDN Git Service

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 24 May 2012 01:11:45 +0000 (18:11 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 24 May 2012 01:11:45 +0000 (18:11 -0700)
Pull first series of signal handling cleanups from Al Viro:
 "This is just the first part of the queue (about a half of it);
  assorted fixes all over the place in signal handling.

  This one ends with all sigsuspend() implementations switched to
  generic one (->saved_sigmask-based).

  With this, a bunch of assorted old buglets are fixed and most of the
  missing bits of NOTIFY_RESUME hookup are in place.  Two more fixes sit
  in arm and um trees respectively, and there's a couple of broken ones
  that need obvious fixes - parisc and avr32 check TIF_NOTIFY_RESUME
  only on one of two codepaths; fixes for that will happen in the next
  series"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (55 commits)
  unicore32: if there's no handler we need to restore sigmask, syscall or no syscall
  xtensa: add handling of TIF_NOTIFY_RESUME
  microblaze: drop 'oldset' argument of do_notify_resume()
  microblaze: handle TIF_NOTIFY_RESUME
  score: add handling of NOTIFY_RESUME to do_notify_resume()
  m68k: add TIF_NOTIFY_RESUME and handle it.
  sparc: kill ancient comment in sparc_sigaction()
  h8300: missing checks of __get_user()/__put_user() return values
  frv: missing checks of __get_user()/__put_user() return values
  cris: missing checks of __get_user()/__put_user() return values
  powerpc: missing checks of __get_user()/__put_user() return values
  sh: missing checks of __get_user()/__put_user() return values
  sparc: missing checks of __get_user()/__put_user() return values
  avr32: struct old_sigaction is never used
  m32r: struct old_sigaction is never used
  xtensa: xtensa_sigaction doesn't exist
  alpha: tidy signal delivery up
  score: don't open-code force_sigsegv()
  cris: don't open-code force_sigsegv()
  blackfin: don't open-code force_sigsegv()
  ...

54 files changed:
arch/alpha/kernel/signal.c
arch/arm/kernel/signal.c
arch/avr32/include/asm/signal.h
arch/avr32/kernel/signal.c
arch/blackfin/kernel/signal.c
arch/c6x/kernel/signal.c
arch/cris/arch-v10/kernel/signal.c
arch/cris/arch-v32/kernel/signal.c
arch/frv/kernel/signal.c
arch/h8300/include/asm/unistd.h
arch/h8300/kernel/signal.c
arch/h8300/kernel/syscalls.S
arch/hexagon/kernel/signal.c
arch/ia64/kernel/signal.c
arch/m32r/include/asm/signal.h
arch/m32r/kernel/signal.c
arch/m68k/include/asm/thread_info.h
arch/m68k/kernel/entry_mm.S
arch/m68k/kernel/signal.c
arch/m68k/platform/68328/entry.S
arch/m68k/platform/68360/entry.S
arch/m68k/platform/coldfire/entry.S
arch/microblaze/kernel/entry-nommu.S
arch/microblaze/kernel/entry.S
arch/microblaze/kernel/signal.c
arch/mips/kernel/signal.c
arch/mips/kernel/signal32.c
arch/mips/kernel/signal_n32.c
arch/mn10300/kernel/signal.c
arch/parisc/kernel/signal.c
arch/powerpc/kernel/signal_32.c
arch/s390/kernel/signal.c
arch/score/kernel/signal.c
arch/sh/include/asm/syscalls_32.h
arch/sh/include/asm/unistd.h
arch/sh/kernel/signal_32.c
arch/sh/kernel/signal_64.c
arch/sparc/kernel/signal32.c
arch/sparc/kernel/signal_32.c
arch/sparc/kernel/signal_64.c
arch/sparc/kernel/sys_sparc_32.c
arch/um/kernel/signal.c
arch/unicore32/kernel/signal.c
arch/x86/ia32/ia32_signal.c
arch/x86/kernel/signal.c
arch/xtensa/include/asm/signal.h
arch/xtensa/include/asm/syscall.h
arch/xtensa/include/asm/thread_info.h
arch/xtensa/include/asm/unistd.h
arch/xtensa/kernel/entry.S
arch/xtensa/kernel/signal.c
include/linux/signal.h
kernel/compat.c
kernel/signal.c

index 35f2ef4..10ab2d7 100644 (file)
@@ -34,9 +34,6 @@
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
 asmlinkage void ret_from_sys_call(void);
-static void do_signal(struct pt_regs *, struct switch_stack *,
-                     unsigned long, unsigned long);
-
 
 /*
  * The OSF/1 sigprocmask calling sequence is different from the
@@ -121,17 +118,8 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act,
 SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask)
 {
        sigset_t blocked;
-
-       current->saved_sigmask = current->blocked;
-
-       mask &= _BLOCKABLE;
        siginitset(&blocked, mask);
-       set_current_blocked(&blocked);
-
-       current->state = TASK_INTERRUPTIBLE;
-       schedule();
-       set_thread_flag(TIF_RESTORE_SIGMASK);
-       return -ERESTARTNOHAND;
+       return sigsuspend(&blocked);
 }
 
 asmlinkage int
@@ -376,11 +364,11 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
        oldsp = rdusp();
        frame = get_sigframe(ka, oldsp, sizeof(*frame));
        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-               goto give_sigsegv;
+               return -EFAULT;
 
        err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp);
        if (err)
-               goto give_sigsegv;
+               return -EFAULT;
 
        /* Set up to return from userspace.  If provided, use a stub
           already in userspace.  */
@@ -396,7 +384,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
 
        /* Check that everything was written properly.  */
        if (err)
-               goto give_sigsegv;
+               return err;
 
        /* "Return" to the handler */
        regs->r26 = r26;
@@ -410,12 +398,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
        printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
                current->comm, current->pid, frame, regs->pc, regs->r26);
 #endif
-
        return 0;
-
-give_sigsegv:
-       force_sigsegv(sig, current);
-       return -EFAULT;
 }
 
 static int
@@ -428,7 +411,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        oldsp = rdusp();
        frame = get_sigframe(ka, oldsp, sizeof(*frame));
        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-               goto give_sigsegv;
+               return -EFAULT;
 
        err |= copy_siginfo_to_user(&frame->info, info);
 
@@ -443,7 +426,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                                set->sig[0], oldsp);
        err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
        if (err)
-               goto give_sigsegv;
+               return -EFAULT;
 
        /* Set up to return from userspace.  If provided, use a stub
           already in userspace.  */
@@ -459,7 +442,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        }
 
        if (err)
-               goto give_sigsegv;
+               return -EFAULT;
 
        /* "Return" to the handler */
        regs->r26 = r26;
@@ -475,31 +458,37 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 #endif
 
        return 0;
-
-give_sigsegv:
-       force_sigsegv(sig, current);
-       return -EFAULT;
 }
 
 
 /*
  * OK, we're invoking a handler.
  */
-static inline int
+static inline void
 handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
-             sigset_t *oldset, struct pt_regs * regs, struct switch_stack *sw)
+             struct pt_regs * regs, struct switch_stack *sw)
 {
+       sigset_t *oldset = &current->blocked;
        int ret;
 
+       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+               oldset = &current->saved_sigmask;
+
        if (ka->sa.sa_flags & SA_SIGINFO)
                ret = setup_rt_frame(sig, ka, info, oldset, regs, sw);
        else
                ret = setup_frame(sig, ka, oldset, regs, sw);
 
-       if (ret == 0)
-               block_sigmask(ka, sig);
-
-       return ret;
+       if (ret) {
+               force_sigsegv(sig, current);
+               return;
+       }
+       block_sigmask(ka, sig);
+       /* A signal was successfully delivered, and the
+          saved sigmask was stored on the signal frame,
+          and will be restored by sigreturn.  So we can
+          simply clear the restore sigmask flag.  */
+       clear_thread_flag(TIF_RESTORE_SIGMASK);
 }
 
 static inline void
@@ -547,12 +536,6 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw,
        int signr;
        unsigned long single_stepping = ptrace_cancel_bpt(current);
        struct k_sigaction ka;
-       sigset_t *oldset;
-
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-               oldset = &current->saved_sigmask;
-       else
-               oldset = &current->blocked;
 
        /* This lets the debugger run, ... */
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
@@ -564,14 +547,7 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw,
                /* Whee!  Actually deliver the signal.  */
                if (r0)
                        syscall_restart(r0, r19, regs, &ka);
-               if (handle_signal(signr, &ka, &info, oldset, regs, sw) == 0) {
-                       /* A signal was successfully delivered, and the
-                          saved sigmask was stored on the signal frame,
-                          and will be restored by sigreturn.  So we can
-                          simply clear the restore sigmask flag.  */
-                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                               clear_thread_flag(TIF_RESTORE_SIGMASK);
-               }
+               handle_signal(signr, &ka, &info, regs, sw);
                if (single_stepping) 
                        ptrace_set_bpt(current); /* re-set bpt */
                return;
@@ -596,10 +572,8 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw,
        }
 
        /* If there's no signal to deliver, we just restore the saved mask.  */
-       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-               clear_thread_flag(TIF_RESTORE_SIGMASK);
-               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-       }
+       if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
+               set_current_blocked(&current->saved_sigmask);
 
        if (single_stepping)
                ptrace_set_bpt(current);        /* re-set breakpoint */
@@ -610,7 +584,7 @@ do_notify_resume(struct pt_regs *regs, struct switch_stack *sw,
                 unsigned long thread_info_flags,
                 unsigned long r0, unsigned long r19)
 {
-       if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+       if (thread_info_flags & _TIF_SIGPENDING)
                do_signal(regs, sw, r0, r19);
 
        if (thread_info_flags & _TIF_NOTIFY_RESUME) {
index 73d9a42..4e5fdd9 100644 (file)
@@ -67,17 +67,8 @@ const unsigned long syscall_restart_code[2] = {
 asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask)
 {
        sigset_t blocked;
-
-       current->saved_sigmask = current->blocked;
-
-       mask &= _BLOCKABLE;
        siginitset(&blocked, mask);
-       set_current_blocked(&blocked);
-
-       current->state = TASK_INTERRUPTIBLE;
-       schedule();
-       set_restore_sigmask();
-       return -ERESTARTNOHAND;
+       return sigsuspend(&blocked);
 }
 
 asmlinkage int 
index 8790dfc..ae56849 100644 (file)
@@ -115,13 +115,6 @@ typedef unsigned long sigset_t;
 #include <asm-generic/signal-defs.h>
 
 #ifdef __KERNEL__
-struct old_sigaction {
-       __sighandler_t sa_handler;
-       old_sigset_t sa_mask;
-       unsigned long sa_flags;
-       __sigrestore_t sa_restorer;
-};
-
 struct sigaction {
        __sighandler_t sa_handler;
        unsigned long sa_flags;
index 64f886f..ae386c3 100644 (file)
@@ -77,6 +77,9 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
        struct rt_sigframe __user *frame;
        sigset_t set;
 
+       /* Always make any pending restarted system calls return -EINTR */
+       current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
        frame = (struct rt_sigframe __user *)regs->sp;
        pr_debug("SIG return: frame = %p\n", frame);
 
@@ -87,10 +90,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
                goto badframe;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
                goto badframe;
@@ -238,22 +238,16 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
         */
        ret |= !valid_user_regs(regs);
 
-       /*
-        * Block the signal if we were unsuccessful.
-        */
-       if (ret != 0 || !(ka->sa.sa_flags & SA_NODEFER)) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked, &current->blocked,
-                         &ka->sa.sa_mask);
-               sigaddset(&current->blocked, sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
-
-       if (ret == 0)
+       if (ret != 0) {
+               force_sigsegv(sig, current);
                return;
+       }
 
-       force_sigsegv(sig, current);
+       /*
+        * Block the signal if we were successful.
+        */
+       block_sigmask(ka, sig);
+       clear_thread_flag(TIF_RESTORE_SIGMASK);
 }
 
 /*
index d536f35..e5bbc1a 100644 (file)
@@ -99,10 +99,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
                goto badframe;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
 
        if (rt_restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
                goto badframe;
@@ -213,9 +210,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
        return 0;
 
  give_sigsegv:
-       if (sig == SIGSEGV)
-               ka->sa.sa_handler = SIG_DFL;
-       force_sig(SIGSEGV, current);
+       force_sigsegv(sig, current);
        return -EFAULT;
 }
 
@@ -266,15 +261,9 @@ handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
        /* set up the stack frame */
        ret = setup_rt_frame(sig, ka, info, oldset, regs);
 
-       if (ret == 0) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked, &current->blocked,
-                         &ka->sa.sa_mask);
-               if (!(ka->sa.sa_flags & SA_NODEFER))
-                       sigaddset(&current->blocked, sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       if (ret == 0)
+               block_sigmask(ka, sig);
+
        return ret;
 }
 
index 3b5a050..cf37478 100644 (file)
@@ -69,6 +69,9 @@ asmlinkage int do_rt_sigreturn(struct pt_regs *regs)
        struct rt_sigframe __user *frame;
        sigset_t set;
 
+       /* Always make any pending restarted system calls return -EINTR */
+       current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
        /*
         * Since we stacked the signal on a dword boundary,
         * 'sp' should be dword aligned here.  If it's
index 289c584..e16f8f2 100644 (file)
@@ -48,19 +48,11 @@ void do_signal(int canrestart, struct pt_regs *regs);
  * dummy arguments to be able to reach the regs argument.  (Note that this
  * arrangement relies on old_sigset_t occupying one register.)
  */
-int sys_sigsuspend(old_sigset_t mask, long r11, long r12, long r13, long mof,
-       long srp, struct pt_regs *regs)
+int sys_sigsuspend(old_sigset_t mask)
 {
-       mask &= _BLOCKABLE;
-       spin_lock_irq(&current->sighand->siglock);
-       current->saved_sigmask = current->blocked;
-       siginitset(&current->blocked, mask);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-       current->state = TASK_INTERRUPTIBLE;
-       schedule();
-       set_thread_flag(TIF_RESTORE_SIGMASK);
-       return -ERESTARTNOHAND;
+       sigset_t blocked;
+       siginitset(&blocked, mask);
+       return sigsuspend(&blocked);
 }
 
 int sys_sigaction(int sig, const struct old_sigaction __user *act,
@@ -73,10 +65,10 @@ int sys_sigaction(int sig, const struct old_sigaction __user *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))
+                   __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
+                    __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
+                    __get_user(mask, &act->sa_mask))
                        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);
        }
 
@@ -85,10 +77,10 @@ int sys_sigaction(int sig, const struct old_sigaction __user *act,
        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))
+                   __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
+                   __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
+                   __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
                        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;
@@ -185,10 +177,7 @@ asmlinkage int sys_sigreturn(long r10, long r11, long r12, long r13, long mof,
                goto badframe;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->sc))
                goto badframe;
@@ -224,10 +213,7 @@ asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13,
                goto badframe;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
                goto badframe;
@@ -469,15 +455,9 @@ static inline int handle_signal(int canrestart, unsigned long sig,
        else
                ret = setup_frame(sig, ka, oldset, regs);
 
-       if (ret == 0) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked, &current->blocked,
-                       &ka->sa.sa_mask);
-               if (!(ka->sa.sa_flags & SA_NODEFER))
-                       sigaddset(&current->blocked, sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       if (ret == 0)
+               block_sigmask(ka, sig);
+
        return ret;
 }
 
index ce4ab1a..b338d8f 100644 (file)
@@ -59,19 +59,11 @@ void keep_debug_flags(unsigned long oldccs, unsigned long oldspc,
  * dummy arguments to be able to reach the regs argument.
  */
 int
-sys_sigsuspend(old_sigset_t mask, long r11, long r12, long r13, long mof,
-              long srp, struct pt_regs *regs)
+sys_sigsuspend(old_sigset_t mask)
 {
-       mask &= _BLOCKABLE;
-       spin_lock_irq(&current->sighand->siglock);
-       current->saved_sigmask = current->blocked;
-       siginitset(&current->blocked, mask);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-       current->state = TASK_INTERRUPTIBLE;
-       schedule();
-       set_thread_flag(TIF_RESTORE_SIGMASK);
-       return -ERESTARTNOHAND;
+       sigset_t blocked;
+       siginitset(&blocked, mask);
+       return sigsuspend(&blocked);
 }
 
 int
@@ -87,11 +79,11 @@ sys_sigaction(int signal, const struct old_sigaction *act,
 
                if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
                    __get_user(newk.sa.sa_handler, &act->sa_handler) ||
-                   __get_user(newk.sa.sa_restorer, &act->sa_restorer))
+                   __get_user(newk.sa.sa_restorer, &act->sa_restorer) ||
+                   __get_user(newk.sa.sa_flags, &act->sa_flags) ||
+                   __get_user(mask, &act->sa_mask))
                        return -EFAULT;
 
-               __get_user(newk.sa.sa_flags, &act->sa_flags);
-               __get_user(mask, &act->sa_mask);
                siginitset(&newk.sa.sa_mask, mask);
        }
 
@@ -100,11 +92,11 @@ sys_sigaction(int signal, const struct old_sigaction *act,
        if (!retval && oact) {
                if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
                    __put_user(oldk.sa.sa_handler, &oact->sa_handler) ||
-                   __put_user(oldk.sa.sa_restorer, &oact->sa_restorer))
+                   __put_user(oldk.sa.sa_restorer, &oact->sa_restorer) ||
+                   __put_user(oldk.sa.sa_flags, &oact->sa_flags) ||
+                   __put_user(oldk.sa.sa_mask.sig[0], &oact->sa_mask))
                        return -EFAULT;
 
-               __put_user(oldk.sa.sa_flags, &oact->sa_flags);
-               __put_user(oldk.sa.sa_mask.sig[0], &oact->sa_mask);
        }
 
        return retval;
@@ -176,12 +168,7 @@ sys_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp,
                goto badframe;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-
-       current->blocked = set;
-
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->sc))
                goto badframe;
@@ -222,12 +209,7 @@ sys_rt_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp,
                goto badframe;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-
-       current->blocked = set;
-
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
                goto badframe;
@@ -363,10 +345,7 @@ setup_frame(int sig, struct k_sigaction *ka,  sigset_t *set,
        return 0;
 
 give_sigsegv:
-       if (sig == SIGSEGV)
-               ka->sa.sa_handler = SIG_DFL;
-
-       force_sig(SIGSEGV, current);
+       force_sigsegv(sig, current);
        return -EFAULT;
 }
 
@@ -450,10 +429,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        return 0;
 
 give_sigsegv:
-       if (sig == SIGSEGV)
-               ka->sa.sa_handler = SIG_DFL;
-
-       force_sig(SIGSEGV, current);
+       force_sigsegv(sig, current);
        return -EFAULT;
 }
 
@@ -512,18 +488,8 @@ handle_signal(int canrestart, unsigned long sig,
        else
                ret = setup_frame(sig, ka, oldset, regs);
 
-       if (ka->sa.sa_flags & SA_ONESHOT)
-               ka->sa.sa_handler = SIG_DFL;
-
-       if (ret == 0) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked, &current->blocked,
-                       &ka->sa.sa_mask);
-               if (!(ka->sa.sa_flags & SA_NODEFER))
-                       sigaddset(&current->blocked, sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       if (ret == 0)
+               block_sigmask(ka, sig);
 
        return ret;
 }
index bab0129..8cf5dca 100644 (file)
@@ -40,17 +40,9 @@ struct fdpic_func_descriptor {
  */
 asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask)
 {
-       mask &= _BLOCKABLE;
-       spin_lock_irq(&current->sighand->siglock);
-       current->saved_sigmask = current->blocked;
-       siginitset(&current->blocked, mask);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-
-       current->state = TASK_INTERRUPTIBLE;
-       schedule();
-       set_thread_flag(TIF_RESTORE_SIGMASK);
-       return -ERESTARTNOHAND;
+       sigset_t blocked;
+       siginitset(&blocked, mask);
+       return sigsuspend(&blocked);
 }
 
 asmlinkage int sys_sigaction(int sig,
@@ -64,10 +56,10 @@ asmlinkage int sys_sigaction(int sig,
                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))
+                   __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
+                   __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
+                   __get_user(mask, &act->sa_mask))
                        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);
        }
 
@@ -76,10 +68,10 @@ asmlinkage int sys_sigaction(int sig,
        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))
+                   __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
+                   __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
+                   __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
                        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;
@@ -158,10 +150,7 @@ asmlinkage int sys_sigreturn(void)
                goto badframe;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
 
        if (restore_sigcontext(&frame->sc, &gr8))
                goto badframe;
@@ -184,10 +173,7 @@ asmlinkage int sys_rt_sigreturn(void)
                goto badframe;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
 
        if (restore_sigcontext(&frame->uc.uc_mcontext, &gr8))
                goto badframe;
@@ -474,15 +460,8 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
        else
                ret = setup_frame(sig, ka, oldset);
 
-       if (ret == 0) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked, &current->blocked,
-                         &ka->sa.sa_mask);
-               if (!(ka->sa.sa_flags & SA_NODEFER))
-                       sigaddset(&current->blocked, sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       if (ret == 0)
+               block_sigmask(ka, sig);
 
        return ret;
 
index 2c3f8e6..7185113 100644 (file)
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
 
 /*
  * "Conditional" syscalls
index af842c3..d4b0555 100644 (file)
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
-
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
-asmlinkage int do_sigsuspend(struct pt_regs *regs)
-{
-       old_sigset_t mask = regs->er3;
-       sigset_t saveset;
-
-       mask &= _BLOCKABLE;
-       spin_lock_irq(&current->sighand->siglock);
-       saveset = current->blocked;
-       siginitset(&current->blocked, mask);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-
-       regs->er0 = -EINTR;
-       while (1) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule();
-               if (do_signal(regs, &saveset))
-                       return -EINTR;
-       }
-}
-
 asmlinkage int
-do_rt_sigsuspend(struct pt_regs *regs)
+sys_sigsuspend(int unused1, int unused2, old_sigset_t mask)
 {
-       sigset_t *unewset = (sigset_t *)regs->er1;
-       size_t sigsetsize = (size_t)regs->er2;
-       sigset_t saveset, newset;
-
-       /* XXX: Don't preclude handling different sized sigset_t's.  */
-       if (sigsetsize != sizeof(sigset_t))
-               return -EINVAL;
-
-       if (copy_from_user(&newset, unewset, sizeof(newset)))
-               return -EFAULT;
-       sigdelsetmask(&newset, ~_BLOCKABLE);
-
-       spin_lock_irq(&current->sighand->siglock);
-       saveset = current->blocked;
-       current->blocked = newset;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-
-       regs->er0 = -EINTR;
-       while (1) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule();
-               if (do_signal(regs, &saveset))
-                       return -EINTR;
-       }
+       sigset_t blocked;
+       siginitset(&blocked, mask);
+       return sigsuspend(&blocked);
 }
 
 asmlinkage int 
@@ -116,10 +71,10 @@ sys_sigaction(int sig, const struct old_sigaction *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))
+                   __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
+                   __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
+                   __get_user(mask, &act->sa_mask))
                        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);
        }
 
@@ -128,10 +83,10 @@ sys_sigaction(int sig, const struct old_sigaction *act,
        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))
+                   __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
+                   __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
+                   __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
                        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;
@@ -232,10 +187,7 @@ asmlinkage int do_sigreturn(unsigned long __unused,...)
                goto badframe;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
        
        if (restore_sigcontext(regs, &frame->sc, &er0))
                goto badframe;
@@ -260,10 +212,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused,...)
                goto badframe;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_unlock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_lock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
        
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &er0))
                goto badframe;
@@ -314,7 +263,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
        return (void *)((usp - frame_size) & -8UL);
 }
 
-static void setup_frame (int sig, struct k_sigaction *ka,
+static int setup_frame (int sig, struct k_sigaction *ka,
                         sigset_t *set, struct pt_regs *regs)
 {
        struct sigframe *frame;
@@ -375,13 +324,14 @@ static void setup_frame (int sig, struct k_sigaction *ka,
        regs->er1 = (unsigned long)&(frame->sc);
        regs->er5 = current->mm->start_data;    /* GOT base */
 
-       return;
+       return 0;
 
 give_sigsegv:
        force_sigsegv(sig, current);
+       return -EFAULT;
 }
 
-static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
+static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
                            sigset_t *set, struct pt_regs *regs)
 {
        struct rt_sigframe *frame;
@@ -450,10 +400,11 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
        regs->er2 = (unsigned long)&frame->uc;
        regs->er5 = current->mm->start_data;    /* GOT base */
 
-       return;
+       return 0;
 
 give_sigsegv:
        force_sigsegv(sig, current);
+       return -EFAULT;
 }
 
 /*
@@ -463,6 +414,7 @@ static void
 handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
              sigset_t *oldset, struct pt_regs * regs)
 {
+       int ret;
        /* are we from a system call? */
        if (regs->orig_er0 >= 0) {
                switch (regs->er0) {
@@ -485,16 +437,14 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
 
        /* set up the stack frame */
        if (ka->sa.sa_flags & SA_SIGINFO)
-               setup_rt_frame(sig, ka, info, oldset, regs);
+               ret = setup_rt_frame(sig, ka, info, oldset, regs);
        else
-               setup_frame(sig, ka, oldset, regs);
-
-       spin_lock_irq(&current->sighand->siglock);
-       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
-       if (!(ka->sa.sa_flags & SA_NODEFER))
-               sigaddset(&current->blocked,sig);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+               ret = setup_frame(sig, ka, oldset, regs);
+
+       if (!ret) {
+               block_sigmask(ka, sig);
+               clear_thread_flag(TIF_RESTORE_SIGMASK);
+       }
 }
 
 /*
@@ -502,11 +452,12 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  */
-asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset)
+statis void do_signal(struct pt_regs *regs)
 {
        siginfo_t info;
        int signr;
        struct k_sigaction ka;
+       sigset_t *oldset;
 
        /*
         * We want the common case to go fast, which
@@ -515,21 +466,23 @@ asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset)
         * if so.
         */
        if ((regs->ccr & 0x10))
-               return 1;
+               return;
 
        if (try_to_freeze())
                goto no_signal;
 
        current->thread.esp0 = (unsigned long) regs;
 
-       if (!oldset)
+       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+               oldset = &current->saved_sigmask;
+       else
                oldset = &current->blocked;
 
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
                /* Whee!  Actually deliver the signal.  */
                handle_signal(signr, &info, &ka, oldset, regs);
-               return 1;
+               return;
        }
  no_signal:
        /* Did we come from a system call? */
@@ -546,13 +499,16 @@ asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset)
                        regs->pc -= 2;
                }
        }
-       return 0;
+
+       /* If there's no signal to deliver, we just restore the saved mask.  */
+       if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
+               set_current_blocked(&current->saved_sigmask);
 }
 
 asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
 {
-       if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
-               do_signal(regs, NULL);
+       if (thread_info_flags & _TIF_SIGPENDING)
+               do_signal(regs);
 
        if (thread_info_flags & _TIF_NOTIFY_RESUME) {
                clear_thread_flag(TIF_NOTIFY_RESUME);
index 4be2ea2..9d77e71 100644 (file)
@@ -343,12 +343,6 @@ SYMBOL_NAME_LABEL(sys_call_table)
 SYMBOL_NAME_LABEL(sys_clone)   
        call_sp h8300_clone
        
-SYMBOL_NAME_LABEL(sys_sigsuspend)
-       call_sp do_sigsuspend
-
-SYMBOL_NAME_LABEL(sys_rt_sigsuspend)
-       call_sp do_rt_sigsuspend
-
 SYMBOL_NAME_LABEL(sys_sigreturn)
        call_sp do_sigreturn
 
index ecbab34..434866e 100644 (file)
@@ -272,6 +272,7 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
 
        if (thread_info_flags & _TIF_NOTIFY_RESUME) {
                clear_thread_flag(TIF_NOTIFY_RESUME);
+               tracehook_notify_resume(regs);
                if (current->replacement_session_keyring)
                        key_replace_session_keyring();
        }
@@ -293,6 +294,9 @@ asmlinkage int sys_rt_sigreturn(void)
        struct rt_sigframe __user *frame;
        sigset_t blocked;
 
+       /* Always make any pending restarted system calls return -EINTR */
+       current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
        frame = (struct rt_sigframe __user *)pt_psp(regs);
        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
index 7bdafc8..7523501 100644 (file)
@@ -201,13 +201,7 @@ ia64_rt_sigreturn (struct sigscratch *scr)
                goto give_sigsegv;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
-
-       spin_lock_irq(&current->sighand->siglock);
-       {
-               current->blocked = set;
-               recalc_sigpending();
-       }
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
 
        if (restore_sigcontext(sc, scr))
                goto give_sigsegv;
@@ -427,12 +421,7 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigse
        if (!setup_frame(sig, ka, info, oldset, scr))
                return 0;
 
-       spin_lock_irq(&current->sighand->siglock);
-       sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
-       if (!(ka->sa.sa_flags & SA_NODEFER))
-               sigaddset(&current->blocked, sig);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       block_sigmask(ka, sig);
 
        /*
         * Let tracing know that we've done the handler setup.
index b2eeb0d..ea5f95e 100644 (file)
@@ -110,13 +110,6 @@ typedef unsigned long sigset_t;
 #include <asm-generic/signal-defs.h>
 
 #ifdef __KERNEL__
-struct old_sigaction {
-       __sighandler_t sa_handler;
-       old_sigset_t sa_mask;
-       unsigned long sa_flags;
-       __sigrestore_t sa_restorer;
-};
-
 struct sigaction {
        __sighandler_t sa_handler;
        unsigned long sa_flags;
index a08697f..f54d969 100644 (file)
@@ -112,10 +112,7 @@ sys_rt_sigreturn(unsigned long r0, unsigned long r1,
                goto badframe;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &result))
                goto badframe;
@@ -300,12 +297,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
        if (setup_rt_frame(sig, ka, info, oldset, regs))
                return -EFAULT;
 
-       spin_lock_irq(&current->sighand->siglock);
-       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
-       if (!(ka->sa.sa_flags & SA_NODEFER))
-               sigaddset(&current->blocked,sig);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       block_sigmask(ka, sig);
        return 0;
 }
 
index e8665e6..126131f 100644 (file)
@@ -71,6 +71,7 @@ static inline struct thread_info *current_thread_info(void)
  * bits 0-7 are tested at every exception exit
  * bits 8-15 are also tested at syscall exit
  */
+#define TIF_NOTIFY_RESUME      5       /* callback before returning to user */
 #define TIF_SIGPENDING         6       /* signal pending */
 #define TIF_NEED_RESCHED       7       /* rescheduling necessary */
 #define TIF_DELAYED_TRACE      14      /* single step a syscall */
index 675a854..f29e73c 100644 (file)
@@ -148,7 +148,7 @@ syscall_exit_work:
        jcs     do_trace_exit
        jmi     do_delayed_trace
        lslw    #8,%d0
-       jmi     do_signal_return
+       jne     do_signal_return
        pea     resume_userspace
        jra     schedule
 
@@ -172,7 +172,7 @@ exit_work:
        | save top of frame
        movel   %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
        lslb    #1,%d0
-       jmi     do_signal_return
+       jne     do_signal_return
        pea     resume_userspace
        jra     schedule
 
@@ -182,7 +182,7 @@ do_signal_return:
        subql   #4,%sp                  | dummy return address
        SAVE_SWITCH_STACK
        pea     %sp@(SWITCH_STACK_SIZE)
-       bsrl    do_signal
+       bsrl    do_notify_resume
        addql   #4,%sp
        RESTORE_SWITCH_STACK
        addql   #4,%sp
index 1747c70..d9f3d19 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/tty.h>
 #include <linux/binfmts.h>
 #include <linux/module.h>
+#include <linux/tracehook.h>
 
 #include <asm/setup.h>
 #include <asm/uaccess.h>
@@ -230,18 +231,9 @@ static inline void push_cache(unsigned long vaddr)
 asmlinkage int
 sys_sigsuspend(int unused0, int unused1, old_sigset_t mask)
 {
-       mask &= _BLOCKABLE;
-       spin_lock_irq(&current->sighand->siglock);
-       current->saved_sigmask = current->blocked;
-       siginitset(&current->blocked, mask);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-
-       current->state = TASK_INTERRUPTIBLE;
-       schedule();
-       set_restore_sigmask();
-
-       return -ERESTARTNOHAND;
+       sigset_t blocked;
+       siginitset(&blocked, mask);
+       return sigsuspend(&blocked);
 }
 
 asmlinkage int
@@ -804,8 +796,7 @@ asmlinkage int do_sigreturn(unsigned long __unused)
                goto badframe;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
-       current->blocked = set;
-       recalc_sigpending();
+       set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->sc, frame + 1))
                goto badframe;
@@ -830,8 +821,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
                goto badframe;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
-       current->blocked = set;
-       recalc_sigpending();
+       set_current_blocked(&set);
 
        if (rt_restore_ucontext(regs, sw, &frame->uc))
                goto badframe;
@@ -1150,10 +1140,7 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
        if (err)
                return;
 
-       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
-       if (!(ka->sa.sa_flags & SA_NODEFER))
-               sigaddset(&current->blocked,sig);
-       recalc_sigpending();
+       block_sigmask(ka, sig);
 
        if (test_thread_flag(TIF_DELAYED_TRACE)) {
                regs->sr &= ~0x8000;
@@ -1168,7 +1155,7 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  */
-asmlinkage void do_signal(struct pt_regs *regs)
+static void do_signal(struct pt_regs *regs)
 {
        siginfo_t info;
        struct k_sigaction ka;
@@ -1200,3 +1187,15 @@ asmlinkage void do_signal(struct pt_regs *regs)
                sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
        }
 }
+
+void do_notify_resume(struct pt_regs *regs)
+{
+       if (test_thread_flag(TIF_SIGPENDING))
+               do_signal(regs);
+
+       if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) {
+               tracehook_notify_resume(regs);
+               if (current->replacement_session_keyring)
+                       key_replace_session_keyring();
+       }
+}
index 5c39b80..7f91c2f 100644 (file)
@@ -119,7 +119,7 @@ Lsignal_return:
        subql   #4,%sp                  /* dummy return address*/
        SAVE_SWITCH_STACK
        pea     %sp@(SWITCH_STACK_SIZE)
-       bsrw    do_signal
+       bsrw    do_notify_resume
        addql   #4,%sp
        RESTORE_SWITCH_STACK
        addql   #4,%sp
index aa47d1d..904fd9a 100644 (file)
@@ -115,7 +115,7 @@ Lsignal_return:
        subql   #4,%sp                  /* dummy return address*/
        SAVE_SWITCH_STACK
        pea     %sp@(SWITCH_STACK_SIZE)
-       bsrw    do_signal
+       bsrw    do_notify_resume
        addql   #4,%sp
        RESTORE_SWITCH_STACK
        addql   #4,%sp
index 281e38c..881ab8e 100644 (file)
@@ -152,7 +152,7 @@ Lsignal_return:
        subql   #4,%sp                  /* dummy return address */
        SAVE_SWITCH_STACK
        pea     %sp@(SWITCH_STACK_SIZE)
-       jsr     do_signal
+       jsr     do_notify_resume
        addql   #4,%sp
        RESTORE_SWITCH_STACK
        addql   #4,%sp
index 34b526f..75c3ea1 100644 (file)
@@ -132,11 +132,10 @@ ret_from_intr:
        beqi    r11, 1f
        bralid  r15, schedule
        nop
-1:     andi    r11, r19, _TIF_SIGPENDING
+1:     andi    r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME
        beqid   r11, no_intr_resched
        addk    r5, r1, r0
-       addk    r7, r0, r0
-       bralid  r15, do_signal
+       bralid  r15, do_notify_resume
        addk    r6, r0, r0
 
 no_intr_resched:
@@ -292,8 +291,8 @@ ENTRY(_user_exception)
 
 /*
  * Debug traps are like a system call, but entered via brki r14, 0x60
- * All we need to do is send the SIGTRAP signal to current, ptrace and do_signal
- * will handle the rest
+ * All we need to do is send the SIGTRAP signal to current, ptrace and
+ * do_notify_resume will handle the rest
  */
 ENTRY(_debug_exception)
        swi     r1, r0, PER_CPU(ENTRY_SP)       /* save the current sp */
@@ -482,12 +481,11 @@ work_pending:
        beqi    r11, 1f
        bralid  r15, schedule
        nop
-1:     andi    r11, r19, _TIF_SIGPENDING
+1:     andi    r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME
        beqi    r11, no_work_pending
        addk    r5, r1, r0
-       addik   r7, r0, 1
-       bralid  r15, do_signal
-       addk    r6, r0, r0
+       bralid  r15, do_notify_resume
+       addik   r6, r0, 1
        bri     no_work_pending
 
 ENTRY(ret_to_user)
@@ -569,10 +567,6 @@ sys_rt_sigreturn_wrapper:
        brid    sys_rt_sigreturn
        addk    r5, r1, r0
 
-sys_rt_sigsuspend_wrapper:
-       brid    sys_rt_sigsuspend
-       addk    r7, r1, r0
-
        /* Interrupt vector table */
        .section        .init.ivt, "ax"
        .org 0x0
index 66e34a3..daff9e5 100644 (file)
@@ -430,13 +430,12 @@ C_ENTRY(ret_from_trap):
 5:     /* get thread info from current task*/
        lwi     r11, CURRENT_TASK, TS_THREAD_INFO;
        lwi     r11, r11, TI_FLAGS;     /* get flags in thread info */
-       andi    r11, r11, _TIF_SIGPENDING;
+       andi    r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
        beqi    r11, 1f;                /* Signals to handle, handle them */
 
        addik   r5, r1, 0;              /* Arg 1: struct pt_regs *regs */
-       addi    r7, r0, 1;              /* Arg 3: int in_syscall */
-       bralid  r15, do_signal; /* Handle any signals */
-       add     r6, r0, r0;             /* Arg 2: sigset_t *oldset */
+       bralid  r15, do_notify_resume;  /* Handle any signals */
+       addi    r6, r0, 1;              /* Arg 2: int in_syscall */
 
 /* Finally, return to user state.  */
 1:     set_bip;                        /*  Ints masked for state restore */
@@ -622,7 +621,7 @@ C_ENTRY(ret_from_exc):
        /* Maybe handle a signal */
 5:     lwi     r11, CURRENT_TASK, TS_THREAD_INFO;      /* get thread info */
        lwi     r11, r11, TI_FLAGS;     /* get flags in thread info */
-       andi    r11, r11, _TIF_SIGPENDING;
+       andi    r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
        beqi    r11, 1f;                /* Signals to handle, handle them */
 
        /*
@@ -635,11 +634,10 @@ C_ENTRY(ret_from_exc):
         * traps), but signal handlers may want to examine or change the
         * complete register state.  Here we save anything not saved by
         * the normal entry sequence, so that it may be safely restored
-        * (in a possibly modified form) after do_signal returns. */
+        * (in a possibly modified form) after do_notify_resume returns. */
        addik   r5, r1, 0;              /* Arg 1: struct pt_regs *regs */
-       addi    r7, r0, 0;              /* Arg 3: int in_syscall */
-       bralid  r15, do_signal; /* Handle any signals */
-       add     r6, r0, r0;             /* Arg 2: sigset_t *oldset */
+       bralid  r15, do_notify_resume;  /* Handle any signals */
+       addi    r6, r0, 0;              /* Arg 2: int in_syscall */
 
 /* Finally, return to user state.  */
 1:     set_bip;                        /* Ints masked for state restore */
@@ -732,13 +730,12 @@ ret_from_irq:
     /* Maybe handle a signal */
 5:     lwi     r11, CURRENT_TASK, TS_THREAD_INFO; /* MS: get thread info */
        lwi     r11, r11, TI_FLAGS; /* get flags in thread info */
-       andi    r11, r11, _TIF_SIGPENDING;
+       andi    r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
        beqid   r11, no_intr_resched
 /* Handle a signal return; Pending signals should be in r18. */
-       addi    r7, r0, 0; /* Arg 3: int in_syscall */
        addik   r5, r1, 0; /* Arg 1: struct pt_regs *regs */
-       bralid  r15, do_signal; /* Handle any signals */
-       add     r6, r0, r0; /* Arg 2: sigset_t *oldset */
+       bralid  r15, do_notify_resume;  /* Handle any signals */
+       addi    r6, r0, 0; /* Arg 2: int in_syscall */
 
 /* Finally, return to user state. */
 no_intr_resched:
@@ -869,13 +866,12 @@ dbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */
        /* Maybe handle a signal */
 5:     lwi     r11, CURRENT_TASK, TS_THREAD_INFO;      /* get thread info */
        lwi     r11, r11, TI_FLAGS;     /* get flags in thread info */
-       andi    r11, r11, _TIF_SIGPENDING;
+       andi    r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
        beqi    r11, 1f;                /* Signals to handle, handle them */
 
        addik   r5, r1, 0;              /* Arg 1: struct pt_regs *regs */
-       addi  r7, r0, 0;        /* Arg 3: int in_syscall */
-       bralid  r15, do_signal; /* Handle any signals */
-       add     r6, r0, r0;             /* Arg 2: sigset_t *oldset */
+       bralid  r15, do_notify_resume;  /* Handle any signals */
+       addi  r6, r0, 0;        /* Arg 2: int in_syscall */
 
 /* Finally, return to user state.  */
 1:     swi     CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
index 5996711..7f4c7be 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/personality.h>
 #include <linux/percpu.h>
 #include <linux/linkage.h>
+#include <linux/tracehook.h>
 #include <asm/entry.h>
 #include <asm/ucontext.h>
 #include <linux/uaccess.h>
@@ -42,8 +43,6 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall);
-
 asmlinkage long
 sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
                struct pt_regs *regs)
@@ -98,6 +97,9 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
        sigset_t set;
        int rval;
 
+       /* Always make any pending restarted system calls return -EINTR */
+       current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
 
@@ -105,10 +107,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
                goto badframe;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval))
                goto badframe;
@@ -169,7 +168,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
        return (void __user *)((sp - frame_size) & -8UL);
 }
 
-static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                        sigset_t *set, struct pt_regs *regs)
 {
        struct rt_sigframe __user *frame;
@@ -267,12 +266,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                current->comm, current->pid, frame, regs->pc);
 #endif
 
-       return;
+       return 0;
 
 give_sigsegv:
-       if (sig == SIGSEGV)
-               ka->sa.sa_handler = SIG_DFL;
-       force_sig(SIGSEGV, current);
+       force_sigsegv(sig, current);
+       return -EFAULT;
 }
 
 /* Handle restarting system calls */
@@ -316,24 +314,20 @@ static int
 handle_signal(unsigned long sig, struct k_sigaction *ka,
                siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
 {
+       int ret;
+
        /* Set up the stack frame */
        if (ka->sa.sa_flags & SA_SIGINFO)
-               setup_rt_frame(sig, ka, info, oldset, regs);
+               ret = setup_rt_frame(sig, ka, info, oldset, regs);
        else
-               setup_rt_frame(sig, ka, NULL, 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);
-               sigaddset(&current->blocked, sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
-       return 1;
+               ret = setup_rt_frame(sig, ka, NULL, oldset, regs);
+
+       if (ret)
+               return ret;
+
+       block_sigmask(ka, sig);
+
+       return 0;
 }
 
 /*
@@ -345,24 +339,17 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
  * the kernel can handle, and then we build all the user-level signal handling
  * stack-frames in one go after that.
  */
-int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall)
+static void do_signal(struct pt_regs *regs, int in_syscall)
 {
        siginfo_t info;
        int signr;
        struct k_sigaction ka;
+       sigset_t *oldset;
 #ifdef DEBUG_SIG
-       printk(KERN_INFO "do signal: %p %p %d\n", regs, oldset, in_syscall);
+       printk(KERN_INFO "do signal: %p %d\n", regs, in_syscall);
        printk(KERN_INFO "do signal2: %lx %lx %ld [%lx]\n", regs->pc, regs->r1,
                        regs->r12, current_thread_info()->flags);
 #endif
-       /*
-        * We want the common case to go fast, which
-        * is why we may in certain cases get here from
-        * kernel mode. Just return without doing anything
-        * if so.
-        */
-       if (kernel_mode(regs))
-               return 1;
 
        if (current_thread_info()->status & TS_RESTORE_SIGMASK)
                oldset = &current->saved_sigmask;
@@ -374,7 +361,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall)
                /* Whee! Actually deliver the signal. */
                if (in_syscall)
                        handle_restart(regs, &ka, 1);
-               if (handle_signal(signr, &ka, &info, oldset, regs)) {
+               if (!handle_signal(signr, &ka, &info, oldset, regs)) {
                        /*
                         * A signal was successfully delivered; the saved
                         * sigmask will have been stored in the signal frame,
@@ -384,7 +371,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall)
                        current_thread_info()->status &=
                            ~TS_RESTORE_SIGMASK;
                }
-               return 1;
+               return;
        }
 
        if (in_syscall)
@@ -398,7 +385,25 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall)
                current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
                sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
        }
+}
 
-       /* Did we come from a system call? */
-       return 0;
+void do_notify_resume(struct pt_regs *regs, int in_syscall)
+{
+       /*
+        * We want the common case to go fast, which
+        * is why we may in certain cases get here from
+        * kernel mode. Just return without doing anything
+        * if so.
+        */
+       if (kernel_mode(regs))
+               return;
+
+       if (test_thread_flag(TIF_SIGPENDING))
+               do_signal(regs, in_syscall);
+
+       if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) {
+               tracehook_notify_resume(regs);
+               if (current->replacement_session_keyring)
+                       key_replace_session_keyring();
+       }
 }
index d5a338a..17f6ee3 100644 (file)
@@ -255,15 +255,7 @@ asmlinkage int sys_sigsuspend(nabi_no_regargs struct pt_regs regs)
        uset = (sigset_t __user *) regs.regs[4];
        if (copy_from_user(&newset, uset, sizeof(sigset_t)))
                return -EFAULT;
-       sigdelsetmask(&newset, ~_BLOCKABLE);
-
-       current->saved_sigmask = current->blocked;
-       set_current_blocked(&newset);
-
-       current->state = TASK_INTERRUPTIBLE;
-       schedule();
-       set_thread_flag(TIF_RESTORE_SIGMASK);
-       return -ERESTARTNOHAND;
+       return sigsuspend(&newset);
 }
 #endif
 
@@ -281,15 +273,7 @@ asmlinkage int sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
        unewset = (sigset_t __user *) regs.regs[4];
        if (copy_from_user(&newset, unewset, sizeof(newset)))
                return -EFAULT;
-       sigdelsetmask(&newset, ~_BLOCKABLE);
-
-       current->saved_sigmask = current->blocked;
-       set_current_blocked(&newset);
-
-       current->state = TASK_INTERRUPTIBLE;
-       schedule();
-       set_thread_flag(TIF_RESTORE_SIGMASK);
-       return -ERESTARTNOHAND;
+       return sigsuspend(&newset);
 }
 
 #ifdef CONFIG_TRAD_SIGNALS
index ac3b8d8..b4fe2ea 100644 (file)
@@ -288,15 +288,7 @@ asmlinkage int sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
        uset = (compat_sigset_t __user *) regs.regs[4];
        if (get_sigset(&newset, uset))
                return -EFAULT;
-       sigdelsetmask(&newset, ~_BLOCKABLE);
-
-       current->saved_sigmask = current->blocked;
-       set_current_blocked(&newset);
-
-       current->state = TASK_INTERRUPTIBLE;
-       schedule();
-       set_thread_flag(TIF_RESTORE_SIGMASK);
-       return -ERESTARTNOHAND;
+       return sigsuspend(&newset);
 }
 
 asmlinkage int sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
@@ -313,15 +305,7 @@ asmlinkage int sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
        uset = (compat_sigset_t __user *) regs.regs[4];
        if (get_sigset(&newset, uset))
                return -EFAULT;
-       sigdelsetmask(&newset, ~_BLOCKABLE);
-
-       current->saved_sigmask = current->blocked;
-       set_current_blocked(&newset);
-
-       current->state = TASK_INTERRUPTIBLE;
-       schedule();
-       set_thread_flag(TIF_RESTORE_SIGMASK);
-       return -ERESTARTNOHAND;
+       return sigsuspend(&newset);
 }
 
 SYSCALL_DEFINE3(32_sigaction, long, sig, const struct sigaction32 __user *, act,
index 86eb4b0..63ffac9 100644 (file)
@@ -91,15 +91,7 @@ asmlinkage int sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
        if (copy_from_user(&uset, unewset, sizeof(uset)))
                return -EFAULT;
        sigset_from_compat(&newset, &uset);
-       sigdelsetmask(&newset, ~_BLOCKABLE);
-
-       current->saved_sigmask = current->blocked;
-       set_current_blocked(&newset);
-
-       current->state = TASK_INTERRUPTIBLE;
-       schedule();
-       set_thread_flag(TIF_RESTORE_SIGMASK);
-       return -ERESTARTNOHAND;
+       return sigsuspend(&newset);
 }
 
 asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
index 690f4e9..890cf91 100644 (file)
  */
 asmlinkage long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
 {
-       mask &= _BLOCKABLE;
-       spin_lock_irq(&current->sighand->siglock);
-       current->saved_sigmask = current->blocked;
-       siginitset(&current->blocked, mask);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-
-       current->state = TASK_INTERRUPTIBLE;
-       schedule();
-       set_thread_flag(TIF_RESTORE_SIGMASK);
-       return -ERESTARTNOHAND;
+       sigset_t blocked;
+       siginitset(&blocked, mask);
+       return sigsuspend(&blocked);
 }
 
 /*
@@ -172,10 +164,7 @@ asmlinkage long sys_sigreturn(void)
                goto badframe;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
 
        if (restore_sigcontext(current_frame(), &frame->sc, &d0))
                goto badframe;
@@ -203,10 +192,7 @@ asmlinkage long sys_rt_sigreturn(void)
                goto badframe;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
 
        if (restore_sigcontext(current_frame(), &frame->uc.uc_mcontext, &d0))
                goto badframe;
@@ -476,15 +462,8 @@ static int handle_signal(int sig,
        else
                ret = setup_frame(sig, ka, oldset, regs);
 
-       if (ret == 0) {
-               spin_lock_irq(&current->sighand->siglock);
-               sigorsets(&current->blocked, &current->blocked,
-                         &ka->sa.sa_mask);
-               if (!(ka->sa.sa_flags & SA_NODEFER))
-                       sigaddset(&current->blocked, sig);
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
-       }
+       if (ret == 0)
+               block_sigmask(ka, sig);
 
        return ret;
 }
index 12c1ed3..4b9cb0d 100644 (file)
@@ -109,6 +109,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
                sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
 #endif
 
+       current_thread_info()->restart_block.fn = do_no_restart_syscall;
 
        /* Unwind the user stack to get the rt_sigframe structure. */
        frame = (struct rt_sigframe __user *)
@@ -131,10 +132,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
        }
                
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
 
        /* Good thing we saved the old gr[30], eh? */
 #ifdef CONFIG_64BIT
@@ -454,12 +452,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
        if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))
                return 0;
 
-       spin_lock_irq(&current->sighand->siglock);
-       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
-       if (!(ka->sa.sa_flags & SA_NODEFER))
-               sigaddset(&current->blocked,sig);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       block_sigmask(ka, sig);
 
        tracehook_signal_handler(sig, info, ka, regs, 
                test_thread_flag(TIF_SINGLESTEP) ||
@@ -474,8 +467,6 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
        /* Check the return code */
        switch (regs->gr[28]) {
        case -ERESTART_RESTARTBLOCK:
-               current_thread_info()->restart_block.fn =
-                       do_no_restart_syscall;
        case -ERESTARTNOHAND:
                DBG(1,"ERESTARTNOHAND: returning -EINTR\n");
                regs->gr[28] = -EINTR;
index 45eb998..61f6aff 100644 (file)
@@ -204,10 +204,10 @@ static inline int get_old_sigaction(struct k_sigaction *new_ka,
 
        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))
+                       __get_user(new_ka->sa.sa_restorer, &act->sa_restorer) ||
+                       __get_user(new_ka->sa.sa_flags, &act->sa_flags) ||
+                       __get_user(mask, &act->sa_mask))
                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);
        return 0;
 }
@@ -244,17 +244,8 @@ static inline int restore_general_regs(struct pt_regs *regs,
 long sys_sigsuspend(old_sigset_t mask)
 {
        sigset_t blocked;
-
-       current->saved_sigmask = current->blocked;
-
-       mask &= _BLOCKABLE;
        siginitset(&blocked, mask);
-       set_current_blocked(&blocked);
-
-       current->state = TASK_INTERRUPTIBLE;
-       schedule();
-       set_restore_sigmask();
-       return -ERESTARTNOHAND;
+       return sigsuspend(&blocked);
 }
 
 long sys_sigaction(int sig, struct old_sigaction __user *act,
index 8a4e2b7..f626232 100644 (file)
@@ -59,15 +59,8 @@ typedef struct
 SYSCALL_DEFINE3(sigsuspend, int, history0, int, history1, old_sigset_t, mask)
 {
        sigset_t blocked;
-
-       current->saved_sigmask = current->blocked;
-       mask &= _BLOCKABLE;
        siginitset(&blocked, mask);
-       set_current_blocked(&blocked);
-       set_current_state(TASK_INTERRUPTIBLE);
-       schedule();
-       set_restore_sigmask();
-       return -ERESTARTNOHAND;
+       return sigsuspend(&blocked);
 }
 
 SYSCALL_DEFINE3(sigaction, int, sig, const struct old_sigaction __user *, act,
index aa57440..d4a4901 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
 #include <linux/uaccess.h>
+#include <linux/tracehook.h>
 
 #include <asm/cacheflush.h>
 #include <asm/syscalls.h>
@@ -152,6 +153,9 @@ score_rt_sigreturn(struct pt_regs *regs)
        stack_t st;
        int sig;
 
+       /* Always make any pending restarted system calls return -EINTR */
+       current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
        frame = (struct rt_sigframe __user *) regs->regs[0];
        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
@@ -159,10 +163,7 @@ score_rt_sigreturn(struct pt_regs *regs)
                goto badframe;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
 
        sig = restore_sigcontext(regs, &frame->rs_uc.uc_mcontext);
        if (sig < 0)
@@ -236,9 +237,7 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
        return 0;
 
 give_sigsegv:
-       if (signr == SIGSEGV)
-               ka->sa.sa_handler = SIG_DFL;
-       force_sig(SIGSEGV, current);
+       force_sigsegv(signr, current);
        return -EFAULT;
 }
 
@@ -272,12 +271,8 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
         */
        ret = setup_rt_frame(ka, regs, sig, oldset, info);
 
-       spin_lock_irq(&current->sighand->siglock);
-       sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
-       if (!(ka->sa.sa_flags & SA_NODEFER))
-               sigaddset(&current->blocked, sig);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       if (ret == 0)
+               block_sigmask(ka, sig);
 
        return ret;
 }
@@ -356,6 +351,12 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
                                __u32 thread_info_flags)
 {
        /* deal with pending signal delivery */
-       if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+       if (thread_info_flags & _TIF_SIGPENDING)
                do_signal(regs);
+       if (thread_info_flags & _TIF_NOTIFY_RESUME) {
+               clear_thread_flag(TIF_NOTIFY_RESUME);
+               tracehook_notify_resume(regs);
+               if (current->replacement_session_keyring)
+                       key_replace_session_keyring();
+       }
 }
index ae717e3..6c1fa55 100644 (file)
@@ -23,9 +23,7 @@ asmlinkage int sys_execve(const char __user *ufilename,
                          const char __user *const __user *uargv,
                          const char __user *const __user *uenvp,
                          unsigned long r7, struct pt_regs __regs);
-asmlinkage int sys_sigsuspend(old_sigset_t mask, unsigned long r5,
-                             unsigned long r6, unsigned long r7,
-                             struct pt_regs __regs);
+asmlinkage int sys_sigsuspend(old_sigset_t mask);
 asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user *act,
                             struct old_sigaction __user *oact);
 asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
index a42a561..e800a38 100644 (file)
@@ -1,13 +1,11 @@
 #ifdef __KERNEL__
 # ifdef CONFIG_SUPERH32
-
 #  include "unistd_32.h"
-#  define __ARCH_WANT_SYS_RT_SIGSUSPEND
-
 # else
 #  include "unistd_64.h"
 # endif
 
+# define __ARCH_WANT_SYS_RT_SIGSUSPEND
 # define __ARCH_WANT_IPC_PARSE_VERSION
 # define __ARCH_WANT_OLD_READDIR
 # define __ARCH_WANT_OLD_STAT
index 5901fba..cb4172c 100644 (file)
@@ -53,23 +53,11 @@ struct fdpic_func_descriptor {
  * Atomically swap in the new signal mask, and wait for a signal.
  */
 asmlinkage int
-sys_sigsuspend(old_sigset_t mask,
-              unsigned long r5, unsigned long r6, unsigned long r7,
-              struct pt_regs __regs)
+sys_sigsuspend(old_sigset_t mask)
 {
        sigset_t blocked;
-
-       current->saved_sigmask = current->blocked;
-
-       mask &= _BLOCKABLE;
        siginitset(&blocked, mask);
-       set_current_blocked(&blocked);
-
-       current->state = TASK_INTERRUPTIBLE;
-       schedule();
-       set_restore_sigmask();
-
-       return -ERESTARTNOHAND;
+       return sigsuspend(&blocked);
 }
 
 asmlinkage int
@@ -83,10 +71,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *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))
+                   __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
+                   __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
+                   __get_user(mask, &act->sa_mask))
                        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);
        }
 
@@ -95,10 +83,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
        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))
+                   __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
+                   __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
+                   __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
                        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;
@@ -162,12 +150,11 @@ static inline int save_sigcontext_fpu(struct sigcontext __user *sc,
        if (!(boot_cpu_data.flags & CPU_HAS_FPU))
                return 0;
 
-       if (!used_math()) {
-               __put_user(0, &sc->sc_ownedfp);
-               return 0;
-       }
+       if (!used_math())
+               return __put_user(0, &sc->sc_ownedfp);
 
-       __put_user(1, &sc->sc_ownedfp);
+       if (__put_user(1, &sc->sc_ownedfp))
+               return -EFAULT;
 
        /* This will cause a "finit" to be triggered by the next
           attempted FPU operation by the 'current' process.
@@ -207,7 +194,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p
                regs->sr |= SR_FD; /* Release FPU */
                clear_fpu(tsk, regs);
                clear_used_math();
-               __get_user (owned_fp, &sc->sc_ownedfp);
+               err |= __get_user (owned_fp, &sc->sc_ownedfp);
                if (owned_fp)
                        err |= restore_sigcontext_fpu(sc);
        }
@@ -398,11 +385,14 @@ static int setup_frame(int sig, struct k_sigaction *ka,
                struct fdpic_func_descriptor __user *funcptr =
                        (struct fdpic_func_descriptor __user *)ka->sa.sa_handler;
 
-               __get_user(regs->pc, &funcptr->text);
-               __get_user(regs->regs[12], &funcptr->GOT);
+               err |= __get_user(regs->pc, &funcptr->text);
+               err |= __get_user(regs->regs[12], &funcptr->GOT);
        } else
                regs->pc = (unsigned long)ka->sa.sa_handler;
 
+       if (err)
+               goto give_sigsegv;
+
        set_fs(USER_DS);
 
        pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
@@ -482,11 +472,14 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                struct fdpic_func_descriptor __user *funcptr =
                        (struct fdpic_func_descriptor __user *)ka->sa.sa_handler;
 
-               __get_user(regs->pc, &funcptr->text);
-               __get_user(regs->regs[12], &funcptr->GOT);
+               err |= __get_user(regs->pc, &funcptr->text);
+               err |= __get_user(regs->regs[12], &funcptr->GOT);
        } else
                regs->pc = (unsigned long)ka->sa.sa_handler;
 
+       if (err)
+               goto give_sigsegv;
+
        set_fs(USER_DS);
 
        pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
index 3c9a6f7..b589a35 100644 (file)
@@ -83,11 +83,12 @@ handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa)
  * the kernel can handle, and then we build all the user-level signal handling
  * stack-frames in one go after that.
  */
-static int do_signal(struct pt_regs *regs, sigset_t *oldset)
+static void do_signal(struct pt_regs *regs)
 {
        siginfo_t info;
        int signr;
        struct k_sigaction ka;
+       sigset_t *oldset;
 
        /*
         * We want the common case to go fast, which
@@ -96,11 +97,11 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset)
         * if so.
         */
        if (!user_mode(regs))
-               return 1;
+               return;
 
        if (current_thread_info()->status & TS_RESTORE_SIGMASK)
                oldset = &current->saved_sigmask;
-       else if (!oldset)
+       else
                oldset = &current->blocked;
 
        signr = get_signal_to_deliver(&info, &ka, regs, 0);
@@ -118,7 +119,7 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset)
 
                        tracehook_signal_handler(signr, &info, &ka, regs,
                                        test_thread_flag(TIF_SINGLESTEP));
-                       return 1;
+                       return;
                }
        }
 
@@ -147,71 +148,18 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset)
                sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
        }
 
-       return 0;
+       return;
 }
 
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
 asmlinkage int
-sys_sigsuspend(old_sigset_t mask,
-              unsigned long r3, unsigned long r4, unsigned long r5,
-              unsigned long r6, unsigned long r7,
-              struct pt_regs * regs)
+sys_sigsuspend(old_sigset_t mask)
 {
-       sigset_t saveset, blocked;
-
-       saveset = current->blocked;
-
-       mask &= _BLOCKABLE;
+       sigset_t blocked;
        siginitset(&blocked, mask);
-       set_current_blocked(&blocked);
-
-       REF_REG_RET = -EINTR;
-       while (1) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule();
-               set_restore_sigmask();
-               regs->pc += 4;    /* because sys_sigreturn decrements the pc */
-               if (do_signal(regs, &saveset)) {
-                       /* pc now points at signal handler. Need to decrement
-                          it because entry.S will increment it. */
-                       regs->pc -= 4;
-                       return -EINTR;
-               }
-       }
-}
-
-asmlinkage int
-sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize,
-                 unsigned long r4, unsigned long r5, unsigned long r6,
-                 unsigned long r7,
-                 struct pt_regs * regs)
-{
-       sigset_t saveset, newset;
-
-       /* XXX: Don't preclude handling different sized sigset_t's.  */
-       if (sigsetsize != sizeof(sigset_t))
-               return -EINVAL;
-
-       if (copy_from_user(&newset, unewset, sizeof(newset)))
-               return -EFAULT;
-       sigdelsetmask(&newset, ~_BLOCKABLE);
-       saveset = current->blocked;
-       set_current_blocked(&newset);
-
-       REF_REG_RET = -EINTR;
-       while (1) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule();
-               regs->pc += 4;    /* because sys_sigreturn decrements the pc */
-               if (do_signal(regs, &saveset)) {
-                       /* pc now points at signal handler. Need to decrement
-                          it because entry.S will increment it. */
-                       regs->pc -= 4;
-                       return -EINTR;
-               }
-       }
+       return sigsuspend(&blocked);
 }
 
 asmlinkage int
@@ -225,10 +173,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *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))
+                   __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
+                   __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
+                   __get_user(mask, &act->sa_mask))
                        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);
        }
 
@@ -237,10 +185,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
        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))
+                   __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
+                   __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
+                   __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
                        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;
@@ -732,7 +680,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
 asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
 {
        if (thread_info_flags & _TIF_SIGPENDING)
-               do_signal(regs, 0);
+               do_signal(regs);
 
        if (thread_info_flags & _TIF_NOTIFY_RESUME) {
                clear_thread_flag(TIF_NOTIFY_RESUME);
index 948700f..bb1513e 100644 (file)
@@ -215,8 +215,9 @@ void do_sigreturn32(struct pt_regs *regs)
            (((unsigned long) sf) & 3))
                goto segv;
 
-       get_user(pc, &sf->info.si_regs.pc);
-       __get_user(npc, &sf->info.si_regs.npc);
+       if (get_user(pc, &sf->info.si_regs.pc) ||
+           __get_user(npc, &sf->info.si_regs.npc))
+               goto segv;
 
        if ((pc | npc) & 3)
                goto segv;
@@ -305,8 +306,9 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
            (((unsigned long) sf) & 3))
                goto segv;
 
-       get_user(pc, &sf->regs.pc);
-       __get_user(npc, &sf->regs.npc);
+       if (get_user(pc, &sf->regs.pc) || 
+           __get_user(npc, &sf->regs.npc))
+               goto segv;
 
        if ((pc | npc) & 3)
                goto segv;
index ac8e66b..2b7e849 100644 (file)
@@ -64,18 +64,8 @@ struct rt_signal_frame {
 static int _sigpause_common(old_sigset_t set)
 {
        sigset_t blocked;
-
-       current->saved_sigmask = current->blocked;
-
-       set &= _BLOCKABLE;
        siginitset(&blocked, set);
-       set_current_blocked(&blocked);
-
-       current->state = TASK_INTERRUPTIBLE;
-       schedule();
-       set_thread_flag(TIF_RESTORE_SIGMASK);
-
-       return -ERESTARTNOHAND;
+       return sigsuspend(&blocked);
 }
 
 asmlinkage int sys_sigsuspend(old_sigset_t set)
index 48b0f57..eafaab4 100644 (file)
@@ -242,19 +242,8 @@ struct rt_signal_frame {
 static long _sigpause_common(old_sigset_t set)
 {
        sigset_t blocked;
-
-       current->saved_sigmask = current->blocked;
-
-       set &= _BLOCKABLE;
        siginitset(&blocked, set);
-       set_current_blocked(&blocked);
-
-       current->state = TASK_INTERRUPTIBLE;
-       schedule();
-
-       set_restore_sigmask();
-
-       return -ERESTARTNOHAND;
+       return sigsuspend(&blocked);
 }
 
 asmlinkage long sys_sigpause(unsigned int set)
index 627e89a..0c9b31b 100644 (file)
@@ -184,10 +184,10 @@ sparc_sigaction (int sig, const struct old_sigaction __user *act,
 
                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))
+                   __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
+                   __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
+                   __get_user(mask, &act->sa_mask))
                        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);
                new_ka.ka_restorer = NULL;
        }
@@ -195,17 +195,12 @@ sparc_sigaction (int sig, const struct old_sigaction __user *act,
        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 
        if (!ret && oact) {
-               /* In the clone() case we could copy half consistent
-                * state to the user, however this could sleep and
-                * deadlock us if we held the signal lock on SMP.  So for
-                * now I take the easy way out and do no locking.
-                */
                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))
+                   __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
+                   __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
+                   __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
                        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;
index 187118f..292e706 100644 (file)
@@ -148,15 +148,8 @@ int do_signal(void)
 long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
 {
        sigset_t blocked;
-
-       mask &= _BLOCKABLE;
        siginitset(&blocked, mask);
-       set_current_blocked(&blocked);
-
-       current->state = TASK_INTERRUPTIBLE;
-       schedule();
-       set_thread_flag(TIF_RESTORE_SIGMASK);
-       return -ERESTARTNOHAND;
+       return sigsuspend(&blocked);
 }
 
 long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
index 911b549..7754df6 100644 (file)
@@ -370,10 +370,7 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
        /*
         * Block the signal if we were successful.
         */
-       sigorsets(&blocked, &tsk->blocked, &ka->sa.sa_mask);
-       if (!(ka->sa.sa_flags & SA_NODEFER))
-               sigaddset(&blocked, sig);
-       set_current_blocked(&blocked);
+       block_sigmask(ka, sig);
 
        return 0;
 }
@@ -450,15 +447,12 @@ static void do_signal(struct pt_regs *regs, int syscall)
                    regs->UCreg_00 == -ERESTARTNOINTR) {
                        setup_syscall_restart(regs);
                }
-
-               /* If there's no signal to deliver, we just put the saved
-                * sigmask back.
-                */
-               if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-                       clear_thread_flag(TIF_RESTORE_SIGMASK);
-                       sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-               }
        }
+       /* If there's no signal to deliver, we just put the saved
+        * sigmask back.
+        */
+       if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
+               set_current_blocked(&current->saved_sigmask);
 }
 
 asmlinkage void do_notify_resume(struct pt_regs *regs,
index 0b3f235..98bd70f 100644 (file)
@@ -131,18 +131,8 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
 asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask)
 {
        sigset_t blocked;
-
-       current->saved_sigmask = current->blocked;
-
-       mask &= _BLOCKABLE;
        siginitset(&blocked, mask);
-       set_current_blocked(&blocked);
-
-       current->state = TASK_INTERRUPTIBLE;
-       schedule();
-
-       set_restore_sigmask();
-       return -ERESTARTNOHAND;
+       return sigsuspend(&blocked);
 }
 
 asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
index 115eac4..b68ccad 100644 (file)
@@ -478,18 +478,8 @@ asmlinkage int
 sys_sigsuspend(int history0, int history1, old_sigset_t mask)
 {
        sigset_t blocked;
-
-       current->saved_sigmask = current->blocked;
-
-       mask &= _BLOCKABLE;
        siginitset(&blocked, mask);
-       set_current_blocked(&blocked);
-
-       current->state = TASK_INTERRUPTIBLE;
-       schedule();
-
-       set_restore_sigmask();
-       return -ERESTARTNOHAND;
+       return sigsuspend(&blocked);
 }
 
 asmlinkage int
index 633ba73..7f201b9 100644 (file)
@@ -120,13 +120,6 @@ typedef void (*__sighandler_t)(int);
 #define SIG_ERR        ((__sighandler_t)-1)    /* error return from signal */
 
 #ifdef __KERNEL__
-struct old_sigaction {
-       __sighandler_t sa_handler;
-       old_sigset_t sa_mask;
-       unsigned long sa_flags;
-       void (*sa_restorer)(void);
-};
-
 struct sigaction {
        __sighandler_t sa_handler;
        unsigned long sa_flags;
index efcf33b..0b9f2e1 100644 (file)
@@ -15,10 +15,6 @@ asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*);
 asmlinkage long xtensa_ptrace(long, long, long, long);
 asmlinkage long xtensa_sigreturn(struct pt_regs*);
 asmlinkage long xtensa_rt_sigreturn(struct pt_regs*);
-asmlinkage long xtensa_sigsuspend(struct pt_regs*);
-asmlinkage long xtensa_rt_sigsuspend(struct pt_regs*);
-asmlinkage long xtensa_sigaction(int, const struct old_sigaction*,
-                                struct old_sigaction*);
 asmlinkage long xtensa_sigaltstack(struct pt_regs *regs);
 asmlinkage long sys_rt_sigaction(int,
                                 const struct sigaction __user *,
index 6abbedd..81abfd5 100644 (file)
@@ -131,6 +131,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_IRET               4       /* return with iret */
 #define TIF_MEMDIE             5       /* is terminating due to OOM killer */
 #define TIF_RESTORE_SIGMASK    6       /* restore signal mask in do_signal() */
+#define TIF_NOTIFY_RESUME      7       /* callback before returning to user */
 #define TIF_POLLING_NRFLAG     16      /* true if poll_idle() is polling TIF_NEED_RESCHED */
 
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
index 798ee6d..bc7e005 100644 (file)
@@ -507,7 +507,7 @@ __SYSCALL(229, sys_rt_sigtimedwait, 4)
 #define __NR_rt_sigqueueinfo                   230
 __SYSCALL(230, sys_rt_sigqueueinfo, 3)
 #define __NR_rt_sigsuspend                     231
-__SYSCALL(231, xtensa_rt_sigsuspend, 2)
+__SYSCALL(231, sys_rt_sigsuspend, 2)
 
 /* Message */
 
index 6223f33..7e62360 100644 (file)
@@ -409,16 +409,16 @@ common_exception_return:
        l32i    a4, a2, TI_FLAGS
 
        _bbsi.l a4, TIF_NEED_RESCHED, 3f
+       _bbsi.l a4, TIF_NOTIFY_RESUME, 2f
        _bbci.l a4, TIF_SIGPENDING, 4f
 
-       l32i    a4, a1, PT_DEPC
+2:     l32i    a4, a1, PT_DEPC
        bgeui   a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f
 
        /* Call do_signal() */
 
-       movi    a4, do_signal   # int do_signal(struct pt_regs*, sigset_t*)
+       movi    a4, do_notify_resume    # int do_notify_resume(struct pt_regs*)
        mov     a6, a1
-       movi    a7, 0
        callx4  a4
        j       1b
 
index d78869a..c5e4ec0 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/ptrace.h>
 #include <linux/personality.h>
 #include <linux/freezer.h>
+#include <linux/tracehook.h>
 
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
@@ -31,8 +32,6 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
-
 extern struct task_struct *coproc_owners[];
 
 struct rt_sigframe
@@ -248,6 +247,9 @@ asmlinkage long xtensa_rt_sigreturn(long a0, long a1, long a2, long a3,
        sigset_t set;
        int ret;
 
+       /* Always make any pending restarted system calls return -EINTR */
+       current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
        if (regs->depc > 64)
                panic("rt_sigreturn in double exception!\n");
 
@@ -426,37 +428,6 @@ give_sigsegv:
        return -EFAULT;
 }
 
-/*
- * Atomically swap in the new signal mask, and wait for a signal.
- */
-
-asmlinkage long xtensa_rt_sigsuspend(sigset_t __user *unewset, 
-                                    size_t sigsetsize,
-                                    long a2, long a3, long a4, long a5, 
-                                    struct pt_regs *regs)
-{
-       sigset_t saveset, newset;
-
-       /* XXX: Don't preclude handling different sized sigset_t's.  */
-       if (sigsetsize != sizeof(sigset_t))
-               return -EINVAL;
-
-       if (copy_from_user(&newset, unewset, sizeof(newset)))
-               return -EFAULT;
-
-       sigdelsetmask(&newset, ~_BLOCKABLE);
-       saveset = current->blocked;
-       set_current_blocked(&newset);
-
-       regs->areg[2] = -EINTR;
-       while (1) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule();
-               if (do_signal(regs, &saveset))
-                       return -EINTR;
-       }
-}
-
 asmlinkage long xtensa_sigaltstack(const stack_t __user *uss, 
                                   stack_t __user *uoss,
                                   long a2, long a3, long a4, long a5,
@@ -476,19 +447,19 @@ asmlinkage long xtensa_sigaltstack(const stack_t __user *uss,
  * the kernel can handle, and then we build all the user-level signal handling
  * stack-frames in one go after that.
  */
-int do_signal(struct pt_regs *regs, sigset_t *oldset)
+static void do_signal(struct pt_regs *regs)
 {
        siginfo_t info;
        int signr;
        struct k_sigaction ka;
-
-       if (!user_mode(regs))
-               return 0;
+       sigset_t oldset;
 
        if (try_to_freeze())
                goto no_signal;
 
-       if (!oldset)
+       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+               oldset = &current->saved_sigmask;
+       else
                oldset = &current->blocked;
 
        task_pt_regs(current)->icountlevel = 0;
@@ -532,13 +503,14 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
                /* Set up the stack frame */
                ret = setup_frame(signr, &ka, &info, oldset, regs);
                if (ret)
-                       return ret;
+                       return;
 
+               clear_thread_flag(TIF_RESTORE_SIGMASK);
                block_sigmask(&ka, signr);
                if (current->ptrace & PT_SINGLESTEP)
                        task_pt_regs(current)->icountlevel = 1;
 
-               return 1;
+               return;
        }
 
 no_signal:
@@ -558,8 +530,27 @@ no_signal:
                        break;
                }
        }
+
+       /* If there's no signal to deliver, we just restore the saved mask.  */
+       if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
+               set_current_blocked(&current->saved_sigmask);
+
        if (current->ptrace & PT_SINGLESTEP)
                task_pt_regs(current)->icountlevel = 1;
-       return 0;
+       return;
 }
 
+void do_notify_resume(struct pt_regs *regs)
+{
+       if (!user_mode(regs))
+               return;
+
+       if (test_thread_flag(TIF_SIGPENDING))
+               do_signal(regs);
+
+       if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) {
+               tracehook_notify_resume(regs);
+               if (current->replacement_session_keyring)
+                       key_replace_session_keyring();
+       }
+}
index 7987ce7..17046cc 100644 (file)
@@ -252,6 +252,7 @@ extern int do_sigtimedwait(const sigset_t *, siginfo_t *,
 extern int sigprocmask(int, sigset_t *, sigset_t *);
 extern void set_current_blocked(const sigset_t *);
 extern int show_unhandled_signals;
+extern int sigsuspend(sigset_t *);
 
 extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie);
 extern void block_sigmask(struct k_sigaction *ka, int signr);
index d2c67aa..c28a306 100644 (file)
@@ -1073,15 +1073,7 @@ asmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, compat
        if (copy_from_user(&newset32, unewset, sizeof(compat_sigset_t)))
                return -EFAULT;
        sigset_from_compat(&newset, &newset32);
-       sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP));
-
-       current->saved_sigmask = current->blocked;
-       set_current_blocked(&newset);
-
-       current->state = TASK_INTERRUPTIBLE;
-       schedule();
-       set_restore_sigmask();
-       return -ERESTARTNOHAND;
+       return sigsuspend(&newset);
 }
 #endif /* __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND */
 
index 21ebe75..4dbf00d 100644 (file)
@@ -3232,6 +3232,21 @@ SYSCALL_DEFINE0(pause)
 
 #endif
 
+#ifdef HAVE_SET_RESTORE_SIGMASK
+int sigsuspend(sigset_t *set)
+{
+       sigdelsetmask(set, sigmask(SIGKILL)|sigmask(SIGSTOP));
+
+       current->saved_sigmask = current->blocked;
+       set_current_blocked(set);
+
+       current->state = TASK_INTERRUPTIBLE;
+       schedule();
+       set_restore_sigmask();
+       return -ERESTARTNOHAND;
+}
+#endif
+
 #ifdef __ARCH_WANT_SYS_RT_SIGSUSPEND
 /**
  *  sys_rt_sigsuspend - replace the signal mask for a value with the
@@ -3249,15 +3264,7 @@ SYSCALL_DEFINE2(rt_sigsuspend, sigset_t __user *, unewset, size_t, sigsetsize)
 
        if (copy_from_user(&newset, unewset, sizeof(newset)))
                return -EFAULT;
-       sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP));
-
-       current->saved_sigmask = current->blocked;
-       set_current_blocked(&newset);
-
-       current->state = TASK_INTERRUPTIBLE;
-       schedule();
-       set_restore_sigmask();
-       return -ERESTARTNOHAND;
+       return sigsuspend(&newset);
 }
 #endif /* __ARCH_WANT_SYS_RT_SIGSUSPEND */