[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: Martin Michlmayr <tbm@cyrius.com> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
committed by
Ralf Baechle
parent
8ecbbcaf08
commit
68fa383f3e
@@ -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
|
|||||||
_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)
|
|||||||
sigdelsetmask(&newset, ~_BLOCKABLE);
|
sigdelsetmask(&newset, ~_BLOCKABLE);
|
||||||
|
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
spin_lock_irq(¤t->sighand->siglock);
|
||||||
saveset = current->blocked;
|
current->saved_sigmask = current->blocked;
|
||||||
current->blocked = newset;
|
current->blocked = newset;
|
||||||
recalc_sigpending();
|
recalc_sigpending();
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
spin_unlock_irq(¤t->sighand->siglock);
|
||||||
|
|
||||||
regs.regs[2] = EINTR;
|
|
||||||
regs.regs[7] = 1;
|
|
||||||
while (1) {
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
current->state = TASK_INTERRUPTIBLE;
|
||||||
schedule();
|
schedule();
|
||||||
if (do_signal32(&saveset, ®s))
|
set_thread_flag(TIF_RESTORE_SIGMASK);
|
||||||
return -EINTR;
|
return -ERESTARTNOHAND;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
save_static_function(sys32_rt_sigsuspend);
|
save_static_function(sys32_rt_sigsuspend);
|
||||||
@@ -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)
|
|||||||
sigdelsetmask(&newset, ~_BLOCKABLE);
|
sigdelsetmask(&newset, ~_BLOCKABLE);
|
||||||
|
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
spin_lock_irq(¤t->sighand->siglock);
|
||||||
saveset = current->blocked;
|
current->saved_sigmask = current->blocked;
|
||||||
current->blocked = newset;
|
current->blocked = newset;
|
||||||
recalc_sigpending();
|
recalc_sigpending();
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
spin_unlock_irq(¤t->sighand->siglock);
|
||||||
|
|
||||||
regs.regs[2] = EINTR;
|
|
||||||
regs.regs[7] = 1;
|
|
||||||
while (1) {
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
current->state = TASK_INTERRUPTIBLE;
|
||||||
schedule();
|
schedule();
|
||||||
if (do_signal32(&saveset, ®s))
|
set_thread_flag(TIF_RESTORE_SIGMASK);
|
||||||
return -EINTR;
|
return -ERESTARTNOHAND;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
asmlinkage int sys32_sigaction(int sig, const struct sigaction32 *act,
|
asmlinkage int sys32_sigaction(int sig, const struct sigaction32 *act,
|
||||||
@@ -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)
|
|||||||
if (try_to_freeze())
|
if (try_to_freeze())
|
||||||
goto no_signal;
|
goto no_signal;
|
||||||
|
|
||||||
if (!oldset)
|
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||||
|
oldset = ¤t->saved_sigmask;
|
||||||
|
else
|
||||||
oldset = ¤t->blocked;
|
oldset = ¤t->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 @@ no_signal:
|
|||||||
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, ¤t->saved_sigmask, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user