[PATCH 1/4] signals/sigaltstack: If SS_AUTODISARM, bypass on_sig_stack

Subsystems: scheduler, the rest

STALE3793d

9 messages, 4 authors, 2016-05-14 · open the first message on its own page

[PATCH 1/4] signals/sigaltstack: If SS_AUTODISARM, bypass on_sig_stack

From: Andy Lutomirski <luto@kernel.org>
Date: 2016-05-03 17:32:12

If a signal stack is set up with SS_AUTODISARM, then the kernel
inherently avoids incorrectly resetting the signal stack if signals
recurse: the signal stack will be reset on the first signal
delivery.  This means that we don't need check the stack pointer
when delivering signals if SS_AUTODISARM is set.

This will make segmented x86 programs more robust: currently there's
a hole that could be triggered if ESP/RSP appears to point to the
signal stack but actually doesn't due to a nonzero SS base.

Signed-off-by: Stas Sergeev <redacted>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Aleksa Sarai <redacted>
Cc: Amanieu d'Antras <redacted>
Cc: Andrea Arcangeli <redacted>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <redacted>
Cc: Denys Vlasenko <redacted>
Cc: Eric W. Biederman <redacted>
Cc: Frederic Weisbecker <redacted>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Heinrich Schuchardt <redacted>
Cc: Jason Low <redacted>
Cc: Josh Triplett <josh@joshtriplett.org>
Cc: Konstantin Khlebnikov <redacted>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Palmer Dabbelt <palmer@dabbelt.com>
Cc: Paul Moore <redacted>
Cc: Pavel Emelyanov <redacted>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Richard Weinberger <richard@nod.at>
Cc: Sasha Levin <redacted>
Cc: Shuah Khan <redacted>
Cc: Tejun Heo <tj@kernel.org>
Cc: Thomas Gleixner <redacted>
Cc: Vladimir Davydov <redacted>
Cc: linux-api@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Andy Lutomirski <luto@kernel.org>
---
 include/linux/sched.h | 12 ++++++++++++
 1 file changed, 12 insertions(+)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 2950c5cd3005..8f03a93348b9 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2576,6 +2576,18 @@ static inline int kill_cad_pid(int sig, int priv)
  */
 static inline int on_sig_stack(unsigned long sp)
 {
+	/*
+	 * If the signal stack is AUTODISARM then, by construction, we
+	 * can't be on the signal stack unless user code deliberately set
+	 * SS_AUTODISARM when we were already on the it.
+	 *
+	 * This improve reliability: if user state gets corrupted such that
+	 * the stack pointer points very close to the end of the signal stack,
+	 * then this check will enable the signal to be handled anyway.
+	 */
+	if (current->sas_ss_flags & SS_AUTODISARM)
+		return 0;
+
 #ifdef CONFIG_STACK_GROWSUP
 	return sp >= current->sas_ss_sp &&
 		sp - current->sas_ss_sp < current->sas_ss_size;
-- 
2.5.5

Re: [PATCH 1/4] signals/sigaltstack: If SS_AUTODISARM, bypass on_sig_stack

From: Ingo Molnar <mingo@kernel.org>
Date: 2016-05-04 06:32:41

* Andy Lutomirski [off-list ref] wrote:
If a signal stack is set up with SS_AUTODISARM, then the kernel
inherently avoids incorrectly resetting the signal stack if signals
recurse: the signal stack will be reset on the first signal
delivery.  This means that we don't need check the stack pointer
when delivering signals if SS_AUTODISARM is set.

This will make segmented x86 programs more robust: currently there's
a hole that could be triggered if ESP/RSP appears to point to the
signal stack but actually doesn't due to a nonzero SS base.

Signed-off-by: Stas Sergeev <redacted>
Presuably that SOB from Stas is stray, as there's no matching From: line?
I've removed it.

Thanks,

	Ingo

Re: [PATCH 1/4] signals/sigaltstack: If SS_AUTODISARM, bypass on_sig_stack

From: Andy Lutomirski <luto@amacapital.net>
Date: 2016-05-04 23:03:18

On May 3, 2016 11:32 PM, "Ingo Molnar" [off-list ref] wrote:

* Andy Lutomirski [off-list ref] wrote:
quoted
If a signal stack is set up with SS_AUTODISARM, then the kernel
inherently avoids incorrectly resetting the signal stack if signals
recurse: the signal stack will be reset on the first signal
delivery.  This means that we don't need check the stack pointer
when delivering signals if SS_AUTODISARM is set.

This will make segmented x86 programs more robust: currently there's
a hole that could be triggered if ESP/RSP appears to point to the
signal stack but actually doesn't due to a nonzero SS base.

Signed-off-by: Stas Sergeev <redacted>
Presuably that SOB from Stas is stray, as there's no matching From: line?
I've removed it.
Yes.  It was a cut-and-paste-o -- I meant to change it to cc.
Thanks,

        Ingo

Re: [PATCH 1/4] signals/sigaltstack: If SS_AUTODISARM, bypass on_sig_stack

From: Stas Sergeev <hidden>
Date: 2016-05-07 14:38:13

03.05.2016 20:31, Andy Lutomirski пишет:
quoted hunk
If a signal stack is set up with SS_AUTODISARM, then the kernel
inherently avoids incorrectly resetting the signal stack if signals
recurse: the signal stack will be reset on the first signal
delivery.  This means that we don't need check the stack pointer
when delivering signals if SS_AUTODISARM is set.

This will make segmented x86 programs more robust: currently there's
a hole that could be triggered if ESP/RSP appears to point to the
signal stack but actually doesn't due to a nonzero SS base.

Signed-off-by: Stas Sergeev <redacted>
Cc: Al Viro <viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
Cc: Aleksa Sarai <cyphar-gVpy/LI/lHzQT0dZR+AlfA@public.gmane.org>
Cc: Amanieu d'Antras <redacted>
Cc: Andrea Arcangeli <redacted>
Cc: Andrew Morton <akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
Cc: Andy Lutomirski <redacted>
Cc: Borislav Petkov <redacted>
Cc: Brian Gerst <redacted>
Cc: Denys Vlasenko <redacted>
Cc: Eric W. Biederman <ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>
Cc: Frederic Weisbecker <redacted>
Cc: H. Peter Anvin <redacted>
Cc: Heinrich Schuchardt <redacted>
Cc: Jason Low <redacted>
Cc: Josh Triplett <redacted>
Cc: Konstantin Khlebnikov <redacted>
Cc: Linus Torvalds <torvalds-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
Cc: Oleg Nesterov <redacted>
Cc: Palmer Dabbelt <redacted>
Cc: Paul Moore <redacted>
Cc: Pavel Emelyanov <redacted>
Cc: Peter Zijlstra <redacted>
Cc: Richard Weinberger <richard-/L3Ra7n9ekc@public.gmane.org>
Cc: Sasha Levin <redacted>
Cc: Shuah Khan <redacted>
Cc: Tejun Heo <redacted>
Cc: Thomas Gleixner <redacted>
Cc: Vladimir Davydov <redacted>
Cc: linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Signed-off-by: Andy Lutomirski <redacted>
---
  include/linux/sched.h | 12 ++++++++++++
  1 file changed, 12 insertions(+)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 2950c5cd3005..8f03a93348b9 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2576,6 +2576,18 @@ static inline int kill_cad_pid(int sig, int priv)
   */
  static inline int on_sig_stack(unsigned long sp)
  {
+	/*
+	 * If the signal stack is AUTODISARM then, by construction, we
+	 * can't be on the signal stack unless user code deliberately set
+	 * SS_AUTODISARM when we were already on the it.
"on the it" -> "on it".

Anyway, I am a bit puzzled with this patch.
You say "unless user code deliberately set
SS_AUTODISARM when we were already on the it"
so what happens in case it actually does?

Without your patch: if user sets up the same sas - no stack switch.
if user sets up different sas - stack switch on nested signal.

With your patch: stack switch in any case, so if user
set up same sas - stack corruption by nested signal.

Or am I missing the intention?

Re: [PATCH 1/4] signals/sigaltstack: If SS_AUTODISARM, bypass on_sig_stack

From: Andy Lutomirski <luto@amacapital.net>
Date: 2016-05-09 01:33:11

On May 7, 2016 7:38 AM, "Stas Sergeev" [off-list ref] wrote:
03.05.2016 20:31, Andy Lutomirski пишет:
quoted
If a signal stack is set up with SS_AUTODISARM, then the kernel
inherently avoids incorrectly resetting the signal stack if signals
recurse: the signal stack will be reset on the first signal
delivery.  This means that we don't need check the stack pointer
when delivering signals if SS_AUTODISARM is set.

This will make segmented x86 programs more robust: currently there's
a hole that could be triggered if ESP/RSP appears to point to the
signal stack but actually doesn't due to a nonzero SS base.

Signed-off-by: Stas Sergeev <redacted>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Aleksa Sarai <redacted>
Cc: Amanieu d'Antras <redacted>
Cc: Andrea Arcangeli <redacted>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <redacted>
Cc: Denys Vlasenko <redacted>
Cc: Eric W. Biederman <redacted>
Cc: Frederic Weisbecker <redacted>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Heinrich Schuchardt <redacted>
Cc: Jason Low <redacted>
Cc: Josh Triplett <josh@joshtriplett.org>
Cc: Konstantin Khlebnikov <redacted>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Palmer Dabbelt <palmer@dabbelt.com>
Cc: Paul Moore <redacted>
Cc: Pavel Emelyanov <redacted>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Richard Weinberger <richard@nod.at>
Cc: Sasha Levin <redacted>
Cc: Shuah Khan <redacted>
Cc: Tejun Heo <tj@kernel.org>
Cc: Thomas Gleixner <redacted>
Cc: Vladimir Davydov <redacted>
Cc: linux-api@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Andy Lutomirski <luto@kernel.org>
---
  include/linux/sched.h | 12 ++++++++++++
  1 file changed, 12 insertions(+)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 2950c5cd3005..8f03a93348b9 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2576,6 +2576,18 @@ static inline int kill_cad_pid(int sig, int priv)
   */
  static inline int on_sig_stack(unsigned long sp)
  {
+       /*
+        * If the signal stack is AUTODISARM then, by construction, we
+        * can't be on the signal stack unless user code deliberately set
+        * SS_AUTODISARM when we were already on the it.
"on the it" -> "on it".

Anyway, I am a bit puzzled with this patch.
You say "unless user code deliberately set

SS_AUTODISARM when we were already on the it"
so what happens in case it actually does?
Stack corruption.  Don't do that.
Without your patch: if user sets up the same sas - no stack switch.
if user sets up different sas - stack switch on nested signal.

With your patch: stack switch in any case, so if user
set up same sas - stack corruption by nested signal.

Or am I missing the intention?
The intention is to make everything completely explicit.  With
SS_AUTODISARM, the kernel knows directly whether you're on the signal
stack, and there should be no need to look at sp.  If you set
SS_AUTODISARM and get a signal, the signal stack gets disarmed.  If
you take a nested signal, it's delivered normally.  When you return
all the way out, the signal stack is re-armed.

For DOSEMU, this means that no 16-bit register state can possibly
cause a signal to be delivered wrong, because the register state when
a signal is raised won't affect delivery, which seems like a good
thing to me.

If this behavior would be problematic for you, can you explain why?

Re: [PATCH 1/4] signals/sigaltstack: If SS_AUTODISARM, bypass on_sig_stack

From: Stas Sergeev <hidden>
Date: 2016-05-09 02:05:17

09.05.2016 04:32, Andy Lutomirski пишет:
On May 7, 2016 7:38 AM, "Stas Sergeev" [off-list ref] wrote:
quoted
03.05.2016 20:31, Andy Lutomirski пишет:
quoted
If a signal stack is set up with SS_AUTODISARM, then the kernel
inherently avoids incorrectly resetting the signal stack if signals
recurse: the signal stack will be reset on the first signal
delivery.  This means that we don't need check the stack pointer
when delivering signals if SS_AUTODISARM is set.

This will make segmented x86 programs more robust: currently there's
a hole that could be triggered if ESP/RSP appears to point to the
signal stack but actually doesn't due to a nonzero SS base.

Signed-off-by: Stas Sergeev <redacted>
Cc: Al Viro <viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
Cc: Aleksa Sarai <cyphar-gVpy/LI/lHzQT0dZR+AlfA@public.gmane.org>
Cc: Amanieu d'Antras <redacted>
Cc: Andrea Arcangeli <redacted>
Cc: Andrew Morton <akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
Cc: Andy Lutomirski <redacted>
Cc: Borislav Petkov <redacted>
Cc: Brian Gerst <redacted>
Cc: Denys Vlasenko <redacted>
Cc: Eric W. Biederman <ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>
Cc: Frederic Weisbecker <redacted>
Cc: H. Peter Anvin <redacted>
Cc: Heinrich Schuchardt <redacted>
Cc: Jason Low <redacted>
Cc: Josh Triplett <redacted>
Cc: Konstantin Khlebnikov <redacted>
Cc: Linus Torvalds <torvalds-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
Cc: Oleg Nesterov <redacted>
Cc: Palmer Dabbelt <redacted>
Cc: Paul Moore <redacted>
Cc: Pavel Emelyanov <redacted>
Cc: Peter Zijlstra <redacted>
Cc: Richard Weinberger <richard-/L3Ra7n9ekc@public.gmane.org>
Cc: Sasha Levin <redacted>
Cc: Shuah Khan <redacted>
Cc: Tejun Heo <redacted>
Cc: Thomas Gleixner <redacted>
Cc: Vladimir Davydov <redacted>
Cc: linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Signed-off-by: Andy Lutomirski <redacted>
---
   include/linux/sched.h | 12 ++++++++++++
   1 file changed, 12 insertions(+)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 2950c5cd3005..8f03a93348b9 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2576,6 +2576,18 @@ static inline int kill_cad_pid(int sig, int priv)
    */
   static inline int on_sig_stack(unsigned long sp)
   {
+       /*
+        * If the signal stack is AUTODISARM then, by construction, we
+        * can't be on the signal stack unless user code deliberately set
+        * SS_AUTODISARM when we were already on the it.
"on the it" -> "on it".

Anyway, I am a bit puzzled with this patch.
You say "unless user code deliberately set

SS_AUTODISARM when we were already on the it"
so what happens in case it actually does?
Stack corruption.  Don't do that.
Only after your change, I have to admit. :)
quoted
Without your patch: if user sets up the same sas - no stack switch.
if user sets up different sas - stack switch on nested signal.

With your patch: stack switch in any case, so if user
set up same sas - stack corruption by nested signal.

Or am I missing the intention?
The intention is to make everything completely explicit.  With
SS_AUTODISARM, the kernel knows directly whether you're on the signal
stack, and there should be no need to look at sp.  If you set
SS_AUTODISARM and get a signal, the signal stack gets disarmed.  If
you take a nested signal, it's delivered normally.  When you return
all the way out, the signal stack is re-armed.

For DOSEMU, this means that no 16-bit register state can possibly
cause a signal to be delivered wrong, because the register state when
a signal is raised won't affect delivery, which seems like a good
thing to me.
Yes, but doesn't affect dosemu1 which doesn't use SS_AUTODISARM.
So IMHO the SS check should still be added, even if not for dosemu2.
If this behavior would be problematic for you, can you explain why?
Only theoretically: if someone sets SS_AUTODISARM inside a
sighandler. Since this doesn't give EPERM, I wouldn't deliberately
make it a broken scenario (esp if it wasn't before the particular change).
Ideally it would give EPERM, but we can't, so doesn't matter much.
I just wanted to warn about the possible regression.

Re: [PATCH 1/4] signals/sigaltstack: If SS_AUTODISARM, bypass on_sig_stack

From: Andy Lutomirski <luto@amacapital.net>
Date: 2016-05-14 04:18:44

On May 8, 2016 7:05 PM, "Stas Sergeev" [off-list ref] wrote:
09.05.2016 04:32, Andy Lutomirski пишет:
quoted
On May 7, 2016 7:38 AM, "Stas Sergeev" [off-list ref] wrote:
quoted
03.05.2016 20:31, Andy Lutomirski пишет:
quoted
If a signal stack is set up with SS_AUTODISARM, then the kernel
inherently avoids incorrectly resetting the signal stack if signals
recurse: the signal stack will be reset on the first signal
delivery.  This means that we don't need check the stack pointer
when delivering signals if SS_AUTODISARM is set.

This will make segmented x86 programs more robust: currently there's
a hole that could be triggered if ESP/RSP appears to point to the
signal stack but actually doesn't due to a nonzero SS base.

Signed-off-by: Stas Sergeev <redacted>
Cc: Al Viro <viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
Cc: Aleksa Sarai <cyphar-gVpy/LI/lHzQT0dZR+AlfA@public.gmane.org>
Cc: Amanieu d'Antras <redacted>
Cc: Andrea Arcangeli <redacted>
Cc: Andrew Morton <akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
Cc: Andy Lutomirski <redacted>
Cc: Borislav Petkov <redacted>
Cc: Brian Gerst <redacted>
Cc: Denys Vlasenko <redacted>
Cc: Eric W. Biederman <ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>
Cc: Frederic Weisbecker <redacted>
Cc: H. Peter Anvin <redacted>
Cc: Heinrich Schuchardt <redacted>
Cc: Jason Low <redacted>
Cc: Josh Triplett <redacted>
Cc: Konstantin Khlebnikov <redacted>
Cc: Linus Torvalds <torvalds-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
Cc: Oleg Nesterov <redacted>
Cc: Palmer Dabbelt <redacted>
Cc: Paul Moore <redacted>
Cc: Pavel Emelyanov <redacted>
Cc: Peter Zijlstra <redacted>
Cc: Richard Weinberger <richard-/L3Ra7n9ekc@public.gmane.org>
Cc: Sasha Levin <redacted>
Cc: Shuah Khan <redacted>
Cc: Tejun Heo <redacted>
Cc: Thomas Gleixner <redacted>
Cc: Vladimir Davydov <redacted>
Cc: linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Signed-off-by: Andy Lutomirski <redacted>
---
   include/linux/sched.h | 12 ++++++++++++
   1 file changed, 12 insertions(+)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 2950c5cd3005..8f03a93348b9 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2576,6 +2576,18 @@ static inline int kill_cad_pid(int sig, int priv)
    */
   static inline int on_sig_stack(unsigned long sp)
   {
+       /*
+        * If the signal stack is AUTODISARM then, by construction, we
+        * can't be on the signal stack unless user code deliberately set
+        * SS_AUTODISARM when we were already on the it.
"on the it" -> "on it".

Anyway, I am a bit puzzled with this patch.
You say "unless user code deliberately set

SS_AUTODISARM when we were already on the it"
so what happens in case it actually does?
Stack corruption.  Don't do that.
Only after your change, I have to admit. :)

quoted
quoted
Without your patch: if user sets up the same sas - no stack switch.
if user sets up different sas - stack switch on nested signal.

With your patch: stack switch in any case, so if user
set up same sas - stack corruption by nested signal.

Or am I missing the intention?
The intention is to make everything completely explicit.  With
SS_AUTODISARM, the kernel knows directly whether you're on the signal
stack, and there should be no need to look at sp.  If you set
SS_AUTODISARM and get a signal, the signal stack gets disarmed.  If
you take a nested signal, it's delivered normally.  When you return
all the way out, the signal stack is re-armed.

For DOSEMU, this means that no 16-bit register state can possibly
cause a signal to be delivered wrong, because the register state when
a signal is raised won't affect delivery, which seems like a good
thing to me.
Yes, but doesn't affect dosemu1 which doesn't use SS_AUTODISARM.
So IMHO the SS check should still be added, even if not for dosemu2.

quoted
If this behavior would be problematic for you, can you explain why?
Only theoretically: if someone sets SS_AUTODISARM inside a
sighandler. Since this doesn't give EPERM, I wouldn't deliberately
make it a broken scenario (esp if it wasn't before the particular change).
Ideally it would give EPERM, but we can't, so doesn't matter much.
I just wanted to warn about the possible regression.
I suppose we could return an error if you are on the sigstack when
setting SS_AUTODISARM, although I was hoping to avoid yet more special
cases.
--
To unsubscribe from this list: send the line "unsubscribe linux-api" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Re: [PATCH 1/4] signals/sigaltstack: If SS_AUTODISARM, bypass on_sig_stack

From: Stas Sergeev <hidden>
Date: 2016-05-14 11:18:44

14.05.2016 07:18, Andy Lutomirski пишет:
On May 8, 2016 7:05 PM, "Stas Sergeev" [off-list ref] wrote:
quoted
09.05.2016 04:32, Andy Lutomirski пишет:
quoted
On May 7, 2016 7:38 AM, "Stas Sergeev" [off-list ref] wrote:
quoted
03.05.2016 20:31, Andy Lutomirski пишет:
quoted
If a signal stack is set up with SS_AUTODISARM, then the kernel
inherently avoids incorrectly resetting the signal stack if signals
recurse: the signal stack will be reset on the first signal
delivery.  This means that we don't need check the stack pointer
when delivering signals if SS_AUTODISARM is set.

This will make segmented x86 programs more robust: currently there's
a hole that could be triggered if ESP/RSP appears to point to the
signal stack but actually doesn't due to a nonzero SS base.

Signed-off-by: Stas Sergeev <redacted>
Cc: Al Viro <viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn@public.gmane.org>
Cc: Aleksa Sarai <cyphar-gVpy/LI/lHzQT0dZR+AlfA@public.gmane.org>
Cc: Amanieu d'Antras <redacted>
Cc: Andrea Arcangeli <redacted>
Cc: Andrew Morton <akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
Cc: Andy Lutomirski <redacted>
Cc: Borislav Petkov <redacted>
Cc: Brian Gerst <redacted>
Cc: Denys Vlasenko <redacted>
Cc: Eric W. Biederman <ebiederm-aS9lmoZGLiVWk0Htik3J/w@public.gmane.org>
Cc: Frederic Weisbecker <redacted>
Cc: H. Peter Anvin <redacted>
Cc: Heinrich Schuchardt <redacted>
Cc: Jason Low <redacted>
Cc: Josh Triplett <redacted>
Cc: Konstantin Khlebnikov <redacted>
Cc: Linus Torvalds <torvalds-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
Cc: Oleg Nesterov <redacted>
Cc: Palmer Dabbelt <redacted>
Cc: Paul Moore <redacted>
Cc: Pavel Emelyanov <redacted>
Cc: Peter Zijlstra <redacted>
Cc: Richard Weinberger <richard-/L3Ra7n9ekc@public.gmane.org>
Cc: Sasha Levin <redacted>
Cc: Shuah Khan <redacted>
Cc: Tejun Heo <redacted>
Cc: Thomas Gleixner <redacted>
Cc: Vladimir Davydov <redacted>
Cc: linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Signed-off-by: Andy Lutomirski <redacted>
---
    include/linux/sched.h | 12 ++++++++++++
    1 file changed, 12 insertions(+)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 2950c5cd3005..8f03a93348b9 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2576,6 +2576,18 @@ static inline int kill_cad_pid(int sig, int priv)
     */
    static inline int on_sig_stack(unsigned long sp)
    {
+       /*
+        * If the signal stack is AUTODISARM then, by construction, we
+        * can't be on the signal stack unless user code deliberately set
+        * SS_AUTODISARM when we were already on the it.
"on the it" -> "on it".

Anyway, I am a bit puzzled with this patch.
You say "unless user code deliberately set

SS_AUTODISARM when we were already on the it"
so what happens in case it actually does?
Stack corruption.  Don't do that.
Only after your change, I have to admit. :)

quoted
quoted
Without your patch: if user sets up the same sas - no stack switch.
if user sets up different sas - stack switch on nested signal.

With your patch: stack switch in any case, so if user
set up same sas - stack corruption by nested signal.

Or am I missing the intention?
The intention is to make everything completely explicit.  With
SS_AUTODISARM, the kernel knows directly whether you're on the signal
stack, and there should be no need to look at sp.  If you set
SS_AUTODISARM and get a signal, the signal stack gets disarmed.  If
you take a nested signal, it's delivered normally.  When you return
all the way out, the signal stack is re-armed.

For DOSEMU, this means that no 16-bit register state can possibly
cause a signal to be delivered wrong, because the register state when
a signal is raised won't affect delivery, which seems like a good
thing to me.
Yes, but doesn't affect dosemu1 which doesn't use SS_AUTODISARM.
So IMHO the SS check should still be added, even if not for dosemu2.

quoted
If this behavior would be problematic for you, can you explain why?
Only theoretically: if someone sets SS_AUTODISARM inside a
sighandler. Since this doesn't give EPERM, I wouldn't deliberately
make it a broken scenario (esp if it wasn't before the particular change).
Ideally it would give EPERM, but we can't, so doesn't matter much.
I just wanted to warn about the possible regression.
I suppose we could return an error if you are on the sigstack when
setting SS_AUTODISARM, although I was hoping to avoid yet more special
cases.
Hmm.
How about extending the generic check then?
Currently it is roughly:
if (on_sig_stack(sp)) return -EPERM;

and we could do:
if (on_sig_stack(sp) || on_new_sas(new_sas, sp)) return -EPERM;

Looks like it will close the potential hole opened by your commit
without introducing the special case for SS_AUTODISARM.
What do you think?

Re: [PATCH 1/4] signals/sigaltstack: If SS_AUTODISARM, bypass on_sig_stack

From: Andy Lutomirski <luto@amacapital.net>
Date: 2016-05-14 16:36:05

On May 14, 2016 4:18 AM, "Stas Sergeev" [off-list ref] wrote:
14.05.2016 07:18, Andy Lutomirski пишет:
quoted
On May 8, 2016 7:05 PM, "Stas Sergeev" [off-list ref] wrote:
quoted
09.05.2016 04:32, Andy Lutomirski пишет:
quoted
On May 7, 2016 7:38 AM, "Stas Sergeev" [off-list ref] wrote:
quoted
03.05.2016 20:31, Andy Lutomirski пишет:
quoted
If a signal stack is set up with SS_AUTODISARM, then the kernel
inherently avoids incorrectly resetting the signal stack if signals
recurse: the signal stack will be reset on the first signal
delivery.  This means that we don't need check the stack pointer
when delivering signals if SS_AUTODISARM is set.

This will make segmented x86 programs more robust: currently there's
a hole that could be triggered if ESP/RSP appears to point to the
signal stack but actually doesn't due to a nonzero SS base.

Signed-off-by: Stas Sergeev <redacted>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Aleksa Sarai <redacted>
Cc: Amanieu d'Antras <redacted>
Cc: Andrea Arcangeli <redacted>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <redacted>
Cc: Denys Vlasenko <redacted>
Cc: Eric W. Biederman <redacted>
Cc: Frederic Weisbecker <redacted>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Heinrich Schuchardt <redacted>
Cc: Jason Low <redacted>
Cc: Josh Triplett <josh@joshtriplett.org>
Cc: Konstantin Khlebnikov <redacted>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Palmer Dabbelt <palmer@dabbelt.com>
Cc: Paul Moore <redacted>
Cc: Pavel Emelyanov <redacted>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Richard Weinberger <richard@nod.at>
Cc: Sasha Levin <redacted>
Cc: Shuah Khan <redacted>
Cc: Tejun Heo <tj@kernel.org>
Cc: Thomas Gleixner <redacted>
Cc: Vladimir Davydov <redacted>
Cc: linux-api@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Andy Lutomirski <luto@kernel.org>
---
    include/linux/sched.h | 12 ++++++++++++
    1 file changed, 12 insertions(+)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 2950c5cd3005..8f03a93348b9 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2576,6 +2576,18 @@ static inline int kill_cad_pid(int sig, int priv)
     */
    static inline int on_sig_stack(unsigned long sp)
    {
+       /*
+        * If the signal stack is AUTODISARM then, by construction, we
+        * can't be on the signal stack unless user code deliberately set
+        * SS_AUTODISARM when we were already on the it.
"on the it" -> "on it".

Anyway, I am a bit puzzled with this patch.
You say "unless user code deliberately set

SS_AUTODISARM when we were already on the it"
so what happens in case it actually does?
Stack corruption.  Don't do that.
Only after your change, I have to admit. :)

quoted
quoted
Without your patch: if user sets up the same sas - no stack switch.
if user sets up different sas - stack switch on nested signal.

With your patch: stack switch in any case, so if user
set up same sas - stack corruption by nested signal.

Or am I missing the intention?
The intention is to make everything completely explicit.  With
SS_AUTODISARM, the kernel knows directly whether you're on the signal
stack, and there should be no need to look at sp.  If you set
SS_AUTODISARM and get a signal, the signal stack gets disarmed.  If
you take a nested signal, it's delivered normally.  When you return
all the way out, the signal stack is re-armed.

For DOSEMU, this means that no 16-bit register state can possibly
cause a signal to be delivered wrong, because the register state when
a signal is raised won't affect delivery, which seems like a good
thing to me.
Yes, but doesn't affect dosemu1 which doesn't use SS_AUTODISARM.
So IMHO the SS check should still be added, even if not for dosemu2.

quoted
If this behavior would be problematic for you, can you explain why?
Only theoretically: if someone sets SS_AUTODISARM inside a
sighandler. Since this doesn't give EPERM, I wouldn't deliberately
make it a broken scenario (esp if it wasn't before the particular change).
Ideally it would give EPERM, but we can't, so doesn't matter much.
I just wanted to warn about the possible regression.
I suppose we could return an error if you are on the sigstack when
setting SS_AUTODISARM, although I was hoping to avoid yet more special
cases.
Hmm.
How about extending the generic check then?
Currently it is roughly:
if (on_sig_stack(sp)) return -EPERM;

and we could do:
if (on_sig_stack(sp) || on_new_sas(new_sas, sp)) return -EPERM;

Looks like it will close the potential hole opened by your commit
without introducing the special case for SS_AUTODISARM.
What do you think?
It's still a wee bit ugly.  Also, doesn't that change existing
behavior for the existing non-AUTODISARM case?  Also, we'd have to
make sure that sigreturn doesn't trigger this check.

My inclination would be leave it alone.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help