diff options
54 files changed, 386 insertions, 817 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 | } | ||
diff --git a/include/linux/signal.h b/include/linux/signal.h index 7987ce74874b..17046cc484bc 100644 --- a/include/linux/signal.h +++ b/include/linux/signal.h | |||
| @@ -252,6 +252,7 @@ extern int do_sigtimedwait(const sigset_t *, siginfo_t *, | |||
| 252 | extern int sigprocmask(int, sigset_t *, sigset_t *); | 252 | extern int sigprocmask(int, sigset_t *, sigset_t *); |
| 253 | extern void set_current_blocked(const sigset_t *); | 253 | extern void set_current_blocked(const sigset_t *); |
| 254 | extern int show_unhandled_signals; | 254 | extern int show_unhandled_signals; |
| 255 | extern int sigsuspend(sigset_t *); | ||
| 255 | 256 | ||
| 256 | extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie); | 257 | extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie); |
| 257 | extern void block_sigmask(struct k_sigaction *ka, int signr); | 258 | extern void block_sigmask(struct k_sigaction *ka, int signr); |
diff --git a/kernel/compat.c b/kernel/compat.c index d2c67aa49ae6..c28a306ae05c 100644 --- a/kernel/compat.c +++ b/kernel/compat.c | |||
| @@ -1073,15 +1073,7 @@ asmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, compat | |||
| 1073 | if (copy_from_user(&newset32, unewset, sizeof(compat_sigset_t))) | 1073 | if (copy_from_user(&newset32, unewset, sizeof(compat_sigset_t))) |
| 1074 | return -EFAULT; | 1074 | return -EFAULT; |
| 1075 | sigset_from_compat(&newset, &newset32); | 1075 | sigset_from_compat(&newset, &newset32); |
| 1076 | sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP)); | 1076 | return sigsuspend(&newset); |
| 1077 | |||
| 1078 | current->saved_sigmask = current->blocked; | ||
| 1079 | set_current_blocked(&newset); | ||
| 1080 | |||
| 1081 | current->state = TASK_INTERRUPTIBLE; | ||
| 1082 | schedule(); | ||
| 1083 | set_restore_sigmask(); | ||
| 1084 | return -ERESTARTNOHAND; | ||
| 1085 | } | 1077 | } |
| 1086 | #endif /* __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND */ | 1078 | #endif /* __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND */ |
| 1087 | 1079 | ||
diff --git a/kernel/signal.c b/kernel/signal.c index 21ebe75ff85f..4dbf00dfb359 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
| @@ -3232,6 +3232,21 @@ SYSCALL_DEFINE0(pause) | |||
| 3232 | 3232 | ||
| 3233 | #endif | 3233 | #endif |
| 3234 | 3234 | ||
| 3235 | #ifdef HAVE_SET_RESTORE_SIGMASK | ||
| 3236 | int sigsuspend(sigset_t *set) | ||
| 3237 | { | ||
| 3238 | sigdelsetmask(set, sigmask(SIGKILL)|sigmask(SIGSTOP)); | ||
| 3239 | |||
| 3240 | current->saved_sigmask = current->blocked; | ||
| 3241 | set_current_blocked(set); | ||
| 3242 | |||
| 3243 | current->state = TASK_INTERRUPTIBLE; | ||
| 3244 | schedule(); | ||
| 3245 | set_restore_sigmask(); | ||
| 3246 | return -ERESTARTNOHAND; | ||
| 3247 | } | ||
| 3248 | #endif | ||
| 3249 | |||
| 3235 | #ifdef __ARCH_WANT_SYS_RT_SIGSUSPEND | 3250 | #ifdef __ARCH_WANT_SYS_RT_SIGSUSPEND |
| 3236 | /** | 3251 | /** |
| 3237 | * sys_rt_sigsuspend - replace the signal mask for a value with the | 3252 | * sys_rt_sigsuspend - replace the signal mask for a value with the |
| @@ -3249,15 +3264,7 @@ SYSCALL_DEFINE2(rt_sigsuspend, sigset_t __user *, unewset, size_t, sigsetsize) | |||
| 3249 | 3264 | ||
| 3250 | if (copy_from_user(&newset, unewset, sizeof(newset))) | 3265 | if (copy_from_user(&newset, unewset, sizeof(newset))) |
| 3251 | return -EFAULT; | 3266 | return -EFAULT; |
| 3252 | sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP)); | 3267 | return sigsuspend(&newset); |
| 3253 | |||
| 3254 | current->saved_sigmask = current->blocked; | ||
| 3255 | set_current_blocked(&newset); | ||
| 3256 | |||
| 3257 | current->state = TASK_INTERRUPTIBLE; | ||
| 3258 | schedule(); | ||
| 3259 | set_restore_sigmask(); | ||
| 3260 | return -ERESTARTNOHAND; | ||
| 3261 | } | 3268 | } |
| 3262 | #endif /* __ARCH_WANT_SYS_RT_SIGSUSPEND */ | 3269 | #endif /* __ARCH_WANT_SYS_RT_SIGSUSPEND */ |
| 3263 | 3270 | ||
