From 68f3f16d9ad0f1e28ab3fd0001ab5798c41f15a3 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 21 May 2012 21:42:32 -0400 Subject: new helper: sigsuspend() guts of saved_sigmask-based sigsuspend/rt_sigsuspend. Takes kernel sigset_t *. Open-coded instances replaced with calling it. Signed-off-by: Al Viro --- arch/cris/arch-v10/kernel/signal.c | 16 ++++------------ arch/cris/arch-v32/kernel/signal.c | 16 ++++------------ 2 files changed, 8 insertions(+), 24 deletions(-) (limited to 'arch/cris') diff --git a/arch/cris/arch-v10/kernel/signal.c b/arch/cris/arch-v10/kernel/signal.c index 289c584..170f497 100644 --- a/arch/cris/arch-v10/kernel/signal.c +++ b/arch/cris/arch-v10/kernel/signal.c @@ -48,19 +48,11 @@ void do_signal(int canrestart, struct pt_regs *regs); * dummy arguments to be able to reach the regs argument. (Note that this * arrangement relies on old_sigset_t occupying one register.) */ -int sys_sigsuspend(old_sigset_t mask, long r11, long r12, long r13, long mof, - long srp, struct pt_regs *regs) +int sys_sigsuspend(old_sigset_t mask) { - mask &= _BLOCKABLE; - spin_lock_irq(¤t->sighand->siglock); - current->saved_sigmask = current->blocked; - siginitset(¤t->blocked, mask); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - current->state = TASK_INTERRUPTIBLE; - schedule(); - set_thread_flag(TIF_RESTORE_SIGMASK); - return -ERESTARTNOHAND; + sigset_t blocked; + siginitset(&blocked, mask); + return sigsuspend(&blocked); } int sys_sigaction(int sig, const struct old_sigaction __user *act, diff --git a/arch/cris/arch-v32/kernel/signal.c b/arch/cris/arch-v32/kernel/signal.c index ce4ab1a..e090832 100644 --- a/arch/cris/arch-v32/kernel/signal.c +++ b/arch/cris/arch-v32/kernel/signal.c @@ -59,19 +59,11 @@ void keep_debug_flags(unsigned long oldccs, unsigned long oldspc, * dummy arguments to be able to reach the regs argument. */ int -sys_sigsuspend(old_sigset_t mask, long r11, long r12, long r13, long mof, - long srp, struct pt_regs *regs) +sys_sigsuspend(old_sigset_t mask) { - mask &= _BLOCKABLE; - spin_lock_irq(¤t->sighand->siglock); - current->saved_sigmask = current->blocked; - siginitset(¤t->blocked, mask); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - current->state = TASK_INTERRUPTIBLE; - schedule(); - set_thread_flag(TIF_RESTORE_SIGMASK); - return -ERESTARTNOHAND; + sigset_t blocked; + siginitset(&blocked, mask); + return sigsuspend(&blocked); } int -- cgit v1.1 From f3b5e822739c70663aee8584b7993afe055431c9 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Fri, 11 May 2012 10:58:00 +1000 Subject: cris: use set_current_blocked() and block_sigmask() 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. Also, use the new helper function introduced in commit 5e6292c0f28f ("signal: add block_sigmask() for adding sigmask to current->blocked") which centralises the code for updating current->blocked after successfully delivering a signal and reduces the amount of duplicate code across architectures. In the past some architectures got this code wrong, so using this helper function should stop that from happening again. Acked-by: Oleg Nesterov Cc: Mikael Starvik Acked-by: Jesper Nilsson Signed-off-by: Matt Fleming Signed-off-by: Andrew Morton Signed-off-by: Al Viro --- arch/cris/arch-v10/kernel/signal.c | 22 +++++----------------- arch/cris/arch-v32/kernel/signal.c | 25 ++++--------------------- 2 files changed, 9 insertions(+), 38 deletions(-) (limited to 'arch/cris') diff --git a/arch/cris/arch-v10/kernel/signal.c b/arch/cris/arch-v10/kernel/signal.c index 170f497..df40fa8 100644 --- a/arch/cris/arch-v10/kernel/signal.c +++ b/arch/cris/arch-v10/kernel/signal.c @@ -177,10 +177,7 @@ asmlinkage int sys_sigreturn(long r10, long r11, long r12, long r13, long mof, goto badframe; sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + set_current_blocked(&set); if (restore_sigcontext(regs, &frame->sc)) goto badframe; @@ -216,10 +213,7 @@ asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13, goto badframe; sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + set_current_blocked(&set); if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) goto badframe; @@ -461,15 +455,9 @@ static inline int handle_signal(int canrestart, unsigned long sig, else ret = setup_frame(sig, ka, oldset, regs); - if (ret == 0) { - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked, ¤t->blocked, - &ka->sa.sa_mask); - if (!(ka->sa.sa_flags & SA_NODEFER)) - sigaddset(¤t->blocked, sig); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - } + if (ret == 0) + block_sigmask(ka, sig); + return ret; } diff --git a/arch/cris/arch-v32/kernel/signal.c b/arch/cris/arch-v32/kernel/signal.c index e090832..b0a6cf4 100644 --- a/arch/cris/arch-v32/kernel/signal.c +++ b/arch/cris/arch-v32/kernel/signal.c @@ -168,12 +168,7 @@ sys_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp, goto badframe; sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - - current->blocked = set; - - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + set_current_blocked(&set); if (restore_sigcontext(regs, &frame->sc)) goto badframe; @@ -214,12 +209,7 @@ sys_rt_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp, goto badframe; sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - - current->blocked = set; - - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); + set_current_blocked(&set); if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) goto badframe; @@ -507,15 +497,8 @@ handle_signal(int canrestart, unsigned long sig, if (ka->sa.sa_flags & SA_ONESHOT) ka->sa.sa_handler = SIG_DFL; - if (ret == 0) { - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked, ¤t->blocked, - &ka->sa.sa_mask); - if (!(ka->sa.sa_flags & SA_NODEFER)) - sigaddset(¤t->blocked, sig); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - } + if (ret == 0) + block_sigmask(ka, sig); return ret; } -- cgit v1.1 From a4e075c43e7fd9af769b28b7cb454615f61e2698 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 2 May 2012 09:46:55 -0400 Subject: cris: SA_ONESHOT handling is done by get_signal_to_deliver() ... and resetting sa_handler in local copy filled by get_signal_to_deliver() is obviously pointless anyway. Signed-off-by: Al Viro --- arch/cris/arch-v32/kernel/signal.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch/cris') diff --git a/arch/cris/arch-v32/kernel/signal.c b/arch/cris/arch-v32/kernel/signal.c index b0a6cf4..5590578 100644 --- a/arch/cris/arch-v32/kernel/signal.c +++ b/arch/cris/arch-v32/kernel/signal.c @@ -494,9 +494,6 @@ handle_signal(int canrestart, unsigned long sig, else ret = setup_frame(sig, ka, oldset, regs); - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; - if (ret == 0) block_sigmask(ka, sig); -- cgit v1.1 From 6eef019002e61abdc5e4384e4154d73c9f56d2bc Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 21 Apr 2012 21:35:56 -0400 Subject: cris: don't open-code force_sigsegv() Signed-off-by: Al Viro --- arch/cris/arch-v32/kernel/signal.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'arch/cris') diff --git a/arch/cris/arch-v32/kernel/signal.c b/arch/cris/arch-v32/kernel/signal.c index 5590578..a45efc7 100644 --- a/arch/cris/arch-v32/kernel/signal.c +++ b/arch/cris/arch-v32/kernel/signal.c @@ -345,10 +345,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, return 0; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); return -EFAULT; } @@ -432,10 +429,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, return 0; give_sigsegv: - if (sig == SIGSEGV) - ka->sa.sa_handler = SIG_DFL; - - force_sig(SIGSEGV, current); + force_sigsegv(sig, current); return -EFAULT; } -- cgit v1.1 From 24d696a776e27268a52cb4ff1060337f409d5789 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 22 Apr 2012 17:18:10 -0400 Subject: cris: missing checks of __get_user()/__put_user() return values Signed-off-by: Al Viro --- arch/cris/arch-v10/kernel/signal.c | 12 ++++++------ arch/cris/arch-v32/kernel/signal.c | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'arch/cris') diff --git a/arch/cris/arch-v10/kernel/signal.c b/arch/cris/arch-v10/kernel/signal.c index df40fa8..e16f8f2 100644 --- a/arch/cris/arch-v10/kernel/signal.c +++ b/arch/cris/arch-v10/kernel/signal.c @@ -65,10 +65,10 @@ int sys_sigaction(int sig, const struct old_sigaction __user *act, old_sigset_t mask; if (!access_ok(VERIFY_READ, act, sizeof(*act)) || __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) + __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) || + __get_user(new_ka.sa.sa_flags, &act->sa_flags) || + __get_user(mask, &act->sa_mask)) return -EFAULT; - __get_user(new_ka.sa.sa_flags, &act->sa_flags); - __get_user(mask, &act->sa_mask); siginitset(&new_ka.sa.sa_mask, mask); } @@ -77,10 +77,10 @@ int sys_sigaction(int sig, const struct old_sigaction __user *act, if (!ret && oact) { if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) + __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) || + __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || + __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) return -EFAULT; - __put_user(old_ka.sa.sa_flags, &oact->sa_flags); - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); } return ret; diff --git a/arch/cris/arch-v32/kernel/signal.c b/arch/cris/arch-v32/kernel/signal.c index a45efc7..b338d8f 100644 --- a/arch/cris/arch-v32/kernel/signal.c +++ b/arch/cris/arch-v32/kernel/signal.c @@ -79,11 +79,11 @@ sys_sigaction(int signal, const struct old_sigaction *act, if (!access_ok(VERIFY_READ, act, sizeof(*act)) || __get_user(newk.sa.sa_handler, &act->sa_handler) || - __get_user(newk.sa.sa_restorer, &act->sa_restorer)) + __get_user(newk.sa.sa_restorer, &act->sa_restorer) || + __get_user(newk.sa.sa_flags, &act->sa_flags) || + __get_user(mask, &act->sa_mask)) return -EFAULT; - __get_user(newk.sa.sa_flags, &act->sa_flags); - __get_user(mask, &act->sa_mask); siginitset(&newk.sa.sa_mask, mask); } @@ -92,11 +92,11 @@ sys_sigaction(int signal, const struct old_sigaction *act, if (!retval && oact) { if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || __put_user(oldk.sa.sa_handler, &oact->sa_handler) || - __put_user(oldk.sa.sa_restorer, &oact->sa_restorer)) + __put_user(oldk.sa.sa_restorer, &oact->sa_restorer) || + __put_user(oldk.sa.sa_flags, &oact->sa_flags) || + __put_user(oldk.sa.sa_mask.sig[0], &oact->sa_mask)) return -EFAULT; - __put_user(oldk.sa.sa_flags, &oact->sa_flags); - __put_user(oldk.sa.sa_mask.sig[0], &oact->sa_mask); } return retval; -- cgit v1.1