瀏覽代碼

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal

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()
  ...
Linus Torvalds 13 年之前
父節點
當前提交
f9369910a6
共有 54 個文件被更改,包括 386 次插入817 次删除
  1. 27 53
      arch/alpha/kernel/signal.c
  2. 1 10
      arch/arm/kernel/signal.c
  3. 0 7
      arch/avr32/include/asm/signal.h
  4. 12 18
      arch/avr32/kernel/signal.c
  5. 5 16
      arch/blackfin/kernel/signal.c
  6. 3 0
      arch/c6x/kernel/signal.c
  7. 15 35
      arch/cris/arch-v10/kernel/signal.c
  8. 16 50
      arch/cris/arch-v32/kernel/signal.c
  9. 13 34
      arch/frv/kernel/signal.c
  10. 1 0
      arch/h8300/include/asm/unistd.h
  11. 39 83
      arch/h8300/kernel/signal.c
  12. 0 6
      arch/h8300/kernel/syscalls.S
  13. 4 0
      arch/hexagon/kernel/signal.c
  14. 2 13
      arch/ia64/kernel/signal.c
  15. 0 7
      arch/m32r/include/asm/signal.h
  16. 2 10
      arch/m32r/kernel/signal.c
  17. 1 0
      arch/m68k/include/asm/thread_info.h
  18. 3 3
      arch/m68k/kernel/entry_mm.S
  19. 20 21
      arch/m68k/kernel/signal.c
  20. 1 1
      arch/m68k/platform/68328/entry.S
  21. 1 1
      arch/m68k/platform/68360/entry.S
  22. 1 1
      arch/m68k/platform/coldfire/entry.S
  23. 7 13
      arch/microblaze/kernel/entry-nommu.S
  24. 13 17
      arch/microblaze/kernel/entry.S
  25. 45 40
      arch/microblaze/kernel/signal.c
  26. 2 18
      arch/mips/kernel/signal.c
  27. 2 18
      arch/mips/kernel/signal32.c
  28. 1 9
      arch/mips/kernel/signal_n32.c
  29. 7 28
      arch/mn10300/kernel/signal.c
  30. 3 12
      arch/parisc/kernel/signal.c
  31. 4 13
      arch/powerpc/kernel/signal_32.c
  32. 1 8
      arch/s390/kernel/signal.c
  33. 15 14
      arch/score/kernel/signal.c
  34. 1 3
      arch/sh/include/asm/syscalls_32.h
  35. 1 3
      arch/sh/include/asm/unistd.h
  36. 23 30
      arch/sh/kernel/signal_32.c
  37. 16 68
      arch/sh/kernel/signal_64.c
  38. 6 4
      arch/sparc/kernel/signal32.c
  39. 1 11
      arch/sparc/kernel/signal_32.c
  40. 1 12
      arch/sparc/kernel/signal_64.c
  41. 6 11
      arch/sparc/kernel/sys_sparc_32.c
  42. 1 8
      arch/um/kernel/signal.c
  43. 6 12
      arch/unicore32/kernel/signal.c
  44. 1 11
      arch/x86/ia32/ia32_signal.c
  45. 1 11
      arch/x86/kernel/signal.c
  46. 0 7
      arch/xtensa/include/asm/signal.h
  47. 0 4
      arch/xtensa/include/asm/syscall.h
  48. 1 0
      arch/xtensa/include/asm/thread_info.h
  49. 1 1
      arch/xtensa/include/asm/unistd.h
  50. 3 3
      arch/xtensa/kernel/entry.S
  51. 32 41
      arch/xtensa/kernel/signal.c
  52. 1 0
      include/linux/signal.h
  53. 1 9
      kernel/compat.c
  54. 16 9
      kernel/signal.c

+ 27 - 53
arch/alpha/kernel/signal.c

@@ -34,9 +34,6 @@
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
 
 asmlinkage void ret_from_sys_call(void);
 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
  * 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)
 SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask)
 {
 {
 	sigset_t blocked;
 	sigset_t blocked;
-
-	current->saved_sigmask = current->blocked;
-
-	mask &= _BLOCKABLE;
 	siginitset(&blocked, mask);
 	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
 asmlinkage int
@@ -376,11 +364,11 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
 	oldsp = rdusp();
 	oldsp = rdusp();
 	frame = get_sigframe(ka, oldsp, sizeof(*frame));
 	frame = get_sigframe(ka, oldsp, sizeof(*frame));
 	if (!access_ok(VERIFY_WRITE, frame, 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);
 	err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp);
 	if (err)
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 
 	/* Set up to return from userspace.  If provided, use a stub
 	/* Set up to return from userspace.  If provided, use a stub
 	   already in userspace.  */
 	   already in userspace.  */
@@ -396,7 +384,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
 
 
 	/* Check that everything was written properly.  */
 	/* Check that everything was written properly.  */
 	if (err)
 	if (err)
-		goto give_sigsegv;
+		return err;
 
 
 	/* "Return" to the handler */
 	/* "Return" to the handler */
 	regs->r26 = r26;
 	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",
 	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
 		current->comm, current->pid, frame, regs->pc, regs->r26);
 		current->comm, current->pid, frame, regs->pc, regs->r26);
 #endif
 #endif
-
 	return 0;
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	return -EFAULT;
 }
 }
 
 
 static int
 static int
@@ -428,7 +411,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	oldsp = rdusp();
 	oldsp = rdusp();
 	frame = get_sigframe(ka, oldsp, sizeof(*frame));
 	frame = get_sigframe(ka, oldsp, sizeof(*frame));
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
-		goto give_sigsegv;
+		return -EFAULT;
 
 
 	err |= copy_siginfo_to_user(&frame->info, info);
 	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);
 				set->sig[0], oldsp);
 	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 	if (err)
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 
 	/* Set up to return from userspace.  If provided, use a stub
 	/* Set up to return from userspace.  If provided, use a stub
 	   already in userspace.  */
 	   already in userspace.  */
@@ -459,7 +442,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	}
 	}
 
 
 	if (err)
 	if (err)
-		goto give_sigsegv;
+		return -EFAULT;
 
 
 	/* "Return" to the handler */
 	/* "Return" to the handler */
 	regs->r26 = r26;
 	regs->r26 = r26;
@@ -475,31 +458,37 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 #endif
 #endif
 
 
 	return 0;
 	return 0;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	return -EFAULT;
 }
 }
 
 
 
 
 /*
 /*
  * OK, we're invoking a handler.
  * OK, we're invoking a handler.
  */
  */
-static inline int
+static inline void
 handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
 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;
 	int ret;
 
 
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+
 	if (ka->sa.sa_flags & SA_SIGINFO)
 	if (ka->sa.sa_flags & SA_SIGINFO)
 		ret = setup_rt_frame(sig, ka, info, oldset, regs, sw);
 		ret = setup_rt_frame(sig, ka, info, oldset, regs, sw);
 	else
 	else
 		ret = setup_frame(sig, ka, oldset, regs, sw);
 		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
 static inline void
@@ -547,12 +536,6 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw,
 	int signr;
 	int signr;
 	unsigned long single_stepping = ptrace_cancel_bpt(current);
 	unsigned long single_stepping = ptrace_cancel_bpt(current);
 	struct k_sigaction ka;
 	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, ... */
 	/* This lets the debugger run, ... */
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	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.  */
 		/* Whee!  Actually deliver the signal.  */
 		if (r0)
 		if (r0)
 			syscall_restart(r0, r19, regs, &ka);
 			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) 
 		if (single_stepping) 
 			ptrace_set_bpt(current); /* re-set bpt */
 			ptrace_set_bpt(current); /* re-set bpt */
 		return;
 		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 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)
 	if (single_stepping)
 		ptrace_set_bpt(current);	/* re-set breakpoint */
 		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 thread_info_flags,
 		 unsigned long r0, unsigned long r19)
 		 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);
 		do_signal(regs, sw, r0, r19);
 
 
 	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
 	if (thread_info_flags & _TIF_NOTIFY_RESUME) {

+ 1 - 10
arch/arm/kernel/signal.c

@@ -67,17 +67,8 @@ const unsigned long syscall_restart_code[2] = {
 asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask)
 asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask)
 {
 {
 	sigset_t blocked;
 	sigset_t blocked;
-
-	current->saved_sigmask = current->blocked;
-
-	mask &= _BLOCKABLE;
 	siginitset(&blocked, mask);
 	siginitset(&blocked, mask);
-	set_current_blocked(&blocked);
-
-	current->state = TASK_INTERRUPTIBLE;
-	schedule();
-	set_restore_sigmask();
-	return -ERESTARTNOHAND;
+	return sigsuspend(&blocked);
 }
 }
 
 
 asmlinkage int 
 asmlinkage int 

+ 0 - 7
arch/avr32/include/asm/signal.h

@@ -115,13 +115,6 @@ typedef unsigned long sigset_t;
 #include <asm-generic/signal-defs.h>
 #include <asm-generic/signal-defs.h>
 
 
 #ifdef __KERNEL__
 #ifdef __KERNEL__
-struct old_sigaction {
-	__sighandler_t sa_handler;
-	old_sigset_t sa_mask;
-	unsigned long sa_flags;
-	__sigrestore_t sa_restorer;
-};
-
 struct sigaction {
 struct sigaction {
 	__sighandler_t sa_handler;
 	__sighandler_t sa_handler;
 	unsigned long sa_flags;
 	unsigned long sa_flags;

+ 12 - 18
arch/avr32/kernel/signal.c

@@ -77,6 +77,9 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
 	struct rt_sigframe __user *frame;
 	struct rt_sigframe __user *frame;
 	sigset_t set;
 	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;
 	frame = (struct rt_sigframe __user *)regs->sp;
 	pr_debug("SIG return: frame = %p\n", frame);
 	pr_debug("SIG return: frame = %p\n", frame);
 
 
@@ -87,10 +90,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
 		goto badframe;
 		goto badframe;
 
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
 	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))
 	if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
 		goto badframe;
 		goto badframe;
@@ -238,22 +238,16 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
 	 */
 	 */
 	ret |= !valid_user_regs(regs);
 	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;
 		return;
+	}
 
 
-	force_sigsegv(sig, current);
+	/*
+	 * Block the signal if we were successful.
+	 */
+	block_sigmask(ka, sig);
+	clear_thread_flag(TIF_RESTORE_SIGMASK);
 }
 }
 
 
 /*
 /*

+ 5 - 16
arch/blackfin/kernel/signal.c

@@ -99,10 +99,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
 		goto badframe;
 		goto badframe;
 
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
 	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))
 	if (rt_restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
 		goto badframe;
 		goto badframe;
@@ -213,9 +210,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
 	return 0;
 	return 0;
 
 
  give_sigsegv:
  give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 	return -EFAULT;
 	return -EFAULT;
 }
 }
 
 
@@ -266,15 +261,9 @@ handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
 	/* set up the stack frame */
 	/* set up the stack frame */
 	ret = setup_rt_frame(sig, ka, info, oldset, regs);
 	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;
 	return ret;
 }
 }
 
 

+ 3 - 0
arch/c6x/kernel/signal.c

@@ -69,6 +69,9 @@ asmlinkage int do_rt_sigreturn(struct pt_regs *regs)
 	struct rt_sigframe __user *frame;
 	struct rt_sigframe __user *frame;
 	sigset_t set;
 	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,
 	 * Since we stacked the signal on a dword boundary,
 	 * 'sp' should be dword aligned here.  If it's
 	 * 'sp' should be dword aligned here.  If it's

+ 15 - 35
arch/cris/arch-v10/kernel/signal.c

@@ -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
  * dummy arguments to be able to reach the regs argument.  (Note that this
  * arrangement relies on old_sigset_t occupying one register.)
  * 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,
 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;
 		old_sigset_t mask;
 		if (!access_ok(VERIFY_READ, act, sizeof(*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_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;
 			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);
 		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 (!ret && oact) {
 		if (!access_ok(VERIFY_WRITE, oact, sizeof(*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_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;
 			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;
 	return ret;
@@ -185,10 +177,7 @@ asmlinkage int sys_sigreturn(long r10, long r11, long r12, long r13, long mof,
 		goto badframe;
 		goto badframe;
 
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
 	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))
 	if (restore_sigcontext(regs, &frame->sc))
 		goto badframe;
 		goto badframe;
@@ -224,10 +213,7 @@ asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13,
 		goto badframe;
 		goto badframe;
 
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
 	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))
 	if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
 		goto badframe;
 		goto badframe;
@@ -469,15 +455,9 @@ static inline int handle_signal(int canrestart, unsigned long sig,
 	else
 	else
 		ret = setup_frame(sig, ka, oldset, regs);
 		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;
 	return ret;
 }
 }
 
 

+ 16 - 50
arch/cris/arch-v32/kernel/signal.c

@@ -59,19 +59,11 @@ void keep_debug_flags(unsigned long oldccs, unsigned long oldspc,
  * dummy arguments to be able to reach the regs argument.
  * dummy arguments to be able to reach the regs argument.
  */
  */
 int
 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
 int
@@ -87,11 +79,11 @@ sys_sigaction(int signal, const struct old_sigaction *act,
 
 
 		if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
 		if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
 		    __get_user(newk.sa.sa_handler, &act->sa_handler) ||
 		    __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;
 			return -EFAULT;
 
 
-		__get_user(newk.sa.sa_flags, &act->sa_flags);
-		__get_user(mask, &act->sa_mask);
 		siginitset(&newk.sa.sa_mask, mask);
 		siginitset(&newk.sa.sa_mask, mask);
 	}
 	}
 
 
@@ -100,11 +92,11 @@ sys_sigaction(int signal, const struct old_sigaction *act,
 	if (!retval && oact) {
 	if (!retval && oact) {
 		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
 		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
 		    __put_user(oldk.sa.sa_handler, &oact->sa_handler) ||
 		    __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;
 			return -EFAULT;
 
 
-		__put_user(oldk.sa.sa_flags, &oact->sa_flags);
-		__put_user(oldk.sa.sa_mask.sig[0], &oact->sa_mask);
 	}
 	}
 
 
 	return retval;
 	return retval;
@@ -176,12 +168,7 @@ sys_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp,
 		goto badframe;
 		goto badframe;
 
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
 	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))
 	if (restore_sigcontext(regs, &frame->sc))
 		goto badframe;
 		goto badframe;
@@ -222,12 +209,7 @@ sys_rt_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp,
 		goto badframe;
 		goto badframe;
 
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
 	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))
 	if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
 		goto badframe;
 		goto badframe;
@@ -363,10 +345,7 @@ setup_frame(int sig, struct k_sigaction *ka,  sigset_t *set,
 	return 0;
 	return 0;
 
 
 give_sigsegv:
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 	return -EFAULT;
 	return -EFAULT;
 }
 }
 
 
@@ -450,10 +429,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	return 0;
 	return 0;
 
 
 give_sigsegv:
 give_sigsegv:
-	if (sig == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-
-	force_sig(SIGSEGV, current);
+	force_sigsegv(sig, current);
 	return -EFAULT;
 	return -EFAULT;
 }
 }
 
 
@@ -512,18 +488,8 @@ handle_signal(int canrestart, unsigned long sig,
 	else
 	else
 		ret = setup_frame(sig, ka, oldset, regs);
 		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;
 	return ret;
 }
 }

+ 13 - 34
arch/frv/kernel/signal.c

@@ -40,17 +40,9 @@ struct fdpic_func_descriptor {
  */
  */
 asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask)
 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,
 asmlinkage int sys_sigaction(int sig,
@@ -64,10 +56,10 @@ asmlinkage int sys_sigaction(int sig,
 		old_sigset_t mask;
 		old_sigset_t mask;
 		if (!access_ok(VERIFY_READ, act, sizeof(*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_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;
 			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);
 		siginitset(&new_ka.sa.sa_mask, mask);
 	}
 	}
 
 
@@ -76,10 +68,10 @@ asmlinkage int sys_sigaction(int sig,
 	if (!ret && oact) {
 	if (!ret && oact) {
 		if (!access_ok(VERIFY_WRITE, oact, sizeof(*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_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;
 			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;
 	return ret;
@@ -158,10 +150,7 @@ asmlinkage int sys_sigreturn(void)
 		goto badframe;
 		goto badframe;
 
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
 	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))
 	if (restore_sigcontext(&frame->sc, &gr8))
 		goto badframe;
 		goto badframe;
@@ -184,10 +173,7 @@ asmlinkage int sys_rt_sigreturn(void)
 		goto badframe;
 		goto badframe;
 
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
 	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))
 	if (restore_sigcontext(&frame->uc.uc_mcontext, &gr8))
 		goto badframe;
 		goto badframe;
@@ -474,15 +460,8 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
 	else
 	else
 		ret = setup_frame(sig, ka, oldset);
 		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;
 	return ret;
 
 

+ 1 - 0
arch/h8300/include/asm/unistd.h

@@ -356,6 +356,7 @@
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
 #define __ARCH_WANT_SYS_RT_SIGACTION
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
 
 
 /*
 /*
  * "Conditional" syscalls
  * "Conditional" syscalls

+ 39 - 83
arch/h8300/kernel/signal.c

@@ -49,60 +49,15 @@
 
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 #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.
  * 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
 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 
 asmlinkage int 
@@ -116,10 +71,10 @@ sys_sigaction(int sig, const struct old_sigaction *act,
 		old_sigset_t mask;
 		old_sigset_t mask;
 		if (!access_ok(VERIFY_READ, act, sizeof(*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_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;
 			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);
 		siginitset(&new_ka.sa.sa_mask, mask);
 	}
 	}
 
 
@@ -128,10 +83,10 @@ sys_sigaction(int sig, const struct old_sigaction *act,
 	if (!ret && oact) {
 	if (!ret && oact) {
 		if (!access_ok(VERIFY_WRITE, oact, sizeof(*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_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;
 			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;
 	return ret;
@@ -232,10 +187,7 @@ asmlinkage int do_sigreturn(unsigned long __unused,...)
 		goto badframe;
 		goto badframe;
 
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
 	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))
 	if (restore_sigcontext(regs, &frame->sc, &er0))
 		goto badframe;
 		goto badframe;
@@ -260,10 +212,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused,...)
 		goto badframe;
 		goto badframe;
 
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
 	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))
 	if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &er0))
 		goto badframe;
 		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);
 	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)
 			 sigset_t *set, struct pt_regs *regs)
 {
 {
 	struct sigframe *frame;
 	struct sigframe *frame;
@@ -375,13 +324,14 @@ static void setup_frame (int sig, struct k_sigaction *ka,
 	regs->er1 = (unsigned long)&(frame->sc);
 	regs->er1 = (unsigned long)&(frame->sc);
 	regs->er5 = current->mm->start_data;	/* GOT base */
 	regs->er5 = current->mm->start_data;	/* GOT base */
 
 
-	return;
+	return 0;
 
 
 give_sigsegv:
 give_sigsegv:
 	force_sigsegv(sig, current);
 	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)
 			    sigset_t *set, struct pt_regs *regs)
 {
 {
 	struct rt_sigframe *frame;
 	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->er2 = (unsigned long)&frame->uc;
 	regs->er5 = current->mm->start_data;	/* GOT base */
 	regs->er5 = current->mm->start_data;	/* GOT base */
 
 
-	return;
+	return 0;
 
 
 give_sigsegv:
 give_sigsegv:
 	force_sigsegv(sig, current);
 	force_sigsegv(sig, current);
+	return -EFAULT;
 }
 }
 
 
 /*
 /*
@@ -463,6 +414,7 @@ static void
 handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
 handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
 	      sigset_t *oldset,	struct pt_regs * regs)
 	      sigset_t *oldset,	struct pt_regs * regs)
 {
 {
+	int ret;
 	/* are we from a system call? */
 	/* are we from a system call? */
 	if (regs->orig_er0 >= 0) {
 	if (regs->orig_er0 >= 0) {
 		switch (regs->er0) {
 		switch (regs->er0) {
@@ -485,16 +437,14 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
 
 
 	/* set up the stack frame */
 	/* set up the stack frame */
 	if (ka->sa.sa_flags & SA_SIGINFO)
 	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
 	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
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  * mistake.
  */
  */
-asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset)
+statis void do_signal(struct pt_regs *regs)
 {
 {
 	siginfo_t info;
 	siginfo_t info;
 	int signr;
 	int signr;
 	struct k_sigaction ka;
 	struct k_sigaction ka;
+	sigset_t *oldset;
 
 
 	/*
 	/*
 	 * We want the common case to go fast, which
 	 * 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 so.
 	 */
 	 */
 	if ((regs->ccr & 0x10))
 	if ((regs->ccr & 0x10))
-		return 1;
+		return;
 
 
 	if (try_to_freeze())
 	if (try_to_freeze())
 		goto no_signal;
 		goto no_signal;
 
 
 	current->thread.esp0 = (unsigned long) regs;
 	current->thread.esp0 = (unsigned long) regs;
 
 
-	if (!oldset)
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+	else
 		oldset = &current->blocked;
 		oldset = &current->blocked;
 
 
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	if (signr > 0) {
 	if (signr > 0) {
 		/* Whee!  Actually deliver the signal.  */
 		/* Whee!  Actually deliver the signal.  */
 		handle_signal(signr, &info, &ka, oldset, regs);
 		handle_signal(signr, &info, &ka, oldset, regs);
-		return 1;
+		return;
 	}
 	}
  no_signal:
  no_signal:
 	/* Did we come from a system call? */
 	/* 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;
 			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)
 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) {
 	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
 		clear_thread_flag(TIF_NOTIFY_RESUME);
 		clear_thread_flag(TIF_NOTIFY_RESUME);

+ 0 - 6
arch/h8300/kernel/syscalls.S

@@ -343,12 +343,6 @@ SYMBOL_NAME_LABEL(sys_call_table)
 SYMBOL_NAME_LABEL(sys_clone)	
 SYMBOL_NAME_LABEL(sys_clone)	
 	call_sp	h8300_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)
 SYMBOL_NAME_LABEL(sys_sigreturn)
 	call_sp	do_sigreturn
 	call_sp	do_sigreturn
 
 

+ 4 - 0
arch/hexagon/kernel/signal.c

@@ -272,6 +272,7 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
 
 
 	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
 	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
 		clear_thread_flag(TIF_NOTIFY_RESUME);
 		clear_thread_flag(TIF_NOTIFY_RESUME);
+		tracehook_notify_resume(regs);
 		if (current->replacement_session_keyring)
 		if (current->replacement_session_keyring)
 			key_replace_session_keyring();
 			key_replace_session_keyring();
 	}
 	}
@@ -293,6 +294,9 @@ asmlinkage int sys_rt_sigreturn(void)
 	struct rt_sigframe __user *frame;
 	struct rt_sigframe __user *frame;
 	sigset_t blocked;
 	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);
 	frame = (struct rt_sigframe __user *)pt_psp(regs);
 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
 		goto badframe;

+ 2 - 13
arch/ia64/kernel/signal.c

@@ -201,13 +201,7 @@ ia64_rt_sigreturn (struct sigscratch *scr)
 		goto give_sigsegv;
 		goto give_sigsegv;
 
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
 	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))
 	if (restore_sigcontext(sc, scr))
 		goto give_sigsegv;
 		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))
 	if (!setup_frame(sig, ka, info, oldset, scr))
 		return 0;
 		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.
 	 * Let tracing know that we've done the handler setup.

+ 0 - 7
arch/m32r/include/asm/signal.h

@@ -110,13 +110,6 @@ typedef unsigned long sigset_t;
 #include <asm-generic/signal-defs.h>
 #include <asm-generic/signal-defs.h>
 
 
 #ifdef __KERNEL__
 #ifdef __KERNEL__
-struct old_sigaction {
-	__sighandler_t sa_handler;
-	old_sigset_t sa_mask;
-	unsigned long sa_flags;
-	__sigrestore_t sa_restorer;
-};
-
 struct sigaction {
 struct sigaction {
 	__sighandler_t sa_handler;
 	__sighandler_t sa_handler;
 	unsigned long sa_flags;
 	unsigned long sa_flags;

+ 2 - 10
arch/m32r/kernel/signal.c

@@ -112,10 +112,7 @@ sys_rt_sigreturn(unsigned long r0, unsigned long r1,
 		goto badframe;
 		goto badframe;
 
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
 	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))
 	if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &result))
 		goto badframe;
 		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))
 	if (setup_rt_frame(sig, ka, info, oldset, regs))
 		return -EFAULT;
 		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;
 	return 0;
 }
 }
 
 

+ 1 - 0
arch/m68k/include/asm/thread_info.h

@@ -71,6 +71,7 @@ static inline struct thread_info *current_thread_info(void)
  * bits 0-7 are tested at every exception exit
  * bits 0-7 are tested at every exception exit
  * bits 8-15 are also tested at syscall 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_SIGPENDING		6	/* signal pending */
 #define TIF_NEED_RESCHED	7	/* rescheduling necessary */
 #define TIF_NEED_RESCHED	7	/* rescheduling necessary */
 #define TIF_DELAYED_TRACE	14	/* single step a syscall */
 #define TIF_DELAYED_TRACE	14	/* single step a syscall */

+ 3 - 3
arch/m68k/kernel/entry_mm.S

@@ -148,7 +148,7 @@ syscall_exit_work:
 	jcs	do_trace_exit
 	jcs	do_trace_exit
 	jmi	do_delayed_trace
 	jmi	do_delayed_trace
 	lslw	#8,%d0
 	lslw	#8,%d0
-	jmi	do_signal_return
+	jne	do_signal_return
 	pea	resume_userspace
 	pea	resume_userspace
 	jra	schedule
 	jra	schedule
 
 
@@ -172,7 +172,7 @@ exit_work:
 	| save top of frame
 	| save top of frame
 	movel	%sp,%curptr@(TASK_THREAD+THREAD_ESP0)
 	movel	%sp,%curptr@(TASK_THREAD+THREAD_ESP0)
 	lslb	#1,%d0
 	lslb	#1,%d0
-	jmi	do_signal_return
+	jne	do_signal_return
 	pea	resume_userspace
 	pea	resume_userspace
 	jra	schedule
 	jra	schedule
 
 
@@ -182,7 +182,7 @@ do_signal_return:
 	subql	#4,%sp			| dummy return address
 	subql	#4,%sp			| dummy return address
 	SAVE_SWITCH_STACK
 	SAVE_SWITCH_STACK
 	pea	%sp@(SWITCH_STACK_SIZE)
 	pea	%sp@(SWITCH_STACK_SIZE)
-	bsrl	do_signal
+	bsrl	do_notify_resume
 	addql	#4,%sp
 	addql	#4,%sp
 	RESTORE_SWITCH_STACK
 	RESTORE_SWITCH_STACK
 	addql	#4,%sp
 	addql	#4,%sp

+ 20 - 21
arch/m68k/kernel/signal.c

@@ -43,6 +43,7 @@
 #include <linux/tty.h>
 #include <linux/tty.h>
 #include <linux/binfmts.h>
 #include <linux/binfmts.h>
 #include <linux/module.h>
 #include <linux/module.h>
+#include <linux/tracehook.h>
 
 
 #include <asm/setup.h>
 #include <asm/setup.h>
 #include <asm/uaccess.h>
 #include <asm/uaccess.h>
@@ -230,18 +231,9 @@ static inline void push_cache(unsigned long vaddr)
 asmlinkage int
 asmlinkage int
 sys_sigsuspend(int unused0, int unused1, old_sigset_t mask)
 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
 asmlinkage int
@@ -804,8 +796,7 @@ asmlinkage int do_sigreturn(unsigned long __unused)
 		goto badframe;
 		goto badframe;
 
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
 	sigdelsetmask(&set, ~_BLOCKABLE);
-	current->blocked = set;
-	recalc_sigpending();
+	set_current_blocked(&set);
 
 
 	if (restore_sigcontext(regs, &frame->sc, frame + 1))
 	if (restore_sigcontext(regs, &frame->sc, frame + 1))
 		goto badframe;
 		goto badframe;
@@ -830,8 +821,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
 		goto badframe;
 		goto badframe;
 
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
 	sigdelsetmask(&set, ~_BLOCKABLE);
-	current->blocked = set;
-	recalc_sigpending();
+	set_current_blocked(&set);
 
 
 	if (rt_restore_ucontext(regs, sw, &frame->uc))
 	if (rt_restore_ucontext(regs, sw, &frame->uc))
 		goto badframe;
 		goto badframe;
@@ -1150,10 +1140,7 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
 	if (err)
 	if (err)
 		return;
 		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)) {
 	if (test_thread_flag(TIF_DELAYED_TRACE)) {
 		regs->sr &= ~0x8000;
 		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
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  * mistake.
  */
  */
-asmlinkage void do_signal(struct pt_regs *regs)
+static void do_signal(struct pt_regs *regs)
 {
 {
 	siginfo_t info;
 	siginfo_t info;
 	struct k_sigaction ka;
 	struct k_sigaction ka;
@@ -1200,3 +1187,15 @@ asmlinkage void do_signal(struct pt_regs *regs)
 		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
 		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();
+	}
+}

+ 1 - 1
arch/m68k/platform/68328/entry.S

@@ -119,7 +119,7 @@ Lsignal_return:
 	subql	#4,%sp			/* dummy return address*/
 	subql	#4,%sp			/* dummy return address*/
 	SAVE_SWITCH_STACK
 	SAVE_SWITCH_STACK
 	pea	%sp@(SWITCH_STACK_SIZE)
 	pea	%sp@(SWITCH_STACK_SIZE)
-	bsrw	do_signal
+	bsrw	do_notify_resume
 	addql	#4,%sp
 	addql	#4,%sp
 	RESTORE_SWITCH_STACK
 	RESTORE_SWITCH_STACK
 	addql	#4,%sp
 	addql	#4,%sp

+ 1 - 1
arch/m68k/platform/68360/entry.S

@@ -115,7 +115,7 @@ Lsignal_return:
 	subql	#4,%sp			/* dummy return address*/
 	subql	#4,%sp			/* dummy return address*/
 	SAVE_SWITCH_STACK
 	SAVE_SWITCH_STACK
 	pea	%sp@(SWITCH_STACK_SIZE)
 	pea	%sp@(SWITCH_STACK_SIZE)
-	bsrw	do_signal
+	bsrw	do_notify_resume
 	addql	#4,%sp
 	addql	#4,%sp
 	RESTORE_SWITCH_STACK
 	RESTORE_SWITCH_STACK
 	addql	#4,%sp
 	addql	#4,%sp

+ 1 - 1
arch/m68k/platform/coldfire/entry.S

@@ -152,7 +152,7 @@ Lsignal_return:
 	subql	#4,%sp			/* dummy return address */
 	subql	#4,%sp			/* dummy return address */
 	SAVE_SWITCH_STACK
 	SAVE_SWITCH_STACK
 	pea	%sp@(SWITCH_STACK_SIZE)
 	pea	%sp@(SWITCH_STACK_SIZE)
-	jsr	do_signal
+	jsr	do_notify_resume
 	addql	#4,%sp
 	addql	#4,%sp
 	RESTORE_SWITCH_STACK
 	RESTORE_SWITCH_STACK
 	addql	#4,%sp
 	addql	#4,%sp

+ 7 - 13
arch/microblaze/kernel/entry-nommu.S

@@ -132,11 +132,10 @@ ret_from_intr:
 	beqi	r11, 1f
 	beqi	r11, 1f
 	bralid	r15, schedule
 	bralid	r15, schedule
 	nop
 	nop
-1:	andi	r11, r19, _TIF_SIGPENDING
+1:	andi	r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME
 	beqid	r11, no_intr_resched
 	beqid	r11, no_intr_resched
 	addk	r5, r1, r0
 	addk	r5, r1, r0
-	addk	r7, r0, r0
-	bralid	r15, do_signal
+	bralid	r15, do_notify_resume
 	addk	r6, r0, r0
 	addk	r6, r0, r0
 
 
 no_intr_resched:
 no_intr_resched:
@@ -292,8 +291,8 @@ ENTRY(_user_exception)
 
 
 /*
 /*
  * Debug traps are like a system call, but entered via brki r14, 0x60
  * 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)
 ENTRY(_debug_exception)
 	swi	r1, r0, PER_CPU(ENTRY_SP)	/* save the current sp */
 	swi	r1, r0, PER_CPU(ENTRY_SP)	/* save the current sp */
@@ -482,12 +481,11 @@ work_pending:
 	beqi	r11, 1f
 	beqi	r11, 1f
 	bralid	r15, schedule
 	bralid	r15, schedule
 	nop
 	nop
-1:	andi	r11, r19, _TIF_SIGPENDING
+1:	andi	r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME
 	beqi	r11, no_work_pending
 	beqi	r11, no_work_pending
 	addk	r5, r1, r0
 	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
 	bri	no_work_pending
 
 
 ENTRY(ret_to_user)
 ENTRY(ret_to_user)
@@ -569,10 +567,6 @@ sys_rt_sigreturn_wrapper:
 	brid	sys_rt_sigreturn
 	brid	sys_rt_sigreturn
 	addk	r5, r1, r0
 	addk	r5, r1, r0
 
 
-sys_rt_sigsuspend_wrapper:
-	brid	sys_rt_sigsuspend
-	addk	r7, r1, r0
-
 	/* Interrupt vector table */
 	/* Interrupt vector table */
 	.section	.init.ivt, "ax"
 	.section	.init.ivt, "ax"
 	.org 0x0
 	.org 0x0

+ 13 - 17
arch/microblaze/kernel/entry.S

@@ -430,13 +430,12 @@ C_ENTRY(ret_from_trap):
 5:	/* get thread info from current task*/
 5:	/* get thread info from current task*/
 	lwi	r11, CURRENT_TASK, TS_THREAD_INFO;
 	lwi	r11, CURRENT_TASK, TS_THREAD_INFO;
 	lwi	r11, r11, TI_FLAGS;	/* get flags in 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 */
 	beqi	r11, 1f;		/* Signals to handle, handle them */
 
 
 	addik	r5, r1, 0;		/* Arg 1: struct pt_regs *regs */
 	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.  */
 /* Finally, return to user state.  */
 1:	set_bip;			/*  Ints masked for state restore */
 1:	set_bip;			/*  Ints masked for state restore */
@@ -622,7 +621,7 @@ C_ENTRY(ret_from_exc):
 	/* Maybe handle a signal */
 	/* Maybe handle a signal */
 5:	lwi	r11, CURRENT_TASK, TS_THREAD_INFO;	/* get thread info */
 5:	lwi	r11, CURRENT_TASK, TS_THREAD_INFO;	/* get thread info */
 	lwi	r11, r11, TI_FLAGS;	/* get flags in 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 */
 	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
 	 * traps), but signal handlers may want to examine or change the
 	 * complete register state.  Here we save anything not saved by
 	 * complete register state.  Here we save anything not saved by
 	 * the normal entry sequence, so that it may be safely restored
 	 * 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 */
 	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.  */
 /* Finally, return to user state.  */
 1:	set_bip;			/* Ints masked for state restore */
 1:	set_bip;			/* Ints masked for state restore */
@@ -732,13 +730,12 @@ ret_from_irq:
     /* Maybe handle a signal */
     /* Maybe handle a signal */
 5:	lwi	r11, CURRENT_TASK, TS_THREAD_INFO; /* MS: get thread info */
 5:	lwi	r11, CURRENT_TASK, TS_THREAD_INFO; /* MS: get thread info */
 	lwi	r11, r11, TI_FLAGS; /* get flags in 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
 	beqid	r11, no_intr_resched
 /* Handle a signal return; Pending signals should be in r18. */
 /* 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 */
 	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. */
 /* Finally, return to user state. */
 no_intr_resched:
 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 */
 	/* Maybe handle a signal */
 5:	lwi	r11, CURRENT_TASK, TS_THREAD_INFO;	/* get thread info */
 5:	lwi	r11, CURRENT_TASK, TS_THREAD_INFO;	/* get thread info */
 	lwi	r11, r11, TI_FLAGS;	/* get flags in 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 */
 	beqi	r11, 1f;		/* Signals to handle, handle them */
 
 
 	addik	r5, r1, 0;		/* Arg 1: struct pt_regs *regs */
 	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.  */
 /* Finally, return to user state.  */
 1:	swi	CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
 1:	swi	CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */

+ 45 - 40
arch/microblaze/kernel/signal.c

@@ -31,6 +31,7 @@
 #include <linux/personality.h>
 #include <linux/personality.h>
 #include <linux/percpu.h>
 #include <linux/percpu.h>
 #include <linux/linkage.h>
 #include <linux/linkage.h>
+#include <linux/tracehook.h>
 #include <asm/entry.h>
 #include <asm/entry.h>
 #include <asm/ucontext.h>
 #include <asm/ucontext.h>
 #include <linux/uaccess.h>
 #include <linux/uaccess.h>
@@ -42,8 +43,6 @@
 
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
 
-asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall);
-
 asmlinkage long
 asmlinkage long
 sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
 sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
 		struct pt_regs *regs)
 		struct pt_regs *regs)
@@ -98,6 +97,9 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
 	sigset_t set;
 	sigset_t set;
 	int rval;
 	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)))
 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
 		goto badframe;
 
 
@@ -105,10 +107,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
 		goto badframe;
 		goto badframe;
 
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
 	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))
 	if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval))
 		goto badframe;
 		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);
 	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)
 			sigset_t *set, struct pt_regs *regs)
 {
 {
 	struct rt_sigframe __user *frame;
 	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);
 		current->comm, current->pid, frame, regs->pc);
 #endif
 #endif
 
 
-	return;
+	return 0;
 
 
 give_sigsegv:
 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 */
 /* Handle restarting system calls */
@@ -316,24 +314,20 @@ static int
 handle_signal(unsigned long sig, struct k_sigaction *ka,
 handle_signal(unsigned long sig, struct k_sigaction *ka,
 		siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
 		siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
 {
 {
+	int ret;
+
 	/* Set up the stack frame */
 	/* Set up the stack frame */
 	if (ka->sa.sa_flags & SA_SIGINFO)
 	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
 	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
  * the kernel can handle, and then we build all the user-level signal handling
  * stack-frames in one go after that.
  * 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;
 	siginfo_t info;
 	int signr;
 	int signr;
 	struct k_sigaction ka;
 	struct k_sigaction ka;
+	sigset_t *oldset;
 #ifdef DEBUG_SIG
 #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,
 	printk(KERN_INFO "do signal2: %lx %lx %ld [%lx]\n", regs->pc, regs->r1,
 			regs->r12, current_thread_info()->flags);
 			regs->r12, current_thread_info()->flags);
 #endif
 #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)
 	if (current_thread_info()->status & TS_RESTORE_SIGMASK)
 		oldset = &current->saved_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. */
 		/* Whee! Actually deliver the signal. */
 		if (in_syscall)
 		if (in_syscall)
 			handle_restart(regs, &ka, 1);
 			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
 			 * A signal was successfully delivered; the saved
 			 * sigmask will have been stored in the signal frame,
 			 * 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 &=
 			current_thread_info()->status &=
 			    ~TS_RESTORE_SIGMASK;
 			    ~TS_RESTORE_SIGMASK;
 		}
 		}
-		return 1;
+		return;
 	}
 	}
 
 
 	if (in_syscall)
 	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;
 		current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
 		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
 		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();
+	}
 }
 }

+ 2 - 18
arch/mips/kernel/signal.c

@@ -255,15 +255,7 @@ asmlinkage int sys_sigsuspend(nabi_no_regargs struct pt_regs regs)
 	uset = (sigset_t __user *) regs.regs[4];
 	uset = (sigset_t __user *) regs.regs[4];
 	if (copy_from_user(&newset, uset, sizeof(sigset_t)))
 	if (copy_from_user(&newset, uset, sizeof(sigset_t)))
 		return -EFAULT;
 		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
 #endif
 
 
@@ -281,15 +273,7 @@ asmlinkage int sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
 	unewset = (sigset_t __user *) regs.regs[4];
 	unewset = (sigset_t __user *) regs.regs[4];
 	if (copy_from_user(&newset, unewset, sizeof(newset)))
 	if (copy_from_user(&newset, unewset, sizeof(newset)))
 		return -EFAULT;
 		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
 #ifdef CONFIG_TRAD_SIGNALS

+ 2 - 18
arch/mips/kernel/signal32.c

@@ -288,15 +288,7 @@ asmlinkage int sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
 	uset = (compat_sigset_t __user *) regs.regs[4];
 	uset = (compat_sigset_t __user *) regs.regs[4];
 	if (get_sigset(&newset, uset))
 	if (get_sigset(&newset, uset))
 		return -EFAULT;
 		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)
 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];
 	uset = (compat_sigset_t __user *) regs.regs[4];
 	if (get_sigset(&newset, uset))
 	if (get_sigset(&newset, uset))
 		return -EFAULT;
 		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,
 SYSCALL_DEFINE3(32_sigaction, long, sig, const struct sigaction32 __user *, act,

+ 1 - 9
arch/mips/kernel/signal_n32.c

@@ -91,15 +91,7 @@ asmlinkage int sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
 	if (copy_from_user(&uset, unewset, sizeof(uset)))
 	if (copy_from_user(&uset, unewset, sizeof(uset)))
 		return -EFAULT;
 		return -EFAULT;
 	sigset_from_compat(&newset, &uset);
 	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)
 asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)

+ 7 - 28
arch/mn10300/kernel/signal.c

@@ -38,17 +38,9 @@
  */
  */
 asmlinkage long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
 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;
 		goto badframe;
 
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
 	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))
 	if (restore_sigcontext(current_frame(), &frame->sc, &d0))
 		goto badframe;
 		goto badframe;
@@ -203,10 +192,7 @@ asmlinkage long sys_rt_sigreturn(void)
 		goto badframe;
 		goto badframe;
 
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
 	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))
 	if (restore_sigcontext(current_frame(), &frame->uc.uc_mcontext, &d0))
 		goto badframe;
 		goto badframe;
@@ -476,15 +462,8 @@ static int handle_signal(int sig,
 	else
 	else
 		ret = setup_frame(sig, ka, oldset, regs);
 		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;
 	return ret;
 }
 }

+ 3 - 12
arch/parisc/kernel/signal.c

@@ -109,6 +109,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
 		sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
 		sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
 #endif
 #endif
 
 
+	current_thread_info()->restart_block.fn = do_no_restart_syscall;
 
 
 	/* Unwind the user stack to get the rt_sigframe structure. */
 	/* Unwind the user stack to get the rt_sigframe structure. */
 	frame = (struct rt_sigframe __user *)
 	frame = (struct rt_sigframe __user *)
@@ -131,10 +132,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
 	}
 	}
 		
 		
 	sigdelsetmask(&set, ~_BLOCKABLE);
 	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? */
 	/* Good thing we saved the old gr[30], eh? */
 #ifdef CONFIG_64BIT
 #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))
 	if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))
 		return 0;
 		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, 
 	tracehook_signal_handler(sig, info, ka, regs, 
 		test_thread_flag(TIF_SINGLESTEP) ||
 		test_thread_flag(TIF_SINGLESTEP) ||
@@ -474,8 +467,6 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
 	/* Check the return code */
 	/* Check the return code */
 	switch (regs->gr[28]) {
 	switch (regs->gr[28]) {
 	case -ERESTART_RESTARTBLOCK:
 	case -ERESTART_RESTARTBLOCK:
-		current_thread_info()->restart_block.fn =
-			do_no_restart_syscall;
 	case -ERESTARTNOHAND:
 	case -ERESTARTNOHAND:
 		DBG(1,"ERESTARTNOHAND: returning -EINTR\n");
 		DBG(1,"ERESTARTNOHAND: returning -EINTR\n");
 		regs->gr[28] = -EINTR;
 		regs->gr[28] = -EINTR;

+ 4 - 13
arch/powerpc/kernel/signal_32.c

@@ -204,10 +204,10 @@ static inline int get_old_sigaction(struct k_sigaction *new_ka,
 
 
 	if (!access_ok(VERIFY_READ, act, sizeof(*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_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;
 		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);
 	siginitset(&new_ka->sa.sa_mask, mask);
 	return 0;
 	return 0;
 }
 }
@@ -244,17 +244,8 @@ static inline int restore_general_regs(struct pt_regs *regs,
 long sys_sigsuspend(old_sigset_t mask)
 long sys_sigsuspend(old_sigset_t mask)
 {
 {
 	sigset_t blocked;
 	sigset_t blocked;
-
-	current->saved_sigmask = current->blocked;
-
-	mask &= _BLOCKABLE;
 	siginitset(&blocked, mask);
 	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,
 long sys_sigaction(int sig, struct old_sigaction __user *act,

+ 1 - 8
arch/s390/kernel/signal.c

@@ -59,15 +59,8 @@ typedef struct
 SYSCALL_DEFINE3(sigsuspend, int, history0, int, history1, old_sigset_t, mask)
 SYSCALL_DEFINE3(sigsuspend, int, history0, int, history1, old_sigset_t, mask)
 {
 {
 	sigset_t blocked;
 	sigset_t blocked;
-
-	current->saved_sigmask = current->blocked;
-	mask &= _BLOCKABLE;
 	siginitset(&blocked, mask);
 	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,
 SYSCALL_DEFINE3(sigaction, int, sig, const struct old_sigaction __user *, act,

+ 15 - 14
arch/score/kernel/signal.c

@@ -28,6 +28,7 @@
 #include <linux/ptrace.h>
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
 #include <linux/unistd.h>
 #include <linux/uaccess.h>
 #include <linux/uaccess.h>
+#include <linux/tracehook.h>
 
 
 #include <asm/cacheflush.h>
 #include <asm/cacheflush.h>
 #include <asm/syscalls.h>
 #include <asm/syscalls.h>
@@ -152,6 +153,9 @@ score_rt_sigreturn(struct pt_regs *regs)
 	stack_t st;
 	stack_t st;
 	int sig;
 	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];
 	frame = (struct rt_sigframe __user *) regs->regs[0];
 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
 		goto badframe;
@@ -159,10 +163,7 @@ score_rt_sigreturn(struct pt_regs *regs)
 		goto badframe;
 		goto badframe;
 
 
 	sigdelsetmask(&set, ~_BLOCKABLE);
 	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);
 	sig = restore_sigcontext(regs, &frame->rs_uc.uc_mcontext);
 	if (sig < 0)
 	if (sig < 0)
@@ -236,9 +237,7 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
 	return 0;
 	return 0;
 
 
 give_sigsegv:
 give_sigsegv:
-	if (signr == SIGSEGV)
-		ka->sa.sa_handler = SIG_DFL;
-	force_sig(SIGSEGV, current);
+	force_sigsegv(signr, current);
 	return -EFAULT;
 	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);
 	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;
 	return ret;
 }
 }
@@ -356,6 +351,12 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
 				__u32 thread_info_flags)
 				__u32 thread_info_flags)
 {
 {
 	/* deal with pending signal delivery */
 	/* deal with pending signal delivery */
-	if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+	if (thread_info_flags & _TIF_SIGPENDING)
 		do_signal(regs);
 		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();
+	}
 }
 }

+ 1 - 3
arch/sh/include/asm/syscalls_32.h

@@ -23,9 +23,7 @@ asmlinkage int sys_execve(const char __user *ufilename,
 			  const char __user *const __user *uargv,
 			  const char __user *const __user *uargv,
 			  const char __user *const __user *uenvp,
 			  const char __user *const __user *uenvp,
 			  unsigned long r7, struct pt_regs __regs);
 			  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,
 asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user *act,
 			     struct old_sigaction __user *oact);
 			     struct old_sigaction __user *oact);
 asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
 asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,

+ 1 - 3
arch/sh/include/asm/unistd.h

@@ -1,13 +1,11 @@
 #ifdef __KERNEL__
 #ifdef __KERNEL__
 # ifdef CONFIG_SUPERH32
 # ifdef CONFIG_SUPERH32
-
 #  include "unistd_32.h"
 #  include "unistd_32.h"
-#  define __ARCH_WANT_SYS_RT_SIGSUSPEND
-
 # else
 # else
 #  include "unistd_64.h"
 #  include "unistd_64.h"
 # endif
 # endif
 
 
+# define __ARCH_WANT_SYS_RT_SIGSUSPEND
 # define __ARCH_WANT_IPC_PARSE_VERSION
 # define __ARCH_WANT_IPC_PARSE_VERSION
 # define __ARCH_WANT_OLD_READDIR
 # define __ARCH_WANT_OLD_READDIR
 # define __ARCH_WANT_OLD_STAT
 # define __ARCH_WANT_OLD_STAT

+ 23 - 30
arch/sh/kernel/signal_32.c

@@ -53,23 +53,11 @@ struct fdpic_func_descriptor {
  * Atomically swap in the new signal mask, and wait for a signal.
  * Atomically swap in the new signal mask, and wait for a signal.
  */
  */
 asmlinkage int
 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;
 	sigset_t blocked;
-
-	current->saved_sigmask = current->blocked;
-
-	mask &= _BLOCKABLE;
 	siginitset(&blocked, mask);
 	siginitset(&blocked, mask);
-	set_current_blocked(&blocked);
-
-	current->state = TASK_INTERRUPTIBLE;
-	schedule();
-	set_restore_sigmask();
-
-	return -ERESTARTNOHAND;
+	return sigsuspend(&blocked);
 }
 }
 
 
 asmlinkage int
 asmlinkage int
@@ -83,10 +71,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
 		old_sigset_t mask;
 		old_sigset_t mask;
 		if (!access_ok(VERIFY_READ, act, sizeof(*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_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;
 			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);
 		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 (!ret && oact) {
 		if (!access_ok(VERIFY_WRITE, oact, sizeof(*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_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;
 			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;
 	return ret;
@@ -162,12 +150,11 @@ static inline int save_sigcontext_fpu(struct sigcontext __user *sc,
 	if (!(boot_cpu_data.flags & CPU_HAS_FPU))
 	if (!(boot_cpu_data.flags & CPU_HAS_FPU))
 		return 0;
 		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
 	/* This will cause a "finit" to be triggered by the next
 	   attempted FPU operation by the 'current' process.
 	   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 */
 		regs->sr |= SR_FD; /* Release FPU */
 		clear_fpu(tsk, regs);
 		clear_fpu(tsk, regs);
 		clear_used_math();
 		clear_used_math();
-		__get_user (owned_fp, &sc->sc_ownedfp);
+		err |= __get_user (owned_fp, &sc->sc_ownedfp);
 		if (owned_fp)
 		if (owned_fp)
 			err |= restore_sigcontext_fpu(sc);
 			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 *funcptr =
 			(struct fdpic_func_descriptor __user *)ka->sa.sa_handler;
 			(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
 	} else
 		regs->pc = (unsigned long)ka->sa.sa_handler;
 		regs->pc = (unsigned long)ka->sa.sa_handler;
 
 
+	if (err)
+		goto give_sigsegv;
+
 	set_fs(USER_DS);
 	set_fs(USER_DS);
 
 
 	pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
 	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 *funcptr =
 			(struct fdpic_func_descriptor __user *)ka->sa.sa_handler;
 			(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
 	} else
 		regs->pc = (unsigned long)ka->sa.sa_handler;
 		regs->pc = (unsigned long)ka->sa.sa_handler;
 
 
+	if (err)
+		goto give_sigsegv;
+
 	set_fs(USER_DS);
 	set_fs(USER_DS);
 
 
 	pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
 	pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",

+ 16 - 68
arch/sh/kernel/signal_64.c

@@ -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
  * the kernel can handle, and then we build all the user-level signal handling
  * stack-frames in one go after that.
  * 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;
 	siginfo_t info;
 	int signr;
 	int signr;
 	struct k_sigaction ka;
 	struct k_sigaction ka;
+	sigset_t *oldset;
 
 
 	/*
 	/*
 	 * We want the common case to go fast, which
 	 * 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 so.
 	 */
 	 */
 	if (!user_mode(regs))
 	if (!user_mode(regs))
-		return 1;
+		return;
 
 
 	if (current_thread_info()->status & TS_RESTORE_SIGMASK)
 	if (current_thread_info()->status & TS_RESTORE_SIGMASK)
 		oldset = &current->saved_sigmask;
 		oldset = &current->saved_sigmask;
-	else if (!oldset)
+	else
 		oldset = &current->blocked;
 		oldset = &current->blocked;
 
 
 	signr = get_signal_to_deliver(&info, &ka, regs, 0);
 	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,
 			tracehook_signal_handler(signr, &info, &ka, regs,
 					test_thread_flag(TIF_SINGLESTEP));
 					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);
 		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
 	}
 	}
 
 
-	return 0;
+	return;
 }
 }
 
 
 /*
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  * Atomically swap in the new signal mask, and wait for a signal.
  */
  */
 asmlinkage int
 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);
 	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
 asmlinkage int
@@ -225,10 +173,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
 		old_sigset_t mask;
 		old_sigset_t mask;
 		if (!access_ok(VERIFY_READ, act, sizeof(*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_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;
 			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);
 		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 (!ret && oact) {
 		if (!access_ok(VERIFY_WRITE, oact, sizeof(*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_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;
 			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;
 	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)
 asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
 {
 {
 	if (thread_info_flags & _TIF_SIGPENDING)
 	if (thread_info_flags & _TIF_SIGPENDING)
-		do_signal(regs, 0);
+		do_signal(regs);
 
 
 	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
 	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
 		clear_thread_flag(TIF_NOTIFY_RESUME);
 		clear_thread_flag(TIF_NOTIFY_RESUME);

+ 6 - 4
arch/sparc/kernel/signal32.c

@@ -215,8 +215,9 @@ void do_sigreturn32(struct pt_regs *regs)
 	    (((unsigned long) sf) & 3))
 	    (((unsigned long) sf) & 3))
 		goto segv;
 		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)
 	if ((pc | npc) & 3)
 		goto segv;
 		goto segv;
@@ -305,8 +306,9 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
 	    (((unsigned long) sf) & 3))
 	    (((unsigned long) sf) & 3))
 		goto segv;
 		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)
 	if ((pc | npc) & 3)
 		goto segv;
 		goto segv;

+ 1 - 11
arch/sparc/kernel/signal_32.c

@@ -64,18 +64,8 @@ struct rt_signal_frame {
 static int _sigpause_common(old_sigset_t set)
 static int _sigpause_common(old_sigset_t set)
 {
 {
 	sigset_t blocked;
 	sigset_t blocked;
-
-	current->saved_sigmask = current->blocked;
-
-	set &= _BLOCKABLE;
 	siginitset(&blocked, set);
 	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)
 asmlinkage int sys_sigsuspend(old_sigset_t set)

+ 1 - 12
arch/sparc/kernel/signal_64.c

@@ -242,19 +242,8 @@ struct rt_signal_frame {
 static long _sigpause_common(old_sigset_t set)
 static long _sigpause_common(old_sigset_t set)
 {
 {
 	sigset_t blocked;
 	sigset_t blocked;
-
-	current->saved_sigmask = current->blocked;
-
-	set &= _BLOCKABLE;
 	siginitset(&blocked, set);
 	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)
 asmlinkage long sys_sigpause(unsigned int set)

+ 6 - 11
arch/sparc/kernel/sys_sparc_32.c

@@ -184,10 +184,10 @@ sparc_sigaction (int sig, const struct old_sigaction __user *act,
 
 
 		if (!access_ok(VERIFY_READ, act, sizeof(*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_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;
 			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);
 		siginitset(&new_ka.sa.sa_mask, mask);
 		new_ka.ka_restorer = NULL;
 		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);
 	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 
 
 	if (!ret && oact) {
 	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)) ||
 		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
 		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
 		    __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;
 			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;
 	return ret;

+ 1 - 8
arch/um/kernel/signal.c

@@ -148,15 +148,8 @@ int do_signal(void)
 long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
 long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
 {
 {
 	sigset_t blocked;
 	sigset_t blocked;
-
-	mask &= _BLOCKABLE;
 	siginitset(&blocked, mask);
 	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)
 long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)

+ 6 - 12
arch/unicore32/kernel/signal.c

@@ -370,10 +370,7 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
 	/*
 	/*
 	 * Block the signal if we were successful.
 	 * 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;
 	return 0;
 }
 }
@@ -450,15 +447,12 @@ static void do_signal(struct pt_regs *regs, int syscall)
 		    regs->UCreg_00 == -ERESTARTNOINTR) {
 		    regs->UCreg_00 == -ERESTARTNOINTR) {
 			setup_syscall_restart(regs);
 			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,
 asmlinkage void do_notify_resume(struct pt_regs *regs,

+ 1 - 11
arch/x86/ia32/ia32_signal.c

@@ -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)
 asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask)
 {
 {
 	sigset_t blocked;
 	sigset_t blocked;
-
-	current->saved_sigmask = current->blocked;
-
-	mask &= _BLOCKABLE;
 	siginitset(&blocked, mask);
 	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,
 asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,

+ 1 - 11
arch/x86/kernel/signal.c

@@ -478,18 +478,8 @@ asmlinkage int
 sys_sigsuspend(int history0, int history1, old_sigset_t mask)
 sys_sigsuspend(int history0, int history1, old_sigset_t mask)
 {
 {
 	sigset_t blocked;
 	sigset_t blocked;
-
-	current->saved_sigmask = current->blocked;
-
-	mask &= _BLOCKABLE;
 	siginitset(&blocked, mask);
 	siginitset(&blocked, mask);
-	set_current_blocked(&blocked);
-
-	current->state = TASK_INTERRUPTIBLE;
-	schedule();
-
-	set_restore_sigmask();
-	return -ERESTARTNOHAND;
+	return sigsuspend(&blocked);
 }
 }
 
 
 asmlinkage int
 asmlinkage int

+ 0 - 7
arch/xtensa/include/asm/signal.h

@@ -120,13 +120,6 @@ typedef void (*__sighandler_t)(int);
 #define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
 #define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
 
 
 #ifdef __KERNEL__
 #ifdef __KERNEL__
-struct old_sigaction {
-	__sighandler_t sa_handler;
-	old_sigset_t sa_mask;
-	unsigned long sa_flags;
-	void (*sa_restorer)(void);
-};
-
 struct sigaction {
 struct sigaction {
 	__sighandler_t sa_handler;
 	__sighandler_t sa_handler;
 	unsigned long sa_flags;
 	unsigned long sa_flags;

+ 0 - 4
arch/xtensa/include/asm/syscall.h

@@ -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_ptrace(long, long, long, long);
 asmlinkage long xtensa_sigreturn(struct pt_regs*);
 asmlinkage long xtensa_sigreturn(struct pt_regs*);
 asmlinkage long xtensa_rt_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 xtensa_sigaltstack(struct pt_regs *regs);
 asmlinkage long sys_rt_sigaction(int,
 asmlinkage long sys_rt_sigaction(int,
 				 const struct sigaction __user *,
 				 const struct sigaction __user *,

+ 1 - 0
arch/xtensa/include/asm/thread_info.h

@@ -131,6 +131,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_IRET		4	/* return with iret */
 #define TIF_IRET		4	/* return with iret */
 #define TIF_MEMDIE		5	/* is terminating due to OOM killer */
 #define TIF_MEMDIE		5	/* is terminating due to OOM killer */
 #define TIF_RESTORE_SIGMASK	6	/* restore signal mask in do_signal() */
 #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_POLLING_NRFLAG	16	/* true if poll_idle() is polling TIF_NEED_RESCHED */
 
 
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)

+ 1 - 1
arch/xtensa/include/asm/unistd.h

@@ -507,7 +507,7 @@ __SYSCALL(229, sys_rt_sigtimedwait, 4)
 #define __NR_rt_sigqueueinfo 			230
 #define __NR_rt_sigqueueinfo 			230
 __SYSCALL(230, sys_rt_sigqueueinfo, 3)
 __SYSCALL(230, sys_rt_sigqueueinfo, 3)
 #define __NR_rt_sigsuspend 			231
 #define __NR_rt_sigsuspend 			231
-__SYSCALL(231, xtensa_rt_sigsuspend, 2)
+__SYSCALL(231, sys_rt_sigsuspend, 2)
 
 
 /* Message */
 /* Message */
 
 

+ 3 - 3
arch/xtensa/kernel/entry.S

@@ -409,16 +409,16 @@ common_exception_return:
 	l32i	a4, a2, TI_FLAGS
 	l32i	a4, a2, TI_FLAGS
 
 
 	_bbsi.l	a4, TIF_NEED_RESCHED, 3f
 	_bbsi.l	a4, TIF_NEED_RESCHED, 3f
+	_bbsi.l	a4, TIF_NOTIFY_RESUME, 2f
 	_bbci.l	a4, TIF_SIGPENDING, 4f
 	_bbci.l	a4, TIF_SIGPENDING, 4f
 
 
-	l32i	a4, a1, PT_DEPC
+2:	l32i	a4, a1, PT_DEPC
 	bgeui	a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f
 	bgeui	a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f
 
 
 	/* Call do_signal() */
 	/* 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
 	mov	a6, a1
-	movi	a7, 0
 	callx4	a4
 	callx4	a4
 	j	1b
 	j	1b
 
 

+ 32 - 41
arch/xtensa/kernel/signal.c

@@ -20,6 +20,7 @@
 #include <linux/ptrace.h>
 #include <linux/ptrace.h>
 #include <linux/personality.h>
 #include <linux/personality.h>
 #include <linux/freezer.h>
 #include <linux/freezer.h>
+#include <linux/tracehook.h>
 
 
 #include <asm/ucontext.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/uaccess.h>
@@ -31,8 +32,6 @@
 
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
 
-asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
-
 extern struct task_struct *coproc_owners[];
 extern struct task_struct *coproc_owners[];
 
 
 struct rt_sigframe
 struct rt_sigframe
@@ -248,6 +247,9 @@ asmlinkage long xtensa_rt_sigreturn(long a0, long a1, long a2, long a3,
 	sigset_t set;
 	sigset_t set;
 	int ret;
 	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)
 	if (regs->depc > 64)
 		panic("rt_sigreturn in double exception!\n");
 		panic("rt_sigreturn in double exception!\n");
 
 
@@ -426,37 +428,6 @@ give_sigsegv:
 	return -EFAULT;
 	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, 
 asmlinkage long xtensa_sigaltstack(const stack_t __user *uss, 
 				   stack_t __user *uoss,
 				   stack_t __user *uoss,
     				   long a2, long a3, long a4, long a5,
     				   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
  * the kernel can handle, and then we build all the user-level signal handling
  * stack-frames in one go after that.
  * 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;
 	siginfo_t info;
 	int signr;
 	int signr;
 	struct k_sigaction ka;
 	struct k_sigaction ka;
-
-	if (!user_mode(regs))
-		return 0;
+	sigset_t oldset;
 
 
 	if (try_to_freeze())
 	if (try_to_freeze())
 		goto no_signal;
 		goto no_signal;
 
 
-	if (!oldset)
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+	else
 		oldset = &current->blocked;
 		oldset = &current->blocked;
 
 
 	task_pt_regs(current)->icountlevel = 0;
 	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 */
 		/* Set up the stack frame */
 		ret = setup_frame(signr, &ka, &info, oldset, regs);
 		ret = setup_frame(signr, &ka, &info, oldset, regs);
 		if (ret)
 		if (ret)
-			return ret;
+			return;
 
 
+		clear_thread_flag(TIF_RESTORE_SIGMASK);
 		block_sigmask(&ka, signr);
 		block_sigmask(&ka, signr);
 		if (current->ptrace & PT_SINGLESTEP)
 		if (current->ptrace & PT_SINGLESTEP)
 			task_pt_regs(current)->icountlevel = 1;
 			task_pt_regs(current)->icountlevel = 1;
 
 
-		return 1;
+		return;
 	}
 	}
 
 
 no_signal:
 no_signal:
@@ -558,8 +530,27 @@ no_signal:
 			break;
 			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)
 	if (current->ptrace & PT_SINGLESTEP)
 		task_pt_regs(current)->icountlevel = 1;
 		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();
+	}
+}

+ 1 - 0
include/linux/signal.h

@@ -252,6 +252,7 @@ extern int do_sigtimedwait(const sigset_t *, siginfo_t *,
 extern int sigprocmask(int, sigset_t *, sigset_t *);
 extern int sigprocmask(int, sigset_t *, sigset_t *);
 extern void set_current_blocked(const sigset_t *);
 extern void set_current_blocked(const sigset_t *);
 extern int show_unhandled_signals;
 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 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);
 extern void block_sigmask(struct k_sigaction *ka, int signr);

+ 1 - 9
kernel/compat.c

@@ -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)))
 	if (copy_from_user(&newset32, unewset, sizeof(compat_sigset_t)))
 		return -EFAULT;
 		return -EFAULT;
 	sigset_from_compat(&newset, &newset32);
 	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 */
 #endif /* __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND */
 
 

+ 16 - 9
kernel/signal.c

@@ -3232,6 +3232,21 @@ SYSCALL_DEFINE0(pause)
 
 
 #endif
 #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
 #ifdef __ARCH_WANT_SYS_RT_SIGSUSPEND
 /**
 /**
  *  sys_rt_sigsuspend - replace the signal mask for a value with the
  *  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)))
 	if (copy_from_user(&newset, unewset, sizeof(newset)))
 		return -EFAULT;
 		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 */
 #endif /* __ARCH_WANT_SYS_RT_SIGSUSPEND */