diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-23 21:11:45 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-23 21:11:45 -0400 |
commit | f9369910a6225b8d4892c3f20ae740a711cd5ace (patch) | |
tree | 8650ff79d7607bceb35509c028400ecf1c317de0 /arch | |
parent | 05f144a0d5c2207a0349348127f996e104ad7404 (diff) | |
parent | 415d04d08fec74b226c92c1fb54ad117c9c6bac4 (diff) |
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()
...
Diffstat (limited to 'arch')
51 files changed, 368 insertions, 799 deletions
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index 35f2ef44de12..10ab2d74ecbb 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c | |||
@@ -34,9 +34,6 @@ | |||
34 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 34 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) |
35 | 35 | ||
36 | asmlinkage void ret_from_sys_call(void); | 36 | asmlinkage void ret_from_sys_call(void); |
37 | static void do_signal(struct pt_regs *, struct switch_stack *, | ||
38 | unsigned long, unsigned long); | ||
39 | |||
40 | 37 | ||
41 | /* | 38 | /* |
42 | * The OSF/1 sigprocmask calling sequence is different from the | 39 | * 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, | |||
121 | SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask) | 118 | SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask) |
122 | { | 119 | { |
123 | sigset_t blocked; | 120 | sigset_t blocked; |
124 | |||
125 | current->saved_sigmask = current->blocked; | ||
126 | |||
127 | mask &= _BLOCKABLE; | ||
128 | siginitset(&blocked, mask); | 121 | siginitset(&blocked, mask); |
129 | set_current_blocked(&blocked); | 122 | return sigsuspend(&blocked); |
130 | |||
131 | current->state = TASK_INTERRUPTIBLE; | ||
132 | schedule(); | ||
133 | set_thread_flag(TIF_RESTORE_SIGMASK); | ||
134 | return -ERESTARTNOHAND; | ||
135 | } | 123 | } |
136 | 124 | ||
137 | asmlinkage int | 125 | asmlinkage int |
@@ -376,11 +364,11 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | |||
376 | oldsp = rdusp(); | 364 | oldsp = rdusp(); |
377 | frame = get_sigframe(ka, oldsp, sizeof(*frame)); | 365 | frame = get_sigframe(ka, oldsp, sizeof(*frame)); |
378 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 366 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
379 | goto give_sigsegv; | 367 | return -EFAULT; |
380 | 368 | ||
381 | err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp); | 369 | err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp); |
382 | if (err) | 370 | if (err) |
383 | goto give_sigsegv; | 371 | return -EFAULT; |
384 | 372 | ||
385 | /* Set up to return from userspace. If provided, use a stub | 373 | /* Set up to return from userspace. If provided, use a stub |
386 | already in userspace. */ | 374 | already in userspace. */ |
@@ -396,7 +384,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | |||
396 | 384 | ||
397 | /* Check that everything was written properly. */ | 385 | /* Check that everything was written properly. */ |
398 | if (err) | 386 | if (err) |
399 | goto give_sigsegv; | 387 | return err; |
400 | 388 | ||
401 | /* "Return" to the handler */ | 389 | /* "Return" to the handler */ |
402 | regs->r26 = r26; | 390 | regs->r26 = r26; |
@@ -410,12 +398,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | |||
410 | printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", | 398 | printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n", |
411 | current->comm, current->pid, frame, regs->pc, regs->r26); | 399 | current->comm, current->pid, frame, regs->pc, regs->r26); |
412 | #endif | 400 | #endif |
413 | |||
414 | return 0; | 401 | return 0; |
415 | |||
416 | give_sigsegv: | ||
417 | force_sigsegv(sig, current); | ||
418 | return -EFAULT; | ||
419 | } | 402 | } |
420 | 403 | ||
421 | static int | 404 | static int |
@@ -428,7 +411,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
428 | oldsp = rdusp(); | 411 | oldsp = rdusp(); |
429 | frame = get_sigframe(ka, oldsp, sizeof(*frame)); | 412 | frame = get_sigframe(ka, oldsp, sizeof(*frame)); |
430 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 413 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
431 | goto give_sigsegv; | 414 | return -EFAULT; |
432 | 415 | ||
433 | err |= copy_siginfo_to_user(&frame->info, info); | 416 | err |= copy_siginfo_to_user(&frame->info, info); |
434 | 417 | ||
@@ -443,7 +426,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
443 | set->sig[0], oldsp); | 426 | set->sig[0], oldsp); |
444 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | 427 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
445 | if (err) | 428 | if (err) |
446 | goto give_sigsegv; | 429 | return -EFAULT; |
447 | 430 | ||
448 | /* Set up to return from userspace. If provided, use a stub | 431 | /* Set up to return from userspace. If provided, use a stub |
449 | already in userspace. */ | 432 | already in userspace. */ |
@@ -459,7 +442,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
459 | } | 442 | } |
460 | 443 | ||
461 | if (err) | 444 | if (err) |
462 | goto give_sigsegv; | 445 | return -EFAULT; |
463 | 446 | ||
464 | /* "Return" to the handler */ | 447 | /* "Return" to the handler */ |
465 | regs->r26 = r26; | 448 | regs->r26 = r26; |
@@ -475,31 +458,37 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
475 | #endif | 458 | #endif |
476 | 459 | ||
477 | return 0; | 460 | return 0; |
478 | |||
479 | give_sigsegv: | ||
480 | force_sigsegv(sig, current); | ||
481 | return -EFAULT; | ||
482 | } | 461 | } |
483 | 462 | ||
484 | 463 | ||
485 | /* | 464 | /* |
486 | * OK, we're invoking a handler. | 465 | * OK, we're invoking a handler. |
487 | */ | 466 | */ |
488 | static inline int | 467 | static inline void |
489 | handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, | 468 | handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, |
490 | sigset_t *oldset, struct pt_regs * regs, struct switch_stack *sw) | 469 | struct pt_regs * regs, struct switch_stack *sw) |
491 | { | 470 | { |
471 | sigset_t *oldset = ¤t->blocked; | ||
492 | int ret; | 472 | int ret; |
493 | 473 | ||
474 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
475 | oldset = ¤t->saved_sigmask; | ||
476 | |||
494 | if (ka->sa.sa_flags & SA_SIGINFO) | 477 | if (ka->sa.sa_flags & SA_SIGINFO) |
495 | ret = setup_rt_frame(sig, ka, info, oldset, regs, sw); | 478 | ret = setup_rt_frame(sig, ka, info, oldset, regs, sw); |
496 | else | 479 | else |
497 | ret = setup_frame(sig, ka, oldset, regs, sw); | 480 | ret = setup_frame(sig, ka, oldset, regs, sw); |
498 | 481 | ||
499 | if (ret == 0) | 482 | if (ret) { |
500 | block_sigmask(ka, sig); | 483 | force_sigsegv(sig, current); |
501 | 484 | return; | |
502 | return ret; | 485 | } |
486 | block_sigmask(ka, sig); | ||
487 | /* A signal was successfully delivered, and the | ||
488 | saved sigmask was stored on the signal frame, | ||
489 | and will be restored by sigreturn. So we can | ||
490 | simply clear the restore sigmask flag. */ | ||
491 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
503 | } | 492 | } |
504 | 493 | ||
505 | static inline void | 494 | static inline void |
@@ -547,12 +536,6 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw, | |||
547 | int signr; | 536 | int signr; |
548 | unsigned long single_stepping = ptrace_cancel_bpt(current); | 537 | unsigned long single_stepping = ptrace_cancel_bpt(current); |
549 | struct k_sigaction ka; | 538 | struct k_sigaction ka; |
550 | sigset_t *oldset; | ||
551 | |||
552 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
553 | oldset = ¤t->saved_sigmask; | ||
554 | else | ||
555 | oldset = ¤t->blocked; | ||
556 | 539 | ||
557 | /* This lets the debugger run, ... */ | 540 | /* This lets the debugger run, ... */ |
558 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 541 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
@@ -564,14 +547,7 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw, | |||
564 | /* Whee! Actually deliver the signal. */ | 547 | /* Whee! Actually deliver the signal. */ |
565 | if (r0) | 548 | if (r0) |
566 | syscall_restart(r0, r19, regs, &ka); | 549 | syscall_restart(r0, r19, regs, &ka); |
567 | if (handle_signal(signr, &ka, &info, oldset, regs, sw) == 0) { | 550 | handle_signal(signr, &ka, &info, regs, sw); |
568 | /* A signal was successfully delivered, and the | ||
569 | saved sigmask was stored on the signal frame, | ||
570 | and will be restored by sigreturn. So we can | ||
571 | simply clear the restore sigmask flag. */ | ||
572 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
573 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
574 | } | ||
575 | if (single_stepping) | 551 | if (single_stepping) |
576 | ptrace_set_bpt(current); /* re-set bpt */ | 552 | ptrace_set_bpt(current); /* re-set bpt */ |
577 | return; | 553 | return; |
@@ -596,10 +572,8 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw, | |||
596 | } | 572 | } |
597 | 573 | ||
598 | /* If there's no signal to deliver, we just restore the saved mask. */ | 574 | /* If there's no signal to deliver, we just restore the saved mask. */ |
599 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | 575 | if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK)) |
600 | clear_thread_flag(TIF_RESTORE_SIGMASK); | 576 | set_current_blocked(¤t->saved_sigmask); |
601 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
602 | } | ||
603 | 577 | ||
604 | if (single_stepping) | 578 | if (single_stepping) |
605 | ptrace_set_bpt(current); /* re-set breakpoint */ | 579 | ptrace_set_bpt(current); /* re-set breakpoint */ |
@@ -610,7 +584,7 @@ do_notify_resume(struct pt_regs *regs, struct switch_stack *sw, | |||
610 | unsigned long thread_info_flags, | 584 | unsigned long thread_info_flags, |
611 | unsigned long r0, unsigned long r19) | 585 | unsigned long r0, unsigned long r19) |
612 | { | 586 | { |
613 | if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) | 587 | if (thread_info_flags & _TIF_SIGPENDING) |
614 | do_signal(regs, sw, r0, r19); | 588 | do_signal(regs, sw, r0, r19); |
615 | 589 | ||
616 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 590 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index 73d9a420850d..4e5fdd9bd9e3 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c | |||
@@ -67,17 +67,8 @@ const unsigned long syscall_restart_code[2] = { | |||
67 | asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask) | 67 | asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask) |
68 | { | 68 | { |
69 | sigset_t blocked; | 69 | sigset_t blocked; |
70 | |||
71 | current->saved_sigmask = current->blocked; | ||
72 | |||
73 | mask &= _BLOCKABLE; | ||
74 | siginitset(&blocked, mask); | 70 | siginitset(&blocked, mask); |
75 | set_current_blocked(&blocked); | 71 | return sigsuspend(&blocked); |
76 | |||
77 | current->state = TASK_INTERRUPTIBLE; | ||
78 | schedule(); | ||
79 | set_restore_sigmask(); | ||
80 | return -ERESTARTNOHAND; | ||
81 | } | 72 | } |
82 | 73 | ||
83 | asmlinkage int | 74 | asmlinkage int |
diff --git a/arch/avr32/include/asm/signal.h b/arch/avr32/include/asm/signal.h index 8790dfc10d5b..ae56849fdb2b 100644 --- a/arch/avr32/include/asm/signal.h +++ b/arch/avr32/include/asm/signal.h | |||
@@ -115,13 +115,6 @@ typedef unsigned long sigset_t; | |||
115 | #include <asm-generic/signal-defs.h> | 115 | #include <asm-generic/signal-defs.h> |
116 | 116 | ||
117 | #ifdef __KERNEL__ | 117 | #ifdef __KERNEL__ |
118 | struct old_sigaction { | ||
119 | __sighandler_t sa_handler; | ||
120 | old_sigset_t sa_mask; | ||
121 | unsigned long sa_flags; | ||
122 | __sigrestore_t sa_restorer; | ||
123 | }; | ||
124 | |||
125 | struct sigaction { | 118 | struct sigaction { |
126 | __sighandler_t sa_handler; | 119 | __sighandler_t sa_handler; |
127 | unsigned long sa_flags; | 120 | unsigned long sa_flags; |
diff --git a/arch/avr32/kernel/signal.c b/arch/avr32/kernel/signal.c index 64f886fac2ef..ae386c304bee 100644 --- a/arch/avr32/kernel/signal.c +++ b/arch/avr32/kernel/signal.c | |||
@@ -77,6 +77,9 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) | |||
77 | struct rt_sigframe __user *frame; | 77 | struct rt_sigframe __user *frame; |
78 | sigset_t set; | 78 | sigset_t set; |
79 | 79 | ||
80 | /* Always make any pending restarted system calls return -EINTR */ | ||
81 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | ||
82 | |||
80 | frame = (struct rt_sigframe __user *)regs->sp; | 83 | frame = (struct rt_sigframe __user *)regs->sp; |
81 | pr_debug("SIG return: frame = %p\n", frame); | 84 | pr_debug("SIG return: frame = %p\n", frame); |
82 | 85 | ||
@@ -87,10 +90,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) | |||
87 | goto badframe; | 90 | goto badframe; |
88 | 91 | ||
89 | sigdelsetmask(&set, ~_BLOCKABLE); | 92 | sigdelsetmask(&set, ~_BLOCKABLE); |
90 | spin_lock_irq(¤t->sighand->siglock); | 93 | set_current_blocked(&set); |
91 | current->blocked = set; | ||
92 | recalc_sigpending(); | ||
93 | spin_unlock_irq(¤t->sighand->siglock); | ||
94 | 94 | ||
95 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) | 95 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) |
96 | goto badframe; | 96 | goto badframe; |
@@ -238,22 +238,16 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, | |||
238 | */ | 238 | */ |
239 | ret |= !valid_user_regs(regs); | 239 | ret |= !valid_user_regs(regs); |
240 | 240 | ||
241 | /* | 241 | if (ret != 0) { |
242 | * Block the signal if we were unsuccessful. | 242 | force_sigsegv(sig, current); |
243 | */ | ||
244 | if (ret != 0 || !(ka->sa.sa_flags & SA_NODEFER)) { | ||
245 | spin_lock_irq(¤t->sighand->siglock); | ||
246 | sigorsets(¤t->blocked, ¤t->blocked, | ||
247 | &ka->sa.sa_mask); | ||
248 | sigaddset(¤t->blocked, sig); | ||
249 | recalc_sigpending(); | ||
250 | spin_unlock_irq(¤t->sighand->siglock); | ||
251 | } | ||
252 | |||
253 | if (ret == 0) | ||
254 | return; | 243 | return; |
244 | } | ||
255 | 245 | ||
256 | force_sigsegv(sig, current); | 246 | /* |
247 | * Block the signal if we were successful. | ||
248 | */ | ||
249 | block_sigmask(ka, sig); | ||
250 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
257 | } | 251 | } |
258 | 252 | ||
259 | /* | 253 | /* |
diff --git a/arch/blackfin/kernel/signal.c b/arch/blackfin/kernel/signal.c index d536f35d1f43..e5bbc1a5edc2 100644 --- a/arch/blackfin/kernel/signal.c +++ b/arch/blackfin/kernel/signal.c | |||
@@ -99,10 +99,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused) | |||
99 | goto badframe; | 99 | goto badframe; |
100 | 100 | ||
101 | sigdelsetmask(&set, ~_BLOCKABLE); | 101 | sigdelsetmask(&set, ~_BLOCKABLE); |
102 | spin_lock_irq(¤t->sighand->siglock); | 102 | set_current_blocked(&set); |
103 | current->blocked = set; | ||
104 | recalc_sigpending(); | ||
105 | spin_unlock_irq(¤t->sighand->siglock); | ||
106 | 103 | ||
107 | if (rt_restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) | 104 | if (rt_restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) |
108 | goto badframe; | 105 | goto badframe; |
@@ -213,9 +210,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info, | |||
213 | return 0; | 210 | return 0; |
214 | 211 | ||
215 | give_sigsegv: | 212 | give_sigsegv: |
216 | if (sig == SIGSEGV) | 213 | force_sigsegv(sig, current); |
217 | ka->sa.sa_handler = SIG_DFL; | ||
218 | force_sig(SIGSEGV, current); | ||
219 | return -EFAULT; | 214 | return -EFAULT; |
220 | } | 215 | } |
221 | 216 | ||
@@ -266,15 +261,9 @@ handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, | |||
266 | /* set up the stack frame */ | 261 | /* set up the stack frame */ |
267 | ret = setup_rt_frame(sig, ka, info, oldset, regs); | 262 | ret = setup_rt_frame(sig, ka, info, oldset, regs); |
268 | 263 | ||
269 | if (ret == 0) { | 264 | if (ret == 0) |
270 | spin_lock_irq(¤t->sighand->siglock); | 265 | block_sigmask(ka, sig); |
271 | sigorsets(¤t->blocked, ¤t->blocked, | 266 | |
272 | &ka->sa.sa_mask); | ||
273 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
274 | sigaddset(¤t->blocked, sig); | ||
275 | recalc_sigpending(); | ||
276 | spin_unlock_irq(¤t->sighand->siglock); | ||
277 | } | ||
278 | return ret; | 267 | return ret; |
279 | } | 268 | } |
280 | 269 | ||
diff --git a/arch/c6x/kernel/signal.c b/arch/c6x/kernel/signal.c index 3b5a05099989..cf37478c1169 100644 --- a/arch/c6x/kernel/signal.c +++ b/arch/c6x/kernel/signal.c | |||
@@ -69,6 +69,9 @@ asmlinkage int do_rt_sigreturn(struct pt_regs *regs) | |||
69 | struct rt_sigframe __user *frame; | 69 | struct rt_sigframe __user *frame; |
70 | sigset_t set; | 70 | sigset_t set; |
71 | 71 | ||
72 | /* Always make any pending restarted system calls return -EINTR */ | ||
73 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | ||
74 | |||
72 | /* | 75 | /* |
73 | * Since we stacked the signal on a dword boundary, | 76 | * Since we stacked the signal on a dword boundary, |
74 | * 'sp' should be dword aligned here. If it's | 77 | * 'sp' should be dword aligned here. If it's |
diff --git a/arch/cris/arch-v10/kernel/signal.c b/arch/cris/arch-v10/kernel/signal.c index 289c584ba499..e16f8f297f61 100644 --- a/arch/cris/arch-v10/kernel/signal.c +++ b/arch/cris/arch-v10/kernel/signal.c | |||
@@ -48,19 +48,11 @@ void do_signal(int canrestart, struct pt_regs *regs); | |||
48 | * dummy arguments to be able to reach the regs argument. (Note that this | 48 | * dummy arguments to be able to reach the regs argument. (Note that this |
49 | * arrangement relies on old_sigset_t occupying one register.) | 49 | * arrangement relies on old_sigset_t occupying one register.) |
50 | */ | 50 | */ |
51 | int sys_sigsuspend(old_sigset_t mask, long r11, long r12, long r13, long mof, | 51 | int sys_sigsuspend(old_sigset_t mask) |
52 | long srp, struct pt_regs *regs) | ||
53 | { | 52 | { |
54 | mask &= _BLOCKABLE; | 53 | sigset_t blocked; |
55 | spin_lock_irq(¤t->sighand->siglock); | 54 | siginitset(&blocked, mask); |
56 | current->saved_sigmask = current->blocked; | 55 | return sigsuspend(&blocked); |
57 | siginitset(¤t->blocked, mask); | ||
58 | recalc_sigpending(); | ||
59 | spin_unlock_irq(¤t->sighand->siglock); | ||
60 | current->state = TASK_INTERRUPTIBLE; | ||
61 | schedule(); | ||
62 | set_thread_flag(TIF_RESTORE_SIGMASK); | ||
63 | return -ERESTARTNOHAND; | ||
64 | } | 56 | } |
65 | 57 | ||
66 | int sys_sigaction(int sig, const struct old_sigaction __user *act, | 58 | 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, | |||
73 | old_sigset_t mask; | 65 | old_sigset_t mask; |
74 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || | 66 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || |
75 | __get_user(new_ka.sa.sa_handler, &act->sa_handler) || | 67 | __get_user(new_ka.sa.sa_handler, &act->sa_handler) || |
76 | __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) | 68 | __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) || |
69 | __get_user(new_ka.sa.sa_flags, &act->sa_flags) || | ||
70 | __get_user(mask, &act->sa_mask)) | ||
77 | return -EFAULT; | 71 | return -EFAULT; |
78 | __get_user(new_ka.sa.sa_flags, &act->sa_flags); | ||
79 | __get_user(mask, &act->sa_mask); | ||
80 | siginitset(&new_ka.sa.sa_mask, mask); | 72 | siginitset(&new_ka.sa.sa_mask, mask); |
81 | } | 73 | } |
82 | 74 | ||
@@ -85,10 +77,10 @@ int sys_sigaction(int sig, const struct old_sigaction __user *act, | |||
85 | if (!ret && oact) { | 77 | if (!ret && oact) { |
86 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || | 78 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || |
87 | __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || | 79 | __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || |
88 | __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) | 80 | __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) || |
81 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || | ||
82 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) | ||
89 | return -EFAULT; | 83 | return -EFAULT; |
90 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags); | ||
91 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); | ||
92 | } | 84 | } |
93 | 85 | ||
94 | return ret; | 86 | return ret; |
@@ -185,10 +177,7 @@ asmlinkage int sys_sigreturn(long r10, long r11, long r12, long r13, long mof, | |||
185 | goto badframe; | 177 | goto badframe; |
186 | 178 | ||
187 | sigdelsetmask(&set, ~_BLOCKABLE); | 179 | sigdelsetmask(&set, ~_BLOCKABLE); |
188 | spin_lock_irq(¤t->sighand->siglock); | 180 | set_current_blocked(&set); |
189 | current->blocked = set; | ||
190 | recalc_sigpending(); | ||
191 | spin_unlock_irq(¤t->sighand->siglock); | ||
192 | 181 | ||
193 | if (restore_sigcontext(regs, &frame->sc)) | 182 | if (restore_sigcontext(regs, &frame->sc)) |
194 | goto badframe; | 183 | goto badframe; |
@@ -224,10 +213,7 @@ asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13, | |||
224 | goto badframe; | 213 | goto badframe; |
225 | 214 | ||
226 | sigdelsetmask(&set, ~_BLOCKABLE); | 215 | sigdelsetmask(&set, ~_BLOCKABLE); |
227 | spin_lock_irq(¤t->sighand->siglock); | 216 | set_current_blocked(&set); |
228 | current->blocked = set; | ||
229 | recalc_sigpending(); | ||
230 | spin_unlock_irq(¤t->sighand->siglock); | ||
231 | 217 | ||
232 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) | 218 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) |
233 | goto badframe; | 219 | goto badframe; |
@@ -469,15 +455,9 @@ static inline int handle_signal(int canrestart, unsigned long sig, | |||
469 | else | 455 | else |
470 | ret = setup_frame(sig, ka, oldset, regs); | 456 | ret = setup_frame(sig, ka, oldset, regs); |
471 | 457 | ||
472 | if (ret == 0) { | 458 | if (ret == 0) |
473 | spin_lock_irq(¤t->sighand->siglock); | 459 | block_sigmask(ka, sig); |
474 | sigorsets(¤t->blocked, ¤t->blocked, | 460 | |
475 | &ka->sa.sa_mask); | ||
476 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
477 | sigaddset(¤t->blocked, sig); | ||
478 | recalc_sigpending(); | ||
479 | spin_unlock_irq(¤t->sighand->siglock); | ||
480 | } | ||
481 | return ret; | 461 | return ret; |
482 | } | 462 | } |
483 | 463 | ||
diff --git a/arch/cris/arch-v32/kernel/signal.c b/arch/cris/arch-v32/kernel/signal.c index ce4ab1a5552c..b338d8fc0c12 100644 --- a/arch/cris/arch-v32/kernel/signal.c +++ b/arch/cris/arch-v32/kernel/signal.c | |||
@@ -59,19 +59,11 @@ void keep_debug_flags(unsigned long oldccs, unsigned long oldspc, | |||
59 | * dummy arguments to be able to reach the regs argument. | 59 | * dummy arguments to be able to reach the regs argument. |
60 | */ | 60 | */ |
61 | int | 61 | int |
62 | sys_sigsuspend(old_sigset_t mask, long r11, long r12, long r13, long mof, | 62 | sys_sigsuspend(old_sigset_t mask) |
63 | long srp, struct pt_regs *regs) | ||
64 | { | 63 | { |
65 | mask &= _BLOCKABLE; | 64 | sigset_t blocked; |
66 | spin_lock_irq(¤t->sighand->siglock); | 65 | siginitset(&blocked, mask); |
67 | current->saved_sigmask = current->blocked; | 66 | return sigsuspend(&blocked); |
68 | siginitset(¤t->blocked, mask); | ||
69 | recalc_sigpending(); | ||
70 | spin_unlock_irq(¤t->sighand->siglock); | ||
71 | current->state = TASK_INTERRUPTIBLE; | ||
72 | schedule(); | ||
73 | set_thread_flag(TIF_RESTORE_SIGMASK); | ||
74 | return -ERESTARTNOHAND; | ||
75 | } | 67 | } |
76 | 68 | ||
77 | int | 69 | int |
@@ -87,11 +79,11 @@ sys_sigaction(int signal, const struct old_sigaction *act, | |||
87 | 79 | ||
88 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || | 80 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || |
89 | __get_user(newk.sa.sa_handler, &act->sa_handler) || | 81 | __get_user(newk.sa.sa_handler, &act->sa_handler) || |
90 | __get_user(newk.sa.sa_restorer, &act->sa_restorer)) | 82 | __get_user(newk.sa.sa_restorer, &act->sa_restorer) || |
83 | __get_user(newk.sa.sa_flags, &act->sa_flags) || | ||
84 | __get_user(mask, &act->sa_mask)) | ||
91 | return -EFAULT; | 85 | return -EFAULT; |
92 | 86 | ||
93 | __get_user(newk.sa.sa_flags, &act->sa_flags); | ||
94 | __get_user(mask, &act->sa_mask); | ||
95 | siginitset(&newk.sa.sa_mask, mask); | 87 | siginitset(&newk.sa.sa_mask, mask); |
96 | } | 88 | } |
97 | 89 | ||
@@ -100,11 +92,11 @@ sys_sigaction(int signal, const struct old_sigaction *act, | |||
100 | if (!retval && oact) { | 92 | if (!retval && oact) { |
101 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || | 93 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || |
102 | __put_user(oldk.sa.sa_handler, &oact->sa_handler) || | 94 | __put_user(oldk.sa.sa_handler, &oact->sa_handler) || |
103 | __put_user(oldk.sa.sa_restorer, &oact->sa_restorer)) | 95 | __put_user(oldk.sa.sa_restorer, &oact->sa_restorer) || |
96 | __put_user(oldk.sa.sa_flags, &oact->sa_flags) || | ||
97 | __put_user(oldk.sa.sa_mask.sig[0], &oact->sa_mask)) | ||
104 | return -EFAULT; | 98 | return -EFAULT; |
105 | 99 | ||
106 | __put_user(oldk.sa.sa_flags, &oact->sa_flags); | ||
107 | __put_user(oldk.sa.sa_mask.sig[0], &oact->sa_mask); | ||
108 | } | 100 | } |
109 | 101 | ||
110 | return retval; | 102 | return retval; |
@@ -176,12 +168,7 @@ sys_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp, | |||
176 | goto badframe; | 168 | goto badframe; |
177 | 169 | ||
178 | sigdelsetmask(&set, ~_BLOCKABLE); | 170 | sigdelsetmask(&set, ~_BLOCKABLE); |
179 | spin_lock_irq(¤t->sighand->siglock); | 171 | set_current_blocked(&set); |
180 | |||
181 | current->blocked = set; | ||
182 | |||
183 | recalc_sigpending(); | ||
184 | spin_unlock_irq(¤t->sighand->siglock); | ||
185 | 172 | ||
186 | if (restore_sigcontext(regs, &frame->sc)) | 173 | if (restore_sigcontext(regs, &frame->sc)) |
187 | goto badframe; | 174 | goto badframe; |
@@ -222,12 +209,7 @@ sys_rt_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp, | |||
222 | goto badframe; | 209 | goto badframe; |
223 | 210 | ||
224 | sigdelsetmask(&set, ~_BLOCKABLE); | 211 | sigdelsetmask(&set, ~_BLOCKABLE); |
225 | spin_lock_irq(¤t->sighand->siglock); | 212 | set_current_blocked(&set); |
226 | |||
227 | current->blocked = set; | ||
228 | |||
229 | recalc_sigpending(); | ||
230 | spin_unlock_irq(¤t->sighand->siglock); | ||
231 | 213 | ||
232 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) | 214 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) |
233 | goto badframe; | 215 | goto badframe; |
@@ -363,10 +345,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | |||
363 | return 0; | 345 | return 0; |
364 | 346 | ||
365 | give_sigsegv: | 347 | give_sigsegv: |
366 | if (sig == SIGSEGV) | 348 | force_sigsegv(sig, current); |
367 | ka->sa.sa_handler = SIG_DFL; | ||
368 | |||
369 | force_sig(SIGSEGV, current); | ||
370 | return -EFAULT; | 349 | return -EFAULT; |
371 | } | 350 | } |
372 | 351 | ||
@@ -450,10 +429,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
450 | return 0; | 429 | return 0; |
451 | 430 | ||
452 | give_sigsegv: | 431 | give_sigsegv: |
453 | if (sig == SIGSEGV) | 432 | force_sigsegv(sig, current); |
454 | ka->sa.sa_handler = SIG_DFL; | ||
455 | |||
456 | force_sig(SIGSEGV, current); | ||
457 | return -EFAULT; | 433 | return -EFAULT; |
458 | } | 434 | } |
459 | 435 | ||
@@ -512,18 +488,8 @@ handle_signal(int canrestart, unsigned long sig, | |||
512 | else | 488 | else |
513 | ret = setup_frame(sig, ka, oldset, regs); | 489 | ret = setup_frame(sig, ka, oldset, regs); |
514 | 490 | ||
515 | if (ka->sa.sa_flags & SA_ONESHOT) | 491 | if (ret == 0) |
516 | ka->sa.sa_handler = SIG_DFL; | 492 | block_sigmask(ka, sig); |
517 | |||
518 | if (ret == 0) { | ||
519 | spin_lock_irq(¤t->sighand->siglock); | ||
520 | sigorsets(¤t->blocked, ¤t->blocked, | ||
521 | &ka->sa.sa_mask); | ||
522 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
523 | sigaddset(¤t->blocked, sig); | ||
524 | recalc_sigpending(); | ||
525 | spin_unlock_irq(¤t->sighand->siglock); | ||
526 | } | ||
527 | 493 | ||
528 | return ret; | 494 | return ret; |
529 | } | 495 | } |
diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c index bab01298b58e..8cf5dca01758 100644 --- a/arch/frv/kernel/signal.c +++ b/arch/frv/kernel/signal.c | |||
@@ -40,17 +40,9 @@ struct fdpic_func_descriptor { | |||
40 | */ | 40 | */ |
41 | asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask) | 41 | asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask) |
42 | { | 42 | { |
43 | mask &= _BLOCKABLE; | 43 | sigset_t blocked; |
44 | spin_lock_irq(¤t->sighand->siglock); | 44 | siginitset(&blocked, mask); |
45 | current->saved_sigmask = current->blocked; | 45 | return sigsuspend(&blocked); |
46 | siginitset(¤t->blocked, mask); | ||
47 | recalc_sigpending(); | ||
48 | spin_unlock_irq(¤t->sighand->siglock); | ||
49 | |||
50 | current->state = TASK_INTERRUPTIBLE; | ||
51 | schedule(); | ||
52 | set_thread_flag(TIF_RESTORE_SIGMASK); | ||
53 | return -ERESTARTNOHAND; | ||
54 | } | 46 | } |
55 | 47 | ||
56 | asmlinkage int sys_sigaction(int sig, | 48 | asmlinkage int sys_sigaction(int sig, |
@@ -64,10 +56,10 @@ asmlinkage int sys_sigaction(int sig, | |||
64 | old_sigset_t mask; | 56 | old_sigset_t mask; |
65 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || | 57 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || |
66 | __get_user(new_ka.sa.sa_handler, &act->sa_handler) || | 58 | __get_user(new_ka.sa.sa_handler, &act->sa_handler) || |
67 | __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) | 59 | __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) || |
60 | __get_user(new_ka.sa.sa_flags, &act->sa_flags) || | ||
61 | __get_user(mask, &act->sa_mask)) | ||
68 | return -EFAULT; | 62 | return -EFAULT; |
69 | __get_user(new_ka.sa.sa_flags, &act->sa_flags); | ||
70 | __get_user(mask, &act->sa_mask); | ||
71 | siginitset(&new_ka.sa.sa_mask, mask); | 63 | siginitset(&new_ka.sa.sa_mask, mask); |
72 | } | 64 | } |
73 | 65 | ||
@@ -76,10 +68,10 @@ asmlinkage int sys_sigaction(int sig, | |||
76 | if (!ret && oact) { | 68 | if (!ret && oact) { |
77 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || | 69 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || |
78 | __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || | 70 | __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || |
79 | __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) | 71 | __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) || |
72 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || | ||
73 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) | ||
80 | return -EFAULT; | 74 | return -EFAULT; |
81 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags); | ||
82 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); | ||
83 | } | 75 | } |
84 | 76 | ||
85 | return ret; | 77 | return ret; |
@@ -158,10 +150,7 @@ asmlinkage int sys_sigreturn(void) | |||
158 | goto badframe; | 150 | goto badframe; |
159 | 151 | ||
160 | sigdelsetmask(&set, ~_BLOCKABLE); | 152 | sigdelsetmask(&set, ~_BLOCKABLE); |
161 | spin_lock_irq(¤t->sighand->siglock); | 153 | set_current_blocked(&set); |
162 | current->blocked = set; | ||
163 | recalc_sigpending(); | ||
164 | spin_unlock_irq(¤t->sighand->siglock); | ||
165 | 154 | ||
166 | if (restore_sigcontext(&frame->sc, &gr8)) | 155 | if (restore_sigcontext(&frame->sc, &gr8)) |
167 | goto badframe; | 156 | goto badframe; |
@@ -184,10 +173,7 @@ asmlinkage int sys_rt_sigreturn(void) | |||
184 | goto badframe; | 173 | goto badframe; |
185 | 174 | ||
186 | sigdelsetmask(&set, ~_BLOCKABLE); | 175 | sigdelsetmask(&set, ~_BLOCKABLE); |
187 | spin_lock_irq(¤t->sighand->siglock); | 176 | set_current_blocked(&set); |
188 | current->blocked = set; | ||
189 | recalc_sigpending(); | ||
190 | spin_unlock_irq(¤t->sighand->siglock); | ||
191 | 177 | ||
192 | if (restore_sigcontext(&frame->uc.uc_mcontext, &gr8)) | 178 | if (restore_sigcontext(&frame->uc.uc_mcontext, &gr8)) |
193 | goto badframe; | 179 | goto badframe; |
@@ -474,15 +460,8 @@ static int handle_signal(unsigned long sig, siginfo_t *info, | |||
474 | else | 460 | else |
475 | ret = setup_frame(sig, ka, oldset); | 461 | ret = setup_frame(sig, ka, oldset); |
476 | 462 | ||
477 | if (ret == 0) { | 463 | if (ret == 0) |
478 | spin_lock_irq(¤t->sighand->siglock); | 464 | block_sigmask(ka, sig); |
479 | sigorsets(¤t->blocked, ¤t->blocked, | ||
480 | &ka->sa.sa_mask); | ||
481 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
482 | sigaddset(¤t->blocked, sig); | ||
483 | recalc_sigpending(); | ||
484 | spin_unlock_irq(¤t->sighand->siglock); | ||
485 | } | ||
486 | 465 | ||
487 | return ret; | 466 | return ret; |
488 | 467 | ||
diff --git a/arch/h8300/include/asm/unistd.h b/arch/h8300/include/asm/unistd.h index 2c3f8e60b1e0..718511303b4e 100644 --- a/arch/h8300/include/asm/unistd.h +++ b/arch/h8300/include/asm/unistd.h | |||
@@ -356,6 +356,7 @@ | |||
356 | #define __ARCH_WANT_SYS_SIGPENDING | 356 | #define __ARCH_WANT_SYS_SIGPENDING |
357 | #define __ARCH_WANT_SYS_SIGPROCMASK | 357 | #define __ARCH_WANT_SYS_SIGPROCMASK |
358 | #define __ARCH_WANT_SYS_RT_SIGACTION | 358 | #define __ARCH_WANT_SYS_RT_SIGACTION |
359 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND | ||
359 | 360 | ||
360 | /* | 361 | /* |
361 | * "Conditional" syscalls | 362 | * "Conditional" syscalls |
diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c index af842c369d24..d4b0555d2904 100644 --- a/arch/h8300/kernel/signal.c +++ b/arch/h8300/kernel/signal.c | |||
@@ -49,60 +49,15 @@ | |||
49 | 49 | ||
50 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 50 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) |
51 | 51 | ||
52 | asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); | ||
53 | |||
54 | /* | 52 | /* |
55 | * Atomically swap in the new signal mask, and wait for a signal. | 53 | * Atomically swap in the new signal mask, and wait for a signal. |
56 | */ | 54 | */ |
57 | asmlinkage int do_sigsuspend(struct pt_regs *regs) | ||
58 | { | ||
59 | old_sigset_t mask = regs->er3; | ||
60 | sigset_t saveset; | ||
61 | |||
62 | mask &= _BLOCKABLE; | ||
63 | spin_lock_irq(¤t->sighand->siglock); | ||
64 | saveset = current->blocked; | ||
65 | siginitset(¤t->blocked, mask); | ||
66 | recalc_sigpending(); | ||
67 | spin_unlock_irq(¤t->sighand->siglock); | ||
68 | |||
69 | regs->er0 = -EINTR; | ||
70 | while (1) { | ||
71 | current->state = TASK_INTERRUPTIBLE; | ||
72 | schedule(); | ||
73 | if (do_signal(regs, &saveset)) | ||
74 | return -EINTR; | ||
75 | } | ||
76 | } | ||
77 | |||
78 | asmlinkage int | 55 | asmlinkage int |
79 | do_rt_sigsuspend(struct pt_regs *regs) | 56 | sys_sigsuspend(int unused1, int unused2, old_sigset_t mask) |
80 | { | 57 | { |
81 | sigset_t *unewset = (sigset_t *)regs->er1; | 58 | sigset_t blocked; |
82 | size_t sigsetsize = (size_t)regs->er2; | 59 | siginitset(&blocked, mask); |
83 | sigset_t saveset, newset; | 60 | return sigsuspend(&blocked); |
84 | |||
85 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
86 | if (sigsetsize != sizeof(sigset_t)) | ||
87 | return -EINVAL; | ||
88 | |||
89 | if (copy_from_user(&newset, unewset, sizeof(newset))) | ||
90 | return -EFAULT; | ||
91 | sigdelsetmask(&newset, ~_BLOCKABLE); | ||
92 | |||
93 | spin_lock_irq(¤t->sighand->siglock); | ||
94 | saveset = current->blocked; | ||
95 | current->blocked = newset; | ||
96 | recalc_sigpending(); | ||
97 | spin_unlock_irq(¤t->sighand->siglock); | ||
98 | |||
99 | regs->er0 = -EINTR; | ||
100 | while (1) { | ||
101 | current->state = TASK_INTERRUPTIBLE; | ||
102 | schedule(); | ||
103 | if (do_signal(regs, &saveset)) | ||
104 | return -EINTR; | ||
105 | } | ||
106 | } | 61 | } |
107 | 62 | ||
108 | asmlinkage int | 63 | asmlinkage int |
@@ -116,10 +71,10 @@ sys_sigaction(int sig, const struct old_sigaction *act, | |||
116 | old_sigset_t mask; | 71 | old_sigset_t mask; |
117 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || | 72 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || |
118 | __get_user(new_ka.sa.sa_handler, &act->sa_handler) || | 73 | __get_user(new_ka.sa.sa_handler, &act->sa_handler) || |
119 | __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) | 74 | __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) || |
75 | __get_user(new_ka.sa.sa_flags, &act->sa_flags) || | ||
76 | __get_user(mask, &act->sa_mask)) | ||
120 | return -EFAULT; | 77 | return -EFAULT; |
121 | __get_user(new_ka.sa.sa_flags, &act->sa_flags); | ||
122 | __get_user(mask, &act->sa_mask); | ||
123 | siginitset(&new_ka.sa.sa_mask, mask); | 78 | siginitset(&new_ka.sa.sa_mask, mask); |
124 | } | 79 | } |
125 | 80 | ||
@@ -128,10 +83,10 @@ sys_sigaction(int sig, const struct old_sigaction *act, | |||
128 | if (!ret && oact) { | 83 | if (!ret && oact) { |
129 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || | 84 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || |
130 | __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || | 85 | __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || |
131 | __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) | 86 | __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) || |
87 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || | ||
88 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) | ||
132 | return -EFAULT; | 89 | return -EFAULT; |
133 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags); | ||
134 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); | ||
135 | } | 90 | } |
136 | 91 | ||
137 | return ret; | 92 | return ret; |
@@ -232,10 +187,7 @@ asmlinkage int do_sigreturn(unsigned long __unused,...) | |||
232 | goto badframe; | 187 | goto badframe; |
233 | 188 | ||
234 | sigdelsetmask(&set, ~_BLOCKABLE); | 189 | sigdelsetmask(&set, ~_BLOCKABLE); |
235 | spin_lock_irq(¤t->sighand->siglock); | 190 | set_current_blocked(&set); |
236 | current->blocked = set; | ||
237 | recalc_sigpending(); | ||
238 | spin_unlock_irq(¤t->sighand->siglock); | ||
239 | 191 | ||
240 | if (restore_sigcontext(regs, &frame->sc, &er0)) | 192 | if (restore_sigcontext(regs, &frame->sc, &er0)) |
241 | goto badframe; | 193 | goto badframe; |
@@ -260,10 +212,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused,...) | |||
260 | goto badframe; | 212 | goto badframe; |
261 | 213 | ||
262 | sigdelsetmask(&set, ~_BLOCKABLE); | 214 | sigdelsetmask(&set, ~_BLOCKABLE); |
263 | spin_unlock_irq(¤t->sighand->siglock); | 215 | set_current_blocked(&set); |
264 | current->blocked = set; | ||
265 | recalc_sigpending(); | ||
266 | spin_lock_irq(¤t->sighand->siglock); | ||
267 | 216 | ||
268 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &er0)) | 217 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &er0)) |
269 | goto badframe; | 218 | goto badframe; |
@@ -314,7 +263,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) | |||
314 | return (void *)((usp - frame_size) & -8UL); | 263 | return (void *)((usp - frame_size) & -8UL); |
315 | } | 264 | } |
316 | 265 | ||
317 | static void setup_frame (int sig, struct k_sigaction *ka, | 266 | static int setup_frame (int sig, struct k_sigaction *ka, |
318 | sigset_t *set, struct pt_regs *regs) | 267 | sigset_t *set, struct pt_regs *regs) |
319 | { | 268 | { |
320 | struct sigframe *frame; | 269 | struct sigframe *frame; |
@@ -375,13 +324,14 @@ static void setup_frame (int sig, struct k_sigaction *ka, | |||
375 | regs->er1 = (unsigned long)&(frame->sc); | 324 | regs->er1 = (unsigned long)&(frame->sc); |
376 | regs->er5 = current->mm->start_data; /* GOT base */ | 325 | regs->er5 = current->mm->start_data; /* GOT base */ |
377 | 326 | ||
378 | return; | 327 | return 0; |
379 | 328 | ||
380 | give_sigsegv: | 329 | give_sigsegv: |
381 | force_sigsegv(sig, current); | 330 | force_sigsegv(sig, current); |
331 | return -EFAULT; | ||
382 | } | 332 | } |
383 | 333 | ||
384 | static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, | 334 | static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, |
385 | sigset_t *set, struct pt_regs *regs) | 335 | sigset_t *set, struct pt_regs *regs) |
386 | { | 336 | { |
387 | struct rt_sigframe *frame; | 337 | struct rt_sigframe *frame; |
@@ -450,10 +400,11 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, | |||
450 | regs->er2 = (unsigned long)&frame->uc; | 400 | regs->er2 = (unsigned long)&frame->uc; |
451 | regs->er5 = current->mm->start_data; /* GOT base */ | 401 | regs->er5 = current->mm->start_data; /* GOT base */ |
452 | 402 | ||
453 | return; | 403 | return 0; |
454 | 404 | ||
455 | give_sigsegv: | 405 | give_sigsegv: |
456 | force_sigsegv(sig, current); | 406 | force_sigsegv(sig, current); |
407 | return -EFAULT; | ||
457 | } | 408 | } |
458 | 409 | ||
459 | /* | 410 | /* |
@@ -463,6 +414,7 @@ static void | |||
463 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | 414 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, |
464 | sigset_t *oldset, struct pt_regs * regs) | 415 | sigset_t *oldset, struct pt_regs * regs) |
465 | { | 416 | { |
417 | int ret; | ||
466 | /* are we from a system call? */ | 418 | /* are we from a system call? */ |
467 | if (regs->orig_er0 >= 0) { | 419 | if (regs->orig_er0 >= 0) { |
468 | switch (regs->er0) { | 420 | switch (regs->er0) { |
@@ -485,16 +437,14 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
485 | 437 | ||
486 | /* set up the stack frame */ | 438 | /* set up the stack frame */ |
487 | if (ka->sa.sa_flags & SA_SIGINFO) | 439 | if (ka->sa.sa_flags & SA_SIGINFO) |
488 | setup_rt_frame(sig, ka, info, oldset, regs); | 440 | ret = setup_rt_frame(sig, ka, info, oldset, regs); |
489 | else | 441 | else |
490 | setup_frame(sig, ka, oldset, regs); | 442 | ret = setup_frame(sig, ka, oldset, regs); |
491 | 443 | ||
492 | spin_lock_irq(¤t->sighand->siglock); | 444 | if (!ret) { |
493 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | 445 | block_sigmask(ka, sig); |
494 | if (!(ka->sa.sa_flags & SA_NODEFER)) | 446 | clear_thread_flag(TIF_RESTORE_SIGMASK); |
495 | sigaddset(¤t->blocked,sig); | 447 | } |
496 | recalc_sigpending(); | ||
497 | spin_unlock_irq(¤t->sighand->siglock); | ||
498 | } | 448 | } |
499 | 449 | ||
500 | /* | 450 | /* |
@@ -502,11 +452,12 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
502 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | 452 | * want to handle. Thus you cannot kill init even with a SIGKILL even by |
503 | * mistake. | 453 | * mistake. |
504 | */ | 454 | */ |
505 | asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset) | 455 | statis void do_signal(struct pt_regs *regs) |
506 | { | 456 | { |
507 | siginfo_t info; | 457 | siginfo_t info; |
508 | int signr; | 458 | int signr; |
509 | struct k_sigaction ka; | 459 | struct k_sigaction ka; |
460 | sigset_t *oldset; | ||
510 | 461 | ||
511 | /* | 462 | /* |
512 | * We want the common case to go fast, which | 463 | * We want the common case to go fast, which |
@@ -515,21 +466,23 @@ asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset) | |||
515 | * if so. | 466 | * if so. |
516 | */ | 467 | */ |
517 | if ((regs->ccr & 0x10)) | 468 | if ((regs->ccr & 0x10)) |
518 | return 1; | 469 | return; |
519 | 470 | ||
520 | if (try_to_freeze()) | 471 | if (try_to_freeze()) |
521 | goto no_signal; | 472 | goto no_signal; |
522 | 473 | ||
523 | current->thread.esp0 = (unsigned long) regs; | 474 | current->thread.esp0 = (unsigned long) regs; |
524 | 475 | ||
525 | if (!oldset) | 476 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
477 | oldset = ¤t->saved_sigmask; | ||
478 | else | ||
526 | oldset = ¤t->blocked; | 479 | oldset = ¤t->blocked; |
527 | 480 | ||
528 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 481 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); |
529 | if (signr > 0) { | 482 | if (signr > 0) { |
530 | /* Whee! Actually deliver the signal. */ | 483 | /* Whee! Actually deliver the signal. */ |
531 | handle_signal(signr, &info, &ka, oldset, regs); | 484 | handle_signal(signr, &info, &ka, oldset, regs); |
532 | return 1; | 485 | return; |
533 | } | 486 | } |
534 | no_signal: | 487 | no_signal: |
535 | /* Did we come from a system call? */ | 488 | /* Did we come from a system call? */ |
@@ -546,13 +499,16 @@ asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset) | |||
546 | regs->pc -= 2; | 499 | regs->pc -= 2; |
547 | } | 500 | } |
548 | } | 501 | } |
549 | return 0; | 502 | |
503 | /* If there's no signal to deliver, we just restore the saved mask. */ | ||
504 | if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK)) | ||
505 | set_current_blocked(¤t->saved_sigmask); | ||
550 | } | 506 | } |
551 | 507 | ||
552 | asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags) | 508 | asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags) |
553 | { | 509 | { |
554 | if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) | 510 | if (thread_info_flags & _TIF_SIGPENDING) |
555 | do_signal(regs, NULL); | 511 | do_signal(regs); |
556 | 512 | ||
557 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 513 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |
558 | clear_thread_flag(TIF_NOTIFY_RESUME); | 514 | clear_thread_flag(TIF_NOTIFY_RESUME); |
diff --git a/arch/h8300/kernel/syscalls.S b/arch/h8300/kernel/syscalls.S index 4be2ea2fbe26..9d77e715a2ed 100644 --- a/arch/h8300/kernel/syscalls.S +++ b/arch/h8300/kernel/syscalls.S | |||
@@ -343,12 +343,6 @@ SYMBOL_NAME_LABEL(sys_call_table) | |||
343 | SYMBOL_NAME_LABEL(sys_clone) | 343 | SYMBOL_NAME_LABEL(sys_clone) |
344 | call_sp h8300_clone | 344 | call_sp h8300_clone |
345 | 345 | ||
346 | SYMBOL_NAME_LABEL(sys_sigsuspend) | ||
347 | call_sp do_sigsuspend | ||
348 | |||
349 | SYMBOL_NAME_LABEL(sys_rt_sigsuspend) | ||
350 | call_sp do_rt_sigsuspend | ||
351 | |||
352 | SYMBOL_NAME_LABEL(sys_sigreturn) | 346 | SYMBOL_NAME_LABEL(sys_sigreturn) |
353 | call_sp do_sigreturn | 347 | call_sp do_sigreturn |
354 | 348 | ||
diff --git a/arch/hexagon/kernel/signal.c b/arch/hexagon/kernel/signal.c index ecbab3457606..434866eb0f1c 100644 --- a/arch/hexagon/kernel/signal.c +++ b/arch/hexagon/kernel/signal.c | |||
@@ -272,6 +272,7 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) | |||
272 | 272 | ||
273 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 273 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |
274 | clear_thread_flag(TIF_NOTIFY_RESUME); | 274 | clear_thread_flag(TIF_NOTIFY_RESUME); |
275 | tracehook_notify_resume(regs); | ||
275 | if (current->replacement_session_keyring) | 276 | if (current->replacement_session_keyring) |
276 | key_replace_session_keyring(); | 277 | key_replace_session_keyring(); |
277 | } | 278 | } |
@@ -293,6 +294,9 @@ asmlinkage int sys_rt_sigreturn(void) | |||
293 | struct rt_sigframe __user *frame; | 294 | struct rt_sigframe __user *frame; |
294 | sigset_t blocked; | 295 | sigset_t blocked; |
295 | 296 | ||
297 | /* Always make any pending restarted system calls return -EINTR */ | ||
298 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | ||
299 | |||
296 | frame = (struct rt_sigframe __user *)pt_psp(regs); | 300 | frame = (struct rt_sigframe __user *)pt_psp(regs); |
297 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 301 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
298 | goto badframe; | 302 | goto badframe; |
diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c index 7bdafc8788bd..7523501d3bc0 100644 --- a/arch/ia64/kernel/signal.c +++ b/arch/ia64/kernel/signal.c | |||
@@ -201,13 +201,7 @@ ia64_rt_sigreturn (struct sigscratch *scr) | |||
201 | goto give_sigsegv; | 201 | goto give_sigsegv; |
202 | 202 | ||
203 | sigdelsetmask(&set, ~_BLOCKABLE); | 203 | sigdelsetmask(&set, ~_BLOCKABLE); |
204 | 204 | set_current_blocked(&set); | |
205 | spin_lock_irq(¤t->sighand->siglock); | ||
206 | { | ||
207 | current->blocked = set; | ||
208 | recalc_sigpending(); | ||
209 | } | ||
210 | spin_unlock_irq(¤t->sighand->siglock); | ||
211 | 205 | ||
212 | if (restore_sigcontext(sc, scr)) | 206 | if (restore_sigcontext(sc, scr)) |
213 | goto give_sigsegv; | 207 | goto give_sigsegv; |
@@ -427,12 +421,7 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigse | |||
427 | if (!setup_frame(sig, ka, info, oldset, scr)) | 421 | if (!setup_frame(sig, ka, info, oldset, scr)) |
428 | return 0; | 422 | return 0; |
429 | 423 | ||
430 | spin_lock_irq(¤t->sighand->siglock); | 424 | block_sigmask(ka, sig); |
431 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); | ||
432 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
433 | sigaddset(¤t->blocked, sig); | ||
434 | recalc_sigpending(); | ||
435 | spin_unlock_irq(¤t->sighand->siglock); | ||
436 | 425 | ||
437 | /* | 426 | /* |
438 | * Let tracing know that we've done the handler setup. | 427 | * Let tracing know that we've done the handler setup. |
diff --git a/arch/m32r/include/asm/signal.h b/arch/m32r/include/asm/signal.h index b2eeb0de1c8d..ea5f95e4079e 100644 --- a/arch/m32r/include/asm/signal.h +++ b/arch/m32r/include/asm/signal.h | |||
@@ -110,13 +110,6 @@ typedef unsigned long sigset_t; | |||
110 | #include <asm-generic/signal-defs.h> | 110 | #include <asm-generic/signal-defs.h> |
111 | 111 | ||
112 | #ifdef __KERNEL__ | 112 | #ifdef __KERNEL__ |
113 | struct old_sigaction { | ||
114 | __sighandler_t sa_handler; | ||
115 | old_sigset_t sa_mask; | ||
116 | unsigned long sa_flags; | ||
117 | __sigrestore_t sa_restorer; | ||
118 | }; | ||
119 | |||
120 | struct sigaction { | 113 | struct sigaction { |
121 | __sighandler_t sa_handler; | 114 | __sighandler_t sa_handler; |
122 | unsigned long sa_flags; | 115 | unsigned long sa_flags; |
diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c index a08697f0886d..f54d96993ea1 100644 --- a/arch/m32r/kernel/signal.c +++ b/arch/m32r/kernel/signal.c | |||
@@ -112,10 +112,7 @@ sys_rt_sigreturn(unsigned long r0, unsigned long r1, | |||
112 | goto badframe; | 112 | goto badframe; |
113 | 113 | ||
114 | sigdelsetmask(&set, ~_BLOCKABLE); | 114 | sigdelsetmask(&set, ~_BLOCKABLE); |
115 | spin_lock_irq(¤t->sighand->siglock); | 115 | set_current_blocked(&set); |
116 | current->blocked = set; | ||
117 | recalc_sigpending(); | ||
118 | spin_unlock_irq(¤t->sighand->siglock); | ||
119 | 116 | ||
120 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &result)) | 117 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &result)) |
121 | goto badframe; | 118 | goto badframe; |
@@ -300,12 +297,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, | |||
300 | if (setup_rt_frame(sig, ka, info, oldset, regs)) | 297 | if (setup_rt_frame(sig, ka, info, oldset, regs)) |
301 | return -EFAULT; | 298 | return -EFAULT; |
302 | 299 | ||
303 | spin_lock_irq(¤t->sighand->siglock); | 300 | block_sigmask(ka, sig); |
304 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | ||
305 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
306 | sigaddset(¤t->blocked,sig); | ||
307 | recalc_sigpending(); | ||
308 | spin_unlock_irq(¤t->sighand->siglock); | ||
309 | return 0; | 301 | return 0; |
310 | } | 302 | } |
311 | 303 | ||
diff --git a/arch/m68k/include/asm/thread_info.h b/arch/m68k/include/asm/thread_info.h index e8665e6f9464..126131f94a2c 100644 --- a/arch/m68k/include/asm/thread_info.h +++ b/arch/m68k/include/asm/thread_info.h | |||
@@ -71,6 +71,7 @@ static inline struct thread_info *current_thread_info(void) | |||
71 | * bits 0-7 are tested at every exception exit | 71 | * bits 0-7 are tested at every exception exit |
72 | * bits 8-15 are also tested at syscall exit | 72 | * bits 8-15 are also tested at syscall exit |
73 | */ | 73 | */ |
74 | #define TIF_NOTIFY_RESUME 5 /* callback before returning to user */ | ||
74 | #define TIF_SIGPENDING 6 /* signal pending */ | 75 | #define TIF_SIGPENDING 6 /* signal pending */ |
75 | #define TIF_NEED_RESCHED 7 /* rescheduling necessary */ | 76 | #define TIF_NEED_RESCHED 7 /* rescheduling necessary */ |
76 | #define TIF_DELAYED_TRACE 14 /* single step a syscall */ | 77 | #define TIF_DELAYED_TRACE 14 /* single step a syscall */ |
diff --git a/arch/m68k/kernel/entry_mm.S b/arch/m68k/kernel/entry_mm.S index 675a854966a6..f29e73ca9dbb 100644 --- a/arch/m68k/kernel/entry_mm.S +++ b/arch/m68k/kernel/entry_mm.S | |||
@@ -148,7 +148,7 @@ syscall_exit_work: | |||
148 | jcs do_trace_exit | 148 | jcs do_trace_exit |
149 | jmi do_delayed_trace | 149 | jmi do_delayed_trace |
150 | lslw #8,%d0 | 150 | lslw #8,%d0 |
151 | jmi do_signal_return | 151 | jne do_signal_return |
152 | pea resume_userspace | 152 | pea resume_userspace |
153 | jra schedule | 153 | jra schedule |
154 | 154 | ||
@@ -172,7 +172,7 @@ exit_work: | |||
172 | | save top of frame | 172 | | save top of frame |
173 | movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) | 173 | movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0) |
174 | lslb #1,%d0 | 174 | lslb #1,%d0 |
175 | jmi do_signal_return | 175 | jne do_signal_return |
176 | pea resume_userspace | 176 | pea resume_userspace |
177 | jra schedule | 177 | jra schedule |
178 | 178 | ||
@@ -182,7 +182,7 @@ do_signal_return: | |||
182 | subql #4,%sp | dummy return address | 182 | subql #4,%sp | dummy return address |
183 | SAVE_SWITCH_STACK | 183 | SAVE_SWITCH_STACK |
184 | pea %sp@(SWITCH_STACK_SIZE) | 184 | pea %sp@(SWITCH_STACK_SIZE) |
185 | bsrl do_signal | 185 | bsrl do_notify_resume |
186 | addql #4,%sp | 186 | addql #4,%sp |
187 | RESTORE_SWITCH_STACK | 187 | RESTORE_SWITCH_STACK |
188 | addql #4,%sp | 188 | addql #4,%sp |
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c index 1747c7030a33..d9f3d1900eed 100644 --- a/arch/m68k/kernel/signal.c +++ b/arch/m68k/kernel/signal.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/tty.h> | 43 | #include <linux/tty.h> |
44 | #include <linux/binfmts.h> | 44 | #include <linux/binfmts.h> |
45 | #include <linux/module.h> | 45 | #include <linux/module.h> |
46 | #include <linux/tracehook.h> | ||
46 | 47 | ||
47 | #include <asm/setup.h> | 48 | #include <asm/setup.h> |
48 | #include <asm/uaccess.h> | 49 | #include <asm/uaccess.h> |
@@ -230,18 +231,9 @@ static inline void push_cache(unsigned long vaddr) | |||
230 | asmlinkage int | 231 | asmlinkage int |
231 | sys_sigsuspend(int unused0, int unused1, old_sigset_t mask) | 232 | sys_sigsuspend(int unused0, int unused1, old_sigset_t mask) |
232 | { | 233 | { |
233 | mask &= _BLOCKABLE; | 234 | sigset_t blocked; |
234 | spin_lock_irq(¤t->sighand->siglock); | 235 | siginitset(&blocked, mask); |
235 | current->saved_sigmask = current->blocked; | 236 | return sigsuspend(&blocked); |
236 | siginitset(¤t->blocked, mask); | ||
237 | recalc_sigpending(); | ||
238 | spin_unlock_irq(¤t->sighand->siglock); | ||
239 | |||
240 | current->state = TASK_INTERRUPTIBLE; | ||
241 | schedule(); | ||
242 | set_restore_sigmask(); | ||
243 | |||
244 | return -ERESTARTNOHAND; | ||
245 | } | 237 | } |
246 | 238 | ||
247 | asmlinkage int | 239 | asmlinkage int |
@@ -804,8 +796,7 @@ asmlinkage int do_sigreturn(unsigned long __unused) | |||
804 | goto badframe; | 796 | goto badframe; |
805 | 797 | ||
806 | sigdelsetmask(&set, ~_BLOCKABLE); | 798 | sigdelsetmask(&set, ~_BLOCKABLE); |
807 | current->blocked = set; | 799 | set_current_blocked(&set); |
808 | recalc_sigpending(); | ||
809 | 800 | ||
810 | if (restore_sigcontext(regs, &frame->sc, frame + 1)) | 801 | if (restore_sigcontext(regs, &frame->sc, frame + 1)) |
811 | goto badframe; | 802 | goto badframe; |
@@ -830,8 +821,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused) | |||
830 | goto badframe; | 821 | goto badframe; |
831 | 822 | ||
832 | sigdelsetmask(&set, ~_BLOCKABLE); | 823 | sigdelsetmask(&set, ~_BLOCKABLE); |
833 | current->blocked = set; | 824 | set_current_blocked(&set); |
834 | recalc_sigpending(); | ||
835 | 825 | ||
836 | if (rt_restore_ucontext(regs, sw, &frame->uc)) | 826 | if (rt_restore_ucontext(regs, sw, &frame->uc)) |
837 | goto badframe; | 827 | goto badframe; |
@@ -1150,10 +1140,7 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
1150 | if (err) | 1140 | if (err) |
1151 | return; | 1141 | return; |
1152 | 1142 | ||
1153 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | 1143 | block_sigmask(ka, sig); |
1154 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
1155 | sigaddset(¤t->blocked,sig); | ||
1156 | recalc_sigpending(); | ||
1157 | 1144 | ||
1158 | if (test_thread_flag(TIF_DELAYED_TRACE)) { | 1145 | if (test_thread_flag(TIF_DELAYED_TRACE)) { |
1159 | regs->sr &= ~0x8000; | 1146 | regs->sr &= ~0x8000; |
@@ -1168,7 +1155,7 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
1168 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | 1155 | * want to handle. Thus you cannot kill init even with a SIGKILL even by |
1169 | * mistake. | 1156 | * mistake. |
1170 | */ | 1157 | */ |
1171 | asmlinkage void do_signal(struct pt_regs *regs) | 1158 | static void do_signal(struct pt_regs *regs) |
1172 | { | 1159 | { |
1173 | siginfo_t info; | 1160 | siginfo_t info; |
1174 | struct k_sigaction ka; | 1161 | struct k_sigaction ka; |
@@ -1200,3 +1187,15 @@ asmlinkage void do_signal(struct pt_regs *regs) | |||
1200 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | 1187 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); |
1201 | } | 1188 | } |
1202 | } | 1189 | } |
1190 | |||
1191 | void do_notify_resume(struct pt_regs *regs) | ||
1192 | { | ||
1193 | if (test_thread_flag(TIF_SIGPENDING)) | ||
1194 | do_signal(regs); | ||
1195 | |||
1196 | if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) { | ||
1197 | tracehook_notify_resume(regs); | ||
1198 | if (current->replacement_session_keyring) | ||
1199 | key_replace_session_keyring(); | ||
1200 | } | ||
1201 | } | ||
diff --git a/arch/m68k/platform/68328/entry.S b/arch/m68k/platform/68328/entry.S index 5c39b80ed7de..7f91c2fde509 100644 --- a/arch/m68k/platform/68328/entry.S +++ b/arch/m68k/platform/68328/entry.S | |||
@@ -119,7 +119,7 @@ Lsignal_return: | |||
119 | subql #4,%sp /* dummy return address*/ | 119 | subql #4,%sp /* dummy return address*/ |
120 | SAVE_SWITCH_STACK | 120 | SAVE_SWITCH_STACK |
121 | pea %sp@(SWITCH_STACK_SIZE) | 121 | pea %sp@(SWITCH_STACK_SIZE) |
122 | bsrw do_signal | 122 | bsrw do_notify_resume |
123 | addql #4,%sp | 123 | addql #4,%sp |
124 | RESTORE_SWITCH_STACK | 124 | RESTORE_SWITCH_STACK |
125 | addql #4,%sp | 125 | addql #4,%sp |
diff --git a/arch/m68k/platform/68360/entry.S b/arch/m68k/platform/68360/entry.S index aa47d1d49929..904fd9a4af4e 100644 --- a/arch/m68k/platform/68360/entry.S +++ b/arch/m68k/platform/68360/entry.S | |||
@@ -115,7 +115,7 @@ Lsignal_return: | |||
115 | subql #4,%sp /* dummy return address*/ | 115 | subql #4,%sp /* dummy return address*/ |
116 | SAVE_SWITCH_STACK | 116 | SAVE_SWITCH_STACK |
117 | pea %sp@(SWITCH_STACK_SIZE) | 117 | pea %sp@(SWITCH_STACK_SIZE) |
118 | bsrw do_signal | 118 | bsrw do_notify_resume |
119 | addql #4,%sp | 119 | addql #4,%sp |
120 | RESTORE_SWITCH_STACK | 120 | RESTORE_SWITCH_STACK |
121 | addql #4,%sp | 121 | addql #4,%sp |
diff --git a/arch/m68k/platform/coldfire/entry.S b/arch/m68k/platform/coldfire/entry.S index 281e38c2b6c7..881ab8e379d4 100644 --- a/arch/m68k/platform/coldfire/entry.S +++ b/arch/m68k/platform/coldfire/entry.S | |||
@@ -152,7 +152,7 @@ Lsignal_return: | |||
152 | subql #4,%sp /* dummy return address */ | 152 | subql #4,%sp /* dummy return address */ |
153 | SAVE_SWITCH_STACK | 153 | SAVE_SWITCH_STACK |
154 | pea %sp@(SWITCH_STACK_SIZE) | 154 | pea %sp@(SWITCH_STACK_SIZE) |
155 | jsr do_signal | 155 | jsr do_notify_resume |
156 | addql #4,%sp | 156 | addql #4,%sp |
157 | RESTORE_SWITCH_STACK | 157 | RESTORE_SWITCH_STACK |
158 | addql #4,%sp | 158 | addql #4,%sp |
diff --git a/arch/microblaze/kernel/entry-nommu.S b/arch/microblaze/kernel/entry-nommu.S index 34b526f59b43..75c3ea1f48a1 100644 --- a/arch/microblaze/kernel/entry-nommu.S +++ b/arch/microblaze/kernel/entry-nommu.S | |||
@@ -132,11 +132,10 @@ ret_from_intr: | |||
132 | beqi r11, 1f | 132 | beqi r11, 1f |
133 | bralid r15, schedule | 133 | bralid r15, schedule |
134 | nop | 134 | nop |
135 | 1: andi r11, r19, _TIF_SIGPENDING | 135 | 1: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME |
136 | beqid r11, no_intr_resched | 136 | beqid r11, no_intr_resched |
137 | addk r5, r1, r0 | 137 | addk r5, r1, r0 |
138 | addk r7, r0, r0 | 138 | bralid r15, do_notify_resume |
139 | bralid r15, do_signal | ||
140 | addk r6, r0, r0 | 139 | addk r6, r0, r0 |
141 | 140 | ||
142 | no_intr_resched: | 141 | no_intr_resched: |
@@ -292,8 +291,8 @@ ENTRY(_user_exception) | |||
292 | 291 | ||
293 | /* | 292 | /* |
294 | * Debug traps are like a system call, but entered via brki r14, 0x60 | 293 | * Debug traps are like a system call, but entered via brki r14, 0x60 |
295 | * All we need to do is send the SIGTRAP signal to current, ptrace and do_signal | 294 | * All we need to do is send the SIGTRAP signal to current, ptrace and |
296 | * will handle the rest | 295 | * do_notify_resume will handle the rest |
297 | */ | 296 | */ |
298 | ENTRY(_debug_exception) | 297 | ENTRY(_debug_exception) |
299 | swi r1, r0, PER_CPU(ENTRY_SP) /* save the current sp */ | 298 | swi r1, r0, PER_CPU(ENTRY_SP) /* save the current sp */ |
@@ -482,12 +481,11 @@ work_pending: | |||
482 | beqi r11, 1f | 481 | beqi r11, 1f |
483 | bralid r15, schedule | 482 | bralid r15, schedule |
484 | nop | 483 | nop |
485 | 1: andi r11, r19, _TIF_SIGPENDING | 484 | 1: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME |
486 | beqi r11, no_work_pending | 485 | beqi r11, no_work_pending |
487 | addk r5, r1, r0 | 486 | addk r5, r1, r0 |
488 | addik r7, r0, 1 | 487 | bralid r15, do_notify_resume |
489 | bralid r15, do_signal | 488 | addik r6, r0, 1 |
490 | addk r6, r0, r0 | ||
491 | bri no_work_pending | 489 | bri no_work_pending |
492 | 490 | ||
493 | ENTRY(ret_to_user) | 491 | ENTRY(ret_to_user) |
@@ -569,10 +567,6 @@ sys_rt_sigreturn_wrapper: | |||
569 | brid sys_rt_sigreturn | 567 | brid sys_rt_sigreturn |
570 | addk r5, r1, r0 | 568 | addk r5, r1, r0 |
571 | 569 | ||
572 | sys_rt_sigsuspend_wrapper: | ||
573 | brid sys_rt_sigsuspend | ||
574 | addk r7, r1, r0 | ||
575 | |||
576 | /* Interrupt vector table */ | 570 | /* Interrupt vector table */ |
577 | .section .init.ivt, "ax" | 571 | .section .init.ivt, "ax" |
578 | .org 0x0 | 572 | .org 0x0 |
diff --git a/arch/microblaze/kernel/entry.S b/arch/microblaze/kernel/entry.S index 66e34a3bfe1b..daff9e5e4a1f 100644 --- a/arch/microblaze/kernel/entry.S +++ b/arch/microblaze/kernel/entry.S | |||
@@ -430,13 +430,12 @@ C_ENTRY(ret_from_trap): | |||
430 | 5: /* get thread info from current task*/ | 430 | 5: /* get thread info from current task*/ |
431 | lwi r11, CURRENT_TASK, TS_THREAD_INFO; | 431 | lwi r11, CURRENT_TASK, TS_THREAD_INFO; |
432 | lwi r11, r11, TI_FLAGS; /* get flags in thread info */ | 432 | lwi r11, r11, TI_FLAGS; /* get flags in thread info */ |
433 | andi r11, r11, _TIF_SIGPENDING; | 433 | andi r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME; |
434 | beqi r11, 1f; /* Signals to handle, handle them */ | 434 | beqi r11, 1f; /* Signals to handle, handle them */ |
435 | 435 | ||
436 | addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ | 436 | addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ |
437 | addi r7, r0, 1; /* Arg 3: int in_syscall */ | 437 | bralid r15, do_notify_resume; /* Handle any signals */ |
438 | bralid r15, do_signal; /* Handle any signals */ | 438 | addi r6, r0, 1; /* Arg 2: int in_syscall */ |
439 | add r6, r0, r0; /* Arg 2: sigset_t *oldset */ | ||
440 | 439 | ||
441 | /* Finally, return to user state. */ | 440 | /* Finally, return to user state. */ |
442 | 1: set_bip; /* Ints masked for state restore */ | 441 | 1: set_bip; /* Ints masked for state restore */ |
@@ -622,7 +621,7 @@ C_ENTRY(ret_from_exc): | |||
622 | /* Maybe handle a signal */ | 621 | /* Maybe handle a signal */ |
623 | 5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ | 622 | 5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ |
624 | lwi r11, r11, TI_FLAGS; /* get flags in thread info */ | 623 | lwi r11, r11, TI_FLAGS; /* get flags in thread info */ |
625 | andi r11, r11, _TIF_SIGPENDING; | 624 | andi r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME; |
626 | beqi r11, 1f; /* Signals to handle, handle them */ | 625 | beqi r11, 1f; /* Signals to handle, handle them */ |
627 | 626 | ||
628 | /* | 627 | /* |
@@ -635,11 +634,10 @@ C_ENTRY(ret_from_exc): | |||
635 | * traps), but signal handlers may want to examine or change the | 634 | * traps), but signal handlers may want to examine or change the |
636 | * complete register state. Here we save anything not saved by | 635 | * complete register state. Here we save anything not saved by |
637 | * the normal entry sequence, so that it may be safely restored | 636 | * the normal entry sequence, so that it may be safely restored |
638 | * (in a possibly modified form) after do_signal returns. */ | 637 | * (in a possibly modified form) after do_notify_resume returns. */ |
639 | addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ | 638 | addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ |
640 | addi r7, r0, 0; /* Arg 3: int in_syscall */ | 639 | bralid r15, do_notify_resume; /* Handle any signals */ |
641 | bralid r15, do_signal; /* Handle any signals */ | 640 | addi r6, r0, 0; /* Arg 2: int in_syscall */ |
642 | add r6, r0, r0; /* Arg 2: sigset_t *oldset */ | ||
643 | 641 | ||
644 | /* Finally, return to user state. */ | 642 | /* Finally, return to user state. */ |
645 | 1: set_bip; /* Ints masked for state restore */ | 643 | 1: set_bip; /* Ints masked for state restore */ |
@@ -732,13 +730,12 @@ ret_from_irq: | |||
732 | /* Maybe handle a signal */ | 730 | /* Maybe handle a signal */ |
733 | 5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* MS: get thread info */ | 731 | 5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* MS: get thread info */ |
734 | lwi r11, r11, TI_FLAGS; /* get flags in thread info */ | 732 | lwi r11, r11, TI_FLAGS; /* get flags in thread info */ |
735 | andi r11, r11, _TIF_SIGPENDING; | 733 | andi r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME; |
736 | beqid r11, no_intr_resched | 734 | beqid r11, no_intr_resched |
737 | /* Handle a signal return; Pending signals should be in r18. */ | 735 | /* Handle a signal return; Pending signals should be in r18. */ |
738 | addi r7, r0, 0; /* Arg 3: int in_syscall */ | ||
739 | addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ | 736 | addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ |
740 | bralid r15, do_signal; /* Handle any signals */ | 737 | bralid r15, do_notify_resume; /* Handle any signals */ |
741 | add r6, r0, r0; /* Arg 2: sigset_t *oldset */ | 738 | addi r6, r0, 0; /* Arg 2: int in_syscall */ |
742 | 739 | ||
743 | /* Finally, return to user state. */ | 740 | /* Finally, return to user state. */ |
744 | no_intr_resched: | 741 | no_intr_resched: |
@@ -869,13 +866,12 @@ dbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */ | |||
869 | /* Maybe handle a signal */ | 866 | /* Maybe handle a signal */ |
870 | 5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ | 867 | 5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */ |
871 | lwi r11, r11, TI_FLAGS; /* get flags in thread info */ | 868 | lwi r11, r11, TI_FLAGS; /* get flags in thread info */ |
872 | andi r11, r11, _TIF_SIGPENDING; | 869 | andi r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME; |
873 | beqi r11, 1f; /* Signals to handle, handle them */ | 870 | beqi r11, 1f; /* Signals to handle, handle them */ |
874 | 871 | ||
875 | addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ | 872 | addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */ |
876 | addi r7, r0, 0; /* Arg 3: int in_syscall */ | 873 | bralid r15, do_notify_resume; /* Handle any signals */ |
877 | bralid r15, do_signal; /* Handle any signals */ | 874 | addi r6, r0, 0; /* Arg 2: int in_syscall */ |
878 | add r6, r0, r0; /* Arg 2: sigset_t *oldset */ | ||
879 | 875 | ||
880 | /* Finally, return to user state. */ | 876 | /* Finally, return to user state. */ |
881 | 1: swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */ | 877 | 1: swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */ |
diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c index 599671168980..7f4c7bef1642 100644 --- a/arch/microblaze/kernel/signal.c +++ b/arch/microblaze/kernel/signal.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/personality.h> | 31 | #include <linux/personality.h> |
32 | #include <linux/percpu.h> | 32 | #include <linux/percpu.h> |
33 | #include <linux/linkage.h> | 33 | #include <linux/linkage.h> |
34 | #include <linux/tracehook.h> | ||
34 | #include <asm/entry.h> | 35 | #include <asm/entry.h> |
35 | #include <asm/ucontext.h> | 36 | #include <asm/ucontext.h> |
36 | #include <linux/uaccess.h> | 37 | #include <linux/uaccess.h> |
@@ -42,8 +43,6 @@ | |||
42 | 43 | ||
43 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 44 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) |
44 | 45 | ||
45 | asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall); | ||
46 | |||
47 | asmlinkage long | 46 | asmlinkage long |
48 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | 47 | sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, |
49 | struct pt_regs *regs) | 48 | struct pt_regs *regs) |
@@ -98,6 +97,9 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) | |||
98 | sigset_t set; | 97 | sigset_t set; |
99 | int rval; | 98 | int rval; |
100 | 99 | ||
100 | /* Always make any pending restarted system calls return -EINTR */ | ||
101 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | ||
102 | |||
101 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 103 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
102 | goto badframe; | 104 | goto badframe; |
103 | 105 | ||
@@ -105,10 +107,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs) | |||
105 | goto badframe; | 107 | goto badframe; |
106 | 108 | ||
107 | sigdelsetmask(&set, ~_BLOCKABLE); | 109 | sigdelsetmask(&set, ~_BLOCKABLE); |
108 | spin_lock_irq(¤t->sighand->siglock); | 110 | set_current_blocked(&set); |
109 | current->blocked = set; | ||
110 | recalc_sigpending(); | ||
111 | spin_unlock_irq(¤t->sighand->siglock); | ||
112 | 111 | ||
113 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval)) | 112 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval)) |
114 | goto badframe; | 113 | goto badframe; |
@@ -169,7 +168,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) | |||
169 | return (void __user *)((sp - frame_size) & -8UL); | 168 | return (void __user *)((sp - frame_size) & -8UL); |
170 | } | 169 | } |
171 | 170 | ||
172 | static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 171 | static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, |
173 | sigset_t *set, struct pt_regs *regs) | 172 | sigset_t *set, struct pt_regs *regs) |
174 | { | 173 | { |
175 | struct rt_sigframe __user *frame; | 174 | struct rt_sigframe __user *frame; |
@@ -267,12 +266,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
267 | current->comm, current->pid, frame, regs->pc); | 266 | current->comm, current->pid, frame, regs->pc); |
268 | #endif | 267 | #endif |
269 | 268 | ||
270 | return; | 269 | return 0; |
271 | 270 | ||
272 | give_sigsegv: | 271 | give_sigsegv: |
273 | if (sig == SIGSEGV) | 272 | force_sigsegv(sig, current); |
274 | ka->sa.sa_handler = SIG_DFL; | 273 | return -EFAULT; |
275 | force_sig(SIGSEGV, current); | ||
276 | } | 274 | } |
277 | 275 | ||
278 | /* Handle restarting system calls */ | 276 | /* Handle restarting system calls */ |
@@ -316,24 +314,20 @@ static int | |||
316 | handle_signal(unsigned long sig, struct k_sigaction *ka, | 314 | handle_signal(unsigned long sig, struct k_sigaction *ka, |
317 | siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) | 315 | siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) |
318 | { | 316 | { |
317 | int ret; | ||
318 | |||
319 | /* Set up the stack frame */ | 319 | /* Set up the stack frame */ |
320 | if (ka->sa.sa_flags & SA_SIGINFO) | 320 | if (ka->sa.sa_flags & SA_SIGINFO) |
321 | setup_rt_frame(sig, ka, info, oldset, regs); | 321 | ret = setup_rt_frame(sig, ka, info, oldset, regs); |
322 | else | 322 | else |
323 | setup_rt_frame(sig, ka, NULL, oldset, regs); | 323 | ret = setup_rt_frame(sig, ka, NULL, oldset, regs); |
324 | 324 | ||
325 | if (ka->sa.sa_flags & SA_ONESHOT) | 325 | if (ret) |
326 | ka->sa.sa_handler = SIG_DFL; | 326 | return ret; |
327 | 327 | ||
328 | if (!(ka->sa.sa_flags & SA_NODEFER)) { | 328 | block_sigmask(ka, sig); |
329 | spin_lock_irq(¤t->sighand->siglock); | 329 | |
330 | sigorsets(¤t->blocked, | 330 | return 0; |
331 | ¤t->blocked, &ka->sa.sa_mask); | ||
332 | sigaddset(¤t->blocked, sig); | ||
333 | recalc_sigpending(); | ||
334 | spin_unlock_irq(¤t->sighand->siglock); | ||
335 | } | ||
336 | return 1; | ||
337 | } | 331 | } |
338 | 332 | ||
339 | /* | 333 | /* |
@@ -345,24 +339,17 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, | |||
345 | * the kernel can handle, and then we build all the user-level signal handling | 339 | * the kernel can handle, and then we build all the user-level signal handling |
346 | * stack-frames in one go after that. | 340 | * stack-frames in one go after that. |
347 | */ | 341 | */ |
348 | int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall) | 342 | static void do_signal(struct pt_regs *regs, int in_syscall) |
349 | { | 343 | { |
350 | siginfo_t info; | 344 | siginfo_t info; |
351 | int signr; | 345 | int signr; |
352 | struct k_sigaction ka; | 346 | struct k_sigaction ka; |
347 | sigset_t *oldset; | ||
353 | #ifdef DEBUG_SIG | 348 | #ifdef DEBUG_SIG |
354 | printk(KERN_INFO "do signal: %p %p %d\n", regs, oldset, in_syscall); | 349 | printk(KERN_INFO "do signal: %p %d\n", regs, in_syscall); |
355 | printk(KERN_INFO "do signal2: %lx %lx %ld [%lx]\n", regs->pc, regs->r1, | 350 | printk(KERN_INFO "do signal2: %lx %lx %ld [%lx]\n", regs->pc, regs->r1, |
356 | regs->r12, current_thread_info()->flags); | 351 | regs->r12, current_thread_info()->flags); |
357 | #endif | 352 | #endif |
358 | /* | ||
359 | * We want the common case to go fast, which | ||
360 | * is why we may in certain cases get here from | ||
361 | * kernel mode. Just return without doing anything | ||
362 | * if so. | ||
363 | */ | ||
364 | if (kernel_mode(regs)) | ||
365 | return 1; | ||
366 | 353 | ||
367 | if (current_thread_info()->status & TS_RESTORE_SIGMASK) | 354 | if (current_thread_info()->status & TS_RESTORE_SIGMASK) |
368 | oldset = ¤t->saved_sigmask; | 355 | oldset = ¤t->saved_sigmask; |
@@ -374,7 +361,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall) | |||
374 | /* Whee! Actually deliver the signal. */ | 361 | /* Whee! Actually deliver the signal. */ |
375 | if (in_syscall) | 362 | if (in_syscall) |
376 | handle_restart(regs, &ka, 1); | 363 | handle_restart(regs, &ka, 1); |
377 | if (handle_signal(signr, &ka, &info, oldset, regs)) { | 364 | if (!handle_signal(signr, &ka, &info, oldset, regs)) { |
378 | /* | 365 | /* |
379 | * A signal was successfully delivered; the saved | 366 | * A signal was successfully delivered; the saved |
380 | * sigmask will have been stored in the signal frame, | 367 | * 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) | |||
384 | current_thread_info()->status &= | 371 | current_thread_info()->status &= |
385 | ~TS_RESTORE_SIGMASK; | 372 | ~TS_RESTORE_SIGMASK; |
386 | } | 373 | } |
387 | return 1; | 374 | return; |
388 | } | 375 | } |
389 | 376 | ||
390 | if (in_syscall) | 377 | if (in_syscall) |
@@ -398,7 +385,25 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall) | |||
398 | current_thread_info()->status &= ~TS_RESTORE_SIGMASK; | 385 | current_thread_info()->status &= ~TS_RESTORE_SIGMASK; |
399 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | 386 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); |
400 | } | 387 | } |
388 | } | ||
401 | 389 | ||
402 | /* Did we come from a system call? */ | 390 | void do_notify_resume(struct pt_regs *regs, int in_syscall) |
403 | return 0; | 391 | { |
392 | /* | ||
393 | * We want the common case to go fast, which | ||
394 | * is why we may in certain cases get here from | ||
395 | * kernel mode. Just return without doing anything | ||
396 | * if so. | ||
397 | */ | ||
398 | if (kernel_mode(regs)) | ||
399 | return; | ||
400 | |||
401 | if (test_thread_flag(TIF_SIGPENDING)) | ||
402 | do_signal(regs, in_syscall); | ||
403 | |||
404 | if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) { | ||
405 | tracehook_notify_resume(regs); | ||
406 | if (current->replacement_session_keyring) | ||
407 | key_replace_session_keyring(); | ||
408 | } | ||
404 | } | 409 | } |
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index d5a338a1739c..17f6ee30ad0d 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c | |||
@@ -255,15 +255,7 @@ asmlinkage int sys_sigsuspend(nabi_no_regargs struct pt_regs regs) | |||
255 | uset = (sigset_t __user *) regs.regs[4]; | 255 | uset = (sigset_t __user *) regs.regs[4]; |
256 | if (copy_from_user(&newset, uset, sizeof(sigset_t))) | 256 | if (copy_from_user(&newset, uset, sizeof(sigset_t))) |
257 | return -EFAULT; | 257 | return -EFAULT; |
258 | sigdelsetmask(&newset, ~_BLOCKABLE); | 258 | return sigsuspend(&newset); |
259 | |||
260 | current->saved_sigmask = current->blocked; | ||
261 | set_current_blocked(&newset); | ||
262 | |||
263 | current->state = TASK_INTERRUPTIBLE; | ||
264 | schedule(); | ||
265 | set_thread_flag(TIF_RESTORE_SIGMASK); | ||
266 | return -ERESTARTNOHAND; | ||
267 | } | 259 | } |
268 | #endif | 260 | #endif |
269 | 261 | ||
@@ -281,15 +273,7 @@ asmlinkage int sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) | |||
281 | unewset = (sigset_t __user *) regs.regs[4]; | 273 | unewset = (sigset_t __user *) regs.regs[4]; |
282 | if (copy_from_user(&newset, unewset, sizeof(newset))) | 274 | if (copy_from_user(&newset, unewset, sizeof(newset))) |
283 | return -EFAULT; | 275 | return -EFAULT; |
284 | sigdelsetmask(&newset, ~_BLOCKABLE); | 276 | return sigsuspend(&newset); |
285 | |||
286 | current->saved_sigmask = current->blocked; | ||
287 | set_current_blocked(&newset); | ||
288 | |||
289 | current->state = TASK_INTERRUPTIBLE; | ||
290 | schedule(); | ||
291 | set_thread_flag(TIF_RESTORE_SIGMASK); | ||
292 | return -ERESTARTNOHAND; | ||
293 | } | 277 | } |
294 | 278 | ||
295 | #ifdef CONFIG_TRAD_SIGNALS | 279 | #ifdef CONFIG_TRAD_SIGNALS |
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c index ac3b8d89aae5..b4fe2eacbd5d 100644 --- a/arch/mips/kernel/signal32.c +++ b/arch/mips/kernel/signal32.c | |||
@@ -288,15 +288,7 @@ asmlinkage int sys32_sigsuspend(nabi_no_regargs struct pt_regs regs) | |||
288 | uset = (compat_sigset_t __user *) regs.regs[4]; | 288 | uset = (compat_sigset_t __user *) regs.regs[4]; |
289 | if (get_sigset(&newset, uset)) | 289 | if (get_sigset(&newset, uset)) |
290 | return -EFAULT; | 290 | return -EFAULT; |
291 | sigdelsetmask(&newset, ~_BLOCKABLE); | 291 | return sigsuspend(&newset); |
292 | |||
293 | current->saved_sigmask = current->blocked; | ||
294 | set_current_blocked(&newset); | ||
295 | |||
296 | current->state = TASK_INTERRUPTIBLE; | ||
297 | schedule(); | ||
298 | set_thread_flag(TIF_RESTORE_SIGMASK); | ||
299 | return -ERESTARTNOHAND; | ||
300 | } | 292 | } |
301 | 293 | ||
302 | asmlinkage int sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) | 294 | 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) | |||
313 | uset = (compat_sigset_t __user *) regs.regs[4]; | 305 | uset = (compat_sigset_t __user *) regs.regs[4]; |
314 | if (get_sigset(&newset, uset)) | 306 | if (get_sigset(&newset, uset)) |
315 | return -EFAULT; | 307 | return -EFAULT; |
316 | sigdelsetmask(&newset, ~_BLOCKABLE); | 308 | return sigsuspend(&newset); |
317 | |||
318 | current->saved_sigmask = current->blocked; | ||
319 | set_current_blocked(&newset); | ||
320 | |||
321 | current->state = TASK_INTERRUPTIBLE; | ||
322 | schedule(); | ||
323 | set_thread_flag(TIF_RESTORE_SIGMASK); | ||
324 | return -ERESTARTNOHAND; | ||
325 | } | 309 | } |
326 | 310 | ||
327 | SYSCALL_DEFINE3(32_sigaction, long, sig, const struct sigaction32 __user *, act, | 311 | SYSCALL_DEFINE3(32_sigaction, long, sig, const struct sigaction32 __user *, act, |
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c index 86eb4b04631c..63ffac9af7c5 100644 --- a/arch/mips/kernel/signal_n32.c +++ b/arch/mips/kernel/signal_n32.c | |||
@@ -91,15 +91,7 @@ asmlinkage int sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) | |||
91 | if (copy_from_user(&uset, unewset, sizeof(uset))) | 91 | if (copy_from_user(&uset, unewset, sizeof(uset))) |
92 | return -EFAULT; | 92 | return -EFAULT; |
93 | sigset_from_compat(&newset, &uset); | 93 | sigset_from_compat(&newset, &uset); |
94 | sigdelsetmask(&newset, ~_BLOCKABLE); | 94 | return sigsuspend(&newset); |
95 | |||
96 | current->saved_sigmask = current->blocked; | ||
97 | set_current_blocked(&newset); | ||
98 | |||
99 | current->state = TASK_INTERRUPTIBLE; | ||
100 | schedule(); | ||
101 | set_thread_flag(TIF_RESTORE_SIGMASK); | ||
102 | return -ERESTARTNOHAND; | ||
103 | } | 95 | } |
104 | 96 | ||
105 | asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | 97 | asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) |
diff --git a/arch/mn10300/kernel/signal.c b/arch/mn10300/kernel/signal.c index 690f4e9507d7..890cf91767cc 100644 --- a/arch/mn10300/kernel/signal.c +++ b/arch/mn10300/kernel/signal.c | |||
@@ -38,17 +38,9 @@ | |||
38 | */ | 38 | */ |
39 | asmlinkage long sys_sigsuspend(int history0, int history1, old_sigset_t mask) | 39 | asmlinkage long sys_sigsuspend(int history0, int history1, old_sigset_t mask) |
40 | { | 40 | { |
41 | mask &= _BLOCKABLE; | 41 | sigset_t blocked; |
42 | spin_lock_irq(¤t->sighand->siglock); | 42 | siginitset(&blocked, mask); |
43 | current->saved_sigmask = current->blocked; | 43 | return sigsuspend(&blocked); |
44 | siginitset(¤t->blocked, mask); | ||
45 | recalc_sigpending(); | ||
46 | spin_unlock_irq(¤t->sighand->siglock); | ||
47 | |||
48 | current->state = TASK_INTERRUPTIBLE; | ||
49 | schedule(); | ||
50 | set_thread_flag(TIF_RESTORE_SIGMASK); | ||
51 | return -ERESTARTNOHAND; | ||
52 | } | 44 | } |
53 | 45 | ||
54 | /* | 46 | /* |
@@ -172,10 +164,7 @@ asmlinkage long sys_sigreturn(void) | |||
172 | goto badframe; | 164 | goto badframe; |
173 | 165 | ||
174 | sigdelsetmask(&set, ~_BLOCKABLE); | 166 | sigdelsetmask(&set, ~_BLOCKABLE); |
175 | spin_lock_irq(¤t->sighand->siglock); | 167 | set_current_blocked(&set); |
176 | current->blocked = set; | ||
177 | recalc_sigpending(); | ||
178 | spin_unlock_irq(¤t->sighand->siglock); | ||
179 | 168 | ||
180 | if (restore_sigcontext(current_frame(), &frame->sc, &d0)) | 169 | if (restore_sigcontext(current_frame(), &frame->sc, &d0)) |
181 | goto badframe; | 170 | goto badframe; |
@@ -203,10 +192,7 @@ asmlinkage long sys_rt_sigreturn(void) | |||
203 | goto badframe; | 192 | goto badframe; |
204 | 193 | ||
205 | sigdelsetmask(&set, ~_BLOCKABLE); | 194 | sigdelsetmask(&set, ~_BLOCKABLE); |
206 | spin_lock_irq(¤t->sighand->siglock); | 195 | set_current_blocked(&set); |
207 | current->blocked = set; | ||
208 | recalc_sigpending(); | ||
209 | spin_unlock_irq(¤t->sighand->siglock); | ||
210 | 196 | ||
211 | if (restore_sigcontext(current_frame(), &frame->uc.uc_mcontext, &d0)) | 197 | if (restore_sigcontext(current_frame(), &frame->uc.uc_mcontext, &d0)) |
212 | goto badframe; | 198 | goto badframe; |
@@ -476,15 +462,8 @@ static int handle_signal(int sig, | |||
476 | else | 462 | else |
477 | ret = setup_frame(sig, ka, oldset, regs); | 463 | ret = setup_frame(sig, ka, oldset, regs); |
478 | 464 | ||
479 | if (ret == 0) { | 465 | if (ret == 0) |
480 | spin_lock_irq(¤t->sighand->siglock); | 466 | block_sigmask(ka, sig); |
481 | sigorsets(¤t->blocked, ¤t->blocked, | ||
482 | &ka->sa.sa_mask); | ||
483 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
484 | sigaddset(¤t->blocked, sig); | ||
485 | recalc_sigpending(); | ||
486 | spin_unlock_irq(¤t->sighand->siglock); | ||
487 | } | ||
488 | 467 | ||
489 | return ret; | 468 | return ret; |
490 | } | 469 | } |
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c index 12c1ed33dc18..4b9cb0d546d1 100644 --- a/arch/parisc/kernel/signal.c +++ b/arch/parisc/kernel/signal.c | |||
@@ -109,6 +109,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall) | |||
109 | sigframe_size = PARISC_RT_SIGFRAME_SIZE32; | 109 | sigframe_size = PARISC_RT_SIGFRAME_SIZE32; |
110 | #endif | 110 | #endif |
111 | 111 | ||
112 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | ||
112 | 113 | ||
113 | /* Unwind the user stack to get the rt_sigframe structure. */ | 114 | /* Unwind the user stack to get the rt_sigframe structure. */ |
114 | frame = (struct rt_sigframe __user *) | 115 | frame = (struct rt_sigframe __user *) |
@@ -131,10 +132,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall) | |||
131 | } | 132 | } |
132 | 133 | ||
133 | sigdelsetmask(&set, ~_BLOCKABLE); | 134 | sigdelsetmask(&set, ~_BLOCKABLE); |
134 | spin_lock_irq(¤t->sighand->siglock); | 135 | set_current_blocked(&set); |
135 | current->blocked = set; | ||
136 | recalc_sigpending(); | ||
137 | spin_unlock_irq(¤t->sighand->siglock); | ||
138 | 136 | ||
139 | /* Good thing we saved the old gr[30], eh? */ | 137 | /* Good thing we saved the old gr[30], eh? */ |
140 | #ifdef CONFIG_64BIT | 138 | #ifdef CONFIG_64BIT |
@@ -454,12 +452,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
454 | if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall)) | 452 | if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall)) |
455 | return 0; | 453 | return 0; |
456 | 454 | ||
457 | spin_lock_irq(¤t->sighand->siglock); | 455 | block_sigmask(ka, sig); |
458 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | ||
459 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
460 | sigaddset(¤t->blocked,sig); | ||
461 | recalc_sigpending(); | ||
462 | spin_unlock_irq(¤t->sighand->siglock); | ||
463 | 456 | ||
464 | tracehook_signal_handler(sig, info, ka, regs, | 457 | tracehook_signal_handler(sig, info, ka, regs, |
465 | test_thread_flag(TIF_SINGLESTEP) || | 458 | test_thread_flag(TIF_SINGLESTEP) || |
@@ -474,8 +467,6 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) | |||
474 | /* Check the return code */ | 467 | /* Check the return code */ |
475 | switch (regs->gr[28]) { | 468 | switch (regs->gr[28]) { |
476 | case -ERESTART_RESTARTBLOCK: | 469 | case -ERESTART_RESTARTBLOCK: |
477 | current_thread_info()->restart_block.fn = | ||
478 | do_no_restart_syscall; | ||
479 | case -ERESTARTNOHAND: | 470 | case -ERESTARTNOHAND: |
480 | DBG(1,"ERESTARTNOHAND: returning -EINTR\n"); | 471 | DBG(1,"ERESTARTNOHAND: returning -EINTR\n"); |
481 | regs->gr[28] = -EINTR; | 472 | regs->gr[28] = -EINTR; |
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 45eb998557f8..61f6aff25edc 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
@@ -204,10 +204,10 @@ static inline int get_old_sigaction(struct k_sigaction *new_ka, | |||
204 | 204 | ||
205 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || | 205 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || |
206 | __get_user(new_ka->sa.sa_handler, &act->sa_handler) || | 206 | __get_user(new_ka->sa.sa_handler, &act->sa_handler) || |
207 | __get_user(new_ka->sa.sa_restorer, &act->sa_restorer)) | 207 | __get_user(new_ka->sa.sa_restorer, &act->sa_restorer) || |
208 | __get_user(new_ka->sa.sa_flags, &act->sa_flags) || | ||
209 | __get_user(mask, &act->sa_mask)) | ||
208 | return -EFAULT; | 210 | return -EFAULT; |
209 | __get_user(new_ka->sa.sa_flags, &act->sa_flags); | ||
210 | __get_user(mask, &act->sa_mask); | ||
211 | siginitset(&new_ka->sa.sa_mask, mask); | 211 | siginitset(&new_ka->sa.sa_mask, mask); |
212 | return 0; | 212 | return 0; |
213 | } | 213 | } |
@@ -244,17 +244,8 @@ static inline int restore_general_regs(struct pt_regs *regs, | |||
244 | long sys_sigsuspend(old_sigset_t mask) | 244 | long sys_sigsuspend(old_sigset_t mask) |
245 | { | 245 | { |
246 | sigset_t blocked; | 246 | sigset_t blocked; |
247 | |||
248 | current->saved_sigmask = current->blocked; | ||
249 | |||
250 | mask &= _BLOCKABLE; | ||
251 | siginitset(&blocked, mask); | 247 | siginitset(&blocked, mask); |
252 | set_current_blocked(&blocked); | 248 | return sigsuspend(&blocked); |
253 | |||
254 | current->state = TASK_INTERRUPTIBLE; | ||
255 | schedule(); | ||
256 | set_restore_sigmask(); | ||
257 | return -ERESTARTNOHAND; | ||
258 | } | 249 | } |
259 | 250 | ||
260 | long sys_sigaction(int sig, struct old_sigaction __user *act, | 251 | long sys_sigaction(int sig, struct old_sigaction __user *act, |
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index 8a4e2b760d56..f626232e216c 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c | |||
@@ -59,15 +59,8 @@ typedef struct | |||
59 | SYSCALL_DEFINE3(sigsuspend, int, history0, int, history1, old_sigset_t, mask) | 59 | SYSCALL_DEFINE3(sigsuspend, int, history0, int, history1, old_sigset_t, mask) |
60 | { | 60 | { |
61 | sigset_t blocked; | 61 | sigset_t blocked; |
62 | |||
63 | current->saved_sigmask = current->blocked; | ||
64 | mask &= _BLOCKABLE; | ||
65 | siginitset(&blocked, mask); | 62 | siginitset(&blocked, mask); |
66 | set_current_blocked(&blocked); | 63 | return sigsuspend(&blocked); |
67 | set_current_state(TASK_INTERRUPTIBLE); | ||
68 | schedule(); | ||
69 | set_restore_sigmask(); | ||
70 | return -ERESTARTNOHAND; | ||
71 | } | 64 | } |
72 | 65 | ||
73 | SYSCALL_DEFINE3(sigaction, int, sig, const struct old_sigaction __user *, act, | 66 | SYSCALL_DEFINE3(sigaction, int, sig, const struct old_sigaction __user *, act, |
diff --git a/arch/score/kernel/signal.c b/arch/score/kernel/signal.c index aa57440e4973..d4a49011c48a 100644 --- a/arch/score/kernel/signal.c +++ b/arch/score/kernel/signal.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/ptrace.h> | 28 | #include <linux/ptrace.h> |
29 | #include <linux/unistd.h> | 29 | #include <linux/unistd.h> |
30 | #include <linux/uaccess.h> | 30 | #include <linux/uaccess.h> |
31 | #include <linux/tracehook.h> | ||
31 | 32 | ||
32 | #include <asm/cacheflush.h> | 33 | #include <asm/cacheflush.h> |
33 | #include <asm/syscalls.h> | 34 | #include <asm/syscalls.h> |
@@ -152,6 +153,9 @@ score_rt_sigreturn(struct pt_regs *regs) | |||
152 | stack_t st; | 153 | stack_t st; |
153 | int sig; | 154 | int sig; |
154 | 155 | ||
156 | /* Always make any pending restarted system calls return -EINTR */ | ||
157 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | ||
158 | |||
155 | frame = (struct rt_sigframe __user *) regs->regs[0]; | 159 | frame = (struct rt_sigframe __user *) regs->regs[0]; |
156 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) | 160 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
157 | goto badframe; | 161 | goto badframe; |
@@ -159,10 +163,7 @@ score_rt_sigreturn(struct pt_regs *regs) | |||
159 | goto badframe; | 163 | goto badframe; |
160 | 164 | ||
161 | sigdelsetmask(&set, ~_BLOCKABLE); | 165 | sigdelsetmask(&set, ~_BLOCKABLE); |
162 | spin_lock_irq(¤t->sighand->siglock); | 166 | set_current_blocked(&set); |
163 | current->blocked = set; | ||
164 | recalc_sigpending(); | ||
165 | spin_unlock_irq(¤t->sighand->siglock); | ||
166 | 167 | ||
167 | sig = restore_sigcontext(regs, &frame->rs_uc.uc_mcontext); | 168 | sig = restore_sigcontext(regs, &frame->rs_uc.uc_mcontext); |
168 | if (sig < 0) | 169 | if (sig < 0) |
@@ -236,9 +237,7 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, | |||
236 | return 0; | 237 | return 0; |
237 | 238 | ||
238 | give_sigsegv: | 239 | give_sigsegv: |
239 | if (signr == SIGSEGV) | 240 | force_sigsegv(signr, current); |
240 | ka->sa.sa_handler = SIG_DFL; | ||
241 | force_sig(SIGSEGV, current); | ||
242 | return -EFAULT; | 241 | return -EFAULT; |
243 | } | 242 | } |
244 | 243 | ||
@@ -272,12 +271,8 @@ static int handle_signal(unsigned long sig, siginfo_t *info, | |||
272 | */ | 271 | */ |
273 | ret = setup_rt_frame(ka, regs, sig, oldset, info); | 272 | ret = setup_rt_frame(ka, regs, sig, oldset, info); |
274 | 273 | ||
275 | spin_lock_irq(¤t->sighand->siglock); | 274 | if (ret == 0) |
276 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); | 275 | block_sigmask(ka, sig); |
277 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
278 | sigaddset(¤t->blocked, sig); | ||
279 | recalc_sigpending(); | ||
280 | spin_unlock_irq(¤t->sighand->siglock); | ||
281 | 276 | ||
282 | return ret; | 277 | return ret; |
283 | } | 278 | } |
@@ -356,6 +351,12 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused, | |||
356 | __u32 thread_info_flags) | 351 | __u32 thread_info_flags) |
357 | { | 352 | { |
358 | /* deal with pending signal delivery */ | 353 | /* deal with pending signal delivery */ |
359 | if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) | 354 | if (thread_info_flags & _TIF_SIGPENDING) |
360 | do_signal(regs); | 355 | do_signal(regs); |
356 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | ||
357 | clear_thread_flag(TIF_NOTIFY_RESUME); | ||
358 | tracehook_notify_resume(regs); | ||
359 | if (current->replacement_session_keyring) | ||
360 | key_replace_session_keyring(); | ||
361 | } | ||
361 | } | 362 | } |
diff --git a/arch/sh/include/asm/syscalls_32.h b/arch/sh/include/asm/syscalls_32.h index ae717e3c26d6..6c1fa559753c 100644 --- a/arch/sh/include/asm/syscalls_32.h +++ b/arch/sh/include/asm/syscalls_32.h | |||
@@ -23,9 +23,7 @@ asmlinkage int sys_execve(const char __user *ufilename, | |||
23 | const char __user *const __user *uargv, | 23 | const char __user *const __user *uargv, |
24 | const char __user *const __user *uenvp, | 24 | const char __user *const __user *uenvp, |
25 | unsigned long r7, struct pt_regs __regs); | 25 | unsigned long r7, struct pt_regs __regs); |
26 | asmlinkage int sys_sigsuspend(old_sigset_t mask, unsigned long r5, | 26 | asmlinkage int sys_sigsuspend(old_sigset_t mask); |
27 | unsigned long r6, unsigned long r7, | ||
28 | struct pt_regs __regs); | ||
29 | asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user *act, | 27 | asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user *act, |
30 | struct old_sigaction __user *oact); | 28 | struct old_sigaction __user *oact); |
31 | asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, | 29 | asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, |
diff --git a/arch/sh/include/asm/unistd.h b/arch/sh/include/asm/unistd.h index a42a5610a36a..e800a38c9f8d 100644 --- a/arch/sh/include/asm/unistd.h +++ b/arch/sh/include/asm/unistd.h | |||
@@ -1,13 +1,11 @@ | |||
1 | #ifdef __KERNEL__ | 1 | #ifdef __KERNEL__ |
2 | # ifdef CONFIG_SUPERH32 | 2 | # ifdef CONFIG_SUPERH32 |
3 | |||
4 | # include "unistd_32.h" | 3 | # include "unistd_32.h" |
5 | # define __ARCH_WANT_SYS_RT_SIGSUSPEND | ||
6 | |||
7 | # else | 4 | # else |
8 | # include "unistd_64.h" | 5 | # include "unistd_64.h" |
9 | # endif | 6 | # endif |
10 | 7 | ||
8 | # define __ARCH_WANT_SYS_RT_SIGSUSPEND | ||
11 | # define __ARCH_WANT_IPC_PARSE_VERSION | 9 | # define __ARCH_WANT_IPC_PARSE_VERSION |
12 | # define __ARCH_WANT_OLD_READDIR | 10 | # define __ARCH_WANT_OLD_READDIR |
13 | # define __ARCH_WANT_OLD_STAT | 11 | # define __ARCH_WANT_OLD_STAT |
diff --git a/arch/sh/kernel/signal_32.c b/arch/sh/kernel/signal_32.c index 5901fba3176e..cb4172c8af7d 100644 --- a/arch/sh/kernel/signal_32.c +++ b/arch/sh/kernel/signal_32.c | |||
@@ -53,23 +53,11 @@ struct fdpic_func_descriptor { | |||
53 | * Atomically swap in the new signal mask, and wait for a signal. | 53 | * Atomically swap in the new signal mask, and wait for a signal. |
54 | */ | 54 | */ |
55 | asmlinkage int | 55 | asmlinkage int |
56 | sys_sigsuspend(old_sigset_t mask, | 56 | sys_sigsuspend(old_sigset_t mask) |
57 | unsigned long r5, unsigned long r6, unsigned long r7, | ||
58 | struct pt_regs __regs) | ||
59 | { | 57 | { |
60 | sigset_t blocked; | 58 | sigset_t blocked; |
61 | |||
62 | current->saved_sigmask = current->blocked; | ||
63 | |||
64 | mask &= _BLOCKABLE; | ||
65 | siginitset(&blocked, mask); | 59 | siginitset(&blocked, mask); |
66 | set_current_blocked(&blocked); | 60 | return sigsuspend(&blocked); |
67 | |||
68 | current->state = TASK_INTERRUPTIBLE; | ||
69 | schedule(); | ||
70 | set_restore_sigmask(); | ||
71 | |||
72 | return -ERESTARTNOHAND; | ||
73 | } | 61 | } |
74 | 62 | ||
75 | asmlinkage int | 63 | asmlinkage int |
@@ -83,10 +71,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, | |||
83 | old_sigset_t mask; | 71 | old_sigset_t mask; |
84 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || | 72 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || |
85 | __get_user(new_ka.sa.sa_handler, &act->sa_handler) || | 73 | __get_user(new_ka.sa.sa_handler, &act->sa_handler) || |
86 | __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) | 74 | __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) || |
75 | __get_user(new_ka.sa.sa_flags, &act->sa_flags) || | ||
76 | __get_user(mask, &act->sa_mask)) | ||
87 | return -EFAULT; | 77 | return -EFAULT; |
88 | __get_user(new_ka.sa.sa_flags, &act->sa_flags); | ||
89 | __get_user(mask, &act->sa_mask); | ||
90 | siginitset(&new_ka.sa.sa_mask, mask); | 78 | siginitset(&new_ka.sa.sa_mask, mask); |
91 | } | 79 | } |
92 | 80 | ||
@@ -95,10 +83,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, | |||
95 | if (!ret && oact) { | 83 | if (!ret && oact) { |
96 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || | 84 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || |
97 | __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || | 85 | __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || |
98 | __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) | 86 | __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) || |
87 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || | ||
88 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) | ||
99 | return -EFAULT; | 89 | return -EFAULT; |
100 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags); | ||
101 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); | ||
102 | } | 90 | } |
103 | 91 | ||
104 | return ret; | 92 | return ret; |
@@ -162,12 +150,11 @@ static inline int save_sigcontext_fpu(struct sigcontext __user *sc, | |||
162 | if (!(boot_cpu_data.flags & CPU_HAS_FPU)) | 150 | if (!(boot_cpu_data.flags & CPU_HAS_FPU)) |
163 | return 0; | 151 | return 0; |
164 | 152 | ||
165 | if (!used_math()) { | 153 | if (!used_math()) |
166 | __put_user(0, &sc->sc_ownedfp); | 154 | return __put_user(0, &sc->sc_ownedfp); |
167 | return 0; | ||
168 | } | ||
169 | 155 | ||
170 | __put_user(1, &sc->sc_ownedfp); | 156 | if (__put_user(1, &sc->sc_ownedfp)) |
157 | return -EFAULT; | ||
171 | 158 | ||
172 | /* This will cause a "finit" to be triggered by the next | 159 | /* This will cause a "finit" to be triggered by the next |
173 | attempted FPU operation by the 'current' process. | 160 | attempted FPU operation by the 'current' process. |
@@ -207,7 +194,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p | |||
207 | regs->sr |= SR_FD; /* Release FPU */ | 194 | regs->sr |= SR_FD; /* Release FPU */ |
208 | clear_fpu(tsk, regs); | 195 | clear_fpu(tsk, regs); |
209 | clear_used_math(); | 196 | clear_used_math(); |
210 | __get_user (owned_fp, &sc->sc_ownedfp); | 197 | err |= __get_user (owned_fp, &sc->sc_ownedfp); |
211 | if (owned_fp) | 198 | if (owned_fp) |
212 | err |= restore_sigcontext_fpu(sc); | 199 | err |= restore_sigcontext_fpu(sc); |
213 | } | 200 | } |
@@ -398,11 +385,14 @@ static int setup_frame(int sig, struct k_sigaction *ka, | |||
398 | struct fdpic_func_descriptor __user *funcptr = | 385 | struct fdpic_func_descriptor __user *funcptr = |
399 | (struct fdpic_func_descriptor __user *)ka->sa.sa_handler; | 386 | (struct fdpic_func_descriptor __user *)ka->sa.sa_handler; |
400 | 387 | ||
401 | __get_user(regs->pc, &funcptr->text); | 388 | err |= __get_user(regs->pc, &funcptr->text); |
402 | __get_user(regs->regs[12], &funcptr->GOT); | 389 | err |= __get_user(regs->regs[12], &funcptr->GOT); |
403 | } else | 390 | } else |
404 | regs->pc = (unsigned long)ka->sa.sa_handler; | 391 | regs->pc = (unsigned long)ka->sa.sa_handler; |
405 | 392 | ||
393 | if (err) | ||
394 | goto give_sigsegv; | ||
395 | |||
406 | set_fs(USER_DS); | 396 | set_fs(USER_DS); |
407 | 397 | ||
408 | pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n", | 398 | 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, | |||
482 | struct fdpic_func_descriptor __user *funcptr = | 472 | struct fdpic_func_descriptor __user *funcptr = |
483 | (struct fdpic_func_descriptor __user *)ka->sa.sa_handler; | 473 | (struct fdpic_func_descriptor __user *)ka->sa.sa_handler; |
484 | 474 | ||
485 | __get_user(regs->pc, &funcptr->text); | 475 | err |= __get_user(regs->pc, &funcptr->text); |
486 | __get_user(regs->regs[12], &funcptr->GOT); | 476 | err |= __get_user(regs->regs[12], &funcptr->GOT); |
487 | } else | 477 | } else |
488 | regs->pc = (unsigned long)ka->sa.sa_handler; | 478 | regs->pc = (unsigned long)ka->sa.sa_handler; |
489 | 479 | ||
480 | if (err) | ||
481 | goto give_sigsegv; | ||
482 | |||
490 | set_fs(USER_DS); | 483 | set_fs(USER_DS); |
491 | 484 | ||
492 | pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n", | 485 | pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n", |
diff --git a/arch/sh/kernel/signal_64.c b/arch/sh/kernel/signal_64.c index 3c9a6f7dcdce..b589a354c069 100644 --- a/arch/sh/kernel/signal_64.c +++ b/arch/sh/kernel/signal_64.c | |||
@@ -83,11 +83,12 @@ handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa) | |||
83 | * the kernel can handle, and then we build all the user-level signal handling | 83 | * the kernel can handle, and then we build all the user-level signal handling |
84 | * stack-frames in one go after that. | 84 | * stack-frames in one go after that. |
85 | */ | 85 | */ |
86 | static int do_signal(struct pt_regs *regs, sigset_t *oldset) | 86 | static void do_signal(struct pt_regs *regs) |
87 | { | 87 | { |
88 | siginfo_t info; | 88 | siginfo_t info; |
89 | int signr; | 89 | int signr; |
90 | struct k_sigaction ka; | 90 | struct k_sigaction ka; |
91 | sigset_t *oldset; | ||
91 | 92 | ||
92 | /* | 93 | /* |
93 | * We want the common case to go fast, which | 94 | * We want the common case to go fast, which |
@@ -96,11 +97,11 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset) | |||
96 | * if so. | 97 | * if so. |
97 | */ | 98 | */ |
98 | if (!user_mode(regs)) | 99 | if (!user_mode(regs)) |
99 | return 1; | 100 | return; |
100 | 101 | ||
101 | if (current_thread_info()->status & TS_RESTORE_SIGMASK) | 102 | if (current_thread_info()->status & TS_RESTORE_SIGMASK) |
102 | oldset = ¤t->saved_sigmask; | 103 | oldset = ¤t->saved_sigmask; |
103 | else if (!oldset) | 104 | else |
104 | oldset = ¤t->blocked; | 105 | oldset = ¤t->blocked; |
105 | 106 | ||
106 | signr = get_signal_to_deliver(&info, &ka, regs, 0); | 107 | signr = get_signal_to_deliver(&info, &ka, regs, 0); |
@@ -118,7 +119,7 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset) | |||
118 | 119 | ||
119 | tracehook_signal_handler(signr, &info, &ka, regs, | 120 | tracehook_signal_handler(signr, &info, &ka, regs, |
120 | test_thread_flag(TIF_SINGLESTEP)); | 121 | test_thread_flag(TIF_SINGLESTEP)); |
121 | return 1; | 122 | return; |
122 | } | 123 | } |
123 | } | 124 | } |
124 | 125 | ||
@@ -147,71 +148,18 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset) | |||
147 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | 148 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); |
148 | } | 149 | } |
149 | 150 | ||
150 | return 0; | 151 | return; |
151 | } | 152 | } |
152 | 153 | ||
153 | /* | 154 | /* |
154 | * Atomically swap in the new signal mask, and wait for a signal. | 155 | * Atomically swap in the new signal mask, and wait for a signal. |
155 | */ | 156 | */ |
156 | asmlinkage int | 157 | asmlinkage int |
157 | sys_sigsuspend(old_sigset_t mask, | 158 | sys_sigsuspend(old_sigset_t mask) |
158 | unsigned long r3, unsigned long r4, unsigned long r5, | ||
159 | unsigned long r6, unsigned long r7, | ||
160 | struct pt_regs * regs) | ||
161 | { | 159 | { |
162 | sigset_t saveset, blocked; | 160 | sigset_t blocked; |
163 | |||
164 | saveset = current->blocked; | ||
165 | |||
166 | mask &= _BLOCKABLE; | ||
167 | siginitset(&blocked, mask); | 161 | siginitset(&blocked, mask); |
168 | set_current_blocked(&blocked); | 162 | return sigsuspend(&blocked); |
169 | |||
170 | REF_REG_RET = -EINTR; | ||
171 | while (1) { | ||
172 | current->state = TASK_INTERRUPTIBLE; | ||
173 | schedule(); | ||
174 | set_restore_sigmask(); | ||
175 | regs->pc += 4; /* because sys_sigreturn decrements the pc */ | ||
176 | if (do_signal(regs, &saveset)) { | ||
177 | /* pc now points at signal handler. Need to decrement | ||
178 | it because entry.S will increment it. */ | ||
179 | regs->pc -= 4; | ||
180 | return -EINTR; | ||
181 | } | ||
182 | } | ||
183 | } | ||
184 | |||
185 | asmlinkage int | ||
186 | sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, | ||
187 | unsigned long r4, unsigned long r5, unsigned long r6, | ||
188 | unsigned long r7, | ||
189 | struct pt_regs * regs) | ||
190 | { | ||
191 | sigset_t saveset, newset; | ||
192 | |||
193 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
194 | if (sigsetsize != sizeof(sigset_t)) | ||
195 | return -EINVAL; | ||
196 | |||
197 | if (copy_from_user(&newset, unewset, sizeof(newset))) | ||
198 | return -EFAULT; | ||
199 | sigdelsetmask(&newset, ~_BLOCKABLE); | ||
200 | saveset = current->blocked; | ||
201 | set_current_blocked(&newset); | ||
202 | |||
203 | REF_REG_RET = -EINTR; | ||
204 | while (1) { | ||
205 | current->state = TASK_INTERRUPTIBLE; | ||
206 | schedule(); | ||
207 | regs->pc += 4; /* because sys_sigreturn decrements the pc */ | ||
208 | if (do_signal(regs, &saveset)) { | ||
209 | /* pc now points at signal handler. Need to decrement | ||
210 | it because entry.S will increment it. */ | ||
211 | regs->pc -= 4; | ||
212 | return -EINTR; | ||
213 | } | ||
214 | } | ||
215 | } | 163 | } |
216 | 164 | ||
217 | asmlinkage int | 165 | asmlinkage int |
@@ -225,10 +173,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, | |||
225 | old_sigset_t mask; | 173 | old_sigset_t mask; |
226 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || | 174 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || |
227 | __get_user(new_ka.sa.sa_handler, &act->sa_handler) || | 175 | __get_user(new_ka.sa.sa_handler, &act->sa_handler) || |
228 | __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) | 176 | __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) || |
177 | __get_user(new_ka.sa.sa_flags, &act->sa_flags) || | ||
178 | __get_user(mask, &act->sa_mask)) | ||
229 | return -EFAULT; | 179 | return -EFAULT; |
230 | __get_user(new_ka.sa.sa_flags, &act->sa_flags); | ||
231 | __get_user(mask, &act->sa_mask); | ||
232 | siginitset(&new_ka.sa.sa_mask, mask); | 180 | siginitset(&new_ka.sa.sa_mask, mask); |
233 | } | 181 | } |
234 | 182 | ||
@@ -237,10 +185,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act, | |||
237 | if (!ret && oact) { | 185 | if (!ret && oact) { |
238 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || | 186 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || |
239 | __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || | 187 | __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || |
240 | __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) | 188 | __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) || |
189 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || | ||
190 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) | ||
241 | return -EFAULT; | 191 | return -EFAULT; |
242 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags); | ||
243 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); | ||
244 | } | 192 | } |
245 | 193 | ||
246 | return ret; | 194 | return ret; |
@@ -732,7 +680,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
732 | asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) | 680 | asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) |
733 | { | 681 | { |
734 | if (thread_info_flags & _TIF_SIGPENDING) | 682 | if (thread_info_flags & _TIF_SIGPENDING) |
735 | do_signal(regs, 0); | 683 | do_signal(regs); |
736 | 684 | ||
737 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 685 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { |
738 | clear_thread_flag(TIF_NOTIFY_RESUME); | 686 | clear_thread_flag(TIF_NOTIFY_RESUME); |
diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c index 948700fb9036..bb1513e45f1a 100644 --- a/arch/sparc/kernel/signal32.c +++ b/arch/sparc/kernel/signal32.c | |||
@@ -215,8 +215,9 @@ void do_sigreturn32(struct pt_regs *regs) | |||
215 | (((unsigned long) sf) & 3)) | 215 | (((unsigned long) sf) & 3)) |
216 | goto segv; | 216 | goto segv; |
217 | 217 | ||
218 | get_user(pc, &sf->info.si_regs.pc); | 218 | if (get_user(pc, &sf->info.si_regs.pc) || |
219 | __get_user(npc, &sf->info.si_regs.npc); | 219 | __get_user(npc, &sf->info.si_regs.npc)) |
220 | goto segv; | ||
220 | 221 | ||
221 | if ((pc | npc) & 3) | 222 | if ((pc | npc) & 3) |
222 | goto segv; | 223 | goto segv; |
@@ -305,8 +306,9 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) | |||
305 | (((unsigned long) sf) & 3)) | 306 | (((unsigned long) sf) & 3)) |
306 | goto segv; | 307 | goto segv; |
307 | 308 | ||
308 | get_user(pc, &sf->regs.pc); | 309 | if (get_user(pc, &sf->regs.pc) || |
309 | __get_user(npc, &sf->regs.npc); | 310 | __get_user(npc, &sf->regs.npc)) |
311 | goto segv; | ||
310 | 312 | ||
311 | if ((pc | npc) & 3) | 313 | if ((pc | npc) & 3) |
312 | goto segv; | 314 | goto segv; |
diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c index ac8e66b50f07..2b7e849f7c65 100644 --- a/arch/sparc/kernel/signal_32.c +++ b/arch/sparc/kernel/signal_32.c | |||
@@ -64,18 +64,8 @@ struct rt_signal_frame { | |||
64 | static int _sigpause_common(old_sigset_t set) | 64 | static int _sigpause_common(old_sigset_t set) |
65 | { | 65 | { |
66 | sigset_t blocked; | 66 | sigset_t blocked; |
67 | |||
68 | current->saved_sigmask = current->blocked; | ||
69 | |||
70 | set &= _BLOCKABLE; | ||
71 | siginitset(&blocked, set); | 67 | siginitset(&blocked, set); |
72 | set_current_blocked(&blocked); | 68 | return sigsuspend(&blocked); |
73 | |||
74 | current->state = TASK_INTERRUPTIBLE; | ||
75 | schedule(); | ||
76 | set_thread_flag(TIF_RESTORE_SIGMASK); | ||
77 | |||
78 | return -ERESTARTNOHAND; | ||
79 | } | 69 | } |
80 | 70 | ||
81 | asmlinkage int sys_sigsuspend(old_sigset_t set) | 71 | asmlinkage int sys_sigsuspend(old_sigset_t set) |
diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index 48b0f57b65f7..eafaab486b2d 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c | |||
@@ -242,19 +242,8 @@ struct rt_signal_frame { | |||
242 | static long _sigpause_common(old_sigset_t set) | 242 | static long _sigpause_common(old_sigset_t set) |
243 | { | 243 | { |
244 | sigset_t blocked; | 244 | sigset_t blocked; |
245 | |||
246 | current->saved_sigmask = current->blocked; | ||
247 | |||
248 | set &= _BLOCKABLE; | ||
249 | siginitset(&blocked, set); | 245 | siginitset(&blocked, set); |
250 | set_current_blocked(&blocked); | 246 | return sigsuspend(&blocked); |
251 | |||
252 | current->state = TASK_INTERRUPTIBLE; | ||
253 | schedule(); | ||
254 | |||
255 | set_restore_sigmask(); | ||
256 | |||
257 | return -ERESTARTNOHAND; | ||
258 | } | 247 | } |
259 | 248 | ||
260 | asmlinkage long sys_sigpause(unsigned int set) | 249 | asmlinkage long sys_sigpause(unsigned int set) |
diff --git a/arch/sparc/kernel/sys_sparc_32.c b/arch/sparc/kernel/sys_sparc_32.c index 627e89af1d71..0c9b31b22e07 100644 --- a/arch/sparc/kernel/sys_sparc_32.c +++ b/arch/sparc/kernel/sys_sparc_32.c | |||
@@ -184,10 +184,10 @@ sparc_sigaction (int sig, const struct old_sigaction __user *act, | |||
184 | 184 | ||
185 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || | 185 | if (!access_ok(VERIFY_READ, act, sizeof(*act)) || |
186 | __get_user(new_ka.sa.sa_handler, &act->sa_handler) || | 186 | __get_user(new_ka.sa.sa_handler, &act->sa_handler) || |
187 | __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) | 187 | __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) || |
188 | __get_user(new_ka.sa.sa_flags, &act->sa_flags) || | ||
189 | __get_user(mask, &act->sa_mask)) | ||
188 | return -EFAULT; | 190 | return -EFAULT; |
189 | __get_user(new_ka.sa.sa_flags, &act->sa_flags); | ||
190 | __get_user(mask, &act->sa_mask); | ||
191 | siginitset(&new_ka.sa.sa_mask, mask); | 191 | siginitset(&new_ka.sa.sa_mask, mask); |
192 | new_ka.ka_restorer = NULL; | 192 | new_ka.ka_restorer = NULL; |
193 | } | 193 | } |
@@ -195,17 +195,12 @@ sparc_sigaction (int sig, const struct old_sigaction __user *act, | |||
195 | ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); | 195 | ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); |
196 | 196 | ||
197 | if (!ret && oact) { | 197 | if (!ret && oact) { |
198 | /* In the clone() case we could copy half consistent | ||
199 | * state to the user, however this could sleep and | ||
200 | * deadlock us if we held the signal lock on SMP. So for | ||
201 | * now I take the easy way out and do no locking. | ||
202 | */ | ||
203 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || | 198 | if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || |
204 | __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || | 199 | __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || |
205 | __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) | 200 | __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) || |
201 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || | ||
202 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) | ||
206 | return -EFAULT; | 203 | return -EFAULT; |
207 | __put_user(old_ka.sa.sa_flags, &oact->sa_flags); | ||
208 | __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); | ||
209 | } | 204 | } |
210 | 205 | ||
211 | return ret; | 206 | return ret; |
diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c index 187118fbe1bc..292e706016c5 100644 --- a/arch/um/kernel/signal.c +++ b/arch/um/kernel/signal.c | |||
@@ -148,15 +148,8 @@ int do_signal(void) | |||
148 | long sys_sigsuspend(int history0, int history1, old_sigset_t mask) | 148 | long sys_sigsuspend(int history0, int history1, old_sigset_t mask) |
149 | { | 149 | { |
150 | sigset_t blocked; | 150 | sigset_t blocked; |
151 | |||
152 | mask &= _BLOCKABLE; | ||
153 | siginitset(&blocked, mask); | 151 | siginitset(&blocked, mask); |
154 | set_current_blocked(&blocked); | 152 | return sigsuspend(&blocked); |
155 | |||
156 | current->state = TASK_INTERRUPTIBLE; | ||
157 | schedule(); | ||
158 | set_thread_flag(TIF_RESTORE_SIGMASK); | ||
159 | return -ERESTARTNOHAND; | ||
160 | } | 153 | } |
161 | 154 | ||
162 | long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) | 155 | long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) |
diff --git a/arch/unicore32/kernel/signal.c b/arch/unicore32/kernel/signal.c index 911b549a6df5..7754df6ef7d4 100644 --- a/arch/unicore32/kernel/signal.c +++ b/arch/unicore32/kernel/signal.c | |||
@@ -370,10 +370,7 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka, | |||
370 | /* | 370 | /* |
371 | * Block the signal if we were successful. | 371 | * Block the signal if we were successful. |
372 | */ | 372 | */ |
373 | sigorsets(&blocked, &tsk->blocked, &ka->sa.sa_mask); | 373 | block_sigmask(ka, sig); |
374 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
375 | sigaddset(&blocked, sig); | ||
376 | set_current_blocked(&blocked); | ||
377 | 374 | ||
378 | return 0; | 375 | return 0; |
379 | } | 376 | } |
@@ -450,15 +447,12 @@ static void do_signal(struct pt_regs *regs, int syscall) | |||
450 | regs->UCreg_00 == -ERESTARTNOINTR) { | 447 | regs->UCreg_00 == -ERESTARTNOINTR) { |
451 | setup_syscall_restart(regs); | 448 | setup_syscall_restart(regs); |
452 | } | 449 | } |
453 | |||
454 | /* If there's no signal to deliver, we just put the saved | ||
455 | * sigmask back. | ||
456 | */ | ||
457 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
458 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
459 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
460 | } | ||
461 | } | 450 | } |
451 | /* If there's no signal to deliver, we just put the saved | ||
452 | * sigmask back. | ||
453 | */ | ||
454 | if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK)) | ||
455 | set_current_blocked(¤t->saved_sigmask); | ||
462 | } | 456 | } |
463 | 457 | ||
464 | asmlinkage void do_notify_resume(struct pt_regs *regs, | 458 | asmlinkage void do_notify_resume(struct pt_regs *regs, |
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index 0b3f2354f6aa..98bd70faccc5 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c | |||
@@ -131,18 +131,8 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) | |||
131 | asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask) | 131 | asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask) |
132 | { | 132 | { |
133 | sigset_t blocked; | 133 | sigset_t blocked; |
134 | |||
135 | current->saved_sigmask = current->blocked; | ||
136 | |||
137 | mask &= _BLOCKABLE; | ||
138 | siginitset(&blocked, mask); | 134 | siginitset(&blocked, mask); |
139 | set_current_blocked(&blocked); | 135 | return sigsuspend(&blocked); |
140 | |||
141 | current->state = TASK_INTERRUPTIBLE; | ||
142 | schedule(); | ||
143 | |||
144 | set_restore_sigmask(); | ||
145 | return -ERESTARTNOHAND; | ||
146 | } | 136 | } |
147 | 137 | ||
148 | asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr, | 138 | asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr, |
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 115eac431483..b68ccadd2ff4 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c | |||
@@ -478,18 +478,8 @@ asmlinkage int | |||
478 | sys_sigsuspend(int history0, int history1, old_sigset_t mask) | 478 | sys_sigsuspend(int history0, int history1, old_sigset_t mask) |
479 | { | 479 | { |
480 | sigset_t blocked; | 480 | sigset_t blocked; |
481 | |||
482 | current->saved_sigmask = current->blocked; | ||
483 | |||
484 | mask &= _BLOCKABLE; | ||
485 | siginitset(&blocked, mask); | 481 | siginitset(&blocked, mask); |
486 | set_current_blocked(&blocked); | 482 | return sigsuspend(&blocked); |
487 | |||
488 | current->state = TASK_INTERRUPTIBLE; | ||
489 | schedule(); | ||
490 | |||
491 | set_restore_sigmask(); | ||
492 | return -ERESTARTNOHAND; | ||
493 | } | 483 | } |
494 | 484 | ||
495 | asmlinkage int | 485 | asmlinkage int |
diff --git a/arch/xtensa/include/asm/signal.h b/arch/xtensa/include/asm/signal.h index 633ba73bc4d2..7f201b9d4195 100644 --- a/arch/xtensa/include/asm/signal.h +++ b/arch/xtensa/include/asm/signal.h | |||
@@ -120,13 +120,6 @@ typedef void (*__sighandler_t)(int); | |||
120 | #define SIG_ERR ((__sighandler_t)-1) /* error return from signal */ | 120 | #define SIG_ERR ((__sighandler_t)-1) /* error return from signal */ |
121 | 121 | ||
122 | #ifdef __KERNEL__ | 122 | #ifdef __KERNEL__ |
123 | struct old_sigaction { | ||
124 | __sighandler_t sa_handler; | ||
125 | old_sigset_t sa_mask; | ||
126 | unsigned long sa_flags; | ||
127 | void (*sa_restorer)(void); | ||
128 | }; | ||
129 | |||
130 | struct sigaction { | 123 | struct sigaction { |
131 | __sighandler_t sa_handler; | 124 | __sighandler_t sa_handler; |
132 | unsigned long sa_flags; | 125 | unsigned long sa_flags; |
diff --git a/arch/xtensa/include/asm/syscall.h b/arch/xtensa/include/asm/syscall.h index efcf33b92e4c..0b9f2e13c781 100644 --- a/arch/xtensa/include/asm/syscall.h +++ b/arch/xtensa/include/asm/syscall.h | |||
@@ -15,10 +15,6 @@ asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*); | |||
15 | asmlinkage long xtensa_ptrace(long, long, long, long); | 15 | asmlinkage long xtensa_ptrace(long, long, long, long); |
16 | asmlinkage long xtensa_sigreturn(struct pt_regs*); | 16 | asmlinkage long xtensa_sigreturn(struct pt_regs*); |
17 | asmlinkage long xtensa_rt_sigreturn(struct pt_regs*); | 17 | asmlinkage long xtensa_rt_sigreturn(struct pt_regs*); |
18 | asmlinkage long xtensa_sigsuspend(struct pt_regs*); | ||
19 | asmlinkage long xtensa_rt_sigsuspend(struct pt_regs*); | ||
20 | asmlinkage long xtensa_sigaction(int, const struct old_sigaction*, | ||
21 | struct old_sigaction*); | ||
22 | asmlinkage long xtensa_sigaltstack(struct pt_regs *regs); | 18 | asmlinkage long xtensa_sigaltstack(struct pt_regs *regs); |
23 | asmlinkage long sys_rt_sigaction(int, | 19 | asmlinkage long sys_rt_sigaction(int, |
24 | const struct sigaction __user *, | 20 | const struct sigaction __user *, |
diff --git a/arch/xtensa/include/asm/thread_info.h b/arch/xtensa/include/asm/thread_info.h index 6abbedd09d85..81abfd5d01ac 100644 --- a/arch/xtensa/include/asm/thread_info.h +++ b/arch/xtensa/include/asm/thread_info.h | |||
@@ -131,6 +131,7 @@ static inline struct thread_info *current_thread_info(void) | |||
131 | #define TIF_IRET 4 /* return with iret */ | 131 | #define TIF_IRET 4 /* return with iret */ |
132 | #define TIF_MEMDIE 5 /* is terminating due to OOM killer */ | 132 | #define TIF_MEMDIE 5 /* is terminating due to OOM killer */ |
133 | #define TIF_RESTORE_SIGMASK 6 /* restore signal mask in do_signal() */ | 133 | #define TIF_RESTORE_SIGMASK 6 /* restore signal mask in do_signal() */ |
134 | #define TIF_NOTIFY_RESUME 7 /* callback before returning to user */ | ||
134 | #define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ | 135 | #define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ |
135 | 136 | ||
136 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) | 137 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) |
diff --git a/arch/xtensa/include/asm/unistd.h b/arch/xtensa/include/asm/unistd.h index 798ee6d285a1..bc7e005faa60 100644 --- a/arch/xtensa/include/asm/unistd.h +++ b/arch/xtensa/include/asm/unistd.h | |||
@@ -507,7 +507,7 @@ __SYSCALL(229, sys_rt_sigtimedwait, 4) | |||
507 | #define __NR_rt_sigqueueinfo 230 | 507 | #define __NR_rt_sigqueueinfo 230 |
508 | __SYSCALL(230, sys_rt_sigqueueinfo, 3) | 508 | __SYSCALL(230, sys_rt_sigqueueinfo, 3) |
509 | #define __NR_rt_sigsuspend 231 | 509 | #define __NR_rt_sigsuspend 231 |
510 | __SYSCALL(231, xtensa_rt_sigsuspend, 2) | 510 | __SYSCALL(231, sys_rt_sigsuspend, 2) |
511 | 511 | ||
512 | /* Message */ | 512 | /* Message */ |
513 | 513 | ||
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index 6223f3346b5c..7e6236073397 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S | |||
@@ -409,16 +409,16 @@ common_exception_return: | |||
409 | l32i a4, a2, TI_FLAGS | 409 | l32i a4, a2, TI_FLAGS |
410 | 410 | ||
411 | _bbsi.l a4, TIF_NEED_RESCHED, 3f | 411 | _bbsi.l a4, TIF_NEED_RESCHED, 3f |
412 | _bbsi.l a4, TIF_NOTIFY_RESUME, 2f | ||
412 | _bbci.l a4, TIF_SIGPENDING, 4f | 413 | _bbci.l a4, TIF_SIGPENDING, 4f |
413 | 414 | ||
414 | l32i a4, a1, PT_DEPC | 415 | 2: l32i a4, a1, PT_DEPC |
415 | bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f | 416 | bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f |
416 | 417 | ||
417 | /* Call do_signal() */ | 418 | /* Call do_signal() */ |
418 | 419 | ||
419 | movi a4, do_signal # int do_signal(struct pt_regs*, sigset_t*) | 420 | movi a4, do_notify_resume # int do_notify_resume(struct pt_regs*) |
420 | mov a6, a1 | 421 | mov a6, a1 |
421 | movi a7, 0 | ||
422 | callx4 a4 | 422 | callx4 a4 |
423 | j 1b | 423 | j 1b |
424 | 424 | ||
diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c index d78869a00b11..c5e4ec0598d2 100644 --- a/arch/xtensa/kernel/signal.c +++ b/arch/xtensa/kernel/signal.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/ptrace.h> | 20 | #include <linux/ptrace.h> |
21 | #include <linux/personality.h> | 21 | #include <linux/personality.h> |
22 | #include <linux/freezer.h> | 22 | #include <linux/freezer.h> |
23 | #include <linux/tracehook.h> | ||
23 | 24 | ||
24 | #include <asm/ucontext.h> | 25 | #include <asm/ucontext.h> |
25 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
@@ -31,8 +32,6 @@ | |||
31 | 32 | ||
32 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 33 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) |
33 | 34 | ||
34 | asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); | ||
35 | |||
36 | extern struct task_struct *coproc_owners[]; | 35 | extern struct task_struct *coproc_owners[]; |
37 | 36 | ||
38 | struct rt_sigframe | 37 | struct rt_sigframe |
@@ -248,6 +247,9 @@ asmlinkage long xtensa_rt_sigreturn(long a0, long a1, long a2, long a3, | |||
248 | sigset_t set; | 247 | sigset_t set; |
249 | int ret; | 248 | int ret; |
250 | 249 | ||
250 | /* Always make any pending restarted system calls return -EINTR */ | ||
251 | current_thread_info()->restart_block.fn = do_no_restart_syscall; | ||
252 | |||
251 | if (regs->depc > 64) | 253 | if (regs->depc > 64) |
252 | panic("rt_sigreturn in double exception!\n"); | 254 | panic("rt_sigreturn in double exception!\n"); |
253 | 255 | ||
@@ -426,37 +428,6 @@ give_sigsegv: | |||
426 | return -EFAULT; | 428 | return -EFAULT; |
427 | } | 429 | } |
428 | 430 | ||
429 | /* | ||
430 | * Atomically swap in the new signal mask, and wait for a signal. | ||
431 | */ | ||
432 | |||
433 | asmlinkage long xtensa_rt_sigsuspend(sigset_t __user *unewset, | ||
434 | size_t sigsetsize, | ||
435 | long a2, long a3, long a4, long a5, | ||
436 | struct pt_regs *regs) | ||
437 | { | ||
438 | sigset_t saveset, newset; | ||
439 | |||
440 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
441 | if (sigsetsize != sizeof(sigset_t)) | ||
442 | return -EINVAL; | ||
443 | |||
444 | if (copy_from_user(&newset, unewset, sizeof(newset))) | ||
445 | return -EFAULT; | ||
446 | |||
447 | sigdelsetmask(&newset, ~_BLOCKABLE); | ||
448 | saveset = current->blocked; | ||
449 | set_current_blocked(&newset); | ||
450 | |||
451 | regs->areg[2] = -EINTR; | ||
452 | while (1) { | ||
453 | current->state = TASK_INTERRUPTIBLE; | ||
454 | schedule(); | ||
455 | if (do_signal(regs, &saveset)) | ||
456 | return -EINTR; | ||
457 | } | ||
458 | } | ||
459 | |||
460 | asmlinkage long xtensa_sigaltstack(const stack_t __user *uss, | 431 | asmlinkage long xtensa_sigaltstack(const stack_t __user *uss, |
461 | stack_t __user *uoss, | 432 | stack_t __user *uoss, |
462 | long a2, long a3, long a4, long a5, | 433 | long a2, long a3, long a4, long a5, |
@@ -476,19 +447,19 @@ asmlinkage long xtensa_sigaltstack(const stack_t __user *uss, | |||
476 | * the kernel can handle, and then we build all the user-level signal handling | 447 | * the kernel can handle, and then we build all the user-level signal handling |
477 | * stack-frames in one go after that. | 448 | * stack-frames in one go after that. |
478 | */ | 449 | */ |
479 | int do_signal(struct pt_regs *regs, sigset_t *oldset) | 450 | static void do_signal(struct pt_regs *regs) |
480 | { | 451 | { |
481 | siginfo_t info; | 452 | siginfo_t info; |
482 | int signr; | 453 | int signr; |
483 | struct k_sigaction ka; | 454 | struct k_sigaction ka; |
484 | 455 | sigset_t oldset; | |
485 | if (!user_mode(regs)) | ||
486 | return 0; | ||
487 | 456 | ||
488 | if (try_to_freeze()) | 457 | if (try_to_freeze()) |
489 | goto no_signal; | 458 | goto no_signal; |
490 | 459 | ||
491 | if (!oldset) | 460 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
461 | oldset = ¤t->saved_sigmask; | ||
462 | else | ||
492 | oldset = ¤t->blocked; | 463 | oldset = ¤t->blocked; |
493 | 464 | ||
494 | task_pt_regs(current)->icountlevel = 0; | 465 | task_pt_regs(current)->icountlevel = 0; |
@@ -532,13 +503,14 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) | |||
532 | /* Set up the stack frame */ | 503 | /* Set up the stack frame */ |
533 | ret = setup_frame(signr, &ka, &info, oldset, regs); | 504 | ret = setup_frame(signr, &ka, &info, oldset, regs); |
534 | if (ret) | 505 | if (ret) |
535 | return ret; | 506 | return; |
536 | 507 | ||
508 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
537 | block_sigmask(&ka, signr); | 509 | block_sigmask(&ka, signr); |
538 | if (current->ptrace & PT_SINGLESTEP) | 510 | if (current->ptrace & PT_SINGLESTEP) |
539 | task_pt_regs(current)->icountlevel = 1; | 511 | task_pt_regs(current)->icountlevel = 1; |
540 | 512 | ||
541 | return 1; | 513 | return; |
542 | } | 514 | } |
543 | 515 | ||
544 | no_signal: | 516 | no_signal: |
@@ -558,8 +530,27 @@ no_signal: | |||
558 | break; | 530 | break; |
559 | } | 531 | } |
560 | } | 532 | } |
533 | |||
534 | /* If there's no signal to deliver, we just restore the saved mask. */ | ||
535 | if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK)) | ||
536 | set_current_blocked(¤t->saved_sigmask); | ||
537 | |||
561 | if (current->ptrace & PT_SINGLESTEP) | 538 | if (current->ptrace & PT_SINGLESTEP) |
562 | task_pt_regs(current)->icountlevel = 1; | 539 | task_pt_regs(current)->icountlevel = 1; |
563 | return 0; | 540 | return; |
564 | } | 541 | } |
565 | 542 | ||
543 | void do_notify_resume(struct pt_regs *regs) | ||
544 | { | ||
545 | if (!user_mode(regs)) | ||
546 | return; | ||
547 | |||
548 | if (test_thread_flag(TIF_SIGPENDING)) | ||
549 | do_signal(regs); | ||
550 | |||
551 | if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) { | ||
552 | tracehook_notify_resume(regs); | ||
553 | if (current->replacement_session_keyring) | ||
554 | key_replace_session_keyring(); | ||
555 | } | ||
556 | } | ||