From e1b1fd79a04396d5ec971e9e4d4711b5a58ad7e3 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Fri, 11 May 2012 10:57:57 +1000 Subject: avr32: don't mask signals in the error path The current handle_signal() implementation is broken - it will mask signals if we fail to setup the signal stack frame, which isn't the desired behaviour, we should only be masking signals if we succeed in setting up the stack frame. It looks like this code was copied from the old (broken) arm implementation but wasn't updated when the arm code was fixed in commit a6c61e9dfdd0 ("[ARM] 3168/1: Update ARM signal delivery and masking"). Cc: Hans-Christian Egtvedt Acked-by: Havard Skinnemoen Acked-by: Oleg Nesterov Signed-off-by: Matt Fleming Signed-off-by: Andrew Morton Signed-off-by: Al Viro --- arch/avr32/kernel/signal.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'arch/avr32') diff --git a/arch/avr32/kernel/signal.c b/arch/avr32/kernel/signal.c index 64f886fac2ef..9c075e105d60 100644 --- a/arch/avr32/kernel/signal.c +++ b/arch/avr32/kernel/signal.c @@ -238,22 +238,21 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, */ ret |= !valid_user_regs(regs); + if (ret != 0) { + force_sigsegv(sig, current); + return; + } + /* - * Block the signal if we were unsuccessful. + * Block the signal if we were successful. */ - if (ret != 0 || !(ka->sa.sa_flags & SA_NODEFER)) { - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked, ¤t->blocked, - &ka->sa.sa_mask); + 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) - return; - - force_sigsegv(sig, current); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); } /* -- cgit v1.2.3-58-ga151 From 49209590cb1cdd30b35edd65535184e39bfbab99 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Fri, 11 May 2012 10:57:58 +1000 Subject: avr32: use set_current_blocked() in handle_signal/sys_rt_sigreturn It is wrong to change ->blocked directly, see e6fa16ab. Change handle_signal() and sys_rt_sigreturn() to use the right helper, set_current_blocked(). Cc: Hans-Christian Egtvedt Acked-by: Havard Skinnemoen Reviewed-by: Matt Fleming Signed-off-by: Oleg Nesterov Signed-off-by: Andrew Morton Signed-off-by: Al Viro --- arch/avr32/kernel/signal.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'arch/avr32') diff --git a/arch/avr32/kernel/signal.c b/arch/avr32/kernel/signal.c index 9c075e105d60..06f4293f85d8 100644 --- a/arch/avr32/kernel/signal.c +++ b/arch/avr32/kernel/signal.c @@ -87,10 +87,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) 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; @@ -226,6 +223,7 @@ static inline void handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs *regs, int syscall) { + sigset_t blocked; int ret; /* @@ -246,13 +244,10 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, /* * Block the signal if we were successful. */ - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked, ¤t->blocked, - &ka->sa.sa_mask); + sigorsets(&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); + sigaddset(&blocked, sig); + set_current_blocked(&blocked); } /* -- cgit v1.2.3-58-ga151 From 54bbf3e3a9af5e3c439766fda444fb0673a1a721 Mon Sep 17 00:00:00 2001 From: Matt Fleming Date: Fri, 11 May 2012 10:57:58 +1000 Subject: avr32: use block_sigmask() 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: Hans-Christian Egtvedt Cc: Havard Skinnemoen Signed-off-by: Matt Fleming Signed-off-by: Andrew Morton Signed-off-by: Al Viro --- arch/avr32/kernel/signal.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'arch/avr32') diff --git a/arch/avr32/kernel/signal.c b/arch/avr32/kernel/signal.c index 06f4293f85d8..feeb77bd81c7 100644 --- a/arch/avr32/kernel/signal.c +++ b/arch/avr32/kernel/signal.c @@ -223,7 +223,6 @@ static inline void handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs *regs, int syscall) { - sigset_t blocked; int ret; /* @@ -244,10 +243,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, /* * Block the signal if we were successful. */ - sigorsets(&blocked, ¤t->blocked, &ka->sa.sa_mask); - if (!(ka->sa.sa_flags & SA_NODEFER)) - sigaddset(&blocked, sig); - set_current_blocked(&blocked); + block_sigmask(ka, sig); } /* -- cgit v1.2.3-58-ga151 From 446cdd13275bfa38b858a1e99dbd61c07c9767c0 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 22 Apr 2012 03:36:05 -0400 Subject: avr32: ->restart_block.fn needs to be reset on rt_sigreturn Signed-off-by: Al Viro --- arch/avr32/kernel/signal.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/avr32') diff --git a/arch/avr32/kernel/signal.c b/arch/avr32/kernel/signal.c index feeb77bd81c7..a4855aecbe44 100644 --- a/arch/avr32/kernel/signal.c +++ b/arch/avr32/kernel/signal.c @@ -77,6 +77,9 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) struct rt_sigframe __user *frame; sigset_t set; + /* Always make any pending restarted system calls return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + frame = (struct rt_sigframe __user *)regs->sp; pr_debug("SIG return: frame = %p\n", frame); -- cgit v1.2.3-58-ga151 From fe49c1cebf054d5c797ecd6b91d5bf96d4295fe4 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 2 May 2012 09:52:37 -0400 Subject: avr32: need to clear RESTORE_SIGMASK on successful signal delivery Signed-off-by: Al Viro --- arch/avr32/kernel/signal.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/avr32') diff --git a/arch/avr32/kernel/signal.c b/arch/avr32/kernel/signal.c index a4855aecbe44..ae386c304bee 100644 --- a/arch/avr32/kernel/signal.c +++ b/arch/avr32/kernel/signal.c @@ -247,6 +247,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, * Block the signal if we were successful. */ block_sigmask(ka, sig); + clear_thread_flag(TIF_RESTORE_SIGMASK); } /* -- cgit v1.2.3-58-ga151 From 9a07880222b6e50cee2c2d66270cff0c34bfe7b8 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 22 Apr 2012 16:21:28 -0400 Subject: avr32: struct old_sigaction is never used Signed-off-by: Al Viro --- arch/avr32/include/asm/signal.h | 7 ------- 1 file changed, 7 deletions(-) (limited to 'arch/avr32') diff --git a/arch/avr32/include/asm/signal.h b/arch/avr32/include/asm/signal.h index 8790dfc10d5b..ae56849fdb2b 100644 --- a/arch/avr32/include/asm/signal.h +++ b/arch/avr32/include/asm/signal.h @@ -115,13 +115,6 @@ typedef unsigned long sigset_t; #include #ifdef __KERNEL__ -struct old_sigaction { - __sighandler_t sa_handler; - old_sigset_t sa_mask; - unsigned long sa_flags; - __sigrestore_t sa_restorer; -}; - struct sigaction { __sighandler_t sa_handler; unsigned long sa_flags; -- cgit v1.2.3-58-ga151