sparc: Use set_current_blocked()
As described in e6fa16ab
("signal: sigprocmask() should do
retarget_shared_pending()") the modification of current->blocked is
incorrect as we need to check whether the signal we're about to block
is pending in the shared queue.
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Matt Fleming <matt.fleming@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
f22ed71cd6
commit
faddf598f0
@@ -273,10 +273,7 @@ void do_sigreturn32(struct pt_regs *regs)
|
|||||||
case 1: set.sig[0] = seta[0] + (((long)seta[1]) << 32);
|
case 1: set.sig[0] = seta[0] + (((long)seta[1]) << 32);
|
||||||
}
|
}
|
||||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
set_current_blocked(&set);
|
||||||
current->blocked = set;
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
segv:
|
segv:
|
||||||
@@ -377,10 +374,7 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
|
|||||||
case 1: set.sig[0] = seta.sig[0] + (((long)seta.sig[1]) << 32);
|
case 1: set.sig[0] = seta.sig[0] + (((long)seta.sig[1]) << 32);
|
||||||
}
|
}
|
||||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
set_current_blocked(&set);
|
||||||
current->blocked = set;
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
return;
|
return;
|
||||||
segv:
|
segv:
|
||||||
force_sig(SIGSEGV, current);
|
force_sig(SIGSEGV, current);
|
||||||
@@ -782,6 +776,7 @@ static inline int handle_signal32(unsigned long signr, struct k_sigaction *ka,
|
|||||||
siginfo_t *info,
|
siginfo_t *info,
|
||||||
sigset_t *oldset, struct pt_regs *regs)
|
sigset_t *oldset, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
|
sigset_t blocked;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (ka->sa.sa_flags & SA_SIGINFO)
|
if (ka->sa.sa_flags & SA_SIGINFO)
|
||||||
@@ -792,12 +787,10 @@ static inline int handle_signal32(unsigned long signr, struct k_sigaction *ka,
|
|||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
sigorsets(&blocked, ¤t->blocked, &ka->sa.sa_mask);
|
||||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
|
||||||
if (!(ka->sa.sa_flags & SA_NOMASK))
|
if (!(ka->sa.sa_flags & SA_NOMASK))
|
||||||
sigaddset(¤t->blocked,signr);
|
sigaddset(&blocked, signr);
|
||||||
recalc_sigpending();
|
set_current_blocked(&blocked);
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
tracehook_signal_handler(signr, info, ka, regs, 0);
|
tracehook_signal_handler(signr, info, ka, regs, 0);
|
||||||
|
|
||||||
|
@@ -62,12 +62,13 @@ struct rt_signal_frame {
|
|||||||
|
|
||||||
static int _sigpause_common(old_sigset_t set)
|
static int _sigpause_common(old_sigset_t set)
|
||||||
{
|
{
|
||||||
set &= _BLOCKABLE;
|
sigset_t blocked;
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
|
||||||
current->saved_sigmask = current->blocked;
|
current->saved_sigmask = current->blocked;
|
||||||
siginitset(¤t->blocked, set);
|
|
||||||
recalc_sigpending();
|
set &= _BLOCKABLE;
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
siginitset(&blocked, set);
|
||||||
|
set_current_blocked(&blocked);
|
||||||
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
current->state = TASK_INTERRUPTIBLE;
|
||||||
schedule();
|
schedule();
|
||||||
@@ -139,10 +140,7 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
|
|||||||
goto segv_and_exit;
|
goto segv_and_exit;
|
||||||
|
|
||||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
set_current_blocked(&set);
|
||||||
current->blocked = set;
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
segv_and_exit:
|
segv_and_exit:
|
||||||
@@ -209,10 +207,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
set_current_blocked(&set);
|
||||||
current->blocked = set;
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
return;
|
return;
|
||||||
segv:
|
segv:
|
||||||
force_sig(SIGSEGV, current);
|
force_sig(SIGSEGV, current);
|
||||||
@@ -470,6 +465,7 @@ static inline int
|
|||||||
handle_signal(unsigned long signr, struct k_sigaction *ka,
|
handle_signal(unsigned long signr, struct k_sigaction *ka,
|
||||||
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
|
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
|
sigset_t blocked;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (ka->sa.sa_flags & SA_SIGINFO)
|
if (ka->sa.sa_flags & SA_SIGINFO)
|
||||||
@@ -480,12 +476,10 @@ handle_signal(unsigned long signr, struct k_sigaction *ka,
|
|||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
sigorsets(&blocked, ¤t->blocked, &ka->sa.sa_mask);
|
||||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
|
||||||
if (!(ka->sa.sa_flags & SA_NOMASK))
|
if (!(ka->sa.sa_flags & SA_NOMASK))
|
||||||
sigaddset(¤t->blocked, signr);
|
sigaddset(&blocked, signr);
|
||||||
recalc_sigpending();
|
set_current_blocked(&blocked);
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
tracehook_signal_handler(signr, info, ka, regs, 0);
|
tracehook_signal_handler(signr, info, ka, regs, 0);
|
||||||
|
|
||||||
|
@@ -70,10 +70,7 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs)
|
|||||||
goto do_sigsegv;
|
goto do_sigsegv;
|
||||||
}
|
}
|
||||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
set_current_blocked(&set);
|
||||||
current->blocked = set;
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
}
|
}
|
||||||
if (test_thread_flag(TIF_32BIT)) {
|
if (test_thread_flag(TIF_32BIT)) {
|
||||||
pc &= 0xffffffff;
|
pc &= 0xffffffff;
|
||||||
@@ -242,12 +239,13 @@ struct rt_signal_frame {
|
|||||||
|
|
||||||
static long _sigpause_common(old_sigset_t set)
|
static long _sigpause_common(old_sigset_t set)
|
||||||
{
|
{
|
||||||
set &= _BLOCKABLE;
|
sigset_t blocked;
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
|
||||||
current->saved_sigmask = current->blocked;
|
current->saved_sigmask = current->blocked;
|
||||||
siginitset(¤t->blocked, set);
|
|
||||||
recalc_sigpending();
|
set &= _BLOCKABLE;
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
siginitset(&blocked, set);
|
||||||
|
set_current_blocked(&blocked);
|
||||||
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
current->state = TASK_INTERRUPTIBLE;
|
||||||
schedule();
|
schedule();
|
||||||
@@ -327,10 +325,7 @@ void do_rt_sigreturn(struct pt_regs *regs)
|
|||||||
pt_regs_clear_syscall(regs);
|
pt_regs_clear_syscall(regs);
|
||||||
|
|
||||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
set_current_blocked(&set);
|
||||||
current->blocked = set;
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
return;
|
return;
|
||||||
segv:
|
segv:
|
||||||
force_sig(SIGSEGV, current);
|
force_sig(SIGSEGV, current);
|
||||||
@@ -484,18 +479,17 @@ static inline int handle_signal(unsigned long signr, struct k_sigaction *ka,
|
|||||||
siginfo_t *info,
|
siginfo_t *info,
|
||||||
sigset_t *oldset, struct pt_regs *regs)
|
sigset_t *oldset, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
|
sigset_t blocked;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = setup_rt_frame(ka, regs, signr, oldset,
|
err = setup_rt_frame(ka, regs, signr, oldset,
|
||||||
(ka->sa.sa_flags & SA_SIGINFO) ? info : NULL);
|
(ka->sa.sa_flags & SA_SIGINFO) ? info : NULL);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
sigorsets(&blocked, ¤t->blocked, &ka->sa.sa_mask);
|
||||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
|
||||||
if (!(ka->sa.sa_flags & SA_NOMASK))
|
if (!(ka->sa.sa_flags & SA_NOMASK))
|
||||||
sigaddset(¤t->blocked,signr);
|
sigaddset(&blocked, signr);
|
||||||
recalc_sigpending();
|
set_current_blocked(&blocked);
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
tracehook_signal_handler(signr, info, ka, regs, 0);
|
tracehook_signal_handler(signr, info, ka, regs, 0);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user