Commit 68fa383f authored by Martin Michlmayr's avatar Martin Michlmayr Committed by Ralf Baechle

[MIPS] Add support for TIF_RESTORE_SIGMASK for signal32

    
Following the recent implementation of TIF_RESTORE_SIGMASK in
arch/mips/kernel/signal.c, 64-bit kernels with 32-bit user-land
compatibility oops when starting init.  signal32.c needs to be
converted to use TIF_RESTORE_SIGMASK too.
Signed-off-by: default avatarMartin Michlmayr <tbm@cyrius.com>
Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 8ecbbcaf
...@@ -106,8 +106,6 @@ typedef struct compat_siginfo { ...@@ -106,8 +106,6 @@ typedef struct compat_siginfo {
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
extern int do_signal32(sigset_t *oldset, struct pt_regs *regs);
/* 32-bit compatibility types */ /* 32-bit compatibility types */
#define _NSIG_BPW32 32 #define _NSIG_BPW32 32
...@@ -198,7 +196,7 @@ __attribute_used__ noinline static int ...@@ -198,7 +196,7 @@ __attribute_used__ noinline static int
_sys32_sigsuspend(nabi_no_regargs struct pt_regs regs) _sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
{ {
compat_sigset_t *uset; compat_sigset_t *uset;
sigset_t newset, saveset; sigset_t newset;
uset = (compat_sigset_t *) regs.regs[4]; uset = (compat_sigset_t *) regs.regs[4];
if (get_sigset(&newset, uset)) if (get_sigset(&newset, uset))
...@@ -206,19 +204,15 @@ _sys32_sigsuspend(nabi_no_regargs struct pt_regs regs) ...@@ -206,19 +204,15 @@ _sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
sigdelsetmask(&newset, ~_BLOCKABLE); sigdelsetmask(&newset, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
saveset = current->blocked; current->saved_sigmask = current->blocked;
current->blocked = newset; current->blocked = newset;
recalc_sigpending(); recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
regs.regs[2] = EINTR; current->state = TASK_INTERRUPTIBLE;
regs.regs[7] = 1; schedule();
while (1) { set_thread_flag(TIF_RESTORE_SIGMASK);
current->state = TASK_INTERRUPTIBLE; return -ERESTARTNOHAND;
schedule();
if (do_signal32(&saveset, &regs))
return -EINTR;
}
} }
save_static_function(sys32_rt_sigsuspend); save_static_function(sys32_rt_sigsuspend);
...@@ -226,7 +220,7 @@ __attribute_used__ noinline static int ...@@ -226,7 +220,7 @@ __attribute_used__ noinline static int
_sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) _sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
{ {
compat_sigset_t *uset; compat_sigset_t *uset;
sigset_t newset, saveset; sigset_t newset;
size_t sigsetsize; size_t sigsetsize;
/* XXX Don't preclude handling different sized sigset_t's. */ /* XXX Don't preclude handling different sized sigset_t's. */
...@@ -240,19 +234,15 @@ _sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) ...@@ -240,19 +234,15 @@ _sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
sigdelsetmask(&newset, ~_BLOCKABLE); sigdelsetmask(&newset, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
saveset = current->blocked; current->saved_sigmask = current->blocked;
current->blocked = newset; current->blocked = newset;
recalc_sigpending(); recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock); spin_unlock_irq(&current->sighand->siglock);
regs.regs[2] = EINTR; current->state = TASK_INTERRUPTIBLE;
regs.regs[7] = 1; schedule();
while (1) { set_thread_flag(TIF_RESTORE_SIGMASK);
current->state = TASK_INTERRUPTIBLE; return -ERESTARTNOHAND;
schedule();
if (do_signal32(&saveset, &regs))
return -EINTR;
}
} }
asmlinkage int sys32_sigaction(int sig, const struct sigaction32 *act, asmlinkage int sys32_sigaction(int sig, const struct sigaction32 *act,
...@@ -783,7 +773,7 @@ static inline int handle_signal(unsigned long sig, siginfo_t *info, ...@@ -783,7 +773,7 @@ static inline int handle_signal(unsigned long sig, siginfo_t *info,
regs->regs[2] = EINTR; regs->regs[2] = EINTR;
break; break;
case ERESTARTSYS: case ERESTARTSYS:
if(!(ka->sa.sa_flags & SA_RESTART)) { if (!(ka->sa.sa_flags & SA_RESTART)) {
regs->regs[2] = EINTR; regs->regs[2] = EINTR;
break; break;
} }
...@@ -810,9 +800,10 @@ static inline int handle_signal(unsigned long sig, siginfo_t *info, ...@@ -810,9 +800,10 @@ static inline int handle_signal(unsigned long sig, siginfo_t *info,
return ret; return ret;
} }
int do_signal32(sigset_t *oldset, struct pt_regs *regs) int do_signal32(struct pt_regs *regs)
{ {
struct k_sigaction ka; struct k_sigaction ka;
sigset_t *oldset;
siginfo_t info; siginfo_t info;
int signr; int signr;
...@@ -827,12 +818,25 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs) ...@@ -827,12 +818,25 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
if (try_to_freeze()) if (try_to_freeze())
goto no_signal; goto no_signal;
if (!oldset) if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked; oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) if (signr > 0) {
return handle_signal(signr, &info, &ka, oldset, regs); /* Whee! Actually deliver the signal. */
if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
/*
* A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag.
*/
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
}
no_signal: no_signal:
/* /*
...@@ -853,6 +857,16 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs) ...@@ -853,6 +857,16 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
regs->cp0_epc -= 4; regs->cp0_epc -= 4;
} }
} }
/*
* If there's no signal to deliver, we just put the saved sigmask
* back
*/
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
return 0; return 0;
} }
......
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