Commit faddf598 authored by Matt Fleming's avatar Matt Fleming Committed by David S. Miller

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: default avatarMatt Fleming <matt.fleming@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f22ed71c
...@@ -273,10 +273,7 @@ void do_sigreturn32(struct pt_regs *regs) ...@@ -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(&current->sighand->siglock); set_current_blocked(&set);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
return; return;
segv: segv:
...@@ -377,10 +374,7 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) ...@@ -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(&current->sighand->siglock); set_current_blocked(&set);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->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, ...@@ -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, ...@@ -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(&current->sighand->siglock); sigorsets(&blocked, &current->blocked, &ka->sa.sa_mask);
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
if (!(ka->sa.sa_flags & SA_NOMASK)) if (!(ka->sa.sa_flags & SA_NOMASK))
sigaddset(&current->blocked,signr); sigaddset(&blocked, signr);
recalc_sigpending(); set_current_blocked(&blocked);
spin_unlock_irq(&current->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 { ...@@ -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(&current->sighand->siglock);
current->saved_sigmask = current->blocked; current->saved_sigmask = current->blocked;
siginitset(&current->blocked, set);
recalc_sigpending(); set &= _BLOCKABLE;
spin_unlock_irq(&current->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) ...@@ -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(&current->sighand->siglock); set_current_blocked(&set);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
return; return;
segv_and_exit: segv_and_exit:
...@@ -209,10 +207,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs) ...@@ -209,10 +207,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
} }
sigdelsetmask(&set, ~_BLOCKABLE); sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock); set_current_blocked(&set);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
return; return;
segv: segv:
force_sig(SIGSEGV, current); force_sig(SIGSEGV, current);
...@@ -470,6 +465,7 @@ static inline int ...@@ -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, ...@@ -480,12 +476,10 @@ handle_signal(unsigned long signr, struct k_sigaction *ka,
if (err) if (err)
return err; return err;
spin_lock_irq(&current->sighand->siglock); sigorsets(&blocked, &current->blocked, &ka->sa.sa_mask);
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
if (!(ka->sa.sa_flags & SA_NOMASK)) if (!(ka->sa.sa_flags & SA_NOMASK))
sigaddset(&current->blocked, signr); sigaddset(&blocked, signr);
recalc_sigpending(); set_current_blocked(&blocked);
spin_unlock_irq(&current->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) ...@@ -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(&current->sighand->siglock); set_current_blocked(&set);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->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 { ...@@ -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(&current->sighand->siglock);
current->saved_sigmask = current->blocked; current->saved_sigmask = current->blocked;
siginitset(&current->blocked, set);
recalc_sigpending(); set &= _BLOCKABLE;
spin_unlock_irq(&current->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) ...@@ -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(&current->sighand->siglock); set_current_blocked(&set);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->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, ...@@ -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(&current->sighand->siglock); sigorsets(&blocked, &current->blocked, &ka->sa.sa_mask);
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
if (!(ka->sa.sa_flags & SA_NOMASK)) if (!(ka->sa.sa_flags & SA_NOMASK))
sigaddset(&current->blocked,signr); sigaddset(&blocked, signr);
recalc_sigpending(); set_current_blocked(&blocked);
spin_unlock_irq(&current->sighand->siglock);
tracehook_signal_handler(signr, info, ka, regs, 0); tracehook_signal_handler(signr, info, ka, regs, 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