Commit 63cc2511 authored by Paul Mackerras's avatar Paul Mackerras Committed by Linus Torvalds

[PATCH] ppc64: signal race fix

Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 85695322
...@@ -459,17 +459,13 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka, ...@@ -459,17 +459,13 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka,
/* Set up Signal Frame */ /* Set up Signal Frame */
setup_rt_frame(sig, ka, info, oldset, regs); setup_rt_frame(sig, ka, info, oldset, regs);
if (ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
if (!(ka->sa.sa_flags & SA_NODEFER)) { if (!(ka->sa.sa_flags & SA_NODEFER)) {
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask); sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
sigaddset(&current->blocked,sig); sigaddset(&current->blocked,sig);
recalc_sigpending(); recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
} }
return;
} }
static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka) static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
...@@ -512,6 +508,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -512,6 +508,7 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
{ {
siginfo_t info; siginfo_t info;
int signr; int signr;
struct k_sigaction ka;
/* /*
* If the current thread is 32 bit - invoke the * If the current thread is 32 bit - invoke the
...@@ -523,14 +520,12 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) ...@@ -523,14 +520,12 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs)
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
signr = get_signal_to_deliver(&info, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) { if (signr > 0) {
struct k_sigaction *ka = &current->sighand->action[signr-1];
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
if (TRAP(regs) == 0x0C00) if (TRAP(regs) == 0x0C00)
syscall_restart(regs, ka); syscall_restart(regs, &ka);
handle_signal(signr, ka, &info, oldset, regs); handle_signal(signr, &ka, &info, oldset, regs);
return 1; return 1;
} }
......
...@@ -924,18 +924,16 @@ long sys32_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, ...@@ -924,18 +924,16 @@ long sys32_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
int do_signal32(sigset_t *oldset, struct pt_regs *regs) int do_signal32(sigset_t *oldset, struct pt_regs *regs)
{ {
siginfo_t info; siginfo_t info;
struct k_sigaction *ka;
unsigned int frame, newsp; unsigned int frame, newsp;
int signr, ret; int signr, ret;
struct k_sigaction ka;
if (!oldset) if (!oldset)
oldset = &current->blocked; oldset = &current->blocked;
newsp = frame = 0; newsp = frame = 0;
signr = get_signal_to_deliver(&info, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
ka = (signr == 0)? NULL: &current->sighand->action[signr-1];
if (TRAP(regs) == 0x0C00 /* System Call! */ if (TRAP(regs) == 0x0C00 /* System Call! */
&& regs->ccr & 0x10000000 /* error signalled */ && regs->ccr & 0x10000000 /* error signalled */
...@@ -946,7 +944,7 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs) ...@@ -946,7 +944,7 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
if (signr > 0 if (signr > 0
&& (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK && (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK
|| (ret == ERESTARTSYS || (ret == ERESTARTSYS
&& !(ka->sa.sa_flags & SA_RESTART)))) { && !(ka.sa.sa_flags & SA_RESTART)))) {
/* make the system call return an EINTR error */ /* make the system call return an EINTR error */
regs->result = -EINTR; regs->result = -EINTR;
regs->gpr[3] = EINTR; regs->gpr[3] = EINTR;
...@@ -965,7 +963,7 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs) ...@@ -965,7 +963,7 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
if (signr == 0) if (signr == 0)
return 0; /* no signals delivered */ return 0; /* no signals delivered */
if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size
&& (!on_sig_stack(regs->gpr[1]))) && (!on_sig_stack(regs->gpr[1])))
newsp = (current->sas_ss_sp + current->sas_ss_size); newsp = (current->sas_ss_sp + current->sas_ss_size);
else else
...@@ -973,17 +971,15 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs) ...@@ -973,17 +971,15 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
newsp &= ~0xfUL; newsp &= ~0xfUL;
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
if (ka->sa.sa_flags & SA_SIGINFO) if (ka.sa.sa_flags & SA_SIGINFO)
handle_rt_signal32(signr, ka, &info, oldset, regs, newsp); handle_rt_signal32(signr, &ka, &info, oldset, regs, newsp);
else else
handle_signal32(signr, ka, &info, oldset, regs, newsp); handle_signal32(signr, &ka, &info, oldset, regs, newsp);
if (ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
if (!(ka->sa.sa_flags & SA_NODEFER)) { if (!(ka.sa.sa_flags & SA_NODEFER)) {
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask); sigorsets(&current->blocked, &current->blocked,
&ka.sa.sa_mask);
sigaddset(&current->blocked, signr); sigaddset(&current->blocked, signr);
recalc_sigpending(); recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment