2012-02-14 11:41:23

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 00/40] arch: set_current_blocked() and block_sigmask()

From: Matt Fleming <[email protected]>

This series simplifies the architecture code for handling signals by
making use of set_current_blocked() introduced in e6fa16ab ("signal:
sigprocmask() should do retarget_shared_pending()") and
block_sigmask() introduced in commit 5e6292c0f28f ("signal: add
block_sigmask() for adding sigmask to current->blocked").

A number of architectures have bugs in this code. Using the helper
functions should avoid this problem in the future.

Note that I've only been able to compile test the following,

- alpha
- arm
- m68k
- mips
- powerpc
- s390
- sh

and that I don't have the hardware to test any of these patches.

Unlike the previous versions of this series, these patches can be
taken through the arch maintainer's trees because the requisite patch
("signal: add block_sigmask() for adding sigmask to current->blocked")
went into v3.3-rc1.

Matt Fleming (39):
alpha: Use set_current_blocked() and block_sigmask()
arm: Use set_current_blocked() and block_sigmask()
avr32: Don't mask signals in the error path
avr32: Use block_sigmask()
blackfin: Use set_current_blocked() and block_sigmask()
C6X: Use set_current_blocked() and block_sigmask()
cris: Use set_current_blocked() and block_sigmask()
frv: Use set_current_blocked() and block_sigmask()
h8300: Use set_current_blocked() and block_sigmask()
Hexagon: Use set_current_blocked() and block_sigmask()
ia64: Use set_current_blocked() and block_sigmask()
m32r: Use set_current_blocked() and block_sigmask()
m68k: Use set_current_blocked() and block_sigmask()
microblaze: Don't reimplement force_sigsegv()
microblaze: No need to reset handler if SA_ONESHOT
microblaze: Fix signal masking
microblaze: Use set_current_blocked() and block_sigmask()
MIPS: Use set_current_blocked() and block_sigmask()
mn10300: Use set_current_blocked() and block_sigmask()
OpenRISC: Don't reimplement force_sigsegv()
OpenRISC: No need to reset handler if SA_ONESHOT
OpenRISC: Don't mask signals if we fail to setup signal stack
OpenRISC: Use set_current_blocked() and block_sigmask()
parisc: Use set_current_blocked() and block_sigmask()
powerpc: Use set_current_blocked() and block_sigmask()
[S390] Use block_sigmask()
score: Don't mask signals if we fail to setup signal stack
score: Use set_current_blocked() and block_sigmask()
sh: No need to reset handler if SA_ONESHOT
sh: Use set_current_blocked() and block_sigmask()
sparc: Use block_sigmask()
tile: Use set_current_blocked() and block_sigmask()
um: Don't restore current->blocked on error
um: Use set_current_blocked() and block_sigmask()
unicore32: Use block_sigmask()
xtensa: Don't reimplement force_sigsegv()
xtensa: No need to reset handler if SA_ONESHOT
xtensa: Don't mask signals if we fail to setup signal stack
xtensa: Use set_current_blocked() and block_sigmask()

Oleg Nesterov (1):
avr32: use set_current_blocked() in handle_signal/sys_rt_sigreturn

arch/alpha/kernel/signal.c | 31 ++++++++----------------
arch/arm/kernel/signal.c | 24 ++++++------------
arch/avr32/kernel/signal.c | 26 ++++++--------------
arch/blackfin/kernel/signal.c | 17 +++----------
arch/c6x/kernel/signal.c | 16 ++----------
arch/cris/arch-v10/kernel/signal.c | 34 +++++++++-----------------
arch/cris/arch-v32/kernel/signal.c | 37 ++++++++--------------------
arch/frv/kernel/signal.c | 32 ++++++++-----------------
arch/h8300/kernel/signal.c | 33 +++++++-------------------
arch/hexagon/kernel/signal.c | 12 +--------
arch/ia64/kernel/signal.c | 15 +----------
arch/m32r/kernel/signal.c | 12 +--------
arch/m68k/kernel/signal_mm.c | 22 +++++++----------
arch/m68k/kernel/signal_no.c | 28 +++++++---------------
arch/microblaze/kernel/signal.c | 42 +++++++++++++--------------------
arch/mips/kernel/signal.c | 27 ++++-----------------
arch/mips/kernel/signal32.c | 20 +++------------
arch/mips/kernel/signal_n32.c | 10 +------
arch/mn10300/kernel/signal.c | 32 ++++++++-----------------
arch/openrisc/kernel/signal.c | 45 +++++++++++++++--------------------
arch/parisc/kernel/signal.c | 12 +--------
arch/powerpc/kernel/signal.c | 13 +--------
arch/powerpc/kernel/signal_32.c | 11 ++++----
arch/s390/kernel/compat_signal.c | 6 +----
arch/s390/kernel/signal.c | 6 +----
arch/score/kernel/signal.c | 13 ++--------
arch/sh/kernel/signal_32.c | 35 ++++++++--------------------
arch/sh/kernel/signal_64.c | 40 ++++++++------------------------
arch/sparc/kernel/signal32.c | 7 +----
arch/sparc/kernel/signal_32.c | 7 +----
arch/sparc/kernel/signal_64.c | 6 +----
arch/tile/kernel/compat_signal.c | 5 +---
arch/tile/kernel/signal.c | 13 +--------
arch/um/kernel/signal.c | 26 +++++---------------
arch/unicore32/kernel/signal.c | 5 +---
arch/xtensa/kernel/signal.c | 35 ++++++++-------------------
36 files changed, 216 insertions(+), 539 deletions(-)

--
1.7.4.4


2012-02-14 11:41:30

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 03/40] avr32: Don't mask signals in the error path

From: Matt Fleming <[email protected]>

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 <[email protected]>
Acked-by: Havard Skinnemoen <[email protected]>
Acked-by: Oleg Nesterov <[email protected]>
Signed-off-by: Matt Fleming <[email protected]>
---
arch/avr32/kernel/signal.c | 25 ++++++++++++-------------
1 files changed, 12 insertions(+), 13 deletions(-)

diff --git a/arch/avr32/kernel/signal.c b/arch/avr32/kernel/signal.c
index 64f886f..9c075e1 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(&current->sighand->siglock);
- sigorsets(&current->blocked, &current->blocked,
- &ka->sa.sa_mask);
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked, &current->blocked,
+ &ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked, sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
-
- if (ret == 0)
- return;
-
- force_sigsegv(sig, current);
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
}

/*
--
1.7.4.4

2012-02-14 11:41:37

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 04/40] avr32: use set_current_blocked() in handle_signal/sys_rt_sigreturn

From: Oleg Nesterov <[email protected]>

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 <[email protected]>
Acked-by: Havard Skinnemoen <[email protected]>
Reviewed-by: Matt Fleming <[email protected]>
Signed-off-by: Oleg Nesterov <[email protected]>
---
arch/avr32/kernel/signal.c | 15 +++++----------
1 files changed, 5 insertions(+), 10 deletions(-)

diff --git a/arch/avr32/kernel/signal.c b/arch/avr32/kernel/signal.c
index 9c075e1..06f4293 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(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->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(&current->sighand->siglock);
- sigorsets(&current->blocked, &current->blocked,
- &ka->sa.sa_mask);
+ sigorsets(&blocked, &current->blocked, &ka->sa.sa_mask);
if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked, sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ sigaddset(&blocked, sig);
+ set_current_blocked(&blocked);
}

/*
--
1.7.4.4

2012-02-14 11:41:50

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 05/40] avr32: Use block_sigmask()

From: Matt Fleming <[email protected]>

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.

Cc: Oleg Nesterov <[email protected]>
Cc: Hans-Christian Egtvedt <[email protected]>
Cc: Havard Skinnemoen <[email protected]>
Signed-off-by: Matt Fleming <[email protected]>
---
arch/avr32/kernel/signal.c | 6 +-----
1 files changed, 1 insertions(+), 5 deletions(-)

diff --git a/arch/avr32/kernel/signal.c b/arch/avr32/kernel/signal.c
index 06f4293..feeb77b 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, &current->blocked, &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&blocked, sig);
- set_current_blocked(&blocked);
+ block_sigmask(ka, sig);
}

/*
--
1.7.4.4

2012-02-14 11:42:13

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 07/40] C6X: Use set_current_blocked() and block_sigmask()

From: Matt Fleming <[email protected]>

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.

Cc: Mark Salter <[email protected]>
Cc: Aurelien Jacquiot <[email protected]>
Cc: [email protected]
Cc: Oleg Nesterov <[email protected]>
Signed-off-by: Matt Fleming <[email protected]>
---
arch/c6x/kernel/signal.c | 16 +++-------------
1 files changed, 3 insertions(+), 13 deletions(-)

diff --git a/arch/c6x/kernel/signal.c b/arch/c6x/kernel/signal.c
index 304f675..3b5a050 100644
--- a/arch/c6x/kernel/signal.c
+++ b/arch/c6x/kernel/signal.c
@@ -85,10 +85,7 @@ asmlinkage int do_rt_sigreturn(struct pt_regs *regs)
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
goto badframe;
@@ -279,15 +276,8 @@ static int handle_signal(int sig,

/* Set up the stack frame */
ret = setup_rt_frame(sig, ka, info, oldset, regs);
- if (ret == 0) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked, &current->blocked,
- &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked, sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ if (ret == 0)
+ block_sigmask(ka, sig);

return ret;
}
--
1.7.4.4

2012-02-14 11:41:52

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 06/40] blackfin: Use set_current_blocked() and block_sigmask()

From: Matt Fleming <[email protected]>

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.

Cc: Oleg Nesterov <[email protected]>
Acked-by: Mike Frysinger <[email protected]>
Cc: [email protected]
Signed-off-by: Matt Fleming <[email protected]>
---
arch/blackfin/kernel/signal.c | 17 ++++-------------
1 files changed, 4 insertions(+), 13 deletions(-)

diff --git a/arch/blackfin/kernel/signal.c b/arch/blackfin/kernel/signal.c
index d536f35..05ece02 100644
--- a/arch/blackfin/kernel/signal.c
+++ b/arch/blackfin/kernel/signal.c
@@ -99,10 +99,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

if (rt_restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
goto badframe;
@@ -266,15 +263,9 @@ handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
/* set up the stack frame */
ret = setup_rt_frame(sig, ka, info, oldset, regs);

- if (ret == 0) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked, &current->blocked,
- &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked, sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ if (ret == 0)
+ block_sigmask(ka, sig);
+
return ret;
}

--
1.7.4.4

2012-02-14 11:42:28

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 10/40] h8300: Use set_current_blocked() and block_sigmask()

From: Matt Fleming <[email protected]>

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.

Cc: Oleg Nesterov <[email protected]>
Cc: Yoshinori Sato <[email protected]>
Signed-off-by: Matt Fleming <[email protected]>
---
arch/h8300/kernel/signal.c | 33 +++++++++------------------------
1 files changed, 9 insertions(+), 24 deletions(-)

diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c
index af842c3..cd63f5a 100644
--- a/arch/h8300/kernel/signal.c
+++ b/arch/h8300/kernel/signal.c
@@ -57,14 +57,13 @@ asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
asmlinkage int do_sigsuspend(struct pt_regs *regs)
{
old_sigset_t mask = regs->er3;
- sigset_t saveset;
+ sigset_t saveset, blocked;

- mask &= _BLOCKABLE;
- spin_lock_irq(&current->sighand->siglock);
saveset = current->blocked;
- siginitset(&current->blocked, mask);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+
+ mask &= _BLOCKABLE;
+ siginitset(&blocked, mask);
+ set_current_blocked(&blocked);

regs->er0 = -EINTR;
while (1) {
@@ -90,11 +89,8 @@ do_rt_sigsuspend(struct pt_regs *regs)
return -EFAULT;
sigdelsetmask(&newset, ~_BLOCKABLE);

- spin_lock_irq(&current->sighand->siglock);
saveset = current->blocked;
- current->blocked = newset;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&newset);

regs->er0 = -EINTR;
while (1) {
@@ -232,10 +228,7 @@ asmlinkage int do_sigreturn(unsigned long __unused,...)
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

if (restore_sigcontext(regs, &frame->sc, &er0))
goto badframe;
@@ -260,10 +253,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused,...)
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_unlock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_lock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &er0))
goto badframe;
@@ -489,12 +479,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
else
setup_frame(sig, ka, oldset, regs);

- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ block_sigmask(ka, sig);
}

/*
--
1.7.4.4

2012-02-14 11:42:40

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 15/40] microblaze: Don't reimplement force_sigsegv()

From: Matt Fleming <[email protected]>

Instead of open coding the sequence from force_sigsegv() just call
it. This also fixes a bug because we were modifying ka->sa.sa_handler
(which is a copy of sighand->action[]), whereas the intention of the
code was to modify sighand->action[] directly.

As the original code was working with a copy it had no effect on
signal delivery.

Acked-by: Oleg Nesterov <[email protected]>
Acked-by: Michal Simek <[email protected]>
Cc: [email protected]
Signed-off-by: Matt Fleming <[email protected]>
---
arch/microblaze/kernel/signal.c | 4 +---
1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c
index 5996711..90de06d 100644
--- a/arch/microblaze/kernel/signal.c
+++ b/arch/microblaze/kernel/signal.c
@@ -270,9 +270,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
return;

give_sigsegv:
- if (sig == SIGSEGV)
- ka->sa.sa_handler = SIG_DFL;
- force_sig(SIGSEGV, current);
+ force_sigsegv(sig, current);
}

/* Handle restarting system calls */
--
1.7.4.4

2012-02-14 11:42:47

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 19/40] MIPS: Use set_current_blocked() and block_sigmask()

From: Matt Fleming <[email protected]>

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.

Cc: Oleg Nesterov <[email protected]>
Acked-by: Ralf Baechle <[email protected]>
Cc: Al Viro <[email protected]>
Cc: David Daney <[email protected]>
Cc: [email protected]
Signed-off-by: Matt Fleming <[email protected]>
---
arch/mips/kernel/signal.c | 27 +++++----------------------
arch/mips/kernel/signal32.c | 20 ++++----------------
arch/mips/kernel/signal_n32.c | 10 ++--------
3 files changed, 11 insertions(+), 46 deletions(-)

diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index f852400..76084cc 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -256,11 +256,8 @@ asmlinkage int sys_sigsuspend(nabi_no_regargs struct pt_regs regs)
return -EFAULT;
sigdelsetmask(&newset, ~_BLOCKABLE);

- spin_lock_irq(&current->sighand->siglock);
current->saved_sigmask = current->blocked;
- current->blocked = newset;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&newset);

current->state = TASK_INTERRUPTIBLE;
schedule();
@@ -285,11 +282,8 @@ asmlinkage int sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
return -EFAULT;
sigdelsetmask(&newset, ~_BLOCKABLE);

- spin_lock_irq(&current->sighand->siglock);
current->saved_sigmask = current->blocked;
- current->blocked = newset;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&newset);

current->state = TASK_INTERRUPTIBLE;
schedule();
@@ -361,10 +355,7 @@ asmlinkage void sys_sigreturn(nabi_no_regargs struct pt_regs regs)
goto badframe;

sigdelsetmask(&blocked, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = blocked;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&blocked);

sig = restore_sigcontext(&regs, &frame->sf_sc);
if (sig < 0)
@@ -400,10 +391,7 @@ asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

sig = restore_sigcontext(&regs, &frame->rs_uc.uc_mcontext);
if (sig < 0)
@@ -579,12 +567,7 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
if (ret)
return ret;

- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked, sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ block_sigmask(ka, sig);

return ret;
}
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index aae9866..902a889 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -290,11 +290,8 @@ asmlinkage int sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
return -EFAULT;
sigdelsetmask(&newset, ~_BLOCKABLE);

- spin_lock_irq(&current->sighand->siglock);
current->saved_sigmask = current->blocked;
- current->blocked = newset;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&newset);

current->state = TASK_INTERRUPTIBLE;
schedule();
@@ -318,11 +315,8 @@ asmlinkage int sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
return -EFAULT;
sigdelsetmask(&newset, ~_BLOCKABLE);

- spin_lock_irq(&current->sighand->siglock);
current->saved_sigmask = current->blocked;
- current->blocked = newset;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&newset);

current->state = TASK_INTERRUPTIBLE;
schedule();
@@ -488,10 +482,7 @@ asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
goto badframe;

sigdelsetmask(&blocked, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = blocked;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&blocked);

sig = restore_sigcontext32(&regs, &frame->sf_sc);
if (sig < 0)
@@ -529,10 +520,7 @@ asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

sig = restore_sigcontext32(&regs, &frame->rs_uc.uc_mcontext);
if (sig < 0)
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c
index ee24d81..30fc7ff 100644
--- a/arch/mips/kernel/signal_n32.c
+++ b/arch/mips/kernel/signal_n32.c
@@ -94,11 +94,8 @@ asmlinkage int sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
sigset_from_compat(&newset, &uset);
sigdelsetmask(&newset, ~_BLOCKABLE);

- spin_lock_irq(&current->sighand->siglock);
current->saved_sigmask = current->blocked;
- current->blocked = newset;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&newset);

current->state = TASK_INTERRUPTIBLE;
schedule();
@@ -122,10 +119,7 @@ asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

sig = restore_sigcontext(&regs, &frame->rs_uc.uc_mcontext);
if (sig < 0)
--
1.7.4.4

2012-02-14 11:42:59

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 20/40] mn10300: Use set_current_blocked() and block_sigmask()

From: Matt Fleming <[email protected]>

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.

Cc: Oleg Nesterov <[email protected]>
Cc: David Howells <[email protected]>
Cc: Koichi Yasutake <[email protected]>
Cc: Al Viro <[email protected]>
Cc: [email protected]
Signed-off-by: Matt Fleming <[email protected]>
---
arch/mn10300/kernel/signal.c | 32 ++++++++++----------------------
1 files changed, 10 insertions(+), 22 deletions(-)

diff --git a/arch/mn10300/kernel/signal.c b/arch/mn10300/kernel/signal.c
index 690f4e9..bd77c6d 100644
--- a/arch/mn10300/kernel/signal.c
+++ b/arch/mn10300/kernel/signal.c
@@ -38,12 +38,13 @@
*/
asmlinkage long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
{
- mask &= _BLOCKABLE;
- spin_lock_irq(&current->sighand->siglock);
+ sigset_t blocked;
+
current->saved_sigmask = current->blocked;
- siginitset(&current->blocked, mask);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+
+ mask &= _BLOCKABLE;
+ siginitset(&blocked, mask);
+ set_current_blocked(&blocked);

current->state = TASK_INTERRUPTIBLE;
schedule();
@@ -172,10 +173,7 @@ asmlinkage long sys_sigreturn(void)
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

if (restore_sigcontext(current_frame(), &frame->sc, &d0))
goto badframe;
@@ -203,10 +201,7 @@ asmlinkage long sys_rt_sigreturn(void)
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

if (restore_sigcontext(current_frame(), &frame->uc.uc_mcontext, &d0))
goto badframe;
@@ -476,15 +471,8 @@ static int handle_signal(int sig,
else
ret = setup_frame(sig, ka, oldset, regs);

- if (ret == 0) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked, &current->blocked,
- &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked, sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ if (ret == 0)
+ block_sigmask(ka, sig);

return ret;
}
--
1.7.4.4

2012-02-14 11:42:45

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 17/40] microblaze: Fix signal masking

From: Matt Fleming <[email protected]>

There are a couple of problems with the current signal code,

1. If we failed to setup the signal stack frame then we
should not be masking any signals.

2. ka->sa.sa_mask is only added to the current blocked signals list if
SA_NODEFER is set in ka->sa.sa_flags. If we successfully setup the
signal frame and are going to run the handler then we must honour
sa_mask.

Acked-by: Oleg Nesterov <[email protected]>
Acked-by: Michal Simek <[email protected]>
Cc: [email protected]
Signed-off-by: Matt Fleming <[email protected]>
---
arch/microblaze/kernel/signal.c | 31 ++++++++++++++++++-------------
1 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c
index 9e749c0..f2c13d5 100644
--- a/arch/microblaze/kernel/signal.c
+++ b/arch/microblaze/kernel/signal.c
@@ -169,7 +169,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
return (void __user *)((sp - frame_size) & -8UL);
}

-static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs *regs)
{
struct rt_sigframe __user *frame;
@@ -267,10 +267,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
current->comm, current->pid, frame, regs->pc);
#endif

- return;
+ return 0;

give_sigsegv:
force_sigsegv(sig, current);
+ return -EFAULT;
}

/* Handle restarting system calls */
@@ -314,21 +315,25 @@ static int
handle_signal(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
{
+ int ret;
+
/* Set up the stack frame */
if (ka->sa.sa_flags & SA_SIGINFO)
- setup_rt_frame(sig, ka, info, oldset, regs);
+ ret = setup_rt_frame(sig, ka, info, oldset, regs);
else
- setup_rt_frame(sig, ka, NULL, oldset, regs);
+ ret = setup_rt_frame(sig, ka, NULL, oldset, regs);
+
+ if (ret)
+ return ret;

- if (!(ka->sa.sa_flags & SA_NODEFER)) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,
- &current->blocked, &ka->sa.sa_mask);
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked, sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
- return 1;
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+
+ return 0;
}

/*
@@ -369,7 +374,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall)
/* Whee! Actually deliver the signal. */
if (in_syscall)
handle_restart(regs, &ka, 1);
- if (handle_signal(signr, &ka, &info, oldset, regs)) {
+ if (!handle_signal(signr, &ka, &info, oldset, regs)) {
/*
* A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
--
1.7.4.4

2012-02-14 11:43:10

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 21/40] OpenRISC: Don't reimplement force_sigsegv()

From: Matt Fleming <[email protected]>

Instead of open coding the sequence from force_sigsegv() just call
it. This also fixes a bug because we were modifying ka->sa.sa_handler
(which is a copy of sighand->action[]), whereas the intention of the
code was to modify sighand->action[] directly.

As the original code was working with a copy it had no effect on
signal delivery.

Acked-by: Oleg Nesterov <[email protected]>
Cc: Jonas Bonn <[email protected]>
Cc: Arnd Bergmann <[email protected]>
Cc: [email protected]
Signed-off-by: Matt Fleming <[email protected]>
---
arch/openrisc/kernel/signal.c | 4 +---
1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/arch/openrisc/kernel/signal.c b/arch/openrisc/kernel/signal.c
index 95207ab..53741ba 100644
--- a/arch/openrisc/kernel/signal.c
+++ b/arch/openrisc/kernel/signal.c
@@ -250,9 +250,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
return;

give_sigsegv:
- if (sig == SIGSEGV)
- ka->sa.sa_handler = SIG_DFL;
- force_sig(SIGSEGV, current);
+ force_sigsegv(sig, current);
}

static inline void
--
1.7.4.4

2012-02-14 11:43:27

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 25/40] parisc: Use set_current_blocked() and block_sigmask()

From: Matt Fleming <[email protected]>

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.

Cc: Oleg Nesterov <[email protected]>
Cc: Kyle McMartin <[email protected]>
Cc: Helge Deller <[email protected]>
Cc: "James E.J. Bottomley" <[email protected]>
Cc: [email protected]
Signed-off-by: Matt Fleming <[email protected]>
---
arch/parisc/kernel/signal.c | 12 ++----------
1 files changed, 2 insertions(+), 10 deletions(-)

diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
index 12c1ed3..bd36152 100644
--- a/arch/parisc/kernel/signal.c
+++ b/arch/parisc/kernel/signal.c
@@ -131,10 +131,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
}

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

/* Good thing we saved the old gr[30], eh? */
#ifdef CONFIG_64BIT
@@ -454,12 +451,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))
return 0;

- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ block_sigmask(ka, sig);

tracehook_signal_handler(sig, info, ka, regs,
test_thread_flag(TIF_SINGLESTEP) ||
--
1.7.4.4

2012-02-14 11:43:25

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 26/40] powerpc: Use set_current_blocked() and block_sigmask()

From: Matt Fleming <[email protected]>

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.

Cc: Oleg Nesterov <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: [email protected]
Signed-off-by: Matt Fleming <[email protected]>
---
arch/powerpc/kernel/signal.c | 13 ++-----------
arch/powerpc/kernel/signal_32.c | 11 ++++++-----
2 files changed, 8 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c
index 2300426..3867f7b 100644
--- a/arch/powerpc/kernel/signal.c
+++ b/arch/powerpc/kernel/signal.c
@@ -56,10 +56,7 @@ void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
void restore_sigmask(sigset_t *set)
{
sigdelsetmask(set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = *set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(set);
}

static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
@@ -167,13 +164,7 @@ static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs)

regs->trap = 0;
if (ret) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked, &current->blocked,
- &ka.sa.sa_mask);
- if (!(ka.sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked, signr);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ block_sigmask(&ka, signr);

/*
* A signal was successfully delivered; the saved sigmask is in
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 836a5a1..e061ef5 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -242,12 +242,13 @@ static inline int restore_general_regs(struct pt_regs *regs,
*/
long sys_sigsuspend(old_sigset_t mask)
{
- mask &= _BLOCKABLE;
- spin_lock_irq(&current->sighand->siglock);
+ sigset_t blocked;
+
current->saved_sigmask = current->blocked;
- siginitset(&current->blocked, mask);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+
+ mask &= _BLOCKABLE;
+ siginitset(&blocked, mask);
+ set_current_blocked(&blocked);

current->state = TASK_INTERRUPTIBLE;
schedule();
--
1.7.4.4

2012-02-14 11:43:45

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 28/40] score: Don't mask signals if we fail to setup signal stack

From: Matt Fleming <[email protected]>

If setup_rt_frame() returns -EFAULT then we must not block any signals
in the current process.

Acked-by: Oleg Nesterov <[email protected]>
Cc: Chen Liqin <[email protected]>
Cc: Lennox Wu <[email protected]>
Signed-off-by: Matt Fleming <[email protected]>
---
arch/score/kernel/signal.c | 14 ++++++++------
1 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/arch/score/kernel/signal.c b/arch/score/kernel/signal.c
index aa57440..bf9e33e 100644
--- a/arch/score/kernel/signal.c
+++ b/arch/score/kernel/signal.c
@@ -272,12 +272,14 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
*/
ret = setup_rt_frame(ka, regs, sig, oldset, info);

- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked, sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ if (ret == 0) {
+ spin_lock_irq(&current->sighand->siglock);
+ sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
+ sigaddset(&current->blocked, sig);
+ recalc_sigpending();
+ spin_unlock_irq(&current->sighand->siglock);
+ }

return ret;
}
--
1.7.4.4

2012-02-14 11:43:57

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 29/40] score: Use set_current_blocked() and block_sigmask()

From: Matt Fleming <[email protected]>

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.

Cc: Oleg Nesterov <[email protected]>
Cc: Chen Liqin <[email protected]>
Cc: Lennox Wu <[email protected]>
Signed-off-by: Matt Fleming <[email protected]>
---
arch/score/kernel/signal.c | 15 +++------------
1 files changed, 3 insertions(+), 12 deletions(-)

diff --git a/arch/score/kernel/signal.c b/arch/score/kernel/signal.c
index bf9e33e..5a5bd17 100644
--- a/arch/score/kernel/signal.c
+++ b/arch/score/kernel/signal.c
@@ -159,10 +159,7 @@ score_rt_sigreturn(struct pt_regs *regs)
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

sig = restore_sigcontext(regs, &frame->rs_uc.uc_mcontext);
if (sig < 0)
@@ -272,14 +269,8 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
*/
ret = setup_rt_frame(ka, regs, sig, oldset, info);

- if (ret == 0) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked, sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ if (ret == 0)
+ block_sigmask(ka, sig);

return ret;
}
--
1.7.4.4

2012-02-14 11:44:08

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 36/40] unicore32: Use block_sigmask()

From: Matt Fleming <[email protected]>

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.

Cc: Oleg Nesterov <[email protected]>
Acked-by: Guan Xuetao <[email protected]>
Signed-off-by: Matt Fleming <[email protected]>
---
arch/unicore32/kernel/signal.c | 5 +----
1 files changed, 1 insertions(+), 4 deletions(-)

diff --git a/arch/unicore32/kernel/signal.c b/arch/unicore32/kernel/signal.c
index 911b549..72d9531 100644
--- a/arch/unicore32/kernel/signal.c
+++ b/arch/unicore32/kernel/signal.c
@@ -370,10 +370,7 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
/*
* Block the signal if we were successful.
*/
- sigorsets(&blocked, &tsk->blocked, &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&blocked, sig);
- set_current_blocked(&blocked);
+ block_sigmask(ka, sig);

return 0;
}
--
1.7.4.4

2012-02-14 11:44:05

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 37/40] xtensa: Don't reimplement force_sigsegv()

From: Matt Fleming <[email protected]>

Instead of open coding the sequence from force_sigsegv() just call
it. This also fixes a bug because we were modifying ka->sa.sa_handler
(which is a copy of sighand->action[]), whereas the intention of the
code was to modify sighand->action[] directly.

As the original code was working with a copy it had no effect on
signal delivery.

Acked-by: Oleg Nesterov <[email protected]>
Cc: Chris Zankel <[email protected]>
Signed-off-by: Matt Fleming <[email protected]>
---
arch/xtensa/kernel/signal.c | 4 +---
1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c
index f2220b5..4f53770 100644
--- a/arch/xtensa/kernel/signal.c
+++ b/arch/xtensa/kernel/signal.c
@@ -425,9 +425,7 @@ static void setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
return;

give_sigsegv:
- if (sig == SIGSEGV)
- ka->sa.sa_handler = SIG_DFL;
- force_sig(SIGSEGV, current);
+ force_sigsegv(sig, current);
}

/*
--
1.7.4.4

2012-02-14 11:44:23

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 40/40] xtensa: Use set_current_blocked() and block_sigmask()

From: Matt Fleming <[email protected]>

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.

Cc: Oleg Nesterov <[email protected]>
Cc: Chris Zankel <[email protected]>
Signed-off-by: Matt Fleming <[email protected]>
---
arch/xtensa/kernel/signal.c | 17 +++--------------
1 files changed, 3 insertions(+), 14 deletions(-)

diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c
index 17ceab8..b69b000 100644
--- a/arch/xtensa/kernel/signal.c
+++ b/arch/xtensa/kernel/signal.c
@@ -260,10 +260,7 @@ asmlinkage long xtensa_rt_sigreturn(long a0, long a1, long a2, long a3,
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

if (restore_sigcontext(regs, frame))
goto badframe;
@@ -448,11 +445,8 @@ asmlinkage long xtensa_rt_sigsuspend(sigset_t __user *unewset,
return -EFAULT;

sigdelsetmask(&newset, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
saveset = current->blocked;
- current->blocked = newset;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&newset);

regs->areg[2] = -EINTR;
while (1) {
@@ -539,12 +533,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
if (ret)
return ret;

- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked, &current->blocked, &ka.sa.sa_mask);
- if (!(ka.sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked, signr);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ block_sigmask(&ka, signr);
if (current->ptrace & PT_SINGLESTEP)
task_pt_regs(current)->icountlevel = 1;

--
1.7.4.4

2012-02-14 11:44:44

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 39/40] xtensa: Don't mask signals if we fail to setup signal stack

From: Matt Fleming <[email protected]>

setup_frame() needs to return an indication of whether it succeeded or
failed in setting up the signal stack frame. If setup_frame() fails
then we must not modify current->blocked.

Acked-by: Oleg Nesterov <[email protected]>
Cc: Chris Zankel <[email protected]>
Signed-off-by: Matt Fleming <[email protected]>
---
arch/xtensa/kernel/signal.c | 11 +++++++----
1 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c
index 24655e3..17ceab8 100644
--- a/arch/xtensa/kernel/signal.c
+++ b/arch/xtensa/kernel/signal.c
@@ -336,8 +336,8 @@ gen_return_code(unsigned char *codemem)
}


-static void setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
+static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ sigset_t *set, struct pt_regs *regs)
{
struct rt_sigframe *frame;
int err = 0;
@@ -422,10 +422,11 @@ static void setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
current->comm, current->pid, signal, frame, regs->pc);
#endif

- return;
+ return 0;

give_sigsegv:
force_sigsegv(sig, current);
+ return -EFAULT;
}

/*
@@ -534,7 +535,9 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)

/* Whee! Actually deliver the signal. */
/* Set up the stack frame */
- setup_frame(signr, &ka, &info, oldset, regs);
+ ret = setup_frame(signr, &ka, &info, oldset, regs);
+ if (ret)
+ return ret;

spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked, &current->blocked, &ka.sa.sa_mask);
--
1.7.4.4

2012-02-14 11:44:01

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 32/40] sparc: Use block_sigmask()

From: Matt Fleming <[email protected]>

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.

Cc: Oleg Nesterov <[email protected]>
Cc: "David S. Miller" <[email protected]>
Cc: [email protected]
Signed-off-by: Matt Fleming <[email protected]>
---
arch/sparc/kernel/signal32.c | 7 +------
arch/sparc/kernel/signal_32.c | 7 +------
arch/sparc/kernel/signal_64.c | 6 +-----
3 files changed, 3 insertions(+), 17 deletions(-)

diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c
index 023b886..c8f5b50 100644
--- a/arch/sparc/kernel/signal32.c
+++ b/arch/sparc/kernel/signal32.c
@@ -776,7 +776,6 @@ static inline int handle_signal32(unsigned long signr, struct k_sigaction *ka,
siginfo_t *info,
sigset_t *oldset, struct pt_regs *regs)
{
- sigset_t blocked;
int err;

if (ka->sa.sa_flags & SA_SIGINFO)
@@ -787,11 +786,7 @@ static inline int handle_signal32(unsigned long signr, struct k_sigaction *ka,
if (err)
return err;

- sigorsets(&blocked, &current->blocked, &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NOMASK))
- sigaddset(&blocked, signr);
- set_current_blocked(&blocked);
-
+ block_sigmask(ka, signr);
tracehook_signal_handler(signr, info, ka, regs, 0);

return 0;
diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c
index d54c6e5..7bb71b6 100644
--- a/arch/sparc/kernel/signal_32.c
+++ b/arch/sparc/kernel/signal_32.c
@@ -465,7 +465,6 @@ static inline int
handle_signal(unsigned long signr, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
{
- sigset_t blocked;
int err;

if (ka->sa.sa_flags & SA_SIGINFO)
@@ -476,11 +475,7 @@ handle_signal(unsigned long signr, struct k_sigaction *ka,
if (err)
return err;

- sigorsets(&blocked, &current->blocked, &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NOMASK))
- sigaddset(&blocked, signr);
- set_current_blocked(&blocked);
-
+ block_sigmask(ka, signr);
tracehook_signal_handler(signr, info, ka, regs, 0);

return 0;
diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c
index f0836cd..d8a67e6 100644
--- a/arch/sparc/kernel/signal_64.c
+++ b/arch/sparc/kernel/signal_64.c
@@ -479,18 +479,14 @@ static inline int handle_signal(unsigned long signr, struct k_sigaction *ka,
siginfo_t *info,
sigset_t *oldset, struct pt_regs *regs)
{
- sigset_t blocked;
int err;

err = setup_rt_frame(ka, regs, signr, oldset,
(ka->sa.sa_flags & SA_SIGINFO) ? info : NULL);
if (err)
return err;
- sigorsets(&blocked, &current->blocked, &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NOMASK))
- sigaddset(&blocked, signr);
- set_current_blocked(&blocked);

+ block_sigmask(ka, signr);
tracehook_signal_handler(signr, info, ka, regs, 0);

return 0;
--
1.7.4.4

2012-02-14 11:44:59

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 38/40] xtensa: No need to reset handler if SA_ONESHOT

From: Matt Fleming <[email protected]>

get_signal_to_deliver() already resets the signal handler if
SA_ONESHOT is set in ka->sa.sa_flags, there's no need to do it again
in handle_signal(). Furthermore, because we were modifying
ka->sa.sa_handler (which is a copy of sighand->action[]) instead of
sighand->action[] the original code actually had no effect on signal
delivery.

Acked-by: Oleg Nesterov <[email protected]>
Cc: Chris Zankel <[email protected]>
Signed-off-by: Matt Fleming <[email protected]>
---
arch/xtensa/kernel/signal.c | 3 ---
1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c
index 4f53770..24655e3 100644
--- a/arch/xtensa/kernel/signal.c
+++ b/arch/xtensa/kernel/signal.c
@@ -536,9 +536,6 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
/* Set up the stack frame */
setup_frame(signr, &ka, &info, oldset, regs);

- if (ka.sa.sa_flags & SA_ONESHOT)
- ka.sa.sa_handler = SIG_DFL;
-
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked, &current->blocked, &ka.sa.sa_mask);
if (!(ka.sa.sa_flags & SA_NODEFER))
--
1.7.4.4

2012-02-14 11:45:40

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 35/40] um: Use set_current_blocked() and block_sigmask()

From: Matt Fleming <[email protected]>

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.

Cc: Oleg Nesterov <[email protected]>
Cc: Richard Weinberger <[email protected]>
Cc: [email protected]
Signed-off-by: Matt Fleming <[email protected]>
---
arch/um/kernel/signal.c | 20 ++++++--------------
1 files changed, 6 insertions(+), 14 deletions(-)

diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c
index 8382e0b..fb12f4c 100644
--- a/arch/um/kernel/signal.c
+++ b/arch/um/kernel/signal.c
@@ -67,15 +67,8 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,

if (err)
force_sigsegv(signr, current);
- else {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked, &current->blocked,
- &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked, signr);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ else
+ block_sigmask(ka, signr);

return err;
}
@@ -158,12 +151,11 @@ int do_signal(void)
*/
long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
{
+ sigset_t blocked;
+
mask &= _BLOCKABLE;
- spin_lock_irq(&current->sighand->siglock);
- current->saved_sigmask = current->blocked;
- siginitset(&current->blocked, mask);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ siginitset(&blocked, mask);
+ set_current_blocked(&blocked);

current->state = TASK_INTERRUPTIBLE;
schedule();
--
1.7.4.4

2012-02-14 11:45:53

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 34/40] um: Don't restore current->blocked on error

From: Matt Fleming <[email protected]>

If we fail to setup the signal stack frame then we don't need to
restore current->blocked because it is not modified by
setup_signal_stack_*.

Acked-by: Oleg Nesterov <[email protected]>
Acked-by: Richard Weinberger <[email protected]>
Tested-by: Richard Weinberger <[email protected]>
Cc: [email protected]
Signed-off-by: Matt Fleming <[email protected]>
---
arch/um/kernel/signal.c | 8 ++------
1 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/arch/um/kernel/signal.c b/arch/um/kernel/signal.c
index e8b889d..8382e0b 100644
--- a/arch/um/kernel/signal.c
+++ b/arch/um/kernel/signal.c
@@ -65,13 +65,9 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
#endif
err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset);

- if (err) {
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = *oldset;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ if (err)
force_sigsegv(signr, current);
- } else {
+ else {
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked, &current->blocked,
&ka->sa.sa_mask);
--
1.7.4.4

2012-02-14 11:46:10

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 33/40] tile: Use set_current_blocked() and block_sigmask()

From: Matt Fleming <[email protected]>

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.

Cc: Oleg Nesterov <[email protected]>
Cc: Arnd Bergmann <[email protected]>
Cc: Chris Metcalf <[email protected]>
Signed-off-by: Matt Fleming <[email protected]>
---
arch/tile/kernel/compat_signal.c | 5 +----
arch/tile/kernel/signal.c | 13 ++-----------
2 files changed, 3 insertions(+), 15 deletions(-)

diff --git a/arch/tile/kernel/compat_signal.c b/arch/tile/kernel/compat_signal.c
index a7869ad..77763cc 100644
--- a/arch/tile/kernel/compat_signal.c
+++ b/arch/tile/kernel/compat_signal.c
@@ -303,10 +303,7 @@ long compat_sys_rt_sigreturn(struct pt_regs *regs)
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
goto badframe;
diff --git a/arch/tile/kernel/signal.c b/arch/tile/kernel/signal.c
index bedaf4e..f79d4b8 100644
--- a/arch/tile/kernel/signal.c
+++ b/arch/tile/kernel/signal.c
@@ -97,10 +97,7 @@ SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs)
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
goto badframe;
@@ -286,13 +283,7 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
* the work_pending path in the return-to-user code, and
* either way we can re-enable interrupts unconditionally.
*/
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,
- &current->blocked, &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked, sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ block_sigmask(ka, sig);
}

return ret;
--
1.7.4.4

2012-02-14 11:46:31

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 31/40] sh: Use set_current_blocked() and block_sigmask()

From: Matt Fleming <[email protected]>

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.

Cc: Oleg Nesterov <[email protected]>
Cc: Paul Mundt <[email protected]>
Cc: [email protected]
Signed-off-by: Matt Fleming <[email protected]>
---
arch/sh/kernel/signal_32.c | 32 ++++++++++----------------------
arch/sh/kernel/signal_64.c | 37 ++++++++++---------------------------
2 files changed, 20 insertions(+), 49 deletions(-)

diff --git a/arch/sh/kernel/signal_32.c b/arch/sh/kernel/signal_32.c
index 1055146..883d711 100644
--- a/arch/sh/kernel/signal_32.c
+++ b/arch/sh/kernel/signal_32.c
@@ -58,12 +58,13 @@ sys_sigsuspend(old_sigset_t mask,
unsigned long r5, unsigned long r6, unsigned long r7,
struct pt_regs __regs)
{
- mask &= _BLOCKABLE;
- spin_lock_irq(&current->sighand->siglock);
+ sigset_t blocked;
+
current->saved_sigmask = current->blocked;
- siginitset(&current->blocked, mask);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+
+ mask &= _BLOCKABLE;
+ siginitset(&blocked, mask);
+ set_current_blocked(&blocked);

current->state = TASK_INTERRUPTIBLE;
schedule();
@@ -240,11 +241,7 @@ asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5,
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
-
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

if (restore_sigcontext(regs, &frame->sc, &r0))
goto badframe;
@@ -274,10 +271,7 @@ asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
goto badframe;
@@ -548,14 +542,8 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
else
ret = setup_frame(sig, ka, oldset, regs);

- if (ret == 0) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ if (ret == 0)
+ block_sigmask(ka, sig);

return ret;
}
diff --git a/arch/sh/kernel/signal_64.c b/arch/sh/kernel/signal_64.c
index 7b9278d..3c9a6f7 100644
--- a/arch/sh/kernel/signal_64.c
+++ b/arch/sh/kernel/signal_64.c
@@ -159,14 +159,13 @@ sys_sigsuspend(old_sigset_t mask,
unsigned long r6, unsigned long r7,
struct pt_regs * regs)
{
- sigset_t saveset;
+ sigset_t saveset, blocked;

- mask &= _BLOCKABLE;
- spin_lock_irq(&current->sighand->siglock);
saveset = current->blocked;
- siginitset(&current->blocked, mask);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+
+ mask &= _BLOCKABLE;
+ siginitset(&blocked, mask);
+ set_current_blocked(&blocked);

REF_REG_RET = -EINTR;
while (1) {
@@ -198,11 +197,8 @@ sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize,
if (copy_from_user(&newset, unewset, sizeof(newset)))
return -EFAULT;
sigdelsetmask(&newset, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
saveset = current->blocked;
- current->blocked = newset;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&newset);

REF_REG_RET = -EINTR;
while (1) {
@@ -408,11 +404,7 @@ asmlinkage int sys_sigreturn(unsigned long r2, unsigned long r3,
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
-
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

if (restore_sigcontext(regs, &frame->sc, &ret))
goto badframe;
@@ -445,10 +437,7 @@ asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3,
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ret))
goto badframe;
@@ -734,14 +723,8 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
else
ret = setup_frame(sig, ka, oldset, regs);

- if (ret == 0) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ if (ret == 0)
+ block_sigmask(ka, sig);

return ret;
}
--
1.7.4.4

2012-02-14 11:43:20

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 22/40] OpenRISC: No need to reset handler if SA_ONESHOT

From: Matt Fleming <[email protected]>

get_signal_to_deliver() already resets the signal handler if
SA_ONESHOT is set in ka->sa.sa_flags, there's no need to do it again
in handle_signal(). Furthermore, because we were modifying
ka->sa.sa_handler (which is a copy of sighand->action[]) instead of
sighand->action[] the original code actually had no effect on signal
delivery.

Acked-by: Oleg Nesterov <[email protected]>
Cc: Jonas Bonn <[email protected]>
Cc: Arnd Bergmann <[email protected]>
Cc: [email protected]
Signed-off-by: Matt Fleming <[email protected]>
---
arch/openrisc/kernel/signal.c | 3 ---
1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/arch/openrisc/kernel/signal.c b/arch/openrisc/kernel/signal.c
index 53741ba..92d2218 100644
--- a/arch/openrisc/kernel/signal.c
+++ b/arch/openrisc/kernel/signal.c
@@ -260,9 +260,6 @@ handle_signal(unsigned long sig,
{
setup_rt_frame(sig, ka, info, oldset, regs);

- if (ka->sa.sa_flags & SA_ONESHOT)
- ka->sa.sa_handler = SIG_DFL;
-
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
if (!(ka->sa.sa_flags & SA_NODEFER))
--
1.7.4.4

2012-02-14 11:47:08

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 27/40] [S390] Use block_sigmask()

From: Matt Fleming <[email protected]>

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.

Cc: Oleg Nesterov <[email protected]>
Acked-by: Martin Schwidefsky <[email protected]>
Cc: Heiko Carstens <[email protected]>
Cc: [email protected]
Signed-off-by: Matt Fleming <[email protected]>
---
arch/s390/kernel/compat_signal.c | 6 +-----
arch/s390/kernel/signal.c | 6 +-----
2 files changed, 2 insertions(+), 10 deletions(-)

diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index 6fe78c2..53a82c8 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -581,7 +581,6 @@ give_sigsegv:
int handle_signal32(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
{
- sigset_t blocked;
int ret;

/* Set up the stack frame */
@@ -591,10 +590,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
ret = setup_frame32(sig, ka, oldset, regs);
if (ret)
return ret;
- sigorsets(&blocked, &current->blocked, &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&blocked, sig);
- set_current_blocked(&blocked);
+ block_sigmask(ka, sig);
return 0;
}

diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index a8ba840..c4f5790 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -385,7 +385,6 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset,
struct pt_regs *regs)
{
- sigset_t blocked;
int ret;

/* Set up the stack frame */
@@ -395,10 +394,7 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
ret = setup_frame(sig, ka, oldset, regs);
if (ret)
return ret;
- sigorsets(&blocked, &current->blocked, &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&blocked, sig);
- set_current_blocked(&blocked);
+ block_sigmask(ka, sig);
return 0;
}

--
1.7.4.4

2012-02-14 11:46:49

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 30/40] sh: No need to reset handler if SA_ONESHOT

From: Matt Fleming <[email protected]>

get_signal_to_deliver() already resets the signal handler if
SA_ONESHOT is set in ka->sa.sa_flags, there's no need to do it again
in handle_signal(). Furthermore, because we were modifying
ka->sa.sa_handler (which is a copy of sighand->action[]) instead of
sighand->action[] the original code had no effect on signal delivery.

Acked-by: Oleg Nesterov <[email protected]>
Cc: Paul Mundt <[email protected]>
Cc: [email protected]
Signed-off-by: Matt Fleming <[email protected]>
---
arch/sh/kernel/signal_32.c | 3 ---
arch/sh/kernel/signal_64.c | 3 ---
2 files changed, 0 insertions(+), 6 deletions(-)

diff --git a/arch/sh/kernel/signal_32.c b/arch/sh/kernel/signal_32.c
index a7a55ed..1055146 100644
--- a/arch/sh/kernel/signal_32.c
+++ b/arch/sh/kernel/signal_32.c
@@ -548,9 +548,6 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
else
ret = setup_frame(sig, ka, oldset, regs);

- if (ka->sa.sa_flags & SA_ONESHOT)
- ka->sa.sa_handler = SIG_DFL;
-
if (ret == 0) {
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
diff --git a/arch/sh/kernel/signal_64.c b/arch/sh/kernel/signal_64.c
index 6b5603f..7b9278d 100644
--- a/arch/sh/kernel/signal_64.c
+++ b/arch/sh/kernel/signal_64.c
@@ -734,9 +734,6 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
else
ret = setup_frame(sig, ka, oldset, regs);

- if (ka->sa.sa_flags & SA_ONESHOT)
- ka->sa.sa_handler = SIG_DFL;
-
if (ret == 0) {
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
--
1.7.4.4

2012-02-14 11:47:32

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 24/40] OpenRISC: Use set_current_blocked() and block_sigmask()

From: Matt Fleming <[email protected]>

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.

Cc: Oleg Nesterov <[email protected]>
Cc: Jonas Bonn <[email protected]>
Cc: Arnd Bergmann <[email protected]>
Cc: [email protected]
Signed-off-by: Matt Fleming <[email protected]>
---
arch/openrisc/kernel/signal.c | 13 ++-----------
1 files changed, 2 insertions(+), 11 deletions(-)

diff --git a/arch/openrisc/kernel/signal.c b/arch/openrisc/kernel/signal.c
index 14764e8..cf35ea0 100644
--- a/arch/openrisc/kernel/signal.c
+++ b/arch/openrisc/kernel/signal.c
@@ -102,10 +102,7 @@ asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs)
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
goto badframe;
@@ -265,13 +262,7 @@ handle_signal(unsigned long sig,
if (ret)
return ret;

- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked, sig);
- recalc_sigpending();
-
- spin_unlock_irq(&current->sighand->siglock);
+ block_sigmask(ka, sig);

return 0;
}
--
1.7.4.4

2012-02-14 11:47:46

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 23/40] OpenRISC: Don't mask signals if we fail to setup signal stack

From: Matt Fleming <[email protected]>

setup_rt_frame() needs to return an indication of whether it succeeded
or failed in setting up the signal stack frame. If setup_rt_frame()
fails then we must not modify current->blocked.

Acked-by: Oleg Nesterov <[email protected]>
Cc: Jonas Bonn <[email protected]>
Cc: Arnd Bergmann <[email protected]>
Cc: [email protected]
Signed-off-by: Matt Fleming <[email protected]>
---
arch/openrisc/kernel/signal.c | 29 ++++++++++++++++++-----------
1 files changed, 18 insertions(+), 11 deletions(-)

diff --git a/arch/openrisc/kernel/signal.c b/arch/openrisc/kernel/signal.c
index 92d2218..14764e8 100644
--- a/arch/openrisc/kernel/signal.c
+++ b/arch/openrisc/kernel/signal.c
@@ -189,8 +189,8 @@ static inline void __user *get_sigframe(struct k_sigaction *ka,
* trampoline which performs the syscall sigreturn, or a provided
* user-mode trampoline.
*/
-static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
- sigset_t *set, struct pt_regs *regs)
+static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+ sigset_t *set, struct pt_regs *regs)
{
struct rt_sigframe *frame;
unsigned long return_ip;
@@ -247,18 +247,23 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
/* actually move the usp to reflect the stacked frame */
regs->sp = (unsigned long)frame;

- return;
+ return 0;

give_sigsegv:
force_sigsegv(sig, current);
+ return -EFAULT;
}

-static inline void
+static inline int
handle_signal(unsigned long sig,
siginfo_t *info, struct k_sigaction *ka,
sigset_t *oldset, struct pt_regs *regs)
{
- setup_rt_frame(sig, ka, info, oldset, regs);
+ int ret;
+
+ ret = setup_rt_frame(sig, ka, info, oldset, regs);
+ if (ret)
+ return ret;

spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
@@ -267,6 +272,8 @@ handle_signal(unsigned long sig,
recalc_sigpending();

spin_unlock_irq(&current->sighand->siglock);
+
+ return 0;
}

/*
@@ -355,13 +362,13 @@ void do_signal(struct pt_regs *regs)
oldset = &current->blocked;

/* Whee! Actually deliver the signal. */
- handle_signal(signr, &info, &ka, oldset, regs);
- /* 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))
+ if (!handle_signal(signr, &info, &ka, oldset, regs)) {
+ /* 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 */
clear_thread_flag(TIF_RESTORE_SIGMASK);
+ }

tracehook_signal_handler(signr, &info, &ka, regs,
test_thread_flag(TIF_SINGLESTEP));
--
1.7.4.4

2012-02-14 11:48:22

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 18/40] microblaze: Use set_current_blocked() and block_sigmask()

From: Matt Fleming <[email protected]>

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.

Cc: Oleg Nesterov <[email protected]>
Acked-by: Michal Simek <[email protected]>
Cc: [email protected]
Signed-off-by: Matt Fleming <[email protected]>
---
arch/microblaze/kernel/signal.c | 12 ++----------
1 files changed, 2 insertions(+), 10 deletions(-)

diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c
index f2c13d5..99b9708 100644
--- a/arch/microblaze/kernel/signal.c
+++ b/arch/microblaze/kernel/signal.c
@@ -105,10 +105,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval))
goto badframe;
@@ -326,12 +323,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
if (ret)
return ret;

- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked, sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ block_sigmask(ka, sig);

return 0;
}
--
1.7.4.4

2012-02-14 11:42:38

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 14/40] m68k: Use set_current_blocked() and block_sigmask()

From: Matt Fleming <[email protected]>

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.

Cc: Oleg Nesterov <[email protected]>
Cc: Geert Uytterhoeven <[email protected]>
Acked-by: Greg Ungerer <[email protected]>
CC: [email protected]
Signed-off-by: Matt Fleming <[email protected]>
---
arch/m68k/kernel/signal_mm.c | 22 +++++++++-------------
arch/m68k/kernel/signal_no.c | 28 +++++++++-------------------
2 files changed, 18 insertions(+), 32 deletions(-)

diff --git a/arch/m68k/kernel/signal_mm.c b/arch/m68k/kernel/signal_mm.c
index cb856f9..93208b8 100644
--- a/arch/m68k/kernel/signal_mm.c
+++ b/arch/m68k/kernel/signal_mm.c
@@ -105,12 +105,13 @@ int handle_kernel_fault(struct pt_regs *regs)
asmlinkage int
sys_sigsuspend(int unused0, int unused1, old_sigset_t mask)
{
- mask &= _BLOCKABLE;
- spin_lock_irq(&current->sighand->siglock);
+ sigset_t blocked;
+
current->saved_sigmask = current->blocked;
- siginitset(&current->blocked, mask);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+
+ mask &= _BLOCKABLE;
+ siginitset(&blocked, mask);
+ set_current_blocked(&blocked);

current->state = TASK_INTERRUPTIBLE;
schedule();
@@ -528,8 +529,7 @@ asmlinkage int do_sigreturn(unsigned long __unused)
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- current->blocked = set;
- recalc_sigpending();
+ set_current_blocked(&set);

if (restore_sigcontext(regs, &frame->sc, frame + 1))
goto badframe;
@@ -554,8 +554,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- current->blocked = set;
- recalc_sigpending();
+ set_current_blocked(&set);

if (rt_restore_ucontext(regs, sw, &frame->uc))
goto badframe;
@@ -1063,10 +1062,7 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
if (err)
return;

- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked,sig);
- recalc_sigpending();
+ block_sigmask(ka, sig);

if (test_thread_flag(TIF_DELAYED_TRACE)) {
regs->sr &= ~0x8000;
diff --git a/arch/m68k/kernel/signal_no.c b/arch/m68k/kernel/signal_no.c
index 36a81bb..33e8bf5 100644
--- a/arch/m68k/kernel/signal_no.c
+++ b/arch/m68k/kernel/signal_no.c
@@ -60,12 +60,13 @@ void ret_from_user_rt_signal(void);
asmlinkage int
sys_sigsuspend(int unused0, int unused1, old_sigset_t mask)
{
- mask &= _BLOCKABLE;
- spin_lock_irq(&current->sighand->siglock);
+ sigset_t blocked;
+
current->saved_sigmask = current->blocked;
- siginitset(&current->blocked, mask);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+
+ mask &= _BLOCKABLE;
+ siginitset(&blocked, mask);
+ set_current_blocked(&blocked);

current->state = TASK_INTERRUPTIBLE;
schedule();
@@ -343,10 +344,7 @@ asmlinkage int do_sigreturn(unsigned long __unused)
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

if (restore_sigcontext(regs, &frame->sc, frame + 1, &d0))
goto badframe;
@@ -372,10 +370,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

if (rt_restore_ucontext(regs, sw, &frame->uc, &d0))
goto badframe;
@@ -708,12 +703,7 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
if (err)
return;

- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ block_sigmask(ka, sig);

clear_thread_flag(TIF_RESTORE_SIGMASK);
}
--
1.7.4.4

2012-02-14 11:48:38

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 16/40] microblaze: No need to reset handler if SA_ONESHOT

From: Matt Fleming <[email protected]>

get_signal_to_deliver() already resets the signal handler if
SA_ONESHOT is set in ka->sa.sa_flags, there's no need to do it again
in handle_signal(). Furthermore, because we were modifying
ka->sa.sa_handler (which is a copy of sighand->action[]) instead of
sighand->action[] the original code actually had no effect on signal
delivery.

Acked-by: Oleg Nesterov <[email protected]>
Acked-by: Michal Simek <[email protected]>
Cc: [email protected]
Signed-off-by: Matt Fleming <[email protected]>
---
arch/microblaze/kernel/signal.c | 3 ---
1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/arch/microblaze/kernel/signal.c b/arch/microblaze/kernel/signal.c
index 90de06d..9e749c0 100644
--- a/arch/microblaze/kernel/signal.c
+++ b/arch/microblaze/kernel/signal.c
@@ -320,9 +320,6 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
else
setup_rt_frame(sig, ka, NULL, oldset, regs);

- if (ka->sa.sa_flags & SA_ONESHOT)
- ka->sa.sa_handler = SIG_DFL;
-
if (!(ka->sa.sa_flags & SA_NODEFER)) {
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked,
--
1.7.4.4

2012-02-14 11:42:34

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 13/40] m32r: Use set_current_blocked() and block_sigmask()

From: Matt Fleming <[email protected]>

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.

Cc: Oleg Nesterov <[email protected]>
Cc: Hirokazu Takata <[email protected]>
Cc: Al Viro <[email protected]>
Cc: Kyle McMartin <[email protected]>
Cc: [email protected]
Signed-off-by: Matt Fleming <[email protected]>
---
arch/m32r/kernel/signal.c | 12 ++----------
1 files changed, 2 insertions(+), 10 deletions(-)

diff --git a/arch/m32r/kernel/signal.c b/arch/m32r/kernel/signal.c
index a08697f..f54d969 100644
--- a/arch/m32r/kernel/signal.c
+++ b/arch/m32r/kernel/signal.c
@@ -112,10 +112,7 @@ sys_rt_sigreturn(unsigned long r0, unsigned long r1,
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &result))
goto badframe;
@@ -300,12 +297,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
if (setup_rt_frame(sig, ka, info, oldset, regs))
return -EFAULT;

- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ block_sigmask(ka, sig);
return 0;
}

--
1.7.4.4

2012-02-14 11:49:22

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 12/40] ia64: Use set_current_blocked() and block_sigmask()

From: Matt Fleming <[email protected]>

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.

Cc: Oleg Nesterov <[email protected]>
Cc: Tony Luck <[email protected]>
Cc: Fenghua Yu <[email protected]>
Signed-off-by: Matt Fleming <[email protected]>
---
arch/ia64/kernel/signal.c | 15 ++-------------
1 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
index 7bdafc8..7523501 100644
--- a/arch/ia64/kernel/signal.c
+++ b/arch/ia64/kernel/signal.c
@@ -201,13 +201,7 @@ ia64_rt_sigreturn (struct sigscratch *scr)
goto give_sigsegv;

sigdelsetmask(&set, ~_BLOCKABLE);
-
- spin_lock_irq(&current->sighand->siglock);
- {
- current->blocked = set;
- recalc_sigpending();
- }
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

if (restore_sigcontext(sc, scr))
goto give_sigsegv;
@@ -427,12 +421,7 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigse
if (!setup_frame(sig, ka, info, oldset, scr))
return 0;

- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked, sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ block_sigmask(ka, sig);

/*
* Let tracing know that we've done the handler setup.
--
1.7.4.4

2012-02-14 11:42:25

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 09/40] frv: Use set_current_blocked() and block_sigmask()

From: Matt Fleming <[email protected]>

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.

Cc: Oleg Nesterov <[email protected]>
Cc: David Howells <[email protected]>
Cc: Al Viro <[email protected]>
Signed-off-by: Matt Fleming <[email protected]>
---
arch/frv/kernel/signal.c | 32 ++++++++++----------------------
1 files changed, 10 insertions(+), 22 deletions(-)

diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c
index bab0129..dfa460e 100644
--- a/arch/frv/kernel/signal.c
+++ b/arch/frv/kernel/signal.c
@@ -40,12 +40,13 @@ struct fdpic_func_descriptor {
*/
asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask)
{
- mask &= _BLOCKABLE;
- spin_lock_irq(&current->sighand->siglock);
+ sigset_t blocked;
+
current->saved_sigmask = current->blocked;
- siginitset(&current->blocked, mask);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+
+ mask &= _BLOCKABLE;
+ siginitset(&blocked, mask);
+ set_current_blocked(&blocked);

current->state = TASK_INTERRUPTIBLE;
schedule();
@@ -158,10 +159,7 @@ asmlinkage int sys_sigreturn(void)
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

if (restore_sigcontext(&frame->sc, &gr8))
goto badframe;
@@ -184,10 +182,7 @@ asmlinkage int sys_rt_sigreturn(void)
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

if (restore_sigcontext(&frame->uc.uc_mcontext, &gr8))
goto badframe;
@@ -474,15 +469,8 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
else
ret = setup_frame(sig, ka, oldset);

- if (ret == 0) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked, &current->blocked,
- &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked, sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ if (ret == 0)
+ block_sigmask(ka, sig);

return ret;

--
1.7.4.4

2012-02-14 11:49:46

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 11/40] Hexagon: Use set_current_blocked() and block_sigmask()

From: Matt Fleming <[email protected]>

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.

Cc: Oleg Nesterov <[email protected]>
Cc: Richard Kuo <[email protected]>
Cc: [email protected]
Signed-off-by: Matt Fleming <[email protected]>
---
arch/hexagon/kernel/signal.c | 12 ++----------
1 files changed, 2 insertions(+), 10 deletions(-)

diff --git a/arch/hexagon/kernel/signal.c b/arch/hexagon/kernel/signal.c
index b45be31..ecbab34 100644
--- a/arch/hexagon/kernel/signal.c
+++ b/arch/hexagon/kernel/signal.c
@@ -192,12 +192,7 @@ static int handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
if (rc)
return rc;

- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked, sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ block_sigmask(ka, sig);

return 0;
}
@@ -305,10 +300,7 @@ asmlinkage int sys_rt_sigreturn(void)
goto badframe;

sigdelsetmask(&blocked, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = blocked;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&blocked);

if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
goto badframe;
--
1.7.4.4

2012-02-14 11:50:22

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 08/40] cris: Use set_current_blocked() and block_sigmask()

From: Matt Fleming <[email protected]>

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.

Cc: Oleg Nesterov <[email protected]>
Cc: Mikael Starvik <[email protected]>
Cc: Jesper Nilsson <[email protected]>
Cc: [email protected]
Signed-off-by: Matt Fleming <[email protected]>
---
arch/cris/arch-v10/kernel/signal.c | 34 +++++++++++---------------------
arch/cris/arch-v32/kernel/signal.c | 37 ++++++++++-------------------------
2 files changed, 23 insertions(+), 48 deletions(-)

diff --git a/arch/cris/arch-v10/kernel/signal.c b/arch/cris/arch-v10/kernel/signal.c
index e78fe49..a6e1ff0 100644
--- a/arch/cris/arch-v10/kernel/signal.c
+++ b/arch/cris/arch-v10/kernel/signal.c
@@ -50,12 +50,14 @@ void do_signal(int canrestart, struct pt_regs *regs);
int sys_sigsuspend(old_sigset_t mask, long r11, long r12, long r13, long mof,
long srp, struct pt_regs *regs)
{
- mask &= _BLOCKABLE;
- spin_lock_irq(&current->sighand->siglock);
+ sigset_t blocked;
+
current->saved_sigmask = current->blocked;
- siginitset(&current->blocked, mask);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+
+ mask &= _BLOCKABLE;
+ siginitset(&blocked, mask);
+ set_current_blocked(&blocked);
+
current->state = TASK_INTERRUPTIBLE;
schedule();
set_thread_flag(TIF_RESTORE_SIGMASK);
@@ -184,10 +186,7 @@ asmlinkage int sys_sigreturn(long r10, long r11, long r12, long r13, long mof,
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

if (restore_sigcontext(regs, &frame->sc))
goto badframe;
@@ -223,10 +222,7 @@ asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13,
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
goto badframe;
@@ -468,15 +464,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(&current->sighand->siglock);
- sigorsets(&current->blocked, &current->blocked,
- &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked, sig);
- recalc_sigpending();
- spin_unlock_irq(&current->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 ce4ab1a..e7ea1ea 100644
--- a/arch/cris/arch-v32/kernel/signal.c
+++ b/arch/cris/arch-v32/kernel/signal.c
@@ -62,12 +62,14 @@ int
sys_sigsuspend(old_sigset_t mask, long r11, long r12, long r13, long mof,
long srp, struct pt_regs *regs)
{
- mask &= _BLOCKABLE;
- spin_lock_irq(&current->sighand->siglock);
+ sigset_t blocked;
+
current->saved_sigmask = current->blocked;
- siginitset(&current->blocked, mask);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+
+ mask &= _BLOCKABLE;
+ siginitset(&blocked, mask);
+ set_current_blocked(&blocked);
+
current->state = TASK_INTERRUPTIBLE;
schedule();
set_thread_flag(TIF_RESTORE_SIGMASK);
@@ -176,12 +178,7 @@ sys_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp,
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
-
- current->blocked = set;
-
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

if (restore_sigcontext(regs, &frame->sc))
goto badframe;
@@ -222,12 +219,7 @@ sys_rt_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp,
goto badframe;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
-
- current->blocked = set;
-
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
goto badframe;
@@ -515,15 +507,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(&current->sighand->siglock);
- sigorsets(&current->blocked, &current->blocked,
- &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked, sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ if (ret == 0)
+ block_sigmask(ka, sig);

return ret;
}
--
1.7.4.4

2012-02-14 11:41:29

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 01/40] alpha: Use set_current_blocked() and block_sigmask()

From: Matt Fleming <[email protected]>

As described in e6fa16ab ("signal: sigprocmask() should do
retarget_shared_pending()") the modification of current->blocked is
incorrect as we need to check for shared signals we're about to block.

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.

Cc: Oleg Nesterov <[email protected]>
Cc: Richard Henderson <[email protected]>
Cc: Ivan Kokshaysky <[email protected]>
Cc: Matt Turner <[email protected]>
Cc: Al Viro <[email protected]>
Cc: [email protected]
Signed-off-by: Matt Fleming <[email protected]>
---
arch/alpha/kernel/signal.c | 31 ++++++++++---------------------
1 files changed, 10 insertions(+), 21 deletions(-)

diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index 6f7feb5..35f2ef4 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -120,12 +120,13 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act,
*/
SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask)
{
- mask &= _BLOCKABLE;
- spin_lock_irq(&current->sighand->siglock);
+ sigset_t blocked;
+
current->saved_sigmask = current->blocked;
- siginitset(&current->blocked, mask);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+
+ mask &= _BLOCKABLE;
+ siginitset(&blocked, mask);
+ set_current_blocked(&blocked);

current->state = TASK_INTERRUPTIBLE;
schedule();
@@ -238,10 +239,7 @@ do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs,
goto give_sigsegv;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

if (restore_sigcontext(sc, regs, sw))
goto give_sigsegv;
@@ -276,10 +274,7 @@ do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs,
goto give_sigsegv;

sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);

if (restore_sigcontext(&frame->uc.uc_mcontext, regs, sw))
goto give_sigsegv;
@@ -501,14 +496,8 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
else
ret = setup_frame(sig, ka, oldset, regs, sw);

- if (ret == 0) {
- spin_lock_irq(&current->sighand->siglock);
- sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&current->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
- }
+ if (ret == 0)
+ block_sigmask(ka, sig);

return ret;
}
--
1.7.4.4

2012-02-14 11:41:27

by Matt Fleming

[permalink] [raw]
Subject: [PATCH 02/40] arm: Use set_current_blocked() and block_sigmask()

From: Matt Fleming <[email protected]>

As described in e6fa16ab ("signal: sigprocmask() should do
retarget_shared_pending()") the modification of current->blocked is
incorrect as we need to check for shared signals we're about to block.

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.

Cc: Oleg Nesterov <[email protected]>
Cc: Russell King <[email protected]>
Cc: Arnd Bergmann <[email protected]>
Cc: Dave Martin <[email protected]>
Cc: Nicolas Pitre <[email protected]>
Cc: Will Deacon <[email protected]>
Cc: [email protected]
Signed-off-by: Matt Fleming <[email protected]>
---
arch/arm/kernel/signal.c | 24 ++++++++----------------
1 files changed, 8 insertions(+), 16 deletions(-)

diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 9e617bd..7cb532f 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -66,12 +66,13 @@ const unsigned long syscall_restart_code[2] = {
*/
asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask)
{
- mask &= _BLOCKABLE;
- spin_lock_irq(&current->sighand->siglock);
+ sigset_t blocked;
+
current->saved_sigmask = current->blocked;
- siginitset(&current->blocked, mask);
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+
+ mask &= _BLOCKABLE;
+ siginitset(&blocked, mask);
+ set_current_blocked(&blocked);

current->state = TASK_INTERRUPTIBLE;
schedule();
@@ -280,10 +281,7 @@ static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
if (err == 0) {
sigdelsetmask(&set, ~_BLOCKABLE);
- spin_lock_irq(&current->sighand->siglock);
- current->blocked = set;
- recalc_sigpending();
- spin_unlock_irq(&current->sighand->siglock);
+ set_current_blocked(&set);
}

__get_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err);
@@ -636,13 +634,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
/*
* Block the signal if we were successful.
*/
- spin_lock_irq(&tsk->sighand->siglock);
- sigorsets(&tsk->blocked, &tsk->blocked,
- &ka->sa.sa_mask);
- if (!(ka->sa.sa_flags & SA_NODEFER))
- sigaddset(&tsk->blocked, sig);
- recalc_sigpending();
- spin_unlock_irq(&tsk->sighand->siglock);
+ block_sigmask(ka, sig);

return 0;
}
--
1.7.4.4

2012-02-14 13:45:14

by Mark Salter

[permalink] [raw]
Subject: Re: [PATCH 00/40] arch: set_current_blocked() and block_sigmask()

On Tue, 2012-02-14 at 11:40 +0000, Matt Fleming wrote:
> From: Matt Fleming <[email protected]>
>
> This series simplifies the architecture code for handling signals by
> making use of set_current_blocked() introduced in e6fa16ab ("signal:
> sigprocmask() should do retarget_shared_pending()") and
> block_sigmask() introduced in commit 5e6292c0f28f ("signal: add
> block_sigmask() for adding sigmask to current->blocked").
>
...
> Matt Fleming (39):
...
> C6X: Use set_current_blocked() and block_sigmask()
...
> arch/c6x/kernel/signal.c | 16 ++----------

The c6x patch seems to be missing from the series.

--Mark

2012-02-14 13:53:45

by Matt Fleming

[permalink] [raw]
Subject: Re: [PATCH 00/40] arch: set_current_blocked() and block_sigmask()

On Tue, 2012-02-14 at 08:45 -0500, Mark Salter wrote:
> The c6x patch seems to be missing from the series.

I don't think it is. It reached lkml.org OK,

https://lkml.org/lkml/2012/2/14/123

The post to the linux-c6x-dev mailing list is awaiting moderator
approval but seeing as you were Cc'd on the patch I would have expected
it to reach your inbox with problems.

--
Matt Fleming, Intel Open Source Technology Center

2012-02-14 13:58:56

by Mark Salter

[permalink] [raw]
Subject: Re: [PATCH 00/40] arch: set_current_blocked() and block_sigmask()

On Tue, 2012-02-14 at 13:52 +0000, Matt Fleming wrote:
> On Tue, 2012-02-14 at 08:45 -0500, Mark Salter wrote:
> > The c6x patch seems to be missing from the series.
>
> I don't think it is. It reached lkml.org OK,
>
> https://lkml.org/lkml/2012/2/14/123
>
> The post to the linux-c6x-dev mailing list is awaiting moderator
> approval but seeing as you were Cc'd on the patch I would have expected
> it to reach your inbox with problems.
>
Yup. I should have been more patient. I see it now.

2012-02-14 14:08:46

by Matt Fleming

[permalink] [raw]
Subject: Re: [PATCH 00/40] arch: set_current_blocked() and block_sigmask()

On Tue, 2012-02-14 at 08:58 -0500, Mark Salter wrote:
> On Tue, 2012-02-14 at 13:52 +0000, Matt Fleming wrote:
> > On Tue, 2012-02-14 at 08:45 -0500, Mark Salter wrote:
> > > The c6x patch seems to be missing from the series.
> >
> > I don't think it is. It reached lkml.org OK,
> >
> > https://lkml.org/lkml/2012/2/14/123
> >
> > The post to the linux-c6x-dev mailing list is awaiting moderator
> > approval but seeing as you were Cc'd on the patch I would have expected
> > it to reach your inbox with problems.
> >
> Yup. I should have been more patient. I see it now.

Heh, I meant *without* problems ;-)

--
Matt Fleming, Intel Open Source Technology Center

2012-02-14 15:56:39

by David Howells

[permalink] [raw]
Subject: Re: [PATCH 20/40] mn10300: Use set_current_blocked() and block_sigmask()

Matt Fleming <[email protected]> wrote:

> asmlinkage long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
> {
> - mask &= _BLOCKABLE;
> - spin_lock_irq(&current->sighand->siglock);
> + sigset_t blocked;
> +
> current->saved_sigmask = current->blocked;

Can this line create a race, now that it's not protected by a lock? It is
possible for current->blocked to get altered by another thread.

David

2012-02-14 17:30:29

by Oleg Nesterov

[permalink] [raw]
Subject: Re: [PATCH 20/40] mn10300: Use set_current_blocked() and block_sigmask()

On 02/14, David Howells wrote:
>
> Matt Fleming <[email protected]> wrote:
>
> > asmlinkage long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
> > {
> > - mask &= _BLOCKABLE;
> > - spin_lock_irq(&current->sighand->siglock);
> > + sigset_t blocked;
> > +
> > current->saved_sigmask = current->blocked;
>
> Can this line create a race, now that it's not protected by a lock? It is
> possible for current->blocked to get altered by another thread.

No, only current can change ->blocked. This is even documented in
sigprocmask(). And more, the only correct way to change ->blocked
is set_current_blocked(). OK, with a couple of "I know what I am
doing" exceptions in kernel/signal.c.

Oleg.

2012-02-14 17:39:02

by Oleg Nesterov

[permalink] [raw]
Subject: Re: [PATCH 00/40] arch: set_current_blocked() and block_sigmask()

On 02/14, Matt Fleming wrote:
>
> This series simplifies the architecture code for handling signals by
> making use of set_current_blocked() introduced in e6fa16ab ("signal:
> sigprocmask() should do retarget_shared_pending()") and
> block_sigmask() introduced in commit 5e6292c0f28f ("signal: add
> block_sigmask() for adding sigmask to current->blocked").

Matt, I assume this series was not changed since we discussed it ?

If yes. I do not want to spam lkml, I'll reply to 0/40 only.

All patches look right to me, for the whole series:

Acked-by: Oleg Nesterov <[email protected]>

2012-02-14 17:59:48

by Matt Fleming

[permalink] [raw]
Subject: Re: [PATCH 20/40] mn10300: Use set_current_blocked() and block_sigmask()

On Tue, 2012-02-14 at 15:56 +0000, David Howells wrote:
> Matt Fleming <[email protected]> wrote:
>
> > asmlinkage long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
> > {
> > - mask &= _BLOCKABLE;
> > - spin_lock_irq(&current->sighand->siglock);
> > + sigset_t blocked;
> > +
> > current->saved_sigmask = current->blocked;
>
> Can this line create a race, now that it's not protected by a lock? It is
> possible for current->blocked to get altered by another thread.

->blocked can only ever be altered by current, not another thread. See
the following comment from sigprocmask() in kernel/signal.c,

/* Lockless, only current can change ->blocked, never from irq */
if (oldset)
*oldset = tsk->blocked;

--
Matt Fleming, Intel Open Source Technology Center

2012-02-14 18:13:22

by David Howells

[permalink] [raw]
Subject: Re: [PATCH 20/40] mn10300: Use set_current_blocked() and block_sigmask()

Oleg Nesterov <[email protected]> wrote:

> No, only current can change ->blocked. This is even documented in
> sigprocmask(). And more, the only correct way to change ->blocked
> is set_current_blocked(). OK, with a couple of "I know what I am
> doing" exceptions in kernel/signal.c.

I was looking at force_sig_info() and derivatives. Is that what you refer to?

If so, is it worth providing a force_sig_info_current(),
force_sigsegv_current() and force_sig_current() to make things clearer to grep
for, I wonder?

David

2012-02-14 18:30:34

by David Howells

[permalink] [raw]
Subject: Re: [PATCH 20/40] mn10300: Use set_current_blocked() and block_sigmask()


Matt Fleming <[email protected]> wrote:

> > Can this line create a race, now that it's not protected by a lock? It is
> > possible for current->blocked to get altered by another thread.
>
> ->blocked can only ever be altered by current, not another thread. See
> the following comment from sigprocmask() in kernel/signal.c,

Okay, I've managed to convince myself. Feel free to my Acked-by to the
MN10300 and FRV patches.

David

2012-02-14 18:31:15

by Oleg Nesterov

[permalink] [raw]
Subject: Re: [PATCH 20/40] mn10300: Use set_current_blocked() and block_sigmask()

On 02/14, David Howells wrote:
>
> Oleg Nesterov <[email protected]> wrote:
>
> > No, only current can change ->blocked. This is even documented in
> > sigprocmask(). And more, the only correct way to change ->blocked
> > is set_current_blocked(). OK, with a couple of "I know what I am
> > doing" exceptions in kernel/signal.c.
>
> I was looking at force_sig_info() and derivatives. Is that what you refer to?

Ah, sorry, forgot to mention...

force_sig_info() (and its callers) need the cleanups and fixes. It
is almost always wrong if t != current.

For example, please look at

[PATCH 1/4] signal: give SEND_SIG_FORCED more power to beat SIGNAL_UNKILLABLE
http://marc.info/?l=linux-kernel&m=132890442717122

Hopefully we can fix all ab-users soon.



Just in case... if we race with force_sig_info() the task will be
killed anyway. But I agree, this is not nice and should be fixed.
And in any case, there are other places which assume it is safe
to read current->blocked lockless.

> If so, is it worth providing a force_sig_info_current(),
> force_sigsegv_current() and force_sig_current() to make things clearer to grep
> for, I wonder?

Yes, I think the "task_struct *t" argument should die.

Oleg.

2012-02-15 03:57:27

by David Miller

[permalink] [raw]
Subject: Re: [PATCH 32/40] sparc: Use block_sigmask()

From: Matt Fleming <[email protected]>
Date: Tue, 14 Feb 2012 11:41:05 +0000

> From: Matt Fleming <[email protected]>
>
> 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.
>
> Cc: Oleg Nesterov <[email protected]>
> Cc: "David S. Miller" <[email protected]>
> Cc: [email protected]
> Signed-off-by: Matt Fleming <[email protected]>

Acked-by: David S. Miller <[email protected]>

2012-02-15 08:44:05

by Jesper Nilsson

[permalink] [raw]
Subject: Re: [PATCH 08/40] cris: Use set_current_blocked() and block_sigmask()

On Tue, Feb 14, 2012 at 12:40:41PM +0100, Matt Fleming wrote:
> From: Matt Fleming <[email protected]>
>
> 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.
>
> Cc: Oleg Nesterov <[email protected]>
> Cc: Mikael Starvik <[email protected]>
> Cc: Jesper Nilsson <[email protected]>

Acked-by: Jesper Nilsson <[email protected]>

> Cc: [email protected]
> Signed-off-by: Matt Fleming <[email protected]>

/^JN - Jesper Nilsson
--
Jesper Nilsson -- [email protected]

2012-02-15 11:48:04

by Matt Fleming

[permalink] [raw]
Subject: Re: [PATCH 00/40] arch: set_current_blocked() and block_sigmask()

On Tue, 2012-02-14 at 18:32 +0100, Oleg Nesterov wrote:
> On 02/14, Matt Fleming wrote:
> >
> > This series simplifies the architecture code for handling signals by
> > making use of set_current_blocked() introduced in e6fa16ab ("signal:
> > sigprocmask() should do retarget_shared_pending()") and
> > block_sigmask() introduced in commit 5e6292c0f28f ("signal: add
> > block_sigmask() for adding sigmask to current->blocked").
>
> Matt, I assume this series was not changed since we discussed it ?

Correct. The only new additions are the C6X and hexagon patches here,

https://lkml.org/lkml/2012/2/14/123
https://lkml.org/lkml/2012/2/14/155

But they're pretty much the same as all the others in the series.

> If yes. I do not want to spam lkml, I'll reply to 0/40 only.
>
> All patches look right to me, for the whole series:
>
> Acked-by: Oleg Nesterov <[email protected]>

Great, thanks!

--
Matt Fleming, Intel Open Source Technology Center

2012-02-15 11:50:04

by Matt Fleming

[permalink] [raw]
Subject: Re: [PATCH 20/40] mn10300: Use set_current_blocked() and block_sigmask()

On Tue, 2012-02-14 at 18:30 +0000, David Howells wrote:
> Matt Fleming <[email protected]> wrote:
>
> > > Can this line create a race, now that it's not protected by a lock? It is
> > > possible for current->blocked to get altered by another thread.
> >
> > ->blocked can only ever be altered by current, not another thread. See
> > the following comment from sigprocmask() in kernel/signal.c,
>
> Okay, I've managed to convince myself. Feel free to my Acked-by to the
> MN10300 and FRV patches.

Thanks! I think Andrew is picking these up, unless you want to take them
through the arch trees?

--
Matt Fleming, Intel Open Source Technology Center

2012-02-15 15:49:09

by Matt Fleming

[permalink] [raw]
Subject: Re: [PATCH 21/40] OpenRISC: Don't reimplement force_sigsegv()

On Wed, 2012-02-15 at 16:40 +0100, Jonas Bonn wrote:
> Acked-by: Jonas Bonn <[email protected]>
>
> ...for OpenRISC, all 4 patches (20-23 in this series).
>
> Should I take these in the OpenRISC tree or how did you want to do?

Whatever you prefer. Feel free to take them through the OpenRISC tree.

--
Matt Fleming, Intel Open Source Technology Center

2012-02-15 15:57:54

by Jonas Bonn

[permalink] [raw]
Subject: Re: [PATCH 21/40] OpenRISC: Don't reimplement force_sigsegv()


On Wed, 2012-02-15 at 15:49 +0000, Matt Fleming wrote:
> On Wed, 2012-02-15 at 16:40 +0100, Jonas Bonn wrote:
> > Acked-by: Jonas Bonn <[email protected]>
> >
> > ...for OpenRISC, all 4 patches (20-23 in this series).
> >
> > Should I take these in the OpenRISC tree or how did you want to do?
>
> Whatever you prefer. Feel free to take them through the OpenRISC tree.

OK, great, I'll pull them into the OpenRISC tree for 3.4.

Thanks,
Jonas

2012-02-15 16:03:00

by Jonas Bonn

[permalink] [raw]
Subject: Re: [PATCH 21/40] OpenRISC: Don't reimplement force_sigsegv()


Acked-by: Jonas Bonn <[email protected]>

...for OpenRISC, all 4 patches (20-23 in this series).

Should I take these in the OpenRISC tree or how did you want to do?

/Jonas

On Tue, 2012-02-14 at 11:40 +0000, Matt Fleming wrote:
> From: Matt Fleming <[email protected]>
>
> Instead of open coding the sequence from force_sigsegv() just call
> it. This also fixes a bug because we were modifying ka->sa.sa_handler
> (which is a copy of sighand->action[]), whereas the intention of the
> code was to modify sighand->action[] directly.
>
> As the original code was working with a copy it had no effect on
> signal delivery.
>
> Acked-by: Oleg Nesterov <[email protected]>
> Cc: Jonas Bonn <[email protected]>
> Cc: Arnd Bergmann <[email protected]>
> Cc: [email protected]
> Signed-off-by: Matt Fleming <[email protected]>
> ---
> arch/openrisc/kernel/signal.c | 4 +---
> 1 files changed, 1 insertions(+), 3 deletions(-)
>
> diff --git a/arch/openrisc/kernel/signal.c b/arch/openrisc/kernel/signal.c
> index 95207ab..53741ba 100644
> --- a/arch/openrisc/kernel/signal.c
> +++ b/arch/openrisc/kernel/signal.c
> @@ -250,9 +250,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
> return;
>
> give_sigsegv:
> - if (sig == SIGSEGV)
> - ka->sa.sa_handler = SIG_DFL;
> - force_sig(SIGSEGV, current);
> + force_sigsegv(sig, current);
> }
>
> static inline void

--
Jonas Bonn South Pole AB
Phone : +46-8-56237100 Anderstorpsvägen 16
Mobile: +46-768-527755 SE-17154 Solna
[email protected] http://www.southpoleconsulting.com




2012-02-16 09:29:05

by Bob Liu

[permalink] [raw]
Subject: Re: [PATCH 06/40] blackfin: Use set_current_blocked() and block_sigmask()

On Tue, Feb 14, 2012 at 7:40 PM, Matt Fleming <[email protected]> wrote:
> From: Matt Fleming <[email protected]>
>
> 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.
>
> Cc: Oleg Nesterov <[email protected]>
> Acked-by: Mike Frysinger <[email protected]>
> Cc: [email protected]
> Signed-off-by: Matt Fleming <[email protected]>
> ---
>  arch/blackfin/kernel/signal.c |   17 ++++-------------
>  1 files changed, 4 insertions(+), 13 deletions(-)
>
> diff --git a/arch/blackfin/kernel/signal.c b/arch/blackfin/kernel/signal.c
> index d536f35..05ece02 100644
> --- a/arch/blackfin/kernel/signal.c
> +++ b/arch/blackfin/kernel/signal.c
> @@ -99,10 +99,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
>                goto badframe;
>
>        sigdelsetmask(&set, ~_BLOCKABLE);
> -       spin_lock_irq(&current->sighand->siglock);
> -       current->blocked = set;
> -       recalc_sigpending();
> -       spin_unlock_irq(&current->sighand->siglock);
> +       set_current_blocked(&set);
>
>        if (rt_restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
>                goto badframe;
> @@ -266,15 +263,9 @@ handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
>        /* set up the stack frame */
>        ret = setup_rt_frame(sig, ka, info, oldset, regs);
>
> -       if (ret == 0) {
> -               spin_lock_irq(&current->sighand->siglock);
> -               sigorsets(&current->blocked, &current->blocked,
> -                         &ka->sa.sa_mask);
> -               if (!(ka->sa.sa_flags & SA_NODEFER))
> -                       sigaddset(&current->blocked, sig);
> -               recalc_sigpending();
> -               spin_unlock_irq(&current->sighand->siglock);
> -       }
> +       if (ret == 0)
> +               block_sigmask(ka, sig);
> +
>        return ret;
>  }
>

Thanks. I'll apply it.

--
Regards,
--Bob