All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v10 0/7] arm64: expose FAR_EL1 tag bits in siginfo
@ 2020-08-22  5:10 ` Peter Collingbourne
  0 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-08-22  5:10 UTC (permalink / raw)
  To: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	Eric W. Biederman, James E.J. Bottomley
  Cc: Peter Collingbourne, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-parisc, David Spickett

The kernel currently clears the tag bits (i.e. bits 56-63) in the fault
address exposed via siginfo.si_addr and sigcontext.fault_address. However,
the tag bits may be needed by tools in order to accurately diagnose
memory errors, such as HWASan [1] or future tools based on the Memory
Tagging Extension (MTE).

We should not stop clearing these bits in the existing fault address
fields, because there may be existing userspace applications that are
expecting the tag bits to be cleared. Instead, create a new pair of
union fields in siginfo._sigfault, and store the tag bits of FAR_EL1
there, together with a mask specifying which bits are valid.

However, one does not simply add fields to siginfo, especially since
userspace would have no way to detect that they are present and valid.
Therefore, the first five patches in this series introduce a mechanism
for userspace to detect the presence of our new siginfo fields,
and the last patch uses it to advertise the presence of said fields.

The series can be viewed on Gerrit here:
https://linux-review.googlesource.com/q/Ia8876bad8c798e0a32df7c2ce1256c4771c81446

[1] http://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html

Peter Collingbourne (7):
  parisc: start using signal-defs.h
  arch: move SA_* definitions to generic headers
  signal: clear non-uapi flag bits when passing/returning sa_flags
  signal: define the SA_UNSUPPORTED bit in sa_flags
  signal: deduplicate code dealing with common _sigfault fields
  signal: define the field siginfo.si_xflags
  arm64: expose FAR_EL1 tag bits in siginfo

 Documentation/arm64/tagged-pointers.rst    |  21 +++-
 arch/alpha/include/uapi/asm/signal.h       |  14 ---
 arch/arm/include/asm/signal.h              |   2 +
 arch/arm/include/uapi/asm/signal.h         |  28 +----
 arch/arm64/include/asm/exception.h         |   2 +-
 arch/arm64/include/asm/signal.h            |  17 +++
 arch/arm64/include/asm/system_misc.h       |   2 +-
 arch/arm64/include/asm/traps.h             |   6 +-
 arch/arm64/kernel/debug-monitors.c         |   5 +-
 arch/arm64/kernel/entry-common.c           |   2 -
 arch/arm64/kernel/ptrace.c                 |   7 +-
 arch/arm64/kernel/sys_compat.c             |   5 +-
 arch/arm64/kernel/traps.c                  |  29 ++---
 arch/arm64/mm/fault.c                      |  59 +++++-----
 arch/h8300/include/uapi/asm/signal.h       |  24 ----
 arch/ia64/include/uapi/asm/signal.h        |  24 ----
 arch/m68k/include/uapi/asm/signal.h        |  24 ----
 arch/mips/include/uapi/asm/signal.h        |  12 --
 arch/parisc/include/asm/signal.h           |   2 +
 arch/parisc/include/uapi/asm/signal.h      |  22 +---
 arch/powerpc/include/uapi/asm/signal.h     |  24 ----
 arch/powerpc/platforms/powernv/vas-fault.c |   1 +
 arch/s390/include/uapi/asm/signal.h        |  24 ----
 arch/sparc/include/uapi/asm/signal.h       |   4 +-
 arch/x86/include/uapi/asm/signal.h         |  24 ----
 arch/x86/kernel/signal_compat.c            |  11 +-
 arch/xtensa/include/uapi/asm/signal.h      |  24 ----
 include/linux/compat.h                     |   4 +
 include/linux/signal.h                     |  21 ++++
 include/linux/signal_types.h               |  12 ++
 include/uapi/asm-generic/siginfo.h         |  14 +++
 include/uapi/asm-generic/signal-defs.h     |  64 ++++++++++
 include/uapi/asm-generic/signal.h          |  29 -----
 include/uapi/linux/ptrace.h                |   2 +
 kernel/ptrace.c                            |  29 +++++
 kernel/signal.c                            | 130 +++++++++++----------
 36 files changed, 315 insertions(+), 409 deletions(-)
 create mode 100644 arch/arm64/include/asm/signal.h

-- 
2.28.0.297.g1956fa8f8d-goog


^ permalink raw reply	[flat|nested] 59+ messages in thread

* [PATCH v10 0/7] arm64: expose FAR_EL1 tag bits in siginfo
@ 2020-08-22  5:10 ` Peter Collingbourne
  0 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-08-22  5:10 UTC (permalink / raw)
  To: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	Eric W. Biederman, James E.J. Bottomley
  Cc: linux-parisc, Andrey Konovalov, Kevin Brodsky, David Spickett,
	Peter Collingbourne, Linux ARM, Richard Henderson

The kernel currently clears the tag bits (i.e. bits 56-63) in the fault
address exposed via siginfo.si_addr and sigcontext.fault_address. However,
the tag bits may be needed by tools in order to accurately diagnose
memory errors, such as HWASan [1] or future tools based on the Memory
Tagging Extension (MTE).

We should not stop clearing these bits in the existing fault address
fields, because there may be existing userspace applications that are
expecting the tag bits to be cleared. Instead, create a new pair of
union fields in siginfo._sigfault, and store the tag bits of FAR_EL1
there, together with a mask specifying which bits are valid.

However, one does not simply add fields to siginfo, especially since
userspace would have no way to detect that they are present and valid.
Therefore, the first five patches in this series introduce a mechanism
for userspace to detect the presence of our new siginfo fields,
and the last patch uses it to advertise the presence of said fields.

The series can be viewed on Gerrit here:
https://linux-review.googlesource.com/q/Ia8876bad8c798e0a32df7c2ce1256c4771c81446

[1] http://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html

Peter Collingbourne (7):
  parisc: start using signal-defs.h
  arch: move SA_* definitions to generic headers
  signal: clear non-uapi flag bits when passing/returning sa_flags
  signal: define the SA_UNSUPPORTED bit in sa_flags
  signal: deduplicate code dealing with common _sigfault fields
  signal: define the field siginfo.si_xflags
  arm64: expose FAR_EL1 tag bits in siginfo

 Documentation/arm64/tagged-pointers.rst    |  21 +++-
 arch/alpha/include/uapi/asm/signal.h       |  14 ---
 arch/arm/include/asm/signal.h              |   2 +
 arch/arm/include/uapi/asm/signal.h         |  28 +----
 arch/arm64/include/asm/exception.h         |   2 +-
 arch/arm64/include/asm/signal.h            |  17 +++
 arch/arm64/include/asm/system_misc.h       |   2 +-
 arch/arm64/include/asm/traps.h             |   6 +-
 arch/arm64/kernel/debug-monitors.c         |   5 +-
 arch/arm64/kernel/entry-common.c           |   2 -
 arch/arm64/kernel/ptrace.c                 |   7 +-
 arch/arm64/kernel/sys_compat.c             |   5 +-
 arch/arm64/kernel/traps.c                  |  29 ++---
 arch/arm64/mm/fault.c                      |  59 +++++-----
 arch/h8300/include/uapi/asm/signal.h       |  24 ----
 arch/ia64/include/uapi/asm/signal.h        |  24 ----
 arch/m68k/include/uapi/asm/signal.h        |  24 ----
 arch/mips/include/uapi/asm/signal.h        |  12 --
 arch/parisc/include/asm/signal.h           |   2 +
 arch/parisc/include/uapi/asm/signal.h      |  22 +---
 arch/powerpc/include/uapi/asm/signal.h     |  24 ----
 arch/powerpc/platforms/powernv/vas-fault.c |   1 +
 arch/s390/include/uapi/asm/signal.h        |  24 ----
 arch/sparc/include/uapi/asm/signal.h       |   4 +-
 arch/x86/include/uapi/asm/signal.h         |  24 ----
 arch/x86/kernel/signal_compat.c            |  11 +-
 arch/xtensa/include/uapi/asm/signal.h      |  24 ----
 include/linux/compat.h                     |   4 +
 include/linux/signal.h                     |  21 ++++
 include/linux/signal_types.h               |  12 ++
 include/uapi/asm-generic/siginfo.h         |  14 +++
 include/uapi/asm-generic/signal-defs.h     |  64 ++++++++++
 include/uapi/asm-generic/signal.h          |  29 -----
 include/uapi/linux/ptrace.h                |   2 +
 kernel/ptrace.c                            |  29 +++++
 kernel/signal.c                            | 130 +++++++++++----------
 36 files changed, 315 insertions(+), 409 deletions(-)
 create mode 100644 arch/arm64/include/asm/signal.h

-- 
2.28.0.297.g1956fa8f8d-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* [PATCH v10 1/7] parisc: start using signal-defs.h
  2020-08-22  5:10 ` Peter Collingbourne
@ 2020-08-22  5:10   ` Peter Collingbourne
  -1 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-08-22  5:10 UTC (permalink / raw)
  To: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	Eric W. Biederman, James E.J. Bottomley
  Cc: Peter Collingbourne, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-parisc, David Spickett

We currently include signal-defs.h on all architectures except parisc.
Make parisc fall in line. This will make maintenance easier once the
flag bits are moved here.

Signed-off-by: Peter Collingbourne <pcc@google.com>
---
View this change in Gerrit: https://linux-review.googlesource.com/q/If03a5135fb514fe96548fb74610e6c3586a04064

 arch/parisc/include/uapi/asm/signal.h  | 9 +--------
 include/uapi/asm-generic/signal-defs.h | 6 ++++++
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/arch/parisc/include/uapi/asm/signal.h b/arch/parisc/include/uapi/asm/signal.h
index d38563a394f2..92a1c7ea44b4 100644
--- a/arch/parisc/include/uapi/asm/signal.h
+++ b/arch/parisc/include/uapi/asm/signal.h
@@ -69,14 +69,7 @@
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
 
-
-#define SIG_BLOCK          0	/* for blocking signals */
-#define SIG_UNBLOCK        1	/* for unblocking signals */
-#define SIG_SETMASK        2	/* for setting the signal mask */
-
-#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
-#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
-#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+#include <asm/signal-defs.h>
 
 # ifndef __ASSEMBLY__
 
diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
index e9304c95ceea..ecdf6312bfa5 100644
--- a/include/uapi/asm-generic/signal-defs.h
+++ b/include/uapi/asm-generic/signal-defs.h
@@ -15,8 +15,14 @@
 #endif
 
 #ifndef __ASSEMBLY__
+#ifndef __hppa__
+/*
+ * These have a special definition on parisc, see:
+ * arch/parisc/include/uapi/asm/signal.h
+ */
 typedef void __signalfn_t(int);
 typedef __signalfn_t __user *__sighandler_t;
+#endif
 
 typedef void __restorefn_t(void);
 typedef __restorefn_t __user *__sigrestore_t;
-- 
2.28.0.297.g1956fa8f8d-goog


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v10 1/7] parisc: start using signal-defs.h
@ 2020-08-22  5:10   ` Peter Collingbourne
  0 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-08-22  5:10 UTC (permalink / raw)
  To: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	Eric W. Biederman, James E.J. Bottomley
  Cc: linux-parisc, Andrey Konovalov, Kevin Brodsky, David Spickett,
	Peter Collingbourne, Linux ARM, Richard Henderson

We currently include signal-defs.h on all architectures except parisc.
Make parisc fall in line. This will make maintenance easier once the
flag bits are moved here.

Signed-off-by: Peter Collingbourne <pcc@google.com>
---
View this change in Gerrit: https://linux-review.googlesource.com/q/If03a5135fb514fe96548fb74610e6c3586a04064

 arch/parisc/include/uapi/asm/signal.h  | 9 +--------
 include/uapi/asm-generic/signal-defs.h | 6 ++++++
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/arch/parisc/include/uapi/asm/signal.h b/arch/parisc/include/uapi/asm/signal.h
index d38563a394f2..92a1c7ea44b4 100644
--- a/arch/parisc/include/uapi/asm/signal.h
+++ b/arch/parisc/include/uapi/asm/signal.h
@@ -69,14 +69,7 @@
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
 
-
-#define SIG_BLOCK          0	/* for blocking signals */
-#define SIG_UNBLOCK        1	/* for unblocking signals */
-#define SIG_SETMASK        2	/* for setting the signal mask */
-
-#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
-#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
-#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+#include <asm/signal-defs.h>
 
 # ifndef __ASSEMBLY__
 
diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
index e9304c95ceea..ecdf6312bfa5 100644
--- a/include/uapi/asm-generic/signal-defs.h
+++ b/include/uapi/asm-generic/signal-defs.h
@@ -15,8 +15,14 @@
 #endif
 
 #ifndef __ASSEMBLY__
+#ifndef __hppa__
+/*
+ * These have a special definition on parisc, see:
+ * arch/parisc/include/uapi/asm/signal.h
+ */
 typedef void __signalfn_t(int);
 typedef __signalfn_t __user *__sighandler_t;
+#endif
 
 typedef void __restorefn_t(void);
 typedef __restorefn_t __user *__sigrestore_t;
-- 
2.28.0.297.g1956fa8f8d-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v10 2/7] arch: move SA_* definitions to generic headers
  2020-08-22  5:10 ` Peter Collingbourne
@ 2020-08-22  5:10   ` Peter Collingbourne
  -1 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-08-22  5:10 UTC (permalink / raw)
  To: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	Eric W. Biederman, James E.J. Bottomley
  Cc: Peter Collingbourne, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-parisc, David Spickett

Most architectures with the exception of alpha, mips, parisc and
sparc use the same values for these flags. Move their definitions into
asm-generic/signal-defs.h and allow the architectures with non-standard
values to override them. Also, document the non-standard flag values
in order to make it easier to add new generic flags in the future.

Signed-off-by: Peter Collingbourne <pcc@google.com>
---
View this change in Gerrit: https://linux-review.googlesource.com/q/Ia3849f18b8009bf41faca374e701cdca36974528

v10:
- move the comments around and add one for SA_SIGINFO

 arch/alpha/include/uapi/asm/signal.h   | 14 --------
 arch/arm/include/uapi/asm/signal.h     | 28 ++-------------
 arch/h8300/include/uapi/asm/signal.h   | 24 -------------
 arch/ia64/include/uapi/asm/signal.h    | 24 -------------
 arch/m68k/include/uapi/asm/signal.h    | 24 -------------
 arch/mips/include/uapi/asm/signal.h    | 12 -------
 arch/parisc/include/uapi/asm/signal.h  | 13 -------
 arch/powerpc/include/uapi/asm/signal.h | 24 -------------
 arch/s390/include/uapi/asm/signal.h    | 24 -------------
 arch/sparc/include/uapi/asm/signal.h   |  4 +--
 arch/x86/include/uapi/asm/signal.h     | 24 -------------
 arch/xtensa/include/uapi/asm/signal.h  | 24 -------------
 include/uapi/asm-generic/signal-defs.h | 47 ++++++++++++++++++++++++++
 include/uapi/asm-generic/signal.h      | 29 ----------------
 14 files changed, 51 insertions(+), 264 deletions(-)

diff --git a/arch/alpha/include/uapi/asm/signal.h b/arch/alpha/include/uapi/asm/signal.h
index 74c750bf1c1a..a69dd8d080a8 100644
--- a/arch/alpha/include/uapi/asm/signal.h
+++ b/arch/alpha/include/uapi/asm/signal.h
@@ -60,20 +60,6 @@ typedef unsigned long sigset_t;
 #define SIGRTMIN	32
 #define SIGRTMAX	_NSIG
 
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-
 #define SA_ONSTACK	0x00000001
 #define SA_RESTART	0x00000002
 #define SA_NOCLDSTOP	0x00000004
diff --git a/arch/arm/include/uapi/asm/signal.h b/arch/arm/include/uapi/asm/signal.h
index 9b4185ba4f8a..7727f0984d26 100644
--- a/arch/arm/include/uapi/asm/signal.h
+++ b/arch/arm/include/uapi/asm/signal.h
@@ -60,33 +60,11 @@ typedef unsigned long sigset_t;
 #define SIGSWI		32
 
 /*
- * SA_FLAGS values:
- *
- * SA_NOCLDSTOP		flag to turn off SIGCHLD when children stop.
- * SA_NOCLDWAIT		flag on SIGCHLD to inhibit zombies.
- * SA_SIGINFO		deliver the signal with SIGINFO structs
- * SA_THIRTYTWO		delivers the signal in 32-bit mode, even if the task 
- *			is running in 26-bit.
- * SA_ONSTACK		allows alternate signal stacks (see sigaltstack(2)).
- * SA_RESTART		flag to get restarting signals (which were the default long ago)
- * SA_NODEFER		prevents the current signal from being masked in the handler.
- * SA_RESETHAND		clears the handler when the signal is delivered.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
+ * SA_THIRTYTWO historically meant deliver the signal in 32-bit mode, even if
+ * the task is running in 26-bit. But since the kernel no longer supports
+ * 26-bit mode, the flag has no effect.
  */
-#define SA_NOCLDSTOP	0x00000001
-#define SA_NOCLDWAIT	0x00000002
-#define SA_SIGINFO	0x00000004
 #define SA_THIRTYTWO	0x02000000
-#define SA_RESTORER	0x04000000
-#define SA_ONSTACK	0x08000000
-#define SA_RESTART	0x10000000
-#define SA_NODEFER	0x40000000
-#define SA_RESETHAND	0x80000000
-
-#define SA_NOMASK	SA_NODEFER
-#define SA_ONESHOT	SA_RESETHAND
 
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
diff --git a/arch/h8300/include/uapi/asm/signal.h b/arch/h8300/include/uapi/asm/signal.h
index e15521037348..2cd0dce2b6a6 100644
--- a/arch/h8300/include/uapi/asm/signal.h
+++ b/arch/h8300/include/uapi/asm/signal.h
@@ -57,30 +57,6 @@ typedef unsigned long sigset_t;
 #define SIGRTMIN	32
 #define SIGRTMAX	_NSIG
 
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP	0x00000001
-#define SA_NOCLDWAIT	0x00000002 /* not supported yet */
-#define SA_SIGINFO	0x00000004
-#define SA_ONSTACK	0x08000000
-#define SA_RESTART	0x10000000
-#define SA_NODEFER	0x40000000
-#define SA_RESETHAND	0x80000000
-
-#define SA_NOMASK	SA_NODEFER
-#define SA_ONESHOT	SA_RESETHAND
-
 #define SA_RESTORER	0x04000000
 
 #define MINSIGSTKSZ	2048
diff --git a/arch/ia64/include/uapi/asm/signal.h b/arch/ia64/include/uapi/asm/signal.h
index aa98ff1b9e22..38166a88e4c9 100644
--- a/arch/ia64/include/uapi/asm/signal.h
+++ b/arch/ia64/include/uapi/asm/signal.h
@@ -53,30 +53,6 @@
 #define SIGRTMIN	32
 #define SIGRTMAX	_NSIG
 
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP	0x00000001
-#define SA_NOCLDWAIT	0x00000002
-#define SA_SIGINFO	0x00000004
-#define SA_ONSTACK	0x08000000
-#define SA_RESTART	0x10000000
-#define SA_NODEFER	0x40000000
-#define SA_RESETHAND	0x80000000
-
-#define SA_NOMASK	SA_NODEFER
-#define SA_ONESHOT	SA_RESETHAND
-
 #define SA_RESTORER	0x04000000
 
 /*
diff --git a/arch/m68k/include/uapi/asm/signal.h b/arch/m68k/include/uapi/asm/signal.h
index 915cc755a184..4619291df601 100644
--- a/arch/m68k/include/uapi/asm/signal.h
+++ b/arch/m68k/include/uapi/asm/signal.h
@@ -57,30 +57,6 @@ typedef unsigned long sigset_t;
 #define SIGRTMIN	32
 #define SIGRTMAX	_NSIG
 
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP	0x00000001
-#define SA_NOCLDWAIT	0x00000002
-#define SA_SIGINFO	0x00000004
-#define SA_ONSTACK	0x08000000
-#define SA_RESTART	0x10000000
-#define SA_NODEFER	0x40000000
-#define SA_RESETHAND	0x80000000
-
-#define SA_NOMASK	SA_NODEFER
-#define SA_ONESHOT	SA_RESETHAND
-
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
 
diff --git a/arch/mips/include/uapi/asm/signal.h b/arch/mips/include/uapi/asm/signal.h
index 53104b10aae2..e6c78a15cb2f 100644
--- a/arch/mips/include/uapi/asm/signal.h
+++ b/arch/mips/include/uapi/asm/signal.h
@@ -62,18 +62,6 @@ typedef unsigned long old_sigset_t;		/* at least 32 bits */
 #define SIGRTMAX	_NSIG
 
 /*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- *
  * SA_RESTORER used to be defined as 0x04000000 but only the O32 ABI ever
  * supported its use and no libc was using it, so the entire sa-restorer
  * functionality was removed with lmo commit 39bffc12c3580ab for 2.5.48
diff --git a/arch/parisc/include/uapi/asm/signal.h b/arch/parisc/include/uapi/asm/signal.h
index 92a1c7ea44b4..32ec2e64c6ca 100644
--- a/arch/parisc/include/uapi/asm/signal.h
+++ b/arch/parisc/include/uapi/asm/signal.h
@@ -41,19 +41,6 @@
 #define SIGRTMIN	32
 #define SIGRTMAX	_NSIG /* it's 44 under HP/UX */
 
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
 #define SA_ONSTACK	0x00000001
 #define SA_RESETHAND	0x00000004
 #define SA_NOCLDSTOP	0x00000008
diff --git a/arch/powerpc/include/uapi/asm/signal.h b/arch/powerpc/include/uapi/asm/signal.h
index 85b0a7aa43e7..04873dd311c2 100644
--- a/arch/powerpc/include/uapi/asm/signal.h
+++ b/arch/powerpc/include/uapi/asm/signal.h
@@ -60,30 +60,6 @@ typedef struct {
 #define SIGRTMIN	32
 #define SIGRTMAX	_NSIG
 
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK is not currently supported, but will allow sigaltstack(2).
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP	0x00000001U
-#define SA_NOCLDWAIT	0x00000002U
-#define SA_SIGINFO	0x00000004U
-#define SA_ONSTACK	0x08000000U
-#define SA_RESTART	0x10000000U
-#define SA_NODEFER	0x40000000U
-#define SA_RESETHAND	0x80000000U
-
-#define SA_NOMASK	SA_NODEFER
-#define SA_ONESHOT	SA_RESETHAND
-
 #define SA_RESTORER	0x04000000U
 
 #define MINSIGSTKSZ	2048
diff --git a/arch/s390/include/uapi/asm/signal.h b/arch/s390/include/uapi/asm/signal.h
index 9a14a611ed82..0189f326aac5 100644
--- a/arch/s390/include/uapi/asm/signal.h
+++ b/arch/s390/include/uapi/asm/signal.h
@@ -65,30 +65,6 @@ typedef unsigned long sigset_t;
 #define SIGRTMIN        32
 #define SIGRTMAX        _NSIG
 
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP    0x00000001
-#define SA_NOCLDWAIT    0x00000002
-#define SA_SIGINFO      0x00000004
-#define SA_ONSTACK      0x08000000
-#define SA_RESTART      0x10000000
-#define SA_NODEFER      0x40000000
-#define SA_RESETHAND    0x80000000
-
-#define SA_NOMASK       SA_NODEFER
-#define SA_ONESHOT      SA_RESETHAND
-
 #define SA_RESTORER     0x04000000
 
 #define MINSIGSTKSZ     2048
diff --git a/arch/sparc/include/uapi/asm/signal.h b/arch/sparc/include/uapi/asm/signal.h
index ff9505923b9a..53758d53ac0e 100644
--- a/arch/sparc/include/uapi/asm/signal.h
+++ b/arch/sparc/include/uapi/asm/signal.h
@@ -137,13 +137,11 @@ struct sigstack {
 #define SA_STACK	_SV_SSTACK
 #define SA_ONSTACK	_SV_SSTACK
 #define SA_RESTART	_SV_INTR
-#define SA_ONESHOT	_SV_RESET
+#define SA_RESETHAND	_SV_RESET
 #define SA_NODEFER	0x20u
 #define SA_NOCLDWAIT    0x100u
 #define SA_SIGINFO      0x200u
 
-#define SA_NOMASK	SA_NODEFER
-
 #define SIG_BLOCK          0x01	/* for blocking signals */
 #define SIG_UNBLOCK        0x02	/* for unblocking signals */
 #define SIG_SETMASK        0x04	/* for setting the signal mask */
diff --git a/arch/x86/include/uapi/asm/signal.h b/arch/x86/include/uapi/asm/signal.h
index e5745d593dc7..164a22a72984 100644
--- a/arch/x86/include/uapi/asm/signal.h
+++ b/arch/x86/include/uapi/asm/signal.h
@@ -62,30 +62,6 @@ typedef unsigned long sigset_t;
 #define SIGRTMIN	32
 #define SIGRTMAX	_NSIG
 
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP	0x00000001u
-#define SA_NOCLDWAIT	0x00000002u
-#define SA_SIGINFO	0x00000004u
-#define SA_ONSTACK	0x08000000u
-#define SA_RESTART	0x10000000u
-#define SA_NODEFER	0x40000000u
-#define SA_RESETHAND	0x80000000u
-
-#define SA_NOMASK	SA_NODEFER
-#define SA_ONESHOT	SA_RESETHAND
-
 #define SA_RESTORER	0x04000000
 
 #define MINSIGSTKSZ	2048
diff --git a/arch/xtensa/include/uapi/asm/signal.h b/arch/xtensa/include/uapi/asm/signal.h
index 005dec5bfde4..79ddabaa4e5d 100644
--- a/arch/xtensa/include/uapi/asm/signal.h
+++ b/arch/xtensa/include/uapi/asm/signal.h
@@ -72,30 +72,6 @@ typedef struct {
 #define SIGRTMIN	32
 #define SIGRTMAX	(_NSIG-1)
 
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP	0x00000001
-#define SA_NOCLDWAIT	0x00000002 /* not supported yet */
-#define SA_SIGINFO	0x00000004
-#define SA_ONSTACK	0x08000000
-#define SA_RESTART	0x10000000
-#define SA_NODEFER	0x40000000
-#define SA_RESETHAND	0x80000000
-
-#define SA_NOMASK	SA_NODEFER
-#define SA_ONESHOT	SA_RESETHAND
-
 #define SA_RESTORER	0x04000000
 
 #define MINSIGSTKSZ	2048
diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
index ecdf6312bfa5..319628058a53 100644
--- a/include/uapi/asm-generic/signal-defs.h
+++ b/include/uapi/asm-generic/signal-defs.h
@@ -4,6 +4,53 @@
 
 #include <linux/compiler.h>
 
+/*
+ * SA_FLAGS values:
+ *
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_SIGINFO delivers the signal with SIGINFO structs.
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ *
+ * The following bits are used in architecture-specific SA_* definitions and
+ * should be avoided for new generic flags: 3, 4, 5, 6, 7, 8, 9, 16, 24, 25, 26.
+ */
+#ifndef SA_NOCLDSTOP
+#define SA_NOCLDSTOP	0x00000001
+#endif
+#ifndef SA_NOCLDWAIT
+#define SA_NOCLDWAIT	0x00000002
+#endif
+#ifndef SA_SIGINFO
+#define SA_SIGINFO	0x00000004
+#endif
+#ifndef SA_ONSTACK
+#define SA_ONSTACK	0x08000000
+#endif
+#ifndef SA_RESTART
+#define SA_RESTART	0x10000000
+#endif
+#ifndef SA_NODEFER
+#define SA_NODEFER	0x40000000
+#endif
+#ifndef SA_RESETHAND
+#define SA_RESETHAND	0x80000000
+#endif
+
+#define SA_NOMASK	SA_NODEFER
+#define SA_ONESHOT	SA_RESETHAND
+
+/*
+ * New architectures should not define the obsolete
+ *	SA_RESTORER	0x04000000
+ */
+
 #ifndef SIG_BLOCK
 #define SIG_BLOCK          0	/* for blocking signals */
 #endif
diff --git a/include/uapi/asm-generic/signal.h b/include/uapi/asm-generic/signal.h
index 5c716a952cbe..f634822906e4 100644
--- a/include/uapi/asm-generic/signal.h
+++ b/include/uapi/asm-generic/signal.h
@@ -52,35 +52,6 @@
 #define SIGRTMAX	_NSIG
 #endif
 
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP	0x00000001
-#define SA_NOCLDWAIT	0x00000002
-#define SA_SIGINFO	0x00000004
-#define SA_ONSTACK	0x08000000
-#define SA_RESTART	0x10000000
-#define SA_NODEFER	0x40000000
-#define SA_RESETHAND	0x80000000
-
-#define SA_NOMASK	SA_NODEFER
-#define SA_ONESHOT	SA_RESETHAND
-
-/*
- * New architectures should not define the obsolete
- *	SA_RESTORER	0x04000000
- */
-
 #if !defined MINSIGSTKSZ || !defined SIGSTKSZ
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
-- 
2.28.0.297.g1956fa8f8d-goog


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v10 2/7] arch: move SA_* definitions to generic headers
@ 2020-08-22  5:10   ` Peter Collingbourne
  0 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-08-22  5:10 UTC (permalink / raw)
  To: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	Eric W. Biederman, James E.J. Bottomley
  Cc: linux-parisc, Andrey Konovalov, Kevin Brodsky, David Spickett,
	Peter Collingbourne, Linux ARM, Richard Henderson

Most architectures with the exception of alpha, mips, parisc and
sparc use the same values for these flags. Move their definitions into
asm-generic/signal-defs.h and allow the architectures with non-standard
values to override them. Also, document the non-standard flag values
in order to make it easier to add new generic flags in the future.

Signed-off-by: Peter Collingbourne <pcc@google.com>
---
View this change in Gerrit: https://linux-review.googlesource.com/q/Ia3849f18b8009bf41faca374e701cdca36974528

v10:
- move the comments around and add one for SA_SIGINFO

 arch/alpha/include/uapi/asm/signal.h   | 14 --------
 arch/arm/include/uapi/asm/signal.h     | 28 ++-------------
 arch/h8300/include/uapi/asm/signal.h   | 24 -------------
 arch/ia64/include/uapi/asm/signal.h    | 24 -------------
 arch/m68k/include/uapi/asm/signal.h    | 24 -------------
 arch/mips/include/uapi/asm/signal.h    | 12 -------
 arch/parisc/include/uapi/asm/signal.h  | 13 -------
 arch/powerpc/include/uapi/asm/signal.h | 24 -------------
 arch/s390/include/uapi/asm/signal.h    | 24 -------------
 arch/sparc/include/uapi/asm/signal.h   |  4 +--
 arch/x86/include/uapi/asm/signal.h     | 24 -------------
 arch/xtensa/include/uapi/asm/signal.h  | 24 -------------
 include/uapi/asm-generic/signal-defs.h | 47 ++++++++++++++++++++++++++
 include/uapi/asm-generic/signal.h      | 29 ----------------
 14 files changed, 51 insertions(+), 264 deletions(-)

diff --git a/arch/alpha/include/uapi/asm/signal.h b/arch/alpha/include/uapi/asm/signal.h
index 74c750bf1c1a..a69dd8d080a8 100644
--- a/arch/alpha/include/uapi/asm/signal.h
+++ b/arch/alpha/include/uapi/asm/signal.h
@@ -60,20 +60,6 @@ typedef unsigned long sigset_t;
 #define SIGRTMIN	32
 #define SIGRTMAX	_NSIG
 
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-
 #define SA_ONSTACK	0x00000001
 #define SA_RESTART	0x00000002
 #define SA_NOCLDSTOP	0x00000004
diff --git a/arch/arm/include/uapi/asm/signal.h b/arch/arm/include/uapi/asm/signal.h
index 9b4185ba4f8a..7727f0984d26 100644
--- a/arch/arm/include/uapi/asm/signal.h
+++ b/arch/arm/include/uapi/asm/signal.h
@@ -60,33 +60,11 @@ typedef unsigned long sigset_t;
 #define SIGSWI		32
 
 /*
- * SA_FLAGS values:
- *
- * SA_NOCLDSTOP		flag to turn off SIGCHLD when children stop.
- * SA_NOCLDWAIT		flag on SIGCHLD to inhibit zombies.
- * SA_SIGINFO		deliver the signal with SIGINFO structs
- * SA_THIRTYTWO		delivers the signal in 32-bit mode, even if the task 
- *			is running in 26-bit.
- * SA_ONSTACK		allows alternate signal stacks (see sigaltstack(2)).
- * SA_RESTART		flag to get restarting signals (which were the default long ago)
- * SA_NODEFER		prevents the current signal from being masked in the handler.
- * SA_RESETHAND		clears the handler when the signal is delivered.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
+ * SA_THIRTYTWO historically meant deliver the signal in 32-bit mode, even if
+ * the task is running in 26-bit. But since the kernel no longer supports
+ * 26-bit mode, the flag has no effect.
  */
-#define SA_NOCLDSTOP	0x00000001
-#define SA_NOCLDWAIT	0x00000002
-#define SA_SIGINFO	0x00000004
 #define SA_THIRTYTWO	0x02000000
-#define SA_RESTORER	0x04000000
-#define SA_ONSTACK	0x08000000
-#define SA_RESTART	0x10000000
-#define SA_NODEFER	0x40000000
-#define SA_RESETHAND	0x80000000
-
-#define SA_NOMASK	SA_NODEFER
-#define SA_ONESHOT	SA_RESETHAND
 
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
diff --git a/arch/h8300/include/uapi/asm/signal.h b/arch/h8300/include/uapi/asm/signal.h
index e15521037348..2cd0dce2b6a6 100644
--- a/arch/h8300/include/uapi/asm/signal.h
+++ b/arch/h8300/include/uapi/asm/signal.h
@@ -57,30 +57,6 @@ typedef unsigned long sigset_t;
 #define SIGRTMIN	32
 #define SIGRTMAX	_NSIG
 
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP	0x00000001
-#define SA_NOCLDWAIT	0x00000002 /* not supported yet */
-#define SA_SIGINFO	0x00000004
-#define SA_ONSTACK	0x08000000
-#define SA_RESTART	0x10000000
-#define SA_NODEFER	0x40000000
-#define SA_RESETHAND	0x80000000
-
-#define SA_NOMASK	SA_NODEFER
-#define SA_ONESHOT	SA_RESETHAND
-
 #define SA_RESTORER	0x04000000
 
 #define MINSIGSTKSZ	2048
diff --git a/arch/ia64/include/uapi/asm/signal.h b/arch/ia64/include/uapi/asm/signal.h
index aa98ff1b9e22..38166a88e4c9 100644
--- a/arch/ia64/include/uapi/asm/signal.h
+++ b/arch/ia64/include/uapi/asm/signal.h
@@ -53,30 +53,6 @@
 #define SIGRTMIN	32
 #define SIGRTMAX	_NSIG
 
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP	0x00000001
-#define SA_NOCLDWAIT	0x00000002
-#define SA_SIGINFO	0x00000004
-#define SA_ONSTACK	0x08000000
-#define SA_RESTART	0x10000000
-#define SA_NODEFER	0x40000000
-#define SA_RESETHAND	0x80000000
-
-#define SA_NOMASK	SA_NODEFER
-#define SA_ONESHOT	SA_RESETHAND
-
 #define SA_RESTORER	0x04000000
 
 /*
diff --git a/arch/m68k/include/uapi/asm/signal.h b/arch/m68k/include/uapi/asm/signal.h
index 915cc755a184..4619291df601 100644
--- a/arch/m68k/include/uapi/asm/signal.h
+++ b/arch/m68k/include/uapi/asm/signal.h
@@ -57,30 +57,6 @@ typedef unsigned long sigset_t;
 #define SIGRTMIN	32
 #define SIGRTMAX	_NSIG
 
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP	0x00000001
-#define SA_NOCLDWAIT	0x00000002
-#define SA_SIGINFO	0x00000004
-#define SA_ONSTACK	0x08000000
-#define SA_RESTART	0x10000000
-#define SA_NODEFER	0x40000000
-#define SA_RESETHAND	0x80000000
-
-#define SA_NOMASK	SA_NODEFER
-#define SA_ONESHOT	SA_RESETHAND
-
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
 
diff --git a/arch/mips/include/uapi/asm/signal.h b/arch/mips/include/uapi/asm/signal.h
index 53104b10aae2..e6c78a15cb2f 100644
--- a/arch/mips/include/uapi/asm/signal.h
+++ b/arch/mips/include/uapi/asm/signal.h
@@ -62,18 +62,6 @@ typedef unsigned long old_sigset_t;		/* at least 32 bits */
 #define SIGRTMAX	_NSIG
 
 /*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- *
  * SA_RESTORER used to be defined as 0x04000000 but only the O32 ABI ever
  * supported its use and no libc was using it, so the entire sa-restorer
  * functionality was removed with lmo commit 39bffc12c3580ab for 2.5.48
diff --git a/arch/parisc/include/uapi/asm/signal.h b/arch/parisc/include/uapi/asm/signal.h
index 92a1c7ea44b4..32ec2e64c6ca 100644
--- a/arch/parisc/include/uapi/asm/signal.h
+++ b/arch/parisc/include/uapi/asm/signal.h
@@ -41,19 +41,6 @@
 #define SIGRTMIN	32
 #define SIGRTMAX	_NSIG /* it's 44 under HP/UX */
 
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
 #define SA_ONSTACK	0x00000001
 #define SA_RESETHAND	0x00000004
 #define SA_NOCLDSTOP	0x00000008
diff --git a/arch/powerpc/include/uapi/asm/signal.h b/arch/powerpc/include/uapi/asm/signal.h
index 85b0a7aa43e7..04873dd311c2 100644
--- a/arch/powerpc/include/uapi/asm/signal.h
+++ b/arch/powerpc/include/uapi/asm/signal.h
@@ -60,30 +60,6 @@ typedef struct {
 #define SIGRTMIN	32
 #define SIGRTMAX	_NSIG
 
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK is not currently supported, but will allow sigaltstack(2).
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP	0x00000001U
-#define SA_NOCLDWAIT	0x00000002U
-#define SA_SIGINFO	0x00000004U
-#define SA_ONSTACK	0x08000000U
-#define SA_RESTART	0x10000000U
-#define SA_NODEFER	0x40000000U
-#define SA_RESETHAND	0x80000000U
-
-#define SA_NOMASK	SA_NODEFER
-#define SA_ONESHOT	SA_RESETHAND
-
 #define SA_RESTORER	0x04000000U
 
 #define MINSIGSTKSZ	2048
diff --git a/arch/s390/include/uapi/asm/signal.h b/arch/s390/include/uapi/asm/signal.h
index 9a14a611ed82..0189f326aac5 100644
--- a/arch/s390/include/uapi/asm/signal.h
+++ b/arch/s390/include/uapi/asm/signal.h
@@ -65,30 +65,6 @@ typedef unsigned long sigset_t;
 #define SIGRTMIN        32
 #define SIGRTMAX        _NSIG
 
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP    0x00000001
-#define SA_NOCLDWAIT    0x00000002
-#define SA_SIGINFO      0x00000004
-#define SA_ONSTACK      0x08000000
-#define SA_RESTART      0x10000000
-#define SA_NODEFER      0x40000000
-#define SA_RESETHAND    0x80000000
-
-#define SA_NOMASK       SA_NODEFER
-#define SA_ONESHOT      SA_RESETHAND
-
 #define SA_RESTORER     0x04000000
 
 #define MINSIGSTKSZ     2048
diff --git a/arch/sparc/include/uapi/asm/signal.h b/arch/sparc/include/uapi/asm/signal.h
index ff9505923b9a..53758d53ac0e 100644
--- a/arch/sparc/include/uapi/asm/signal.h
+++ b/arch/sparc/include/uapi/asm/signal.h
@@ -137,13 +137,11 @@ struct sigstack {
 #define SA_STACK	_SV_SSTACK
 #define SA_ONSTACK	_SV_SSTACK
 #define SA_RESTART	_SV_INTR
-#define SA_ONESHOT	_SV_RESET
+#define SA_RESETHAND	_SV_RESET
 #define SA_NODEFER	0x20u
 #define SA_NOCLDWAIT    0x100u
 #define SA_SIGINFO      0x200u
 
-#define SA_NOMASK	SA_NODEFER
-
 #define SIG_BLOCK          0x01	/* for blocking signals */
 #define SIG_UNBLOCK        0x02	/* for unblocking signals */
 #define SIG_SETMASK        0x04	/* for setting the signal mask */
diff --git a/arch/x86/include/uapi/asm/signal.h b/arch/x86/include/uapi/asm/signal.h
index e5745d593dc7..164a22a72984 100644
--- a/arch/x86/include/uapi/asm/signal.h
+++ b/arch/x86/include/uapi/asm/signal.h
@@ -62,30 +62,6 @@ typedef unsigned long sigset_t;
 #define SIGRTMIN	32
 #define SIGRTMAX	_NSIG
 
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP	0x00000001u
-#define SA_NOCLDWAIT	0x00000002u
-#define SA_SIGINFO	0x00000004u
-#define SA_ONSTACK	0x08000000u
-#define SA_RESTART	0x10000000u
-#define SA_NODEFER	0x40000000u
-#define SA_RESETHAND	0x80000000u
-
-#define SA_NOMASK	SA_NODEFER
-#define SA_ONESHOT	SA_RESETHAND
-
 #define SA_RESTORER	0x04000000
 
 #define MINSIGSTKSZ	2048
diff --git a/arch/xtensa/include/uapi/asm/signal.h b/arch/xtensa/include/uapi/asm/signal.h
index 005dec5bfde4..79ddabaa4e5d 100644
--- a/arch/xtensa/include/uapi/asm/signal.h
+++ b/arch/xtensa/include/uapi/asm/signal.h
@@ -72,30 +72,6 @@ typedef struct {
 #define SIGRTMIN	32
 #define SIGRTMAX	(_NSIG-1)
 
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP	0x00000001
-#define SA_NOCLDWAIT	0x00000002 /* not supported yet */
-#define SA_SIGINFO	0x00000004
-#define SA_ONSTACK	0x08000000
-#define SA_RESTART	0x10000000
-#define SA_NODEFER	0x40000000
-#define SA_RESETHAND	0x80000000
-
-#define SA_NOMASK	SA_NODEFER
-#define SA_ONESHOT	SA_RESETHAND
-
 #define SA_RESTORER	0x04000000
 
 #define MINSIGSTKSZ	2048
diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
index ecdf6312bfa5..319628058a53 100644
--- a/include/uapi/asm-generic/signal-defs.h
+++ b/include/uapi/asm-generic/signal-defs.h
@@ -4,6 +4,53 @@
 
 #include <linux/compiler.h>
 
+/*
+ * SA_FLAGS values:
+ *
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_SIGINFO delivers the signal with SIGINFO structs.
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ *
+ * The following bits are used in architecture-specific SA_* definitions and
+ * should be avoided for new generic flags: 3, 4, 5, 6, 7, 8, 9, 16, 24, 25, 26.
+ */
+#ifndef SA_NOCLDSTOP
+#define SA_NOCLDSTOP	0x00000001
+#endif
+#ifndef SA_NOCLDWAIT
+#define SA_NOCLDWAIT	0x00000002
+#endif
+#ifndef SA_SIGINFO
+#define SA_SIGINFO	0x00000004
+#endif
+#ifndef SA_ONSTACK
+#define SA_ONSTACK	0x08000000
+#endif
+#ifndef SA_RESTART
+#define SA_RESTART	0x10000000
+#endif
+#ifndef SA_NODEFER
+#define SA_NODEFER	0x40000000
+#endif
+#ifndef SA_RESETHAND
+#define SA_RESETHAND	0x80000000
+#endif
+
+#define SA_NOMASK	SA_NODEFER
+#define SA_ONESHOT	SA_RESETHAND
+
+/*
+ * New architectures should not define the obsolete
+ *	SA_RESTORER	0x04000000
+ */
+
 #ifndef SIG_BLOCK
 #define SIG_BLOCK          0	/* for blocking signals */
 #endif
diff --git a/include/uapi/asm-generic/signal.h b/include/uapi/asm-generic/signal.h
index 5c716a952cbe..f634822906e4 100644
--- a/include/uapi/asm-generic/signal.h
+++ b/include/uapi/asm-generic/signal.h
@@ -52,35 +52,6 @@
 #define SIGRTMAX	_NSIG
 #endif
 
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP	0x00000001
-#define SA_NOCLDWAIT	0x00000002
-#define SA_SIGINFO	0x00000004
-#define SA_ONSTACK	0x08000000
-#define SA_RESTART	0x10000000
-#define SA_NODEFER	0x40000000
-#define SA_RESETHAND	0x80000000
-
-#define SA_NOMASK	SA_NODEFER
-#define SA_ONESHOT	SA_RESETHAND
-
-/*
- * New architectures should not define the obsolete
- *	SA_RESTORER	0x04000000
- */
-
 #if !defined MINSIGSTKSZ || !defined SIGSTKSZ
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
-- 
2.28.0.297.g1956fa8f8d-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v10 3/7] signal: clear non-uapi flag bits when passing/returning sa_flags
  2020-08-22  5:10 ` Peter Collingbourne
@ 2020-08-22  5:10   ` Peter Collingbourne
  -1 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-08-22  5:10 UTC (permalink / raw)
  To: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	Eric W. Biederman, James E.J. Bottomley
  Cc: Peter Collingbourne, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-parisc, David Spickett

Previously we were not clearing non-uapi flag bits in
sigaction.sa_flags when storing the userspace-provided sa_flags or
when returning them via oldact. Start doing so.

This allows userspace to detect missing support for flag bits and
allows the kernel to use non-uapi bits internally, as we are already
doing in arch/x86 for two flag bits. Now that this change is in
place, we no longer need the code in arch/x86 that was hiding these
bits from userspace, so remove it.

This is technically a userspace-visible behavior change for sigaction, as
the unknown bits returned via oldact.sa_flags are no longer set. However,
we are free to define the behavior for unknown bits exactly because
their behavior is currently undefined, so for now we can define the
meaning of each of them to be "clear the bit in oldact.sa_flags unless
the bit becomes known in the future". Furthermore, this behavior is
consistent with OpenBSD [1], illumos [2] and XNU [3] (FreeBSD [4] and
NetBSD [5] fail the syscall if unknown bits are set). So there is some
precedent for this behavior in other kernels, and in particular in XNU,
which is probably the most popular kernel among those that I looked at,
which means that this change is less likely to be a compatibility issue.

Link: [1] https://github.com/openbsd/src/blob/f634a6a4b5bf832e9c1de77f7894ae2625e74484/sys/kern/kern_sig.c#L278
Link: [2] https://github.com/illumos/illumos-gate/blob/76f19f5fdc974fe5be5c82a556e43a4df93f1de1/usr/src/uts/common/syscall/sigaction.c#L86
Link: [3] https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/kern/kern_sig.c#L480
Link: [4] https://github.com/freebsd/freebsd/blob/eded70c37057857c6e23fae51f86b8f8f43cd2d0/sys/kern/kern_sig.c#L699
Link: [5] https://github.com/NetBSD/src/blob/3365779becdcedfca206091a645a0e8e22b2946e/sys/kern/sys_sig.c#L473
Signed-off-by: Peter Collingbourne <pcc@google.com>
---
View this change in Gerrit: https://linux-review.googlesource.com/q/I35aab6f5be932505d90f3b3450c083b4db1eca86

v10:
- rename SA_UAPI_FLAGS -> UAPI_SA_FLAGS
- refactor how we define it to avoid mentioning flags more
  than once

 arch/arm/include/asm/signal.h    |  2 ++
 arch/parisc/include/asm/signal.h |  2 ++
 arch/x86/kernel/signal_compat.c  |  7 -------
 include/linux/signal_types.h     | 12 ++++++++++++
 kernel/signal.c                  | 10 ++++++++++
 5 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/arch/arm/include/asm/signal.h b/arch/arm/include/asm/signal.h
index 65530a042009..430be7774402 100644
--- a/arch/arm/include/asm/signal.h
+++ b/arch/arm/include/asm/signal.h
@@ -17,6 +17,8 @@ typedef struct {
 	unsigned long sig[_NSIG_WORDS];
 } sigset_t;
 
+#define __ARCH_UAPI_SA_FLAGS	(SA_THIRTYTWO | SA_RESTORER)
+
 #define __ARCH_HAS_SA_RESTORER
 
 #include <asm/sigcontext.h>
diff --git a/arch/parisc/include/asm/signal.h b/arch/parisc/include/asm/signal.h
index 715c96ba2ec8..30dd1e43ef88 100644
--- a/arch/parisc/include/asm/signal.h
+++ b/arch/parisc/include/asm/signal.h
@@ -21,6 +21,8 @@ typedef struct {
 	unsigned long sig[_NSIG_WORDS];
 } sigset_t;
 
+#define __ARCH_UAPI_SA_FLAGS	_SA_SIGGFAULT
+
 #include <asm/sigcontext.h>
 
 #endif /* !__ASSEMBLY */
diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
index 9ccbf0576cd0..c599013ae8cb 100644
--- a/arch/x86/kernel/signal_compat.c
+++ b/arch/x86/kernel/signal_compat.c
@@ -165,16 +165,9 @@ void sigaction_compat_abi(struct k_sigaction *act, struct k_sigaction *oact)
 {
 	signal_compat_build_tests();
 
-	/* Don't leak in-kernel non-uapi flags to user-space */
-	if (oact)
-		oact->sa.sa_flags &= ~(SA_IA32_ABI | SA_X32_ABI);
-
 	if (!act)
 		return;
 
-	/* Don't let flags to be set from userspace */
-	act->sa.sa_flags &= ~(SA_IA32_ABI | SA_X32_ABI);
-
 	if (in_ia32_syscall())
 		act->sa.sa_flags |= SA_IA32_ABI;
 	if (in_x32_syscall())
diff --git a/include/linux/signal_types.h b/include/linux/signal_types.h
index f8a90ae9c6ec..a7887ad84d36 100644
--- a/include/linux/signal_types.h
+++ b/include/linux/signal_types.h
@@ -68,4 +68,16 @@ struct ksignal {
 	int sig;
 };
 
+#ifndef __ARCH_UAPI_SA_FLAGS
+#ifdef SA_RESTORER
+#define __ARCH_UAPI_SA_FLAGS	SA_RESTORER
+#else
+#define __ARCH_UAPI_SA_FLAGS	0
+#endif
+#endif
+
+#define UAPI_SA_FLAGS                                                          \
+	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
+	 SA_NODEFER | SA_RESETHAND | __ARCH_UAPI_SA_FLAGS)
+
 #endif /* _LINUX_SIGNAL_TYPES_H */
diff --git a/kernel/signal.c b/kernel/signal.c
index 42b67d2cea37..f802c82c7bcc 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -3984,6 +3984,16 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
 	if (oact)
 		*oact = *k;
 
+	/*
+	 * Clear unknown flag bits in order to allow userspace to detect missing
+	 * support for flag bits and to allow the kernel to use non-uapi bits
+	 * internally.
+	 */
+	if (act)
+		act->sa.sa_flags &= UAPI_SA_FLAGS;
+	if (oact)
+		oact->sa.sa_flags &= UAPI_SA_FLAGS;
+
 	sigaction_compat_abi(act, oact);
 
 	if (act) {
-- 
2.28.0.297.g1956fa8f8d-goog


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v10 3/7] signal: clear non-uapi flag bits when passing/returning sa_flags
@ 2020-08-22  5:10   ` Peter Collingbourne
  0 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-08-22  5:10 UTC (permalink / raw)
  To: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	Eric W. Biederman, James E.J. Bottomley
  Cc: linux-parisc, Andrey Konovalov, Kevin Brodsky, David Spickett,
	Peter Collingbourne, Linux ARM, Richard Henderson

Previously we were not clearing non-uapi flag bits in
sigaction.sa_flags when storing the userspace-provided sa_flags or
when returning them via oldact. Start doing so.

This allows userspace to detect missing support for flag bits and
allows the kernel to use non-uapi bits internally, as we are already
doing in arch/x86 for two flag bits. Now that this change is in
place, we no longer need the code in arch/x86 that was hiding these
bits from userspace, so remove it.

This is technically a userspace-visible behavior change for sigaction, as
the unknown bits returned via oldact.sa_flags are no longer set. However,
we are free to define the behavior for unknown bits exactly because
their behavior is currently undefined, so for now we can define the
meaning of each of them to be "clear the bit in oldact.sa_flags unless
the bit becomes known in the future". Furthermore, this behavior is
consistent with OpenBSD [1], illumos [2] and XNU [3] (FreeBSD [4] and
NetBSD [5] fail the syscall if unknown bits are set). So there is some
precedent for this behavior in other kernels, and in particular in XNU,
which is probably the most popular kernel among those that I looked at,
which means that this change is less likely to be a compatibility issue.

Link: [1] https://github.com/openbsd/src/blob/f634a6a4b5bf832e9c1de77f7894ae2625e74484/sys/kern/kern_sig.c#L278
Link: [2] https://github.com/illumos/illumos-gate/blob/76f19f5fdc974fe5be5c82a556e43a4df93f1de1/usr/src/uts/common/syscall/sigaction.c#L86
Link: [3] https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/kern/kern_sig.c#L480
Link: [4] https://github.com/freebsd/freebsd/blob/eded70c37057857c6e23fae51f86b8f8f43cd2d0/sys/kern/kern_sig.c#L699
Link: [5] https://github.com/NetBSD/src/blob/3365779becdcedfca206091a645a0e8e22b2946e/sys/kern/sys_sig.c#L473
Signed-off-by: Peter Collingbourne <pcc@google.com>
---
View this change in Gerrit: https://linux-review.googlesource.com/q/I35aab6f5be932505d90f3b3450c083b4db1eca86

v10:
- rename SA_UAPI_FLAGS -> UAPI_SA_FLAGS
- refactor how we define it to avoid mentioning flags more
  than once

 arch/arm/include/asm/signal.h    |  2 ++
 arch/parisc/include/asm/signal.h |  2 ++
 arch/x86/kernel/signal_compat.c  |  7 -------
 include/linux/signal_types.h     | 12 ++++++++++++
 kernel/signal.c                  | 10 ++++++++++
 5 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/arch/arm/include/asm/signal.h b/arch/arm/include/asm/signal.h
index 65530a042009..430be7774402 100644
--- a/arch/arm/include/asm/signal.h
+++ b/arch/arm/include/asm/signal.h
@@ -17,6 +17,8 @@ typedef struct {
 	unsigned long sig[_NSIG_WORDS];
 } sigset_t;
 
+#define __ARCH_UAPI_SA_FLAGS	(SA_THIRTYTWO | SA_RESTORER)
+
 #define __ARCH_HAS_SA_RESTORER
 
 #include <asm/sigcontext.h>
diff --git a/arch/parisc/include/asm/signal.h b/arch/parisc/include/asm/signal.h
index 715c96ba2ec8..30dd1e43ef88 100644
--- a/arch/parisc/include/asm/signal.h
+++ b/arch/parisc/include/asm/signal.h
@@ -21,6 +21,8 @@ typedef struct {
 	unsigned long sig[_NSIG_WORDS];
 } sigset_t;
 
+#define __ARCH_UAPI_SA_FLAGS	_SA_SIGGFAULT
+
 #include <asm/sigcontext.h>
 
 #endif /* !__ASSEMBLY */
diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
index 9ccbf0576cd0..c599013ae8cb 100644
--- a/arch/x86/kernel/signal_compat.c
+++ b/arch/x86/kernel/signal_compat.c
@@ -165,16 +165,9 @@ void sigaction_compat_abi(struct k_sigaction *act, struct k_sigaction *oact)
 {
 	signal_compat_build_tests();
 
-	/* Don't leak in-kernel non-uapi flags to user-space */
-	if (oact)
-		oact->sa.sa_flags &= ~(SA_IA32_ABI | SA_X32_ABI);
-
 	if (!act)
 		return;
 
-	/* Don't let flags to be set from userspace */
-	act->sa.sa_flags &= ~(SA_IA32_ABI | SA_X32_ABI);
-
 	if (in_ia32_syscall())
 		act->sa.sa_flags |= SA_IA32_ABI;
 	if (in_x32_syscall())
diff --git a/include/linux/signal_types.h b/include/linux/signal_types.h
index f8a90ae9c6ec..a7887ad84d36 100644
--- a/include/linux/signal_types.h
+++ b/include/linux/signal_types.h
@@ -68,4 +68,16 @@ struct ksignal {
 	int sig;
 };
 
+#ifndef __ARCH_UAPI_SA_FLAGS
+#ifdef SA_RESTORER
+#define __ARCH_UAPI_SA_FLAGS	SA_RESTORER
+#else
+#define __ARCH_UAPI_SA_FLAGS	0
+#endif
+#endif
+
+#define UAPI_SA_FLAGS                                                          \
+	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
+	 SA_NODEFER | SA_RESETHAND | __ARCH_UAPI_SA_FLAGS)
+
 #endif /* _LINUX_SIGNAL_TYPES_H */
diff --git a/kernel/signal.c b/kernel/signal.c
index 42b67d2cea37..f802c82c7bcc 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -3984,6 +3984,16 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
 	if (oact)
 		*oact = *k;
 
+	/*
+	 * Clear unknown flag bits in order to allow userspace to detect missing
+	 * support for flag bits and to allow the kernel to use non-uapi bits
+	 * internally.
+	 */
+	if (act)
+		act->sa.sa_flags &= UAPI_SA_FLAGS;
+	if (oact)
+		oact->sa.sa_flags &= UAPI_SA_FLAGS;
+
 	sigaction_compat_abi(act, oact);
 
 	if (act) {
-- 
2.28.0.297.g1956fa8f8d-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v10 4/7] signal: define the SA_UNSUPPORTED bit in sa_flags
  2020-08-22  5:10 ` Peter Collingbourne
@ 2020-08-22  5:10   ` Peter Collingbourne
  -1 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-08-22  5:10 UTC (permalink / raw)
  To: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	Eric W. Biederman, James E.J. Bottomley
  Cc: Peter Collingbourne, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-parisc, David Spickett

This bit will never be supported in the uapi. The purpose of this flag
bit is to allow userspace to distinguish an old kernel that does not
clear unknown sa_flags bits from a kernel that supports every flag bit.

In other words, if userspace finds that this bit remains set in
oldact.sa_flags, it means that the kernel cannot be trusted to have
cleared unknown flag bits from sa_flags, so no assumptions about flag
bit support can be made.

Signed-off-by: Peter Collingbourne <pcc@google.com>
---
View this change in Gerrit: https://linux-review.googlesource.com/q/Ic2501ad150a3a79c1cf27fb8c99be342e9dffbcb

 include/uapi/asm-generic/signal-defs.h | 7 +++++++
 kernel/signal.c                        | 6 ++++++
 2 files changed, 13 insertions(+)

diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
index 319628058a53..e853cbe8722d 100644
--- a/include/uapi/asm-generic/signal-defs.h
+++ b/include/uapi/asm-generic/signal-defs.h
@@ -14,6 +14,12 @@
  * SA_RESTART flag to get restarting signals (which were the default long ago)
  * SA_NODEFER prevents the current signal from being masked in the handler.
  * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_UNSUPPORTED is a flag bit that will never be supported. Kernels from
+ * before the introduction of SA_UNSUPPORTED did not clear unknown bits from
+ * sa_flags when read using the oldact argument to sigaction and rt_sigaction,
+ * so this bit allows flag bit support to be detected from userspace while
+ * allowing an old kernel to be distinguished from a kernel that supports every
+ * flag bit.
  *
  * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
  * Unix names RESETHAND and NODEFER respectively.
@@ -42,6 +48,7 @@
 #ifndef SA_RESETHAND
 #define SA_RESETHAND	0x80000000
 #endif
+#define SA_UNSUPPORTED	0x00000400
 
 #define SA_NOMASK	SA_NODEFER
 #define SA_ONESHOT	SA_RESETHAND
diff --git a/kernel/signal.c b/kernel/signal.c
index f802c82c7bcc..c80e70bde11d 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -3984,6 +3984,12 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
 	if (oact)
 		*oact = *k;
 
+	/*
+	 * Make sure that we never accidentally claim to support SA_UNSUPPORTED,
+	 * e.g. by having an architecture use the bit in their uapi.
+	 */
+	BUILD_BUG_ON(UAPI_SA_FLAGS & SA_UNSUPPORTED);
+
 	/*
 	 * Clear unknown flag bits in order to allow userspace to detect missing
 	 * support for flag bits and to allow the kernel to use non-uapi bits
-- 
2.28.0.297.g1956fa8f8d-goog


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v10 4/7] signal: define the SA_UNSUPPORTED bit in sa_flags
@ 2020-08-22  5:10   ` Peter Collingbourne
  0 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-08-22  5:10 UTC (permalink / raw)
  To: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	Eric W. Biederman, James E.J. Bottomley
  Cc: linux-parisc, Andrey Konovalov, Kevin Brodsky, David Spickett,
	Peter Collingbourne, Linux ARM, Richard Henderson

This bit will never be supported in the uapi. The purpose of this flag
bit is to allow userspace to distinguish an old kernel that does not
clear unknown sa_flags bits from a kernel that supports every flag bit.

In other words, if userspace finds that this bit remains set in
oldact.sa_flags, it means that the kernel cannot be trusted to have
cleared unknown flag bits from sa_flags, so no assumptions about flag
bit support can be made.

Signed-off-by: Peter Collingbourne <pcc@google.com>
---
View this change in Gerrit: https://linux-review.googlesource.com/q/Ic2501ad150a3a79c1cf27fb8c99be342e9dffbcb

 include/uapi/asm-generic/signal-defs.h | 7 +++++++
 kernel/signal.c                        | 6 ++++++
 2 files changed, 13 insertions(+)

diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
index 319628058a53..e853cbe8722d 100644
--- a/include/uapi/asm-generic/signal-defs.h
+++ b/include/uapi/asm-generic/signal-defs.h
@@ -14,6 +14,12 @@
  * SA_RESTART flag to get restarting signals (which were the default long ago)
  * SA_NODEFER prevents the current signal from being masked in the handler.
  * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_UNSUPPORTED is a flag bit that will never be supported. Kernels from
+ * before the introduction of SA_UNSUPPORTED did not clear unknown bits from
+ * sa_flags when read using the oldact argument to sigaction and rt_sigaction,
+ * so this bit allows flag bit support to be detected from userspace while
+ * allowing an old kernel to be distinguished from a kernel that supports every
+ * flag bit.
  *
  * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
  * Unix names RESETHAND and NODEFER respectively.
@@ -42,6 +48,7 @@
 #ifndef SA_RESETHAND
 #define SA_RESETHAND	0x80000000
 #endif
+#define SA_UNSUPPORTED	0x00000400
 
 #define SA_NOMASK	SA_NODEFER
 #define SA_ONESHOT	SA_RESETHAND
diff --git a/kernel/signal.c b/kernel/signal.c
index f802c82c7bcc..c80e70bde11d 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -3984,6 +3984,12 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
 	if (oact)
 		*oact = *k;
 
+	/*
+	 * Make sure that we never accidentally claim to support SA_UNSUPPORTED,
+	 * e.g. by having an architecture use the bit in their uapi.
+	 */
+	BUILD_BUG_ON(UAPI_SA_FLAGS & SA_UNSUPPORTED);
+
 	/*
 	 * Clear unknown flag bits in order to allow userspace to detect missing
 	 * support for flag bits and to allow the kernel to use non-uapi bits
-- 
2.28.0.297.g1956fa8f8d-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v10 5/7] signal: deduplicate code dealing with common _sigfault fields
  2020-08-22  5:10 ` Peter Collingbourne
@ 2020-08-22  5:10   ` Peter Collingbourne
  -1 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-08-22  5:10 UTC (permalink / raw)
  To: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	Eric W. Biederman, James E.J. Bottomley
  Cc: Peter Collingbourne, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-parisc, David Spickett

We're about to add more common _sigfault fields, so deduplicate the
existing code for initializing _sigfault fields in {send,force}_sig_*,
and for copying _sigfault fields in copy_siginfo_to_external32 and
post_copy_siginfo_from_user32, to reduce the number of places that
will need to be updated by upcoming changes.

Signed-off-by: Peter Collingbourne <pcc@google.com>
---
View this change in Gerrit: https://linux-review.googlesource.com/q/I4f56174e1b7b2bf4a3c8139e6879cbfd52750a24

 include/linux/signal.h |  13 ++++++
 kernel/signal.c        | 101 ++++++++++++++++-------------------------
 2 files changed, 53 insertions(+), 61 deletions(-)

diff --git a/include/linux/signal.h b/include/linux/signal.h
index 6bb1a3f0258c..3edbf54493ee 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -50,6 +50,19 @@ enum siginfo_layout {
 
 enum siginfo_layout siginfo_layout(unsigned sig, int si_code);
 
+static inline bool siginfo_layout_is_fault(enum siginfo_layout layout)
+{
+	switch (layout) {
+	case SIL_FAULT:
+	case SIL_FAULT_MCEERR:
+	case SIL_FAULT_BNDERR:
+	case SIL_FAULT_PKUERR:
+		return true;
+	default:
+		return false;
+	}
+}
+
 /*
  * Define some primitives to manipulate sigset_t.
  */
diff --git a/kernel/signal.c b/kernel/signal.c
index c80e70bde11d..4ee9dc03f20f 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1649,6 +1649,15 @@ void force_sigsegv(int sig)
 	force_sig(SIGSEGV);
 }
 
+static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
+				       int code, void __user *addr)
+{
+	info->si_signo = sig;
+	info->si_errno = 0;
+	info->si_code = code;
+	info->si_addr = addr;
+}
+
 int force_sig_fault_to_task(int sig, int code, void __user *addr
 	___ARCH_SI_TRAPNO(int trapno)
 	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
@@ -1657,10 +1666,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
 	struct kernel_siginfo info;
 
 	clear_siginfo(&info);
-	info.si_signo = sig;
-	info.si_errno = 0;
-	info.si_code  = code;
-	info.si_addr  = addr;
+	set_sigfault_common_fields(&info, sig, code, addr);
 #ifdef __ARCH_SI_TRAPNO
 	info.si_trapno = trapno;
 #endif
@@ -1689,10 +1695,7 @@ int send_sig_fault(int sig, int code, void __user *addr
 	struct kernel_siginfo info;
 
 	clear_siginfo(&info);
-	info.si_signo = sig;
-	info.si_errno = 0;
-	info.si_code  = code;
-	info.si_addr  = addr;
+	set_sigfault_common_fields(&info, sig, code, addr);
 #ifdef __ARCH_SI_TRAPNO
 	info.si_trapno = trapno;
 #endif
@@ -1710,10 +1713,7 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
 
 	WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
 	clear_siginfo(&info);
-	info.si_signo = SIGBUS;
-	info.si_errno = 0;
-	info.si_code = code;
-	info.si_addr = addr;
+	set_sigfault_common_fields(&info, SIGBUS, code, addr);
 	info.si_addr_lsb = lsb;
 	return force_sig_info(&info);
 }
@@ -1724,10 +1724,7 @@ int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *
 
 	WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
 	clear_siginfo(&info);
-	info.si_signo = SIGBUS;
-	info.si_errno = 0;
-	info.si_code = code;
-	info.si_addr = addr;
+	set_sigfault_common_fields(&info, SIGBUS, code, addr);
 	info.si_addr_lsb = lsb;
 	return send_sig_info(info.si_signo, &info, t);
 }
@@ -1738,10 +1735,7 @@ int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
 	struct kernel_siginfo info;
 
 	clear_siginfo(&info);
-	info.si_signo = SIGSEGV;
-	info.si_errno = 0;
-	info.si_code  = SEGV_BNDERR;
-	info.si_addr  = addr;
+	set_sigfault_common_fields(&info, SIGSEGV, SEGV_BNDERR, addr);
 	info.si_lower = lower;
 	info.si_upper = upper;
 	return force_sig_info(&info);
@@ -1753,10 +1747,7 @@ int force_sig_pkuerr(void __user *addr, u32 pkey)
 	struct kernel_siginfo info;
 
 	clear_siginfo(&info);
-	info.si_signo = SIGSEGV;
-	info.si_errno = 0;
-	info.si_code  = SEGV_PKUERR;
-	info.si_addr  = addr;
+	set_sigfault_common_fields(&info, SIGSEGV, SEGV_PKUERR, addr);
 	info.si_pkey  = pkey;
 	return force_sig_info(&info);
 }
@@ -1770,10 +1761,8 @@ int force_sig_ptrace_errno_trap(int errno, void __user *addr)
 	struct kernel_siginfo info;
 
 	clear_siginfo(&info);
-	info.si_signo = SIGTRAP;
+	set_sigfault_common_fields(&info, SIGTRAP, TRAP_HWBKPT, addr);
 	info.si_errno = errno;
-	info.si_code  = TRAP_HWBKPT;
-	info.si_addr  = addr;
 	return force_sig_info(&info);
 }
 
@@ -3266,12 +3255,23 @@ int copy_siginfo_from_user(kernel_siginfo_t *to, const siginfo_t __user *from)
 void copy_siginfo_to_external32(struct compat_siginfo *to,
 		const struct kernel_siginfo *from)
 {
+	enum siginfo_layout layout =
+		siginfo_layout(from->si_signo, from->si_code);
+
 	memset(to, 0, sizeof(*to));
 
 	to->si_signo = from->si_signo;
 	to->si_errno = from->si_errno;
 	to->si_code  = from->si_code;
-	switch(siginfo_layout(from->si_signo, from->si_code)) {
+
+	if (siginfo_layout_is_fault(layout)) {
+		to->si_addr = ptr_to_compat(from->si_addr);
+#ifdef __ARCH_SI_TRAPNO
+		to->si_trapno = from->si_trapno;
+#endif
+	}
+
+	switch (layout) {
 	case SIL_KILL:
 		to->si_pid = from->si_pid;
 		to->si_uid = from->si_uid;
@@ -3286,31 +3286,15 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
 		to->si_fd   = from->si_fd;
 		break;
 	case SIL_FAULT:
-		to->si_addr = ptr_to_compat(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		break;
 	case SIL_FAULT_MCEERR:
-		to->si_addr = ptr_to_compat(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		to->si_addr_lsb = from->si_addr_lsb;
 		break;
 	case SIL_FAULT_BNDERR:
-		to->si_addr = ptr_to_compat(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		to->si_lower = ptr_to_compat(from->si_lower);
 		to->si_upper = ptr_to_compat(from->si_upper);
 		break;
 	case SIL_FAULT_PKUERR:
-		to->si_addr = ptr_to_compat(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		to->si_pkey = from->si_pkey;
 		break;
 	case SIL_CHLD:
@@ -3347,11 +3331,22 @@ int __copy_siginfo_to_user32(struct compat_siginfo __user *to,
 static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 					 const struct compat_siginfo *from)
 {
+	enum siginfo_layout layout =
+		siginfo_layout(from->si_signo, from->si_code);
+
 	clear_siginfo(to);
 	to->si_signo = from->si_signo;
 	to->si_errno = from->si_errno;
 	to->si_code  = from->si_code;
-	switch(siginfo_layout(from->si_signo, from->si_code)) {
+
+	if (siginfo_layout_is_fault(layout)) {
+		to->si_addr = compat_ptr(from->si_addr);
+#ifdef __ARCH_SI_TRAPNO
+		to->si_trapno = from->si_trapno;
+#endif
+	}
+
+	switch (layout) {
 	case SIL_KILL:
 		to->si_pid = from->si_pid;
 		to->si_uid = from->si_uid;
@@ -3366,31 +3361,15 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 		to->si_fd   = from->si_fd;
 		break;
 	case SIL_FAULT:
-		to->si_addr = compat_ptr(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		break;
 	case SIL_FAULT_MCEERR:
-		to->si_addr = compat_ptr(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		to->si_addr_lsb = from->si_addr_lsb;
 		break;
 	case SIL_FAULT_BNDERR:
-		to->si_addr = compat_ptr(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		to->si_lower = compat_ptr(from->si_lower);
 		to->si_upper = compat_ptr(from->si_upper);
 		break;
 	case SIL_FAULT_PKUERR:
-		to->si_addr = compat_ptr(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		to->si_pkey = from->si_pkey;
 		break;
 	case SIL_CHLD:
-- 
2.28.0.297.g1956fa8f8d-goog


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v10 5/7] signal: deduplicate code dealing with common _sigfault fields
@ 2020-08-22  5:10   ` Peter Collingbourne
  0 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-08-22  5:10 UTC (permalink / raw)
  To: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	Eric W. Biederman, James E.J. Bottomley
  Cc: linux-parisc, Andrey Konovalov, Kevin Brodsky, David Spickett,
	Peter Collingbourne, Linux ARM, Richard Henderson

We're about to add more common _sigfault fields, so deduplicate the
existing code for initializing _sigfault fields in {send,force}_sig_*,
and for copying _sigfault fields in copy_siginfo_to_external32 and
post_copy_siginfo_from_user32, to reduce the number of places that
will need to be updated by upcoming changes.

Signed-off-by: Peter Collingbourne <pcc@google.com>
---
View this change in Gerrit: https://linux-review.googlesource.com/q/I4f56174e1b7b2bf4a3c8139e6879cbfd52750a24

 include/linux/signal.h |  13 ++++++
 kernel/signal.c        | 101 ++++++++++++++++-------------------------
 2 files changed, 53 insertions(+), 61 deletions(-)

diff --git a/include/linux/signal.h b/include/linux/signal.h
index 6bb1a3f0258c..3edbf54493ee 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -50,6 +50,19 @@ enum siginfo_layout {
 
 enum siginfo_layout siginfo_layout(unsigned sig, int si_code);
 
+static inline bool siginfo_layout_is_fault(enum siginfo_layout layout)
+{
+	switch (layout) {
+	case SIL_FAULT:
+	case SIL_FAULT_MCEERR:
+	case SIL_FAULT_BNDERR:
+	case SIL_FAULT_PKUERR:
+		return true;
+	default:
+		return false;
+	}
+}
+
 /*
  * Define some primitives to manipulate sigset_t.
  */
diff --git a/kernel/signal.c b/kernel/signal.c
index c80e70bde11d..4ee9dc03f20f 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1649,6 +1649,15 @@ void force_sigsegv(int sig)
 	force_sig(SIGSEGV);
 }
 
+static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
+				       int code, void __user *addr)
+{
+	info->si_signo = sig;
+	info->si_errno = 0;
+	info->si_code = code;
+	info->si_addr = addr;
+}
+
 int force_sig_fault_to_task(int sig, int code, void __user *addr
 	___ARCH_SI_TRAPNO(int trapno)
 	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
@@ -1657,10 +1666,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
 	struct kernel_siginfo info;
 
 	clear_siginfo(&info);
-	info.si_signo = sig;
-	info.si_errno = 0;
-	info.si_code  = code;
-	info.si_addr  = addr;
+	set_sigfault_common_fields(&info, sig, code, addr);
 #ifdef __ARCH_SI_TRAPNO
 	info.si_trapno = trapno;
 #endif
@@ -1689,10 +1695,7 @@ int send_sig_fault(int sig, int code, void __user *addr
 	struct kernel_siginfo info;
 
 	clear_siginfo(&info);
-	info.si_signo = sig;
-	info.si_errno = 0;
-	info.si_code  = code;
-	info.si_addr  = addr;
+	set_sigfault_common_fields(&info, sig, code, addr);
 #ifdef __ARCH_SI_TRAPNO
 	info.si_trapno = trapno;
 #endif
@@ -1710,10 +1713,7 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
 
 	WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
 	clear_siginfo(&info);
-	info.si_signo = SIGBUS;
-	info.si_errno = 0;
-	info.si_code = code;
-	info.si_addr = addr;
+	set_sigfault_common_fields(&info, SIGBUS, code, addr);
 	info.si_addr_lsb = lsb;
 	return force_sig_info(&info);
 }
@@ -1724,10 +1724,7 @@ int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *
 
 	WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
 	clear_siginfo(&info);
-	info.si_signo = SIGBUS;
-	info.si_errno = 0;
-	info.si_code = code;
-	info.si_addr = addr;
+	set_sigfault_common_fields(&info, SIGBUS, code, addr);
 	info.si_addr_lsb = lsb;
 	return send_sig_info(info.si_signo, &info, t);
 }
@@ -1738,10 +1735,7 @@ int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
 	struct kernel_siginfo info;
 
 	clear_siginfo(&info);
-	info.si_signo = SIGSEGV;
-	info.si_errno = 0;
-	info.si_code  = SEGV_BNDERR;
-	info.si_addr  = addr;
+	set_sigfault_common_fields(&info, SIGSEGV, SEGV_BNDERR, addr);
 	info.si_lower = lower;
 	info.si_upper = upper;
 	return force_sig_info(&info);
@@ -1753,10 +1747,7 @@ int force_sig_pkuerr(void __user *addr, u32 pkey)
 	struct kernel_siginfo info;
 
 	clear_siginfo(&info);
-	info.si_signo = SIGSEGV;
-	info.si_errno = 0;
-	info.si_code  = SEGV_PKUERR;
-	info.si_addr  = addr;
+	set_sigfault_common_fields(&info, SIGSEGV, SEGV_PKUERR, addr);
 	info.si_pkey  = pkey;
 	return force_sig_info(&info);
 }
@@ -1770,10 +1761,8 @@ int force_sig_ptrace_errno_trap(int errno, void __user *addr)
 	struct kernel_siginfo info;
 
 	clear_siginfo(&info);
-	info.si_signo = SIGTRAP;
+	set_sigfault_common_fields(&info, SIGTRAP, TRAP_HWBKPT, addr);
 	info.si_errno = errno;
-	info.si_code  = TRAP_HWBKPT;
-	info.si_addr  = addr;
 	return force_sig_info(&info);
 }
 
@@ -3266,12 +3255,23 @@ int copy_siginfo_from_user(kernel_siginfo_t *to, const siginfo_t __user *from)
 void copy_siginfo_to_external32(struct compat_siginfo *to,
 		const struct kernel_siginfo *from)
 {
+	enum siginfo_layout layout =
+		siginfo_layout(from->si_signo, from->si_code);
+
 	memset(to, 0, sizeof(*to));
 
 	to->si_signo = from->si_signo;
 	to->si_errno = from->si_errno;
 	to->si_code  = from->si_code;
-	switch(siginfo_layout(from->si_signo, from->si_code)) {
+
+	if (siginfo_layout_is_fault(layout)) {
+		to->si_addr = ptr_to_compat(from->si_addr);
+#ifdef __ARCH_SI_TRAPNO
+		to->si_trapno = from->si_trapno;
+#endif
+	}
+
+	switch (layout) {
 	case SIL_KILL:
 		to->si_pid = from->si_pid;
 		to->si_uid = from->si_uid;
@@ -3286,31 +3286,15 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
 		to->si_fd   = from->si_fd;
 		break;
 	case SIL_FAULT:
-		to->si_addr = ptr_to_compat(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		break;
 	case SIL_FAULT_MCEERR:
-		to->si_addr = ptr_to_compat(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		to->si_addr_lsb = from->si_addr_lsb;
 		break;
 	case SIL_FAULT_BNDERR:
-		to->si_addr = ptr_to_compat(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		to->si_lower = ptr_to_compat(from->si_lower);
 		to->si_upper = ptr_to_compat(from->si_upper);
 		break;
 	case SIL_FAULT_PKUERR:
-		to->si_addr = ptr_to_compat(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		to->si_pkey = from->si_pkey;
 		break;
 	case SIL_CHLD:
@@ -3347,11 +3331,22 @@ int __copy_siginfo_to_user32(struct compat_siginfo __user *to,
 static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 					 const struct compat_siginfo *from)
 {
+	enum siginfo_layout layout =
+		siginfo_layout(from->si_signo, from->si_code);
+
 	clear_siginfo(to);
 	to->si_signo = from->si_signo;
 	to->si_errno = from->si_errno;
 	to->si_code  = from->si_code;
-	switch(siginfo_layout(from->si_signo, from->si_code)) {
+
+	if (siginfo_layout_is_fault(layout)) {
+		to->si_addr = compat_ptr(from->si_addr);
+#ifdef __ARCH_SI_TRAPNO
+		to->si_trapno = from->si_trapno;
+#endif
+	}
+
+	switch (layout) {
 	case SIL_KILL:
 		to->si_pid = from->si_pid;
 		to->si_uid = from->si_uid;
@@ -3366,31 +3361,15 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 		to->si_fd   = from->si_fd;
 		break;
 	case SIL_FAULT:
-		to->si_addr = compat_ptr(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		break;
 	case SIL_FAULT_MCEERR:
-		to->si_addr = compat_ptr(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		to->si_addr_lsb = from->si_addr_lsb;
 		break;
 	case SIL_FAULT_BNDERR:
-		to->si_addr = compat_ptr(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		to->si_lower = compat_ptr(from->si_lower);
 		to->si_upper = compat_ptr(from->si_upper);
 		break;
 	case SIL_FAULT_PKUERR:
-		to->si_addr = compat_ptr(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		to->si_pkey = from->si_pkey;
 		break;
 	case SIL_CHLD:
-- 
2.28.0.297.g1956fa8f8d-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v10 6/7] signal: define the field siginfo.si_xflags
  2020-08-22  5:10 ` Peter Collingbourne
@ 2020-08-22  5:10   ` Peter Collingbourne
  -1 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-08-22  5:10 UTC (permalink / raw)
  To: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	Eric W. Biederman, James E.J. Bottomley
  Cc: Peter Collingbourne, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-parisc, David Spickett

This field will contain flags that may be used by signal handlers to
determine whether other fields in the _sigfault portion of siginfo are
valid. An example use case is the following patch, which introduces
the si_addr_ignored_bits{,_mask} fields.

A new sigcontext flag, SA_XFLAGS, is introduced in order to allow
a signal handler to require the kernel to set the field (but note
that the field will be set anyway if the kernel supports the flag,
regardless of its value). In combination with the previous patches,
this allows a userspace program to determine whether the kernel will
set the field.

It is possible for an si_xflags-unaware program to cause a signal
handler in an si_xflags-aware program to be called with a provided
siginfo data structure by using one of the following syscalls:

- ptrace(PTRACE_SETSIGINFO)
- pidfd_send_signal
- rt_sigqueueinfo
- rt_tgsigqueueinfo

So we need to prevent the si_xflags-unaware program from causing an
uninitialized read of si_xflags in the si_xflags-aware program when
it uses one of these syscalls.

The last three cases can be handled by observing that each of these
syscalls fails if si_code >= 0, so we define si_xflags to only be
valid if si_code >= 0.

There is no such check on si_code in ptrace(PTRACE_SETSIGINFO), so
we make ptrace(PTRACE_SETSIGINFO) clear the si_xflags field if it
detects that the signal would use the _sigfault layout, and introduce
a new ptrace request type, PTRACE_SETSIGINFO2, that a si_xflags-aware
program may use to opt out of this behavior.

It is also possible for the kernel to inject a signal specified to
use _sigfault by calling force_sig (e.g. there are numerous calls to
force_sig(SIGSEGV)). In this case si_code is set to SI_KERNEL and the
_kill union member is used, so document that si_code must be < SI_KERNEL.

Ideally this field could have just been named si_flags, but that
name was already taken by ia64, so a different name was chosen.

Alternatively, we may consider making ia64's si_flags a generic field
and having it appear at the end of _sigfault (in the same place as
this patch has si_xflags) on non-ia64, keeping it in the same place
on ia64. ia64's si_flags is a 32-bit field with only one flag bit
allocated, so we would have 31 bits to use if we do this.

Signed-off-by: Peter Collingbourne <pcc@google.com>
---
View this change in Gerrit: https://linux-review.googlesource.com/q/Ide155ce29366c3eab2a944ae4c51205982e5b8b2

v10:
- make the new field compatible with the various ways
  that a siginfo can be injected from another process
- eliminate some duplication by adding a refactoring patch
  before this one

 arch/powerpc/platforms/powernv/vas-fault.c |  1 +
 arch/x86/kernel/signal_compat.c            |  4 +--
 include/linux/compat.h                     |  2 ++
 include/linux/signal_types.h               |  2 +-
 include/uapi/asm-generic/siginfo.h         |  4 +++
 include/uapi/asm-generic/signal-defs.h     |  4 +++
 include/uapi/linux/ptrace.h                |  2 ++
 kernel/ptrace.c                            | 29 ++++++++++++++++++++++
 kernel/signal.c                            |  3 +++
 9 files changed, 48 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/platforms/powernv/vas-fault.c b/arch/powerpc/platforms/powernv/vas-fault.c
index 3d21fce254b7..3bbb335561f5 100644
--- a/arch/powerpc/platforms/powernv/vas-fault.c
+++ b/arch/powerpc/platforms/powernv/vas-fault.c
@@ -154,6 +154,7 @@ static void update_csb(struct vas_window *window,
 	info.si_errno = EFAULT;
 	info.si_code = SEGV_MAPERR;
 	info.si_addr = csb_addr;
+	info.si_xflags = 0;
 
 	/*
 	 * process will be polling on csb.flags after request is sent to
diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
index c599013ae8cb..6b99f0c8a068 100644
--- a/arch/x86/kernel/signal_compat.c
+++ b/arch/x86/kernel/signal_compat.c
@@ -121,8 +121,8 @@ static inline void signal_compat_build_tests(void)
 #endif
 
 	CHECK_CSI_OFFSET(_sigfault);
-	CHECK_CSI_SIZE  (_sigfault, 4*sizeof(int));
-	CHECK_SI_SIZE   (_sigfault, 8*sizeof(int));
+	CHECK_CSI_SIZE  (_sigfault, 8*sizeof(int));
+	CHECK_SI_SIZE   (_sigfault, 16*sizeof(int));
 
 	BUILD_BUG_ON(offsetof(siginfo_t, si_addr) != 0x10);
 	BUILD_BUG_ON(offsetof(compat_siginfo_t, si_addr) != 0x0C);
diff --git a/include/linux/compat.h b/include/linux/compat.h
index d38c4d7e83bd..55d4228dfd88 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -231,7 +231,9 @@ typedef struct compat_siginfo {
 					char _dummy_pkey[__COMPAT_ADDR_BND_PKEY_PAD];
 					u32 _pkey;
 				} _addr_pkey;
+				compat_uptr_t _pad[6];
 			};
+			compat_uptr_t _xflags;
 		} _sigfault;
 
 		/* SIGPOLL */
diff --git a/include/linux/signal_types.h b/include/linux/signal_types.h
index a7887ad84d36..75ca861d982a 100644
--- a/include/linux/signal_types.h
+++ b/include/linux/signal_types.h
@@ -78,6 +78,6 @@ struct ksignal {
 
 #define UAPI_SA_FLAGS                                                          \
 	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
-	 SA_NODEFER | SA_RESETHAND | __ARCH_UAPI_SA_FLAGS)
+	 SA_NODEFER | SA_RESETHAND | SA_XFLAGS | __ARCH_UAPI_SA_FLAGS)
 
 #endif /* _LINUX_SIGNAL_TYPES_H */
diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
index cb3d6c267181..1fbd88d64f38 100644
--- a/include/uapi/asm-generic/siginfo.h
+++ b/include/uapi/asm-generic/siginfo.h
@@ -91,7 +91,9 @@ union __sifields {
 				char _dummy_pkey[__ADDR_BND_PKEY_PAD];
 				__u32 _pkey;
 			} _addr_pkey;
+			void *_pad[6];
 		};
+		unsigned long _xflags;
 	} _sigfault;
 
 	/* SIGPOLL */
@@ -152,6 +154,8 @@ typedef struct siginfo {
 #define si_trapno	_sifields._sigfault._trapno
 #endif
 #define si_addr_lsb	_sifields._sigfault._addr_lsb
+/* si_xflags is only valid if 0 <= si_code < SI_KERNEL */
+#define si_xflags	_sifields._sigfault._xflags
 #define si_lower	_sifields._sigfault._addr_bnd._lower
 #define si_upper	_sifields._sigfault._addr_bnd._upper
 #define si_pkey		_sifields._sigfault._addr_pkey._pkey
diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
index e853cbe8722d..bdbe1fe7a779 100644
--- a/include/uapi/asm-generic/signal-defs.h
+++ b/include/uapi/asm-generic/signal-defs.h
@@ -20,6 +20,9 @@
  * so this bit allows flag bit support to be detected from userspace while
  * allowing an old kernel to be distinguished from a kernel that supports every
  * flag bit.
+ * SA_XFLAGS indicates that the signal handler requires the siginfo.si_xflags
+ * field to be valid. Note that if the kernel supports SA_XFLAGS, the field will
+ * be valid regardless of the value of this flag.
  *
  * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
  * Unix names RESETHAND and NODEFER respectively.
@@ -49,6 +52,7 @@
 #define SA_RESETHAND	0x80000000
 #endif
 #define SA_UNSUPPORTED	0x00000400
+#define SA_XFLAGS	0x00000800
 
 #define SA_NOMASK	SA_NODEFER
 #define SA_ONESHOT	SA_RESETHAND
diff --git a/include/uapi/linux/ptrace.h b/include/uapi/linux/ptrace.h
index a71b6e3b03eb..de5ebd5b0fae 100644
--- a/include/uapi/linux/ptrace.h
+++ b/include/uapi/linux/ptrace.h
@@ -101,6 +101,8 @@ struct ptrace_syscall_info {
 	};
 };
 
+#define PTRACE_SETSIGINFO2	0x420f
+
 /*
  * These values are stored in task->ptrace_message
  * by tracehook_report_syscall_* to describe the current syscall-stop.
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 43d6179508d6..11ee5e2d65ff 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -1038,6 +1038,20 @@ int ptrace_request(struct task_struct *child, long request,
 		break;
 
 	case PTRACE_SETSIGINFO:
+		ret = copy_siginfo_from_user(&siginfo, datavp);
+		if (!ret) {
+			/*
+                         * Assume that the caller is unaware of si_xflags, so
+                         * fill it in if we're using a layout that requires it.
+                         */
+			if (siginfo_layout_is_fault(siginfo_layout(
+				    siginfo.si_signo, siginfo.si_code)))
+				siginfo.si_xflags = 0;
+			ret = ptrace_setsiginfo(child, &siginfo);
+                }
+		break;
+
+	case PTRACE_SETSIGINFO2:
 		ret = copy_siginfo_from_user(&siginfo, datavp);
 		if (!ret)
 			ret = ptrace_setsiginfo(child, &siginfo);
@@ -1347,6 +1361,21 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
 		break;
 
 	case PTRACE_SETSIGINFO:
+		ret = copy_siginfo_from_user32(
+			&siginfo, (struct compat_siginfo __user *) datap);
+		if (!ret) {
+			/*
+                         * Assume that the caller is unaware of si_xflags, so
+                         * fill it in if we're using a layout that requires it.
+                         */
+			if (siginfo_layout_is_fault(siginfo_layout(
+				    siginfo.si_signo, siginfo.si_code)))
+				siginfo.si_xflags = 0;
+			ret = ptrace_setsiginfo(child, &siginfo);
+                }
+		break;
+
+	case PTRACE_SETSIGINFO2:
 		ret = copy_siginfo_from_user32(
 			&siginfo, (struct compat_siginfo __user *) datap);
 		if (!ret)
diff --git a/kernel/signal.c b/kernel/signal.c
index 4ee9dc03f20f..4259903b95cb 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1656,6 +1656,7 @@ static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
 	info->si_errno = 0;
 	info->si_code = code;
 	info->si_addr = addr;
+	info->si_xflags = 0;
 }
 
 int force_sig_fault_to_task(int sig, int code, void __user *addr
@@ -3269,6 +3270,7 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
 #ifdef __ARCH_SI_TRAPNO
 		to->si_trapno = from->si_trapno;
 #endif
+		to->si_xflags = from->si_xflags;
 	}
 
 	switch (layout) {
@@ -3344,6 +3346,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 #ifdef __ARCH_SI_TRAPNO
 		to->si_trapno = from->si_trapno;
 #endif
+		to->si_xflags = from->si_xflags;
 	}
 
 	switch (layout) {
-- 
2.28.0.297.g1956fa8f8d-goog


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v10 6/7] signal: define the field siginfo.si_xflags
@ 2020-08-22  5:10   ` Peter Collingbourne
  0 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-08-22  5:10 UTC (permalink / raw)
  To: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	Eric W. Biederman, James E.J. Bottomley
  Cc: linux-parisc, Andrey Konovalov, Kevin Brodsky, David Spickett,
	Peter Collingbourne, Linux ARM, Richard Henderson

This field will contain flags that may be used by signal handlers to
determine whether other fields in the _sigfault portion of siginfo are
valid. An example use case is the following patch, which introduces
the si_addr_ignored_bits{,_mask} fields.

A new sigcontext flag, SA_XFLAGS, is introduced in order to allow
a signal handler to require the kernel to set the field (but note
that the field will be set anyway if the kernel supports the flag,
regardless of its value). In combination with the previous patches,
this allows a userspace program to determine whether the kernel will
set the field.

It is possible for an si_xflags-unaware program to cause a signal
handler in an si_xflags-aware program to be called with a provided
siginfo data structure by using one of the following syscalls:

- ptrace(PTRACE_SETSIGINFO)
- pidfd_send_signal
- rt_sigqueueinfo
- rt_tgsigqueueinfo

So we need to prevent the si_xflags-unaware program from causing an
uninitialized read of si_xflags in the si_xflags-aware program when
it uses one of these syscalls.

The last three cases can be handled by observing that each of these
syscalls fails if si_code >= 0, so we define si_xflags to only be
valid if si_code >= 0.

There is no such check on si_code in ptrace(PTRACE_SETSIGINFO), so
we make ptrace(PTRACE_SETSIGINFO) clear the si_xflags field if it
detects that the signal would use the _sigfault layout, and introduce
a new ptrace request type, PTRACE_SETSIGINFO2, that a si_xflags-aware
program may use to opt out of this behavior.

It is also possible for the kernel to inject a signal specified to
use _sigfault by calling force_sig (e.g. there are numerous calls to
force_sig(SIGSEGV)). In this case si_code is set to SI_KERNEL and the
_kill union member is used, so document that si_code must be < SI_KERNEL.

Ideally this field could have just been named si_flags, but that
name was already taken by ia64, so a different name was chosen.

Alternatively, we may consider making ia64's si_flags a generic field
and having it appear at the end of _sigfault (in the same place as
this patch has si_xflags) on non-ia64, keeping it in the same place
on ia64. ia64's si_flags is a 32-bit field with only one flag bit
allocated, so we would have 31 bits to use if we do this.

Signed-off-by: Peter Collingbourne <pcc@google.com>
---
View this change in Gerrit: https://linux-review.googlesource.com/q/Ide155ce29366c3eab2a944ae4c51205982e5b8b2

v10:
- make the new field compatible with the various ways
  that a siginfo can be injected from another process
- eliminate some duplication by adding a refactoring patch
  before this one

 arch/powerpc/platforms/powernv/vas-fault.c |  1 +
 arch/x86/kernel/signal_compat.c            |  4 +--
 include/linux/compat.h                     |  2 ++
 include/linux/signal_types.h               |  2 +-
 include/uapi/asm-generic/siginfo.h         |  4 +++
 include/uapi/asm-generic/signal-defs.h     |  4 +++
 include/uapi/linux/ptrace.h                |  2 ++
 kernel/ptrace.c                            | 29 ++++++++++++++++++++++
 kernel/signal.c                            |  3 +++
 9 files changed, 48 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/platforms/powernv/vas-fault.c b/arch/powerpc/platforms/powernv/vas-fault.c
index 3d21fce254b7..3bbb335561f5 100644
--- a/arch/powerpc/platforms/powernv/vas-fault.c
+++ b/arch/powerpc/platforms/powernv/vas-fault.c
@@ -154,6 +154,7 @@ static void update_csb(struct vas_window *window,
 	info.si_errno = EFAULT;
 	info.si_code = SEGV_MAPERR;
 	info.si_addr = csb_addr;
+	info.si_xflags = 0;
 
 	/*
 	 * process will be polling on csb.flags after request is sent to
diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
index c599013ae8cb..6b99f0c8a068 100644
--- a/arch/x86/kernel/signal_compat.c
+++ b/arch/x86/kernel/signal_compat.c
@@ -121,8 +121,8 @@ static inline void signal_compat_build_tests(void)
 #endif
 
 	CHECK_CSI_OFFSET(_sigfault);
-	CHECK_CSI_SIZE  (_sigfault, 4*sizeof(int));
-	CHECK_SI_SIZE   (_sigfault, 8*sizeof(int));
+	CHECK_CSI_SIZE  (_sigfault, 8*sizeof(int));
+	CHECK_SI_SIZE   (_sigfault, 16*sizeof(int));
 
 	BUILD_BUG_ON(offsetof(siginfo_t, si_addr) != 0x10);
 	BUILD_BUG_ON(offsetof(compat_siginfo_t, si_addr) != 0x0C);
diff --git a/include/linux/compat.h b/include/linux/compat.h
index d38c4d7e83bd..55d4228dfd88 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -231,7 +231,9 @@ typedef struct compat_siginfo {
 					char _dummy_pkey[__COMPAT_ADDR_BND_PKEY_PAD];
 					u32 _pkey;
 				} _addr_pkey;
+				compat_uptr_t _pad[6];
 			};
+			compat_uptr_t _xflags;
 		} _sigfault;
 
 		/* SIGPOLL */
diff --git a/include/linux/signal_types.h b/include/linux/signal_types.h
index a7887ad84d36..75ca861d982a 100644
--- a/include/linux/signal_types.h
+++ b/include/linux/signal_types.h
@@ -78,6 +78,6 @@ struct ksignal {
 
 #define UAPI_SA_FLAGS                                                          \
 	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
-	 SA_NODEFER | SA_RESETHAND | __ARCH_UAPI_SA_FLAGS)
+	 SA_NODEFER | SA_RESETHAND | SA_XFLAGS | __ARCH_UAPI_SA_FLAGS)
 
 #endif /* _LINUX_SIGNAL_TYPES_H */
diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
index cb3d6c267181..1fbd88d64f38 100644
--- a/include/uapi/asm-generic/siginfo.h
+++ b/include/uapi/asm-generic/siginfo.h
@@ -91,7 +91,9 @@ union __sifields {
 				char _dummy_pkey[__ADDR_BND_PKEY_PAD];
 				__u32 _pkey;
 			} _addr_pkey;
+			void *_pad[6];
 		};
+		unsigned long _xflags;
 	} _sigfault;
 
 	/* SIGPOLL */
@@ -152,6 +154,8 @@ typedef struct siginfo {
 #define si_trapno	_sifields._sigfault._trapno
 #endif
 #define si_addr_lsb	_sifields._sigfault._addr_lsb
+/* si_xflags is only valid if 0 <= si_code < SI_KERNEL */
+#define si_xflags	_sifields._sigfault._xflags
 #define si_lower	_sifields._sigfault._addr_bnd._lower
 #define si_upper	_sifields._sigfault._addr_bnd._upper
 #define si_pkey		_sifields._sigfault._addr_pkey._pkey
diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
index e853cbe8722d..bdbe1fe7a779 100644
--- a/include/uapi/asm-generic/signal-defs.h
+++ b/include/uapi/asm-generic/signal-defs.h
@@ -20,6 +20,9 @@
  * so this bit allows flag bit support to be detected from userspace while
  * allowing an old kernel to be distinguished from a kernel that supports every
  * flag bit.
+ * SA_XFLAGS indicates that the signal handler requires the siginfo.si_xflags
+ * field to be valid. Note that if the kernel supports SA_XFLAGS, the field will
+ * be valid regardless of the value of this flag.
  *
  * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
  * Unix names RESETHAND and NODEFER respectively.
@@ -49,6 +52,7 @@
 #define SA_RESETHAND	0x80000000
 #endif
 #define SA_UNSUPPORTED	0x00000400
+#define SA_XFLAGS	0x00000800
 
 #define SA_NOMASK	SA_NODEFER
 #define SA_ONESHOT	SA_RESETHAND
diff --git a/include/uapi/linux/ptrace.h b/include/uapi/linux/ptrace.h
index a71b6e3b03eb..de5ebd5b0fae 100644
--- a/include/uapi/linux/ptrace.h
+++ b/include/uapi/linux/ptrace.h
@@ -101,6 +101,8 @@ struct ptrace_syscall_info {
 	};
 };
 
+#define PTRACE_SETSIGINFO2	0x420f
+
 /*
  * These values are stored in task->ptrace_message
  * by tracehook_report_syscall_* to describe the current syscall-stop.
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 43d6179508d6..11ee5e2d65ff 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -1038,6 +1038,20 @@ int ptrace_request(struct task_struct *child, long request,
 		break;
 
 	case PTRACE_SETSIGINFO:
+		ret = copy_siginfo_from_user(&siginfo, datavp);
+		if (!ret) {
+			/*
+                         * Assume that the caller is unaware of si_xflags, so
+                         * fill it in if we're using a layout that requires it.
+                         */
+			if (siginfo_layout_is_fault(siginfo_layout(
+				    siginfo.si_signo, siginfo.si_code)))
+				siginfo.si_xflags = 0;
+			ret = ptrace_setsiginfo(child, &siginfo);
+                }
+		break;
+
+	case PTRACE_SETSIGINFO2:
 		ret = copy_siginfo_from_user(&siginfo, datavp);
 		if (!ret)
 			ret = ptrace_setsiginfo(child, &siginfo);
@@ -1347,6 +1361,21 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
 		break;
 
 	case PTRACE_SETSIGINFO:
+		ret = copy_siginfo_from_user32(
+			&siginfo, (struct compat_siginfo __user *) datap);
+		if (!ret) {
+			/*
+                         * Assume that the caller is unaware of si_xflags, so
+                         * fill it in if we're using a layout that requires it.
+                         */
+			if (siginfo_layout_is_fault(siginfo_layout(
+				    siginfo.si_signo, siginfo.si_code)))
+				siginfo.si_xflags = 0;
+			ret = ptrace_setsiginfo(child, &siginfo);
+                }
+		break;
+
+	case PTRACE_SETSIGINFO2:
 		ret = copy_siginfo_from_user32(
 			&siginfo, (struct compat_siginfo __user *) datap);
 		if (!ret)
diff --git a/kernel/signal.c b/kernel/signal.c
index 4ee9dc03f20f..4259903b95cb 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1656,6 +1656,7 @@ static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
 	info->si_errno = 0;
 	info->si_code = code;
 	info->si_addr = addr;
+	info->si_xflags = 0;
 }
 
 int force_sig_fault_to_task(int sig, int code, void __user *addr
@@ -3269,6 +3270,7 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
 #ifdef __ARCH_SI_TRAPNO
 		to->si_trapno = from->si_trapno;
 #endif
+		to->si_xflags = from->si_xflags;
 	}
 
 	switch (layout) {
@@ -3344,6 +3346,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 #ifdef __ARCH_SI_TRAPNO
 		to->si_trapno = from->si_trapno;
 #endif
+		to->si_xflags = from->si_xflags;
 	}
 
 	switch (layout) {
-- 
2.28.0.297.g1956fa8f8d-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v10 7/7] arm64: expose FAR_EL1 tag bits in siginfo
  2020-08-22  5:10 ` Peter Collingbourne
@ 2020-08-22  5:10   ` Peter Collingbourne
  -1 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-08-22  5:10 UTC (permalink / raw)
  To: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	Eric W. Biederman, James E.J. Bottomley
  Cc: Peter Collingbourne, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-parisc, David Spickett

The kernel currently clears the tag bits (i.e. bits 56-63) in the fault
address exposed via siginfo.si_addr and sigcontext.fault_address. However,
the tag bits may be needed by tools in order to accurately diagnose
memory errors, such as HWASan [1] or future tools based on the Memory
Tagging Extension (MTE).

We should not stop clearing these bits in the existing fault address
fields, because there may be existing userspace applications that are
expecting the tag bits to be cleared. Instead, create a new pair of
union fields in siginfo._sigfault, and store the tag bits of FAR_EL1
there, together with a mask specifying which bits are valid.

A flag is added to si_xflags to allow userspace to determine whether
the values in the fields are valid.

[1] http://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html

Signed-off-by: Peter Collingbourne <pcc@google.com>
---
View this change in Gerrit: https://linux-review.googlesource.com/q/Ia8876bad8c798e0a32df7c2ce1256c4771c81446

v10:
- rename the flag to SIXFLAG_ADDR_IGNORED_BITS
- use an arch hook to specify which bits are ignored, instead
  of passing them explicitly
- while refactoring for the arch hook, noticed that my previous
  patches missed a case involving cache maintenance instructions,
  so expose the tag bits for that signal as well

v9:
- make the ignored bits fields generic
- add some new dependent patches that prepare us to store the
  field in such a way that userspace can detect their presence

v8:
- rebase onto 5.8rc2

v7:
- switch to a new siginfo field instead of using sigcontext
- merge the patch back into one since the other patches are now
  unnecessary

v6:
- move fault address and fault code into the kernel_siginfo data structure
- split the patch in three since it was getting large and now has
  generic and arch-specific parts

v5:
- add padding to fault_addr_top_byte_context in order to ensure the correct
  size and preserve sp alignment

v4:
- expose only the tag bits in the context instead of the entire FAR_EL1
- remove mention of the new context from the sigcontext.__reserved[] note

v3:
- add documentation to tagged-pointers.rst
- update comments in sigcontext.h

v2:
- revert changes to hw_breakpoint.c
- rename set_thread_esr to set_thread_far_esr

 Documentation/arm64/tagged-pointers.rst | 21 ++++++---
 arch/arm64/include/asm/exception.h      |  2 +-
 arch/arm64/include/asm/signal.h         | 17 +++++++
 arch/arm64/include/asm/system_misc.h    |  2 +-
 arch/arm64/include/asm/traps.h          |  6 +--
 arch/arm64/kernel/debug-monitors.c      |  5 +--
 arch/arm64/kernel/entry-common.c        |  2 -
 arch/arm64/kernel/ptrace.c              |  7 +--
 arch/arm64/kernel/sys_compat.c          |  5 +--
 arch/arm64/kernel/traps.c               | 29 ++++++------
 arch/arm64/mm/fault.c                   | 59 +++++++++++++------------
 arch/x86/kernel/signal_compat.c         |  4 +-
 include/linux/compat.h                  |  2 +
 include/linux/signal.h                  |  8 ++++
 include/uapi/asm-generic/siginfo.h      | 10 +++++
 kernel/signal.c                         | 14 +++++-
 16 files changed, 122 insertions(+), 71 deletions(-)
 create mode 100644 arch/arm64/include/asm/signal.h

diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst
index eab4323609b9..14273160b38b 100644
--- a/Documentation/arm64/tagged-pointers.rst
+++ b/Documentation/arm64/tagged-pointers.rst
@@ -53,12 +53,21 @@ visibility.
 Preserving tags
 ---------------
 
-Non-zero tags are not preserved when delivering signals. This means that
-signal handlers in applications making use of tags cannot rely on the
-tag information for user virtual addresses being maintained for fields
-inside siginfo_t. One exception to this rule is for signals raised in
-response to watchpoint debug exceptions, where the tag information will
-be preserved.
+Non-zero tags are not preserved in the fault address fields
+siginfo.si_addr or sigcontext.fault_address when delivering
+signals. This means that signal handlers in applications making use
+of tags cannot rely on the tag information for user virtual addresses
+being maintained in these fields. One exception to this rule is for
+signals raised in response to watchpoint debug exceptions, where the
+tag information will be preserved.
+
+The fault address tag is preserved in the si_addr_ignored_bits field
+of siginfo, which is set for signals raised in response to data aborts
+and instruction aborts. The si_addr_ignored_bits_mask field indicates
+which bits of the field are valid. The validity of these fields is
+indicated by the SIXFLAG_ADDR_IGNORED_BITS flag in siginfo.si_xflags,
+and the validity of si_xflags in turn is indicated by the kernel
+indicating support for the sigaction.sa_flags flag SA_XFLAGS.
 
 The architecture prevents the use of a tagged PC, so the upper byte will
 be set to a sign-extension of bit 55 on exception return.
diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h
index 7577a754d443..950d55dae948 100644
--- a/arch/arm64/include/asm/exception.h
+++ b/arch/arm64/include/asm/exception.h
@@ -32,7 +32,7 @@ static inline u32 disr_to_esr(u64 disr)
 }
 
 asmlinkage void enter_from_user_mode(void);
-void do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs);
+void do_mem_abort(unsigned long far, unsigned int esr, struct pt_regs *regs);
 void do_undefinstr(struct pt_regs *regs);
 void do_bti(struct pt_regs *regs);
 asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr);
diff --git a/arch/arm64/include/asm/signal.h b/arch/arm64/include/asm/signal.h
new file mode 100644
index 000000000000..038cc9784c57
--- /dev/null
+++ b/arch/arm64/include/asm/signal.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ARM64_ASM_SIGNAL_H
+#define __ARM64_ASM_SIGNAL_H
+
+#include <uapi/asm/signal.h>
+#include <uapi/asm/siginfo.h>
+
+static inline unsigned long arch_addr_ignored_bits_mask(unsigned long sig,
+							unsigned long si_code)
+{
+	if (sig == SIGTRAP && si_code == TRAP_BRKPT)
+		return 0;
+	return 0xffUL << 56;
+}
+#define arch_addr_ignored_bits_mask arch_addr_ignored_bits_mask
+
+#endif
diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h
index 1ab63cfbbaf1..673be2d1263c 100644
--- a/arch/arm64/include/asm/system_misc.h
+++ b/arch/arm64/include/asm/system_misc.h
@@ -22,7 +22,7 @@ void die(const char *msg, struct pt_regs *regs, int err);
 
 struct siginfo;
 void arm64_notify_die(const char *str, struct pt_regs *regs,
-		      int signo, int sicode, void __user *addr,
+		      int signo, int sicode, unsigned long far,
 		      int err);
 
 void hook_debug_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h
index cee5928e1b7d..9bb5376608d3 100644
--- a/arch/arm64/include/asm/traps.h
+++ b/arch/arm64/include/asm/traps.h
@@ -26,9 +26,9 @@ void register_undef_hook(struct undef_hook *hook);
 void unregister_undef_hook(struct undef_hook *hook);
 void force_signal_inject(int signal, int code, unsigned long address);
 void arm64_notify_segfault(unsigned long addr);
-void arm64_force_sig_fault(int signo, int code, void __user *addr, const char *str);
-void arm64_force_sig_mceerr(int code, void __user *addr, short lsb, const char *str);
-void arm64_force_sig_ptrace_errno_trap(int errno, void __user *addr, const char *str);
+void arm64_force_sig_fault(int signo, int code, unsigned long far, const char *str);
+void arm64_force_sig_mceerr(int code, unsigned long far, short lsb, const char *str);
+void arm64_force_sig_ptrace_errno_trap(int errno, unsigned long far, const char *str);
 
 /*
  * Move regs->pc to next instruction and do necessary setup before it
diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
index 7310a4f7f993..943e932def37 100644
--- a/arch/arm64/kernel/debug-monitors.c
+++ b/arch/arm64/kernel/debug-monitors.c
@@ -234,9 +234,8 @@ static void send_user_sigtrap(int si_code)
 	if (interrupts_enabled(regs))
 		local_irq_enable();
 
-	arm64_force_sig_fault(SIGTRAP, si_code,
-			     (void __user *)instruction_pointer(regs),
-			     "User debug trap");
+	arm64_force_sig_fault(SIGTRAP, si_code, instruction_pointer(regs),
+			      "User debug trap");
 }
 
 static int single_step_handler(unsigned long unused, unsigned int esr,
diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index d3be9dbf5490..65ed01606480 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -22,7 +22,6 @@ static void notrace el1_abort(struct pt_regs *regs, unsigned long esr)
 	unsigned long far = read_sysreg(far_el1);
 
 	local_daif_inherit(regs);
-	far = untagged_addr(far);
 	do_mem_abort(far, esr, regs);
 }
 NOKPROBE_SYMBOL(el1_abort);
@@ -104,7 +103,6 @@ static void notrace el0_da(struct pt_regs *regs, unsigned long esr)
 
 	user_exit_irqoff();
 	local_daif_restore(DAIF_PROCCTX);
-	far = untagged_addr(far);
 	do_mem_abort(far, esr, regs);
 }
 NOKPROBE_SYMBOL(el0_da);
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index d8ebfd813e28..3f12c731fa9a 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -191,14 +191,11 @@ static void ptrace_hbptriggered(struct perf_event *bp,
 				break;
 			}
 		}
-		arm64_force_sig_ptrace_errno_trap(si_errno,
-						  (void __user *)bkpt->trigger,
+		arm64_force_sig_ptrace_errno_trap(si_errno, bkpt->trigger,
 						  desc);
 	}
 #endif
-	arm64_force_sig_fault(SIGTRAP, TRAP_HWBKPT,
-			      (void __user *)(bkpt->trigger),
-			      desc);
+	arm64_force_sig_fault(SIGTRAP, TRAP_HWBKPT, bkpt->trigger, desc);
 }
 
 /*
diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c
index 3c18c2454089..265fe3eb1069 100644
--- a/arch/arm64/kernel/sys_compat.c
+++ b/arch/arm64/kernel/sys_compat.c
@@ -68,7 +68,7 @@ do_compat_cache_op(unsigned long start, unsigned long end, int flags)
  */
 long compat_arm_syscall(struct pt_regs *regs, int scno)
 {
-	void __user *addr;
+	unsigned long addr;
 
 	switch (scno) {
 	/*
@@ -111,8 +111,7 @@ long compat_arm_syscall(struct pt_regs *regs, int scno)
 		break;
 	}
 
-	addr  = (void __user *)instruction_pointer(regs) -
-		(compat_thumb_mode(regs) ? 2 : 4);
+	addr = instruction_pointer(regs) - (compat_thumb_mode(regs) ? 2 : 4);
 
 	arm64_notify_die("Oops - bad compat syscall(2)", regs,
 			 SIGILL, ILL_ILLTRP, addr, scno);
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 13ebd5ca2070..8f8105076f92 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -234,32 +234,32 @@ static void arm64_show_signal(int signo, const char *str)
 	__show_regs(regs);
 }
 
-void arm64_force_sig_fault(int signo, int code, void __user *addr,
+void arm64_force_sig_fault(int signo, int code, unsigned long far,
 			   const char *str)
 {
 	arm64_show_signal(signo, str);
 	if (signo == SIGKILL)
 		force_sig(SIGKILL);
 	else
-		force_sig_fault(signo, code, addr);
+		force_sig_fault(signo, code, (void __user *)far);
 }
 
-void arm64_force_sig_mceerr(int code, void __user *addr, short lsb,
+void arm64_force_sig_mceerr(int code, unsigned long far, short lsb,
 			    const char *str)
 {
 	arm64_show_signal(SIGBUS, str);
-	force_sig_mceerr(code, addr, lsb);
+	force_sig_mceerr(code, (void __user *)far, lsb);
 }
 
-void arm64_force_sig_ptrace_errno_trap(int errno, void __user *addr,
+void arm64_force_sig_ptrace_errno_trap(int errno, unsigned long far,
 				       const char *str)
 {
 	arm64_show_signal(SIGTRAP, str);
-	force_sig_ptrace_errno_trap(errno, addr);
+	force_sig_ptrace_errno_trap(errno, (void __user *)far);
 }
 
 void arm64_notify_die(const char *str, struct pt_regs *regs,
-		      int signo, int sicode, void __user *addr,
+		      int signo, int sicode, unsigned long far,
 		      int err)
 {
 	if (user_mode(regs)) {
@@ -267,7 +267,7 @@ void arm64_notify_die(const char *str, struct pt_regs *regs,
 		current->thread.fault_address = 0;
 		current->thread.fault_code = err;
 
-		arm64_force_sig_fault(signo, sicode, addr, str);
+		arm64_force_sig_fault(signo, sicode, far, str);
 	} else {
 		die(str, regs, err);
 	}
@@ -438,7 +438,7 @@ void force_signal_inject(int signal, int code, unsigned long address)
 		signal = SIGKILL;
 	}
 
-	arm64_notify_die(desc, regs, signal, code, (void __user *)address, 0);
+	arm64_notify_die(desc, regs, signal, code, address, 0);
 }
 
 /*
@@ -449,7 +449,7 @@ void arm64_notify_segfault(unsigned long addr)
 	int code;
 
 	mmap_read_lock(current->mm);
-	if (find_vma(current->mm, addr) == NULL)
+	if (find_vma(current->mm, untagged_addr(addr)) == NULL)
 		code = SEGV_MAPERR;
 	else
 		code = SEGV_ACCERR;
@@ -501,12 +501,13 @@ NOKPROBE_SYMBOL(do_bti);
 
 static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs)
 {
-	unsigned long address;
+	unsigned long tagged_address, address;
 	int rt = ESR_ELx_SYS64_ISS_RT(esr);
 	int crm = (esr & ESR_ELx_SYS64_ISS_CRM_MASK) >> ESR_ELx_SYS64_ISS_CRM_SHIFT;
 	int ret = 0;
 
-	address = untagged_addr(pt_regs_read_reg(regs, rt));
+	tagged_address = pt_regs_read_reg(regs, rt);
+	address = untagged_addr(tagged_address);
 
 	switch (crm) {
 	case ESR_ELx_SYS64_ISS_CRM_DC_CVAU:	/* DC CVAU, gets promoted */
@@ -533,7 +534,7 @@ static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs)
 	}
 
 	if (ret)
-		arm64_notify_segfault(address);
+		arm64_notify_segfault(tagged_address);
 	else
 		arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE);
 }
@@ -824,7 +825,7 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr)
  */
 void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr)
 {
-	void __user *pc = (void __user *)instruction_pointer(regs);
+	unsigned long pc = instruction_pointer(regs);
 
 	current->thread.fault_address = 0;
 	current->thread.fault_code = esr;
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index f07333e86c2f..d17953d9b3d9 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -40,7 +40,7 @@
 #include <asm/traps.h>
 
 struct fault_info {
-	int	(*fn)(unsigned long addr, unsigned int esr,
+	int	(*fn)(unsigned long far, unsigned int esr,
 		      struct pt_regs *regs);
 	int	sig;
 	int	code;
@@ -383,8 +383,11 @@ static void set_thread_esr(unsigned long address, unsigned int esr)
 	current->thread.fault_code = esr;
 }
 
-static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *regs)
+static void do_bad_area(unsigned long far, unsigned int esr,
+			struct pt_regs *regs)
 {
+	unsigned long addr = untagged_addr(far);
+
 	/*
 	 * If we are in kernel mode at this point, we have no context to
 	 * handle this fault with.
@@ -393,8 +396,7 @@ static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *re
 		const struct fault_info *inf = esr_to_fault_info(esr);
 
 		set_thread_esr(addr, esr);
-		arm64_force_sig_fault(inf->sig, inf->code, (void __user *)addr,
-				      inf->name);
+		arm64_force_sig_fault(inf->sig, inf->code, far, inf->name);
 	} else {
 		__do_kernel_fault(addr, esr, regs);
 	}
@@ -446,7 +448,7 @@ static bool is_write_abort(unsigned int esr)
 	return (esr & ESR_ELx_WNR) && !(esr & ESR_ELx_CM);
 }
 
-static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
+static int __kprobes do_page_fault(unsigned long far, unsigned int esr,
 				   struct pt_regs *regs)
 {
 	const struct fault_info *inf;
@@ -454,6 +456,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
 	vm_fault_t fault;
 	unsigned long vm_flags = VM_ACCESS_FLAGS;
 	unsigned int mm_flags = FAULT_FLAG_DEFAULT;
+	unsigned long addr = untagged_addr(far);
 
 	if (kprobe_page_fault(regs, esr))
 		return 0;
@@ -565,8 +568,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
 		 * We had some memory, but were unable to successfully fix up
 		 * this page fault.
 		 */
-		arm64_force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)addr,
-				      inf->name);
+		arm64_force_sig_fault(SIGBUS, BUS_ADRERR, far, inf->name);
 	} else if (fault & (VM_FAULT_HWPOISON_LARGE | VM_FAULT_HWPOISON)) {
 		unsigned int lsb;
 
@@ -574,8 +576,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
 		if (fault & VM_FAULT_HWPOISON_LARGE)
 			lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault));
 
-		arm64_force_sig_mceerr(BUS_MCEERR_AR, (void __user *)addr, lsb,
-				       inf->name);
+		arm64_force_sig_mceerr(BUS_MCEERR_AR, far, lsb, inf->name);
 	} else {
 		/*
 		 * Something tried to access memory that isn't in our memory
@@ -583,8 +584,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
 		 */
 		arm64_force_sig_fault(SIGSEGV,
 				      fault == VM_FAULT_BADACCESS ? SEGV_ACCERR : SEGV_MAPERR,
-				      (void __user *)addr,
-				      inf->name);
+				      far, inf->name);
 	}
 
 	return 0;
@@ -594,33 +594,35 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
 	return 0;
 }
 
-static int __kprobes do_translation_fault(unsigned long addr,
+static int __kprobes do_translation_fault(unsigned long far,
 					  unsigned int esr,
 					  struct pt_regs *regs)
 {
+	unsigned long addr = untagged_addr(far);
+
 	if (is_ttbr0_addr(addr))
-		return do_page_fault(addr, esr, regs);
+		return do_page_fault(far, esr, regs);
 
-	do_bad_area(addr, esr, regs);
+	do_bad_area(far, esr, regs);
 	return 0;
 }
 
-static int do_alignment_fault(unsigned long addr, unsigned int esr,
+static int do_alignment_fault(unsigned long far, unsigned int esr,
 			      struct pt_regs *regs)
 {
-	do_bad_area(addr, esr, regs);
+	do_bad_area(far, esr, regs);
 	return 0;
 }
 
-static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs)
+static int do_bad(unsigned long far, unsigned int esr, struct pt_regs *regs)
 {
 	return 1; /* "fault" */
 }
 
-static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
+static int do_sea(unsigned long far, unsigned int esr, struct pt_regs *regs)
 {
 	const struct fault_info *inf;
-	void __user *siaddr;
+	unsigned long siaddr;
 
 	inf = esr_to_fault_info(esr);
 
@@ -633,9 +635,9 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
 	}
 
 	if (esr & ESR_ELx_FnV)
-		siaddr = NULL;
+		siaddr = 0;
 	else
-		siaddr  = (void __user *)addr;
+		siaddr  = untagged_addr(far);
 	arm64_notify_die(inf->name, regs, inf->sig, inf->code, siaddr, esr);
 
 	return 0;
@@ -708,11 +710,12 @@ static const struct fault_info fault_info[] = {
 	{ do_bad,		SIGKILL, SI_KERNEL,	"unknown 63"			},
 };
 
-void do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs)
+void do_mem_abort(unsigned long far, unsigned int esr, struct pt_regs *regs)
 {
 	const struct fault_info *inf = esr_to_fault_info(esr);
+	unsigned long addr = untagged_addr(far);
 
-	if (!inf->fn(addr, esr, regs))
+	if (!inf->fn(far, esr, regs))
 		return;
 
 	if (!user_mode(regs)) {
@@ -721,8 +724,7 @@ void do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs)
 		show_pte(addr);
 	}
 
-	arm64_notify_die(inf->name, regs,
-			 inf->sig, inf->code, (void __user *)addr, esr);
+	arm64_notify_die(inf->name, regs, inf->sig, inf->code, addr, esr);
 }
 NOKPROBE_SYMBOL(do_mem_abort);
 
@@ -735,8 +737,8 @@ NOKPROBE_SYMBOL(do_el0_irq_bp_hardening);
 
 void do_sp_pc_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs)
 {
-	arm64_notify_die("SP/PC alignment exception", regs,
-			 SIGBUS, BUS_ADRALN, (void __user *)addr, esr);
+	arm64_notify_die("SP/PC alignment exception", regs, SIGBUS, BUS_ADRALN,
+			 addr, esr);
 }
 NOKPROBE_SYMBOL(do_sp_pc_abort);
 
@@ -862,8 +864,7 @@ void do_debug_exception(unsigned long addr_if_watchpoint, unsigned int esr,
 		arm64_apply_bp_hardening();
 
 	if (inf->fn(addr_if_watchpoint, esr, regs)) {
-		arm64_notify_die(inf->name, regs,
-				 inf->sig, inf->code, (void __user *)pc, esr);
+		arm64_notify_die(inf->name, regs, inf->sig, inf->code, pc, esr);
 	}
 
 	debug_exception_exit(regs);
diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
index 6b99f0c8a068..9a40c47f66c2 100644
--- a/arch/x86/kernel/signal_compat.c
+++ b/arch/x86/kernel/signal_compat.c
@@ -121,8 +121,8 @@ static inline void signal_compat_build_tests(void)
 #endif
 
 	CHECK_CSI_OFFSET(_sigfault);
-	CHECK_CSI_SIZE  (_sigfault, 8*sizeof(int));
-	CHECK_SI_SIZE   (_sigfault, 16*sizeof(int));
+	CHECK_CSI_SIZE  (_sigfault, 10*sizeof(int));
+	CHECK_SI_SIZE   (_sigfault, 20*sizeof(int));
 
 	BUILD_BUG_ON(offsetof(siginfo_t, si_addr) != 0x10);
 	BUILD_BUG_ON(offsetof(compat_siginfo_t, si_addr) != 0x0C);
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 55d4228dfd88..273146cf30fd 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -234,6 +234,8 @@ typedef struct compat_siginfo {
 				compat_uptr_t _pad[6];
 			};
 			compat_uptr_t _xflags;
+			compat_uptr_t _addr_ignored_bits;
+			compat_uptr_t _addr_ignored_bits_mask;
 		} _sigfault;
 
 		/* SIGPOLL */
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 3edbf54493ee..b4c473c12a9b 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -480,4 +480,12 @@ struct seq_file;
 extern void render_sigset_t(struct seq_file *, const char *, sigset_t *);
 #endif
 
+#ifndef arch_addr_ignored_bits_mask
+static inline unsigned long arch_addr_ignored_bits_mask(unsigned long sig,
+							unsigned long si_code)
+{
+	return 0;
+}
+#endif
+
 #endif /* _LINUX_SIGNAL_H */
diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
index 1fbd88d64f38..e314a38ce2d0 100644
--- a/include/uapi/asm-generic/siginfo.h
+++ b/include/uapi/asm-generic/siginfo.h
@@ -94,6 +94,8 @@ union __sifields {
 			void *_pad[6];
 		};
 		unsigned long _xflags;
+		unsigned long _addr_ignored_bits;
+		unsigned long _addr_ignored_bits_mask;
 	} _sigfault;
 
 	/* SIGPOLL */
@@ -156,6 +158,8 @@ typedef struct siginfo {
 #define si_addr_lsb	_sifields._sigfault._addr_lsb
 /* si_xflags is only valid if 0 <= si_code < SI_KERNEL */
 #define si_xflags	_sifields._sigfault._xflags
+#define si_addr_ignored_bits		_sifields._sigfault._addr_ignored_bits
+#define si_addr_ignored_bits_mask	_sifields._sigfault._addr_ignored_bits_mask
 #define si_lower	_sifields._sigfault._addr_bnd._lower
 #define si_upper	_sifields._sigfault._addr_bnd._upper
 #define si_pkey		_sifields._sigfault._addr_pkey._pkey
@@ -296,6 +300,12 @@ typedef struct siginfo {
 #define EMT_TAGOVF	1	/* tag overflow */
 #define NSIGEMT		1
 
+/*
+ * SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT si_xflags
+ */
+#define SIXFLAG_ADDR_IGNORED_BITS	1
+/* si_addr_ignored_bits{,_mask} fields valid */
+
 /*
  * sigevent definitions
  * 
diff --git a/kernel/signal.c b/kernel/signal.c
index 4259903b95cb..29654652d3aa 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1652,11 +1652,17 @@ void force_sigsegv(int sig)
 static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
 				       int code, void __user *addr)
 {
+	unsigned long addr_long = (unsigned long)addr;
+	unsigned long ignored_bits_mask =
+		arch_addr_ignored_bits_mask(sig, code);
+
 	info->si_signo = sig;
 	info->si_errno = 0;
 	info->si_code = code;
-	info->si_addr = addr;
-	info->si_xflags = 0;
+	info->si_addr = (void __user *)(addr_long & ~ignored_bits_mask);
+	info->si_xflags = SIXFLAG_ADDR_IGNORED_BITS;
+	info->si_addr_ignored_bits = addr_long & ignored_bits_mask;
+	info->si_addr_ignored_bits_mask = ignored_bits_mask;
 }
 
 int force_sig_fault_to_task(int sig, int code, void __user *addr
@@ -3271,6 +3277,8 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
 		to->si_trapno = from->si_trapno;
 #endif
 		to->si_xflags = from->si_xflags;
+		to->si_addr_ignored_bits = from->si_addr_ignored_bits;
+		to->si_addr_ignored_bits_mask = from->si_addr_ignored_bits_mask;
 	}
 
 	switch (layout) {
@@ -3347,6 +3355,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 		to->si_trapno = from->si_trapno;
 #endif
 		to->si_xflags = from->si_xflags;
+		to->si_addr_ignored_bits = from->si_addr_ignored_bits;
+		to->si_addr_ignored_bits_mask = from->si_addr_ignored_bits_mask;
 	}
 
 	switch (layout) {
-- 
2.28.0.297.g1956fa8f8d-goog


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH v10 7/7] arm64: expose FAR_EL1 tag bits in siginfo
@ 2020-08-22  5:10   ` Peter Collingbourne
  0 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-08-22  5:10 UTC (permalink / raw)
  To: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	Eric W. Biederman, James E.J. Bottomley
  Cc: linux-parisc, Andrey Konovalov, Kevin Brodsky, David Spickett,
	Peter Collingbourne, Linux ARM, Richard Henderson

The kernel currently clears the tag bits (i.e. bits 56-63) in the fault
address exposed via siginfo.si_addr and sigcontext.fault_address. However,
the tag bits may be needed by tools in order to accurately diagnose
memory errors, such as HWASan [1] or future tools based on the Memory
Tagging Extension (MTE).

We should not stop clearing these bits in the existing fault address
fields, because there may be existing userspace applications that are
expecting the tag bits to be cleared. Instead, create a new pair of
union fields in siginfo._sigfault, and store the tag bits of FAR_EL1
there, together with a mask specifying which bits are valid.

A flag is added to si_xflags to allow userspace to determine whether
the values in the fields are valid.

[1] http://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html

Signed-off-by: Peter Collingbourne <pcc@google.com>
---
View this change in Gerrit: https://linux-review.googlesource.com/q/Ia8876bad8c798e0a32df7c2ce1256c4771c81446

v10:
- rename the flag to SIXFLAG_ADDR_IGNORED_BITS
- use an arch hook to specify which bits are ignored, instead
  of passing them explicitly
- while refactoring for the arch hook, noticed that my previous
  patches missed a case involving cache maintenance instructions,
  so expose the tag bits for that signal as well

v9:
- make the ignored bits fields generic
- add some new dependent patches that prepare us to store the
  field in such a way that userspace can detect their presence

v8:
- rebase onto 5.8rc2

v7:
- switch to a new siginfo field instead of using sigcontext
- merge the patch back into one since the other patches are now
  unnecessary

v6:
- move fault address and fault code into the kernel_siginfo data structure
- split the patch in three since it was getting large and now has
  generic and arch-specific parts

v5:
- add padding to fault_addr_top_byte_context in order to ensure the correct
  size and preserve sp alignment

v4:
- expose only the tag bits in the context instead of the entire FAR_EL1
- remove mention of the new context from the sigcontext.__reserved[] note

v3:
- add documentation to tagged-pointers.rst
- update comments in sigcontext.h

v2:
- revert changes to hw_breakpoint.c
- rename set_thread_esr to set_thread_far_esr

 Documentation/arm64/tagged-pointers.rst | 21 ++++++---
 arch/arm64/include/asm/exception.h      |  2 +-
 arch/arm64/include/asm/signal.h         | 17 +++++++
 arch/arm64/include/asm/system_misc.h    |  2 +-
 arch/arm64/include/asm/traps.h          |  6 +--
 arch/arm64/kernel/debug-monitors.c      |  5 +--
 arch/arm64/kernel/entry-common.c        |  2 -
 arch/arm64/kernel/ptrace.c              |  7 +--
 arch/arm64/kernel/sys_compat.c          |  5 +--
 arch/arm64/kernel/traps.c               | 29 ++++++------
 arch/arm64/mm/fault.c                   | 59 +++++++++++++------------
 arch/x86/kernel/signal_compat.c         |  4 +-
 include/linux/compat.h                  |  2 +
 include/linux/signal.h                  |  8 ++++
 include/uapi/asm-generic/siginfo.h      | 10 +++++
 kernel/signal.c                         | 14 +++++-
 16 files changed, 122 insertions(+), 71 deletions(-)
 create mode 100644 arch/arm64/include/asm/signal.h

diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst
index eab4323609b9..14273160b38b 100644
--- a/Documentation/arm64/tagged-pointers.rst
+++ b/Documentation/arm64/tagged-pointers.rst
@@ -53,12 +53,21 @@ visibility.
 Preserving tags
 ---------------
 
-Non-zero tags are not preserved when delivering signals. This means that
-signal handlers in applications making use of tags cannot rely on the
-tag information for user virtual addresses being maintained for fields
-inside siginfo_t. One exception to this rule is for signals raised in
-response to watchpoint debug exceptions, where the tag information will
-be preserved.
+Non-zero tags are not preserved in the fault address fields
+siginfo.si_addr or sigcontext.fault_address when delivering
+signals. This means that signal handlers in applications making use
+of tags cannot rely on the tag information for user virtual addresses
+being maintained in these fields. One exception to this rule is for
+signals raised in response to watchpoint debug exceptions, where the
+tag information will be preserved.
+
+The fault address tag is preserved in the si_addr_ignored_bits field
+of siginfo, which is set for signals raised in response to data aborts
+and instruction aborts. The si_addr_ignored_bits_mask field indicates
+which bits of the field are valid. The validity of these fields is
+indicated by the SIXFLAG_ADDR_IGNORED_BITS flag in siginfo.si_xflags,
+and the validity of si_xflags in turn is indicated by the kernel
+indicating support for the sigaction.sa_flags flag SA_XFLAGS.
 
 The architecture prevents the use of a tagged PC, so the upper byte will
 be set to a sign-extension of bit 55 on exception return.
diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h
index 7577a754d443..950d55dae948 100644
--- a/arch/arm64/include/asm/exception.h
+++ b/arch/arm64/include/asm/exception.h
@@ -32,7 +32,7 @@ static inline u32 disr_to_esr(u64 disr)
 }
 
 asmlinkage void enter_from_user_mode(void);
-void do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs);
+void do_mem_abort(unsigned long far, unsigned int esr, struct pt_regs *regs);
 void do_undefinstr(struct pt_regs *regs);
 void do_bti(struct pt_regs *regs);
 asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr);
diff --git a/arch/arm64/include/asm/signal.h b/arch/arm64/include/asm/signal.h
new file mode 100644
index 000000000000..038cc9784c57
--- /dev/null
+++ b/arch/arm64/include/asm/signal.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ARM64_ASM_SIGNAL_H
+#define __ARM64_ASM_SIGNAL_H
+
+#include <uapi/asm/signal.h>
+#include <uapi/asm/siginfo.h>
+
+static inline unsigned long arch_addr_ignored_bits_mask(unsigned long sig,
+							unsigned long si_code)
+{
+	if (sig == SIGTRAP && si_code == TRAP_BRKPT)
+		return 0;
+	return 0xffUL << 56;
+}
+#define arch_addr_ignored_bits_mask arch_addr_ignored_bits_mask
+
+#endif
diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h
index 1ab63cfbbaf1..673be2d1263c 100644
--- a/arch/arm64/include/asm/system_misc.h
+++ b/arch/arm64/include/asm/system_misc.h
@@ -22,7 +22,7 @@ void die(const char *msg, struct pt_regs *regs, int err);
 
 struct siginfo;
 void arm64_notify_die(const char *str, struct pt_regs *regs,
-		      int signo, int sicode, void __user *addr,
+		      int signo, int sicode, unsigned long far,
 		      int err);
 
 void hook_debug_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h
index cee5928e1b7d..9bb5376608d3 100644
--- a/arch/arm64/include/asm/traps.h
+++ b/arch/arm64/include/asm/traps.h
@@ -26,9 +26,9 @@ void register_undef_hook(struct undef_hook *hook);
 void unregister_undef_hook(struct undef_hook *hook);
 void force_signal_inject(int signal, int code, unsigned long address);
 void arm64_notify_segfault(unsigned long addr);
-void arm64_force_sig_fault(int signo, int code, void __user *addr, const char *str);
-void arm64_force_sig_mceerr(int code, void __user *addr, short lsb, const char *str);
-void arm64_force_sig_ptrace_errno_trap(int errno, void __user *addr, const char *str);
+void arm64_force_sig_fault(int signo, int code, unsigned long far, const char *str);
+void arm64_force_sig_mceerr(int code, unsigned long far, short lsb, const char *str);
+void arm64_force_sig_ptrace_errno_trap(int errno, unsigned long far, const char *str);
 
 /*
  * Move regs->pc to next instruction and do necessary setup before it
diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
index 7310a4f7f993..943e932def37 100644
--- a/arch/arm64/kernel/debug-monitors.c
+++ b/arch/arm64/kernel/debug-monitors.c
@@ -234,9 +234,8 @@ static void send_user_sigtrap(int si_code)
 	if (interrupts_enabled(regs))
 		local_irq_enable();
 
-	arm64_force_sig_fault(SIGTRAP, si_code,
-			     (void __user *)instruction_pointer(regs),
-			     "User debug trap");
+	arm64_force_sig_fault(SIGTRAP, si_code, instruction_pointer(regs),
+			      "User debug trap");
 }
 
 static int single_step_handler(unsigned long unused, unsigned int esr,
diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index d3be9dbf5490..65ed01606480 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -22,7 +22,6 @@ static void notrace el1_abort(struct pt_regs *regs, unsigned long esr)
 	unsigned long far = read_sysreg(far_el1);
 
 	local_daif_inherit(regs);
-	far = untagged_addr(far);
 	do_mem_abort(far, esr, regs);
 }
 NOKPROBE_SYMBOL(el1_abort);
@@ -104,7 +103,6 @@ static void notrace el0_da(struct pt_regs *regs, unsigned long esr)
 
 	user_exit_irqoff();
 	local_daif_restore(DAIF_PROCCTX);
-	far = untagged_addr(far);
 	do_mem_abort(far, esr, regs);
 }
 NOKPROBE_SYMBOL(el0_da);
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index d8ebfd813e28..3f12c731fa9a 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -191,14 +191,11 @@ static void ptrace_hbptriggered(struct perf_event *bp,
 				break;
 			}
 		}
-		arm64_force_sig_ptrace_errno_trap(si_errno,
-						  (void __user *)bkpt->trigger,
+		arm64_force_sig_ptrace_errno_trap(si_errno, bkpt->trigger,
 						  desc);
 	}
 #endif
-	arm64_force_sig_fault(SIGTRAP, TRAP_HWBKPT,
-			      (void __user *)(bkpt->trigger),
-			      desc);
+	arm64_force_sig_fault(SIGTRAP, TRAP_HWBKPT, bkpt->trigger, desc);
 }
 
 /*
diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c
index 3c18c2454089..265fe3eb1069 100644
--- a/arch/arm64/kernel/sys_compat.c
+++ b/arch/arm64/kernel/sys_compat.c
@@ -68,7 +68,7 @@ do_compat_cache_op(unsigned long start, unsigned long end, int flags)
  */
 long compat_arm_syscall(struct pt_regs *regs, int scno)
 {
-	void __user *addr;
+	unsigned long addr;
 
 	switch (scno) {
 	/*
@@ -111,8 +111,7 @@ long compat_arm_syscall(struct pt_regs *regs, int scno)
 		break;
 	}
 
-	addr  = (void __user *)instruction_pointer(regs) -
-		(compat_thumb_mode(regs) ? 2 : 4);
+	addr = instruction_pointer(regs) - (compat_thumb_mode(regs) ? 2 : 4);
 
 	arm64_notify_die("Oops - bad compat syscall(2)", regs,
 			 SIGILL, ILL_ILLTRP, addr, scno);
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 13ebd5ca2070..8f8105076f92 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -234,32 +234,32 @@ static void arm64_show_signal(int signo, const char *str)
 	__show_regs(regs);
 }
 
-void arm64_force_sig_fault(int signo, int code, void __user *addr,
+void arm64_force_sig_fault(int signo, int code, unsigned long far,
 			   const char *str)
 {
 	arm64_show_signal(signo, str);
 	if (signo == SIGKILL)
 		force_sig(SIGKILL);
 	else
-		force_sig_fault(signo, code, addr);
+		force_sig_fault(signo, code, (void __user *)far);
 }
 
-void arm64_force_sig_mceerr(int code, void __user *addr, short lsb,
+void arm64_force_sig_mceerr(int code, unsigned long far, short lsb,
 			    const char *str)
 {
 	arm64_show_signal(SIGBUS, str);
-	force_sig_mceerr(code, addr, lsb);
+	force_sig_mceerr(code, (void __user *)far, lsb);
 }
 
-void arm64_force_sig_ptrace_errno_trap(int errno, void __user *addr,
+void arm64_force_sig_ptrace_errno_trap(int errno, unsigned long far,
 				       const char *str)
 {
 	arm64_show_signal(SIGTRAP, str);
-	force_sig_ptrace_errno_trap(errno, addr);
+	force_sig_ptrace_errno_trap(errno, (void __user *)far);
 }
 
 void arm64_notify_die(const char *str, struct pt_regs *regs,
-		      int signo, int sicode, void __user *addr,
+		      int signo, int sicode, unsigned long far,
 		      int err)
 {
 	if (user_mode(regs)) {
@@ -267,7 +267,7 @@ void arm64_notify_die(const char *str, struct pt_regs *regs,
 		current->thread.fault_address = 0;
 		current->thread.fault_code = err;
 
-		arm64_force_sig_fault(signo, sicode, addr, str);
+		arm64_force_sig_fault(signo, sicode, far, str);
 	} else {
 		die(str, regs, err);
 	}
@@ -438,7 +438,7 @@ void force_signal_inject(int signal, int code, unsigned long address)
 		signal = SIGKILL;
 	}
 
-	arm64_notify_die(desc, regs, signal, code, (void __user *)address, 0);
+	arm64_notify_die(desc, regs, signal, code, address, 0);
 }
 
 /*
@@ -449,7 +449,7 @@ void arm64_notify_segfault(unsigned long addr)
 	int code;
 
 	mmap_read_lock(current->mm);
-	if (find_vma(current->mm, addr) == NULL)
+	if (find_vma(current->mm, untagged_addr(addr)) == NULL)
 		code = SEGV_MAPERR;
 	else
 		code = SEGV_ACCERR;
@@ -501,12 +501,13 @@ NOKPROBE_SYMBOL(do_bti);
 
 static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs)
 {
-	unsigned long address;
+	unsigned long tagged_address, address;
 	int rt = ESR_ELx_SYS64_ISS_RT(esr);
 	int crm = (esr & ESR_ELx_SYS64_ISS_CRM_MASK) >> ESR_ELx_SYS64_ISS_CRM_SHIFT;
 	int ret = 0;
 
-	address = untagged_addr(pt_regs_read_reg(regs, rt));
+	tagged_address = pt_regs_read_reg(regs, rt);
+	address = untagged_addr(tagged_address);
 
 	switch (crm) {
 	case ESR_ELx_SYS64_ISS_CRM_DC_CVAU:	/* DC CVAU, gets promoted */
@@ -533,7 +534,7 @@ static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs)
 	}
 
 	if (ret)
-		arm64_notify_segfault(address);
+		arm64_notify_segfault(tagged_address);
 	else
 		arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE);
 }
@@ -824,7 +825,7 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr)
  */
 void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr)
 {
-	void __user *pc = (void __user *)instruction_pointer(regs);
+	unsigned long pc = instruction_pointer(regs);
 
 	current->thread.fault_address = 0;
 	current->thread.fault_code = esr;
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index f07333e86c2f..d17953d9b3d9 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -40,7 +40,7 @@
 #include <asm/traps.h>
 
 struct fault_info {
-	int	(*fn)(unsigned long addr, unsigned int esr,
+	int	(*fn)(unsigned long far, unsigned int esr,
 		      struct pt_regs *regs);
 	int	sig;
 	int	code;
@@ -383,8 +383,11 @@ static void set_thread_esr(unsigned long address, unsigned int esr)
 	current->thread.fault_code = esr;
 }
 
-static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *regs)
+static void do_bad_area(unsigned long far, unsigned int esr,
+			struct pt_regs *regs)
 {
+	unsigned long addr = untagged_addr(far);
+
 	/*
 	 * If we are in kernel mode at this point, we have no context to
 	 * handle this fault with.
@@ -393,8 +396,7 @@ static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *re
 		const struct fault_info *inf = esr_to_fault_info(esr);
 
 		set_thread_esr(addr, esr);
-		arm64_force_sig_fault(inf->sig, inf->code, (void __user *)addr,
-				      inf->name);
+		arm64_force_sig_fault(inf->sig, inf->code, far, inf->name);
 	} else {
 		__do_kernel_fault(addr, esr, regs);
 	}
@@ -446,7 +448,7 @@ static bool is_write_abort(unsigned int esr)
 	return (esr & ESR_ELx_WNR) && !(esr & ESR_ELx_CM);
 }
 
-static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
+static int __kprobes do_page_fault(unsigned long far, unsigned int esr,
 				   struct pt_regs *regs)
 {
 	const struct fault_info *inf;
@@ -454,6 +456,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
 	vm_fault_t fault;
 	unsigned long vm_flags = VM_ACCESS_FLAGS;
 	unsigned int mm_flags = FAULT_FLAG_DEFAULT;
+	unsigned long addr = untagged_addr(far);
 
 	if (kprobe_page_fault(regs, esr))
 		return 0;
@@ -565,8 +568,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
 		 * We had some memory, but were unable to successfully fix up
 		 * this page fault.
 		 */
-		arm64_force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)addr,
-				      inf->name);
+		arm64_force_sig_fault(SIGBUS, BUS_ADRERR, far, inf->name);
 	} else if (fault & (VM_FAULT_HWPOISON_LARGE | VM_FAULT_HWPOISON)) {
 		unsigned int lsb;
 
@@ -574,8 +576,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
 		if (fault & VM_FAULT_HWPOISON_LARGE)
 			lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault));
 
-		arm64_force_sig_mceerr(BUS_MCEERR_AR, (void __user *)addr, lsb,
-				       inf->name);
+		arm64_force_sig_mceerr(BUS_MCEERR_AR, far, lsb, inf->name);
 	} else {
 		/*
 		 * Something tried to access memory that isn't in our memory
@@ -583,8 +584,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
 		 */
 		arm64_force_sig_fault(SIGSEGV,
 				      fault == VM_FAULT_BADACCESS ? SEGV_ACCERR : SEGV_MAPERR,
-				      (void __user *)addr,
-				      inf->name);
+				      far, inf->name);
 	}
 
 	return 0;
@@ -594,33 +594,35 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
 	return 0;
 }
 
-static int __kprobes do_translation_fault(unsigned long addr,
+static int __kprobes do_translation_fault(unsigned long far,
 					  unsigned int esr,
 					  struct pt_regs *regs)
 {
+	unsigned long addr = untagged_addr(far);
+
 	if (is_ttbr0_addr(addr))
-		return do_page_fault(addr, esr, regs);
+		return do_page_fault(far, esr, regs);
 
-	do_bad_area(addr, esr, regs);
+	do_bad_area(far, esr, regs);
 	return 0;
 }
 
-static int do_alignment_fault(unsigned long addr, unsigned int esr,
+static int do_alignment_fault(unsigned long far, unsigned int esr,
 			      struct pt_regs *regs)
 {
-	do_bad_area(addr, esr, regs);
+	do_bad_area(far, esr, regs);
 	return 0;
 }
 
-static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs)
+static int do_bad(unsigned long far, unsigned int esr, struct pt_regs *regs)
 {
 	return 1; /* "fault" */
 }
 
-static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
+static int do_sea(unsigned long far, unsigned int esr, struct pt_regs *regs)
 {
 	const struct fault_info *inf;
-	void __user *siaddr;
+	unsigned long siaddr;
 
 	inf = esr_to_fault_info(esr);
 
@@ -633,9 +635,9 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
 	}
 
 	if (esr & ESR_ELx_FnV)
-		siaddr = NULL;
+		siaddr = 0;
 	else
-		siaddr  = (void __user *)addr;
+		siaddr  = untagged_addr(far);
 	arm64_notify_die(inf->name, regs, inf->sig, inf->code, siaddr, esr);
 
 	return 0;
@@ -708,11 +710,12 @@ static const struct fault_info fault_info[] = {
 	{ do_bad,		SIGKILL, SI_KERNEL,	"unknown 63"			},
 };
 
-void do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs)
+void do_mem_abort(unsigned long far, unsigned int esr, struct pt_regs *regs)
 {
 	const struct fault_info *inf = esr_to_fault_info(esr);
+	unsigned long addr = untagged_addr(far);
 
-	if (!inf->fn(addr, esr, regs))
+	if (!inf->fn(far, esr, regs))
 		return;
 
 	if (!user_mode(regs)) {
@@ -721,8 +724,7 @@ void do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs)
 		show_pte(addr);
 	}
 
-	arm64_notify_die(inf->name, regs,
-			 inf->sig, inf->code, (void __user *)addr, esr);
+	arm64_notify_die(inf->name, regs, inf->sig, inf->code, addr, esr);
 }
 NOKPROBE_SYMBOL(do_mem_abort);
 
@@ -735,8 +737,8 @@ NOKPROBE_SYMBOL(do_el0_irq_bp_hardening);
 
 void do_sp_pc_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs)
 {
-	arm64_notify_die("SP/PC alignment exception", regs,
-			 SIGBUS, BUS_ADRALN, (void __user *)addr, esr);
+	arm64_notify_die("SP/PC alignment exception", regs, SIGBUS, BUS_ADRALN,
+			 addr, esr);
 }
 NOKPROBE_SYMBOL(do_sp_pc_abort);
 
@@ -862,8 +864,7 @@ void do_debug_exception(unsigned long addr_if_watchpoint, unsigned int esr,
 		arm64_apply_bp_hardening();
 
 	if (inf->fn(addr_if_watchpoint, esr, regs)) {
-		arm64_notify_die(inf->name, regs,
-				 inf->sig, inf->code, (void __user *)pc, esr);
+		arm64_notify_die(inf->name, regs, inf->sig, inf->code, pc, esr);
 	}
 
 	debug_exception_exit(regs);
diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
index 6b99f0c8a068..9a40c47f66c2 100644
--- a/arch/x86/kernel/signal_compat.c
+++ b/arch/x86/kernel/signal_compat.c
@@ -121,8 +121,8 @@ static inline void signal_compat_build_tests(void)
 #endif
 
 	CHECK_CSI_OFFSET(_sigfault);
-	CHECK_CSI_SIZE  (_sigfault, 8*sizeof(int));
-	CHECK_SI_SIZE   (_sigfault, 16*sizeof(int));
+	CHECK_CSI_SIZE  (_sigfault, 10*sizeof(int));
+	CHECK_SI_SIZE   (_sigfault, 20*sizeof(int));
 
 	BUILD_BUG_ON(offsetof(siginfo_t, si_addr) != 0x10);
 	BUILD_BUG_ON(offsetof(compat_siginfo_t, si_addr) != 0x0C);
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 55d4228dfd88..273146cf30fd 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -234,6 +234,8 @@ typedef struct compat_siginfo {
 				compat_uptr_t _pad[6];
 			};
 			compat_uptr_t _xflags;
+			compat_uptr_t _addr_ignored_bits;
+			compat_uptr_t _addr_ignored_bits_mask;
 		} _sigfault;
 
 		/* SIGPOLL */
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 3edbf54493ee..b4c473c12a9b 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -480,4 +480,12 @@ struct seq_file;
 extern void render_sigset_t(struct seq_file *, const char *, sigset_t *);
 #endif
 
+#ifndef arch_addr_ignored_bits_mask
+static inline unsigned long arch_addr_ignored_bits_mask(unsigned long sig,
+							unsigned long si_code)
+{
+	return 0;
+}
+#endif
+
 #endif /* _LINUX_SIGNAL_H */
diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
index 1fbd88d64f38..e314a38ce2d0 100644
--- a/include/uapi/asm-generic/siginfo.h
+++ b/include/uapi/asm-generic/siginfo.h
@@ -94,6 +94,8 @@ union __sifields {
 			void *_pad[6];
 		};
 		unsigned long _xflags;
+		unsigned long _addr_ignored_bits;
+		unsigned long _addr_ignored_bits_mask;
 	} _sigfault;
 
 	/* SIGPOLL */
@@ -156,6 +158,8 @@ typedef struct siginfo {
 #define si_addr_lsb	_sifields._sigfault._addr_lsb
 /* si_xflags is only valid if 0 <= si_code < SI_KERNEL */
 #define si_xflags	_sifields._sigfault._xflags
+#define si_addr_ignored_bits		_sifields._sigfault._addr_ignored_bits
+#define si_addr_ignored_bits_mask	_sifields._sigfault._addr_ignored_bits_mask
 #define si_lower	_sifields._sigfault._addr_bnd._lower
 #define si_upper	_sifields._sigfault._addr_bnd._upper
 #define si_pkey		_sifields._sigfault._addr_pkey._pkey
@@ -296,6 +300,12 @@ typedef struct siginfo {
 #define EMT_TAGOVF	1	/* tag overflow */
 #define NSIGEMT		1
 
+/*
+ * SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT si_xflags
+ */
+#define SIXFLAG_ADDR_IGNORED_BITS	1
+/* si_addr_ignored_bits{,_mask} fields valid */
+
 /*
  * sigevent definitions
  * 
diff --git a/kernel/signal.c b/kernel/signal.c
index 4259903b95cb..29654652d3aa 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1652,11 +1652,17 @@ void force_sigsegv(int sig)
 static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
 				       int code, void __user *addr)
 {
+	unsigned long addr_long = (unsigned long)addr;
+	unsigned long ignored_bits_mask =
+		arch_addr_ignored_bits_mask(sig, code);
+
 	info->si_signo = sig;
 	info->si_errno = 0;
 	info->si_code = code;
-	info->si_addr = addr;
-	info->si_xflags = 0;
+	info->si_addr = (void __user *)(addr_long & ~ignored_bits_mask);
+	info->si_xflags = SIXFLAG_ADDR_IGNORED_BITS;
+	info->si_addr_ignored_bits = addr_long & ignored_bits_mask;
+	info->si_addr_ignored_bits_mask = ignored_bits_mask;
 }
 
 int force_sig_fault_to_task(int sig, int code, void __user *addr
@@ -3271,6 +3277,8 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
 		to->si_trapno = from->si_trapno;
 #endif
 		to->si_xflags = from->si_xflags;
+		to->si_addr_ignored_bits = from->si_addr_ignored_bits;
+		to->si_addr_ignored_bits_mask = from->si_addr_ignored_bits_mask;
 	}
 
 	switch (layout) {
@@ -3347,6 +3355,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 		to->si_trapno = from->si_trapno;
 #endif
 		to->si_xflags = from->si_xflags;
+		to->si_addr_ignored_bits = from->si_addr_ignored_bits;
+		to->si_addr_ignored_bits_mask = from->si_addr_ignored_bits_mask;
 	}
 
 	switch (layout) {
-- 
2.28.0.297.g1956fa8f8d-goog


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 1/7] parisc: start using signal-defs.h
  2020-08-22  5:10   ` Peter Collingbourne
  (?)
@ 2020-08-30 17:07   ` Helge Deller
  2020-10-03  1:22     ` Peter Collingbourne
  -1 siblings, 1 reply; 59+ messages in thread
From: Helge Deller @ 2020-08-30 17:07 UTC (permalink / raw)
  To: Peter Collingbourne, James E.J. Bottomley; +Cc: Richard Henderson, linux-parisc

On 22.08.20 07:10, Peter Collingbourne wrote:
> We currently include signal-defs.h on all architectures except parisc.
> Make parisc fall in line. This will make maintenance easier once the
> flag bits are moved here.

The patch is basically OK, but....

> Signed-off-by: Peter Collingbourne <pcc@google.com>
> ---
> View this change in Gerrit: https://linux-review.googlesource.com/q/If03a5135fb514fe96548fb74610e6c3586a04064
>
>  arch/parisc/include/uapi/asm/signal.h  | 9 +--------
>  include/uapi/asm-generic/signal-defs.h | 6 ++++++
>  2 files changed, 7 insertions(+), 8 deletions(-)
>
> diff --git a/arch/parisc/include/uapi/asm/signal.h b/arch/parisc/include/uapi/asm/signal.h
> index d38563a394f2..92a1c7ea44b4 100644
> --- a/arch/parisc/include/uapi/asm/signal.h
> +++ b/arch/parisc/include/uapi/asm/signal.h
> @@ -69,14 +69,7 @@
>  #define MINSIGSTKSZ	2048
>  #define SIGSTKSZ	8192
>
> -
> -#define SIG_BLOCK          0	/* for blocking signals */
> -#define SIG_UNBLOCK        1	/* for unblocking signals */
> -#define SIG_SETMASK        2	/* for setting the signal mask */
> -
> -#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
> -#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
> -#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
> +#include <asm/signal-defs.h>
>
>  # ifndef __ASSEMBLY__
>
> diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
> index e9304c95ceea..ecdf6312bfa5 100644
> --- a/include/uapi/asm-generic/signal-defs.h
> +++ b/include/uapi/asm-generic/signal-defs.h
> @@ -15,8 +15,14 @@
>  #endif
>
>  #ifndef __ASSEMBLY__

> +#ifndef __hppa__
> +/*
> + * These have a special definition on parisc, see:
> + * arch/parisc/include/uapi/asm/signal.h
> + */
>  typedef void __signalfn_t(int);
>  typedef __signalfn_t __user *__sighandler_t;

please drop this special-case/#ifdef for hppa/parisc.
Instead please drop the typedef in arch/parisc/include/uapi/asm/signal.h,
same as you did for the other architectures.

I've committed this patch to my tree, which will collide with yours:
 https://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux.git/commit/?h=for-next
If you like I can drop mine, and you fix it up on your side.
Just let me know.

Other than that you can add:
Acked-by: Helge Deller <deller@gmx.de>

Thanks!
Helge

> +#endif
>
>  typedef void __restorefn_t(void);
>  typedef __restorefn_t __user *__sigrestore_t;
>


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 1/7] parisc: start using signal-defs.h
  2020-08-22  5:10   ` Peter Collingbourne
@ 2020-09-08 15:12     ` Dave Martin
  -1 siblings, 0 replies; 59+ messages in thread
From: Dave Martin @ 2020-09-08 15:12 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Will Deacon, Oleg Nesterov, Eric W. Biederman,
	James E.J. Bottomley, linux-parisc, Andrey Konovalov,
	Kevin Brodsky, David Spickett, Linux ARM, Richard Henderson

On Fri, Aug 21, 2020 at 10:10:11PM -0700, Peter Collingbourne wrote:
> We currently include signal-defs.h on all architectures except parisc.
> Make parisc fall in line. This will make maintenance easier once the
> flag bits are moved here.
> 
> Signed-off-by: Peter Collingbourne <pcc@google.com>
> ---
> View this change in Gerrit: https://linux-review.googlesource.com/q/If03a5135fb514fe96548fb74610e6c3586a04064
> 
>  arch/parisc/include/uapi/asm/signal.h  | 9 +--------
>  include/uapi/asm-generic/signal-defs.h | 6 ++++++
>  2 files changed, 7 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/parisc/include/uapi/asm/signal.h b/arch/parisc/include/uapi/asm/signal.h
> index d38563a394f2..92a1c7ea44b4 100644
> --- a/arch/parisc/include/uapi/asm/signal.h
> +++ b/arch/parisc/include/uapi/asm/signal.h
> @@ -69,14 +69,7 @@
>  #define MINSIGSTKSZ	2048
>  #define SIGSTKSZ	8192
>  
> -
> -#define SIG_BLOCK          0	/* for blocking signals */
> -#define SIG_UNBLOCK        1	/* for unblocking signals */
> -#define SIG_SETMASK        2	/* for setting the signal mask */
> -
> -#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
> -#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
> -#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
> +#include <asm/signal-defs.h>
>  
>  # ifndef __ASSEMBLY__
>  
> diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
> index e9304c95ceea..ecdf6312bfa5 100644
> --- a/include/uapi/asm-generic/signal-defs.h
> +++ b/include/uapi/asm-generic/signal-defs.h
> @@ -15,8 +15,14 @@
>  #endif
>  
>  #ifndef __ASSEMBLY__
> +#ifndef __hppa__
> +/*
> + * These have a special definition on parisc, see:
> + * arch/parisc/include/uapi/asm/signal.h
> + */
>  typedef void __signalfn_t(int);
>  typedef __signalfn_t __user *__sighandler_t;
> +#endif

Could we do something like

	#ifndef __sighandler_t
	/* ... */
	#define __sighandler_t __sighandler_t
	#endif

Then we don't have to have anything parisc-specific in the common
header, and arches can override this definition independently.

Not a big deal either way, though, and best to keep the comment about
why this is here in any case.

Cheers
---Dave

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 1/7] parisc: start using signal-defs.h
@ 2020-09-08 15:12     ` Dave Martin
  0 siblings, 0 replies; 59+ messages in thread
From: Dave Martin @ 2020-09-08 15:12 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Linux ARM, linux-parisc, Catalin Marinas, Kevin Brodsky,
	Oleg Nesterov, James E.J. Bottomley, Kostya Serebryany,
	Eric W. Biederman, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Will Deacon, Evgenii Stepanov,
	Richard Henderson

On Fri, Aug 21, 2020 at 10:10:11PM -0700, Peter Collingbourne wrote:
> We currently include signal-defs.h on all architectures except parisc.
> Make parisc fall in line. This will make maintenance easier once the
> flag bits are moved here.
> 
> Signed-off-by: Peter Collingbourne <pcc@google.com>
> ---
> View this change in Gerrit: https://linux-review.googlesource.com/q/If03a5135fb514fe96548fb74610e6c3586a04064
> 
>  arch/parisc/include/uapi/asm/signal.h  | 9 +--------
>  include/uapi/asm-generic/signal-defs.h | 6 ++++++
>  2 files changed, 7 insertions(+), 8 deletions(-)
> 
> diff --git a/arch/parisc/include/uapi/asm/signal.h b/arch/parisc/include/uapi/asm/signal.h
> index d38563a394f2..92a1c7ea44b4 100644
> --- a/arch/parisc/include/uapi/asm/signal.h
> +++ b/arch/parisc/include/uapi/asm/signal.h
> @@ -69,14 +69,7 @@
>  #define MINSIGSTKSZ	2048
>  #define SIGSTKSZ	8192
>  
> -
> -#define SIG_BLOCK          0	/* for blocking signals */
> -#define SIG_UNBLOCK        1	/* for unblocking signals */
> -#define SIG_SETMASK        2	/* for setting the signal mask */
> -
> -#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
> -#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
> -#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
> +#include <asm/signal-defs.h>
>  
>  # ifndef __ASSEMBLY__
>  
> diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
> index e9304c95ceea..ecdf6312bfa5 100644
> --- a/include/uapi/asm-generic/signal-defs.h
> +++ b/include/uapi/asm-generic/signal-defs.h
> @@ -15,8 +15,14 @@
>  #endif
>  
>  #ifndef __ASSEMBLY__
> +#ifndef __hppa__
> +/*
> + * These have a special definition on parisc, see:
> + * arch/parisc/include/uapi/asm/signal.h
> + */
>  typedef void __signalfn_t(int);
>  typedef __signalfn_t __user *__sighandler_t;
> +#endif

Could we do something like

	#ifndef __sighandler_t
	/* ... */
	#define __sighandler_t __sighandler_t
	#endif

Then we don't have to have anything parisc-specific in the common
header, and arches can override this definition independently.

Not a big deal either way, though, and best to keep the comment about
why this is here in any case.

Cheers
---Dave

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 2/7] arch: move SA_* definitions to generic headers
  2020-08-22  5:10   ` Peter Collingbourne
@ 2020-09-08 15:12     ` Dave Martin
  -1 siblings, 0 replies; 59+ messages in thread
From: Dave Martin @ 2020-09-08 15:12 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Will Deacon, Oleg Nesterov, Eric W. Biederman,
	James E.J. Bottomley, linux-parisc, Andrey Konovalov,
	Kevin Brodsky, David Spickett, Linux ARM, Richard Henderson

On Fri, Aug 21, 2020 at 10:10:12PM -0700, Peter Collingbourne wrote:
> Most architectures with the exception of alpha, mips, parisc and
> sparc use the same values for these flags. Move their definitions into
> asm-generic/signal-defs.h and allow the architectures with non-standard
> values to override them. Also, document the non-standard flag values
> in order to make it easier to add new generic flags in the future.
> 
> Signed-off-by: Peter Collingbourne <pcc@google.com>

While this looks reasonable, I've just realised that you strip the "U"
from some arches' definitions here.

So, on powerpc and x86, this changes the type of flags other than
SA_RESETHAND from unsigned int to int.

While I can't see this breaking any sensible use of these flags, there's
a chance that there is software relying on this distinction by
accident.


I wonder whether it's worth doing something like

	#ifdef ARCH_WANT_STRICTLY_UNSIGNED_SA_FLAGS
	#define __SA_FLAG_VAL(x) x ## U
	#else
	#define __SA_FLAG_VAL(x) x
	#endif

	#ifndef SA_NOCLDSTOP
	#define SA_NOCLDSTOP __SA_FLAG_VAL(0x00000001)
	#endif

	/* ... */


Mind you, the historical situation also has issues, e.g. because
sa_flags in struct sigaction is an int, assigning

	struct sigaction sa;

	sa.sa_flags = SA_RESETHAND;

implies an overflow and so isn't portably safe (at least in theory).  I
guess we are getting away with it today.  Preserving the situation by
keeping the "U"s where appropriate would at least avoid making the
situation worse.

[...]

Cheers
---Dave

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 2/7] arch: move SA_* definitions to generic headers
@ 2020-09-08 15:12     ` Dave Martin
  0 siblings, 0 replies; 59+ messages in thread
From: Dave Martin @ 2020-09-08 15:12 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Linux ARM, linux-parisc, Catalin Marinas, Kevin Brodsky,
	Oleg Nesterov, James E.J. Bottomley, Kostya Serebryany,
	Eric W. Biederman, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Will Deacon, Evgenii Stepanov,
	Richard Henderson

On Fri, Aug 21, 2020 at 10:10:12PM -0700, Peter Collingbourne wrote:
> Most architectures with the exception of alpha, mips, parisc and
> sparc use the same values for these flags. Move their definitions into
> asm-generic/signal-defs.h and allow the architectures with non-standard
> values to override them. Also, document the non-standard flag values
> in order to make it easier to add new generic flags in the future.
> 
> Signed-off-by: Peter Collingbourne <pcc@google.com>

While this looks reasonable, I've just realised that you strip the "U"
from some arches' definitions here.

So, on powerpc and x86, this changes the type of flags other than
SA_RESETHAND from unsigned int to int.

While I can't see this breaking any sensible use of these flags, there's
a chance that there is software relying on this distinction by
accident.


I wonder whether it's worth doing something like

	#ifdef ARCH_WANT_STRICTLY_UNSIGNED_SA_FLAGS
	#define __SA_FLAG_VAL(x) x ## U
	#else
	#define __SA_FLAG_VAL(x) x
	#endif

	#ifndef SA_NOCLDSTOP
	#define SA_NOCLDSTOP __SA_FLAG_VAL(0x00000001)
	#endif

	/* ... */


Mind you, the historical situation also has issues, e.g. because
sa_flags in struct sigaction is an int, assigning

	struct sigaction sa;

	sa.sa_flags = SA_RESETHAND;

implies an overflow and so isn't portably safe (at least in theory).  I
guess we are getting away with it today.  Preserving the situation by
keeping the "U"s where appropriate would at least avoid making the
situation worse.

[...]

Cheers
---Dave

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 3/7] signal: clear non-uapi flag bits when passing/returning sa_flags
  2020-08-22  5:10   ` Peter Collingbourne
@ 2020-09-08 15:12     ` Dave Martin
  -1 siblings, 0 replies; 59+ messages in thread
From: Dave Martin @ 2020-09-08 15:12 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Will Deacon, Oleg Nesterov, Eric W. Biederman,
	James E.J. Bottomley, linux-parisc, Andrey Konovalov,
	Kevin Brodsky, David Spickett, Linux ARM, Richard Henderson

On Fri, Aug 21, 2020 at 10:10:13PM -0700, Peter Collingbourne wrote:
> Previously we were not clearing non-uapi flag bits in
> sigaction.sa_flags when storing the userspace-provided sa_flags or
> when returning them via oldact. Start doing so.
> 
> This allows userspace to detect missing support for flag bits and
> allows the kernel to use non-uapi bits internally, as we are already
> doing in arch/x86 for two flag bits. Now that this change is in
> place, we no longer need the code in arch/x86 that was hiding these
> bits from userspace, so remove it.
> 
> This is technically a userspace-visible behavior change for sigaction, as
> the unknown bits returned via oldact.sa_flags are no longer set. However,
> we are free to define the behavior for unknown bits exactly because
> their behavior is currently undefined, so for now we can define the
> meaning of each of them to be "clear the bit in oldact.sa_flags unless
> the bit becomes known in the future". Furthermore, this behavior is
> consistent with OpenBSD [1], illumos [2] and XNU [3] (FreeBSD [4] and
> NetBSD [5] fail the syscall if unknown bits are set). So there is some
> precedent for this behavior in other kernels, and in particular in XNU,
> which is probably the most popular kernel among those that I looked at,
> which means that this change is less likely to be a compatibility issue.
> 
> Link: [1] https://github.com/openbsd/src/blob/f634a6a4b5bf832e9c1de77f7894ae2625e74484/sys/kern/kern_sig.c#L278
> Link: [2] https://github.com/illumos/illumos-gate/blob/76f19f5fdc974fe5be5c82a556e43a4df93f1de1/usr/src/uts/common/syscall/sigaction.c#L86
> Link: [3] https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/kern/kern_sig.c#L480
> Link: [4] https://github.com/freebsd/freebsd/blob/eded70c37057857c6e23fae51f86b8f8f43cd2d0/sys/kern/kern_sig.c#L699
> Link: [5] https://github.com/NetBSD/src/blob/3365779becdcedfca206091a645a0e8e22b2946e/sys/kern/sys_sig.c#L473
> Signed-off-by: Peter Collingbourne <pcc@google.com>
> ---
> View this change in Gerrit: https://linux-review.googlesource.com/q/I35aab6f5be932505d90f3b3450c083b4db1eca86
> 
> v10:
> - rename SA_UAPI_FLAGS -> UAPI_SA_FLAGS
> - refactor how we define it to avoid mentioning flags more
>   than once
> 
>  arch/arm/include/asm/signal.h    |  2 ++
>  arch/parisc/include/asm/signal.h |  2 ++
>  arch/x86/kernel/signal_compat.c  |  7 -------
>  include/linux/signal_types.h     | 12 ++++++++++++
>  kernel/signal.c                  | 10 ++++++++++
>  5 files changed, 26 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/arm/include/asm/signal.h b/arch/arm/include/asm/signal.h
> index 65530a042009..430be7774402 100644
> --- a/arch/arm/include/asm/signal.h
> +++ b/arch/arm/include/asm/signal.h
> @@ -17,6 +17,8 @@ typedef struct {
>  	unsigned long sig[_NSIG_WORDS];
>  } sigset_t;
>  
> +#define __ARCH_UAPI_SA_FLAGS	(SA_THIRTYTWO | SA_RESTORER)
> +
>  #define __ARCH_HAS_SA_RESTORER
>  
>  #include <asm/sigcontext.h>
> diff --git a/arch/parisc/include/asm/signal.h b/arch/parisc/include/asm/signal.h
> index 715c96ba2ec8..30dd1e43ef88 100644
> --- a/arch/parisc/include/asm/signal.h
> +++ b/arch/parisc/include/asm/signal.h
> @@ -21,6 +21,8 @@ typedef struct {
>  	unsigned long sig[_NSIG_WORDS];
>  } sigset_t;
>  
> +#define __ARCH_UAPI_SA_FLAGS	_SA_SIGGFAULT
> +
>  #include <asm/sigcontext.h>
>  
>  #endif /* !__ASSEMBLY */
> diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
> index 9ccbf0576cd0..c599013ae8cb 100644
> --- a/arch/x86/kernel/signal_compat.c
> +++ b/arch/x86/kernel/signal_compat.c
> @@ -165,16 +165,9 @@ void sigaction_compat_abi(struct k_sigaction *act, struct k_sigaction *oact)
>  {
>  	signal_compat_build_tests();
>  
> -	/* Don't leak in-kernel non-uapi flags to user-space */
> -	if (oact)
> -		oact->sa.sa_flags &= ~(SA_IA32_ABI | SA_X32_ABI);
> -
>  	if (!act)
>  		return;
>  
> -	/* Don't let flags to be set from userspace */
> -	act->sa.sa_flags &= ~(SA_IA32_ABI | SA_X32_ABI);
> -
>  	if (in_ia32_syscall())
>  		act->sa.sa_flags |= SA_IA32_ABI;
>  	if (in_x32_syscall())
> diff --git a/include/linux/signal_types.h b/include/linux/signal_types.h
> index f8a90ae9c6ec..a7887ad84d36 100644
> --- a/include/linux/signal_types.h
> +++ b/include/linux/signal_types.h
> @@ -68,4 +68,16 @@ struct ksignal {
>  	int sig;
>  };
>  
> +#ifndef __ARCH_UAPI_SA_FLAGS
> +#ifdef SA_RESTORER
> +#define __ARCH_UAPI_SA_FLAGS	SA_RESTORER
> +#else
> +#define __ARCH_UAPI_SA_FLAGS	0
> +#endif
> +#endif
> +
> +#define UAPI_SA_FLAGS                                                          \
> +	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
> +	 SA_NODEFER | SA_RESETHAND | __ARCH_UAPI_SA_FLAGS)
> +

Part of me wants this to be closer to the common flag definitions.  But
we don't really want to define this in the UAPI headers.

Unless you can think of another good place to put it, this is probably
OK as-is.

>  #endif /* _LINUX_SIGNAL_TYPES_H */
> diff --git a/kernel/signal.c b/kernel/signal.c
> index 42b67d2cea37..f802c82c7bcc 100644
> --- a/kernel/signal.c
> +++ b/kernel/signal.c
> @@ -3984,6 +3984,16 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
>  	if (oact)
>  		*oact = *k;
>  
> +	/*
> +	 * Clear unknown flag bits in order to allow userspace to detect missing
> +	 * support for flag bits and to allow the kernel to use non-uapi bits
> +	 * internally.
> +	 */
> +	if (act)
> +		act->sa.sa_flags &= UAPI_SA_FLAGS;
> +	if (oact)
> +		oact->sa.sa_flags &= UAPI_SA_FLAGS;
> +

Seems reasonable.

[...]

Cheers
---Dave

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 3/7] signal: clear non-uapi flag bits when passing/returning sa_flags
@ 2020-09-08 15:12     ` Dave Martin
  0 siblings, 0 replies; 59+ messages in thread
From: Dave Martin @ 2020-09-08 15:12 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Linux ARM, linux-parisc, Catalin Marinas, Kevin Brodsky,
	Oleg Nesterov, James E.J. Bottomley, Kostya Serebryany,
	Eric W. Biederman, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Will Deacon, Evgenii Stepanov,
	Richard Henderson

On Fri, Aug 21, 2020 at 10:10:13PM -0700, Peter Collingbourne wrote:
> Previously we were not clearing non-uapi flag bits in
> sigaction.sa_flags when storing the userspace-provided sa_flags or
> when returning them via oldact. Start doing so.
> 
> This allows userspace to detect missing support for flag bits and
> allows the kernel to use non-uapi bits internally, as we are already
> doing in arch/x86 for two flag bits. Now that this change is in
> place, we no longer need the code in arch/x86 that was hiding these
> bits from userspace, so remove it.
> 
> This is technically a userspace-visible behavior change for sigaction, as
> the unknown bits returned via oldact.sa_flags are no longer set. However,
> we are free to define the behavior for unknown bits exactly because
> their behavior is currently undefined, so for now we can define the
> meaning of each of them to be "clear the bit in oldact.sa_flags unless
> the bit becomes known in the future". Furthermore, this behavior is
> consistent with OpenBSD [1], illumos [2] and XNU [3] (FreeBSD [4] and
> NetBSD [5] fail the syscall if unknown bits are set). So there is some
> precedent for this behavior in other kernels, and in particular in XNU,
> which is probably the most popular kernel among those that I looked at,
> which means that this change is less likely to be a compatibility issue.
> 
> Link: [1] https://github.com/openbsd/src/blob/f634a6a4b5bf832e9c1de77f7894ae2625e74484/sys/kern/kern_sig.c#L278
> Link: [2] https://github.com/illumos/illumos-gate/blob/76f19f5fdc974fe5be5c82a556e43a4df93f1de1/usr/src/uts/common/syscall/sigaction.c#L86
> Link: [3] https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/kern/kern_sig.c#L480
> Link: [4] https://github.com/freebsd/freebsd/blob/eded70c37057857c6e23fae51f86b8f8f43cd2d0/sys/kern/kern_sig.c#L699
> Link: [5] https://github.com/NetBSD/src/blob/3365779becdcedfca206091a645a0e8e22b2946e/sys/kern/sys_sig.c#L473
> Signed-off-by: Peter Collingbourne <pcc@google.com>
> ---
> View this change in Gerrit: https://linux-review.googlesource.com/q/I35aab6f5be932505d90f3b3450c083b4db1eca86
> 
> v10:
> - rename SA_UAPI_FLAGS -> UAPI_SA_FLAGS
> - refactor how we define it to avoid mentioning flags more
>   than once
> 
>  arch/arm/include/asm/signal.h    |  2 ++
>  arch/parisc/include/asm/signal.h |  2 ++
>  arch/x86/kernel/signal_compat.c  |  7 -------
>  include/linux/signal_types.h     | 12 ++++++++++++
>  kernel/signal.c                  | 10 ++++++++++
>  5 files changed, 26 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/arm/include/asm/signal.h b/arch/arm/include/asm/signal.h
> index 65530a042009..430be7774402 100644
> --- a/arch/arm/include/asm/signal.h
> +++ b/arch/arm/include/asm/signal.h
> @@ -17,6 +17,8 @@ typedef struct {
>  	unsigned long sig[_NSIG_WORDS];
>  } sigset_t;
>  
> +#define __ARCH_UAPI_SA_FLAGS	(SA_THIRTYTWO | SA_RESTORER)
> +
>  #define __ARCH_HAS_SA_RESTORER
>  
>  #include <asm/sigcontext.h>
> diff --git a/arch/parisc/include/asm/signal.h b/arch/parisc/include/asm/signal.h
> index 715c96ba2ec8..30dd1e43ef88 100644
> --- a/arch/parisc/include/asm/signal.h
> +++ b/arch/parisc/include/asm/signal.h
> @@ -21,6 +21,8 @@ typedef struct {
>  	unsigned long sig[_NSIG_WORDS];
>  } sigset_t;
>  
> +#define __ARCH_UAPI_SA_FLAGS	_SA_SIGGFAULT
> +
>  #include <asm/sigcontext.h>
>  
>  #endif /* !__ASSEMBLY */
> diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
> index 9ccbf0576cd0..c599013ae8cb 100644
> --- a/arch/x86/kernel/signal_compat.c
> +++ b/arch/x86/kernel/signal_compat.c
> @@ -165,16 +165,9 @@ void sigaction_compat_abi(struct k_sigaction *act, struct k_sigaction *oact)
>  {
>  	signal_compat_build_tests();
>  
> -	/* Don't leak in-kernel non-uapi flags to user-space */
> -	if (oact)
> -		oact->sa.sa_flags &= ~(SA_IA32_ABI | SA_X32_ABI);
> -
>  	if (!act)
>  		return;
>  
> -	/* Don't let flags to be set from userspace */
> -	act->sa.sa_flags &= ~(SA_IA32_ABI | SA_X32_ABI);
> -
>  	if (in_ia32_syscall())
>  		act->sa.sa_flags |= SA_IA32_ABI;
>  	if (in_x32_syscall())
> diff --git a/include/linux/signal_types.h b/include/linux/signal_types.h
> index f8a90ae9c6ec..a7887ad84d36 100644
> --- a/include/linux/signal_types.h
> +++ b/include/linux/signal_types.h
> @@ -68,4 +68,16 @@ struct ksignal {
>  	int sig;
>  };
>  
> +#ifndef __ARCH_UAPI_SA_FLAGS
> +#ifdef SA_RESTORER
> +#define __ARCH_UAPI_SA_FLAGS	SA_RESTORER
> +#else
> +#define __ARCH_UAPI_SA_FLAGS	0
> +#endif
> +#endif
> +
> +#define UAPI_SA_FLAGS                                                          \
> +	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
> +	 SA_NODEFER | SA_RESETHAND | __ARCH_UAPI_SA_FLAGS)
> +

Part of me wants this to be closer to the common flag definitions.  But
we don't really want to define this in the UAPI headers.

Unless you can think of another good place to put it, this is probably
OK as-is.

>  #endif /* _LINUX_SIGNAL_TYPES_H */
> diff --git a/kernel/signal.c b/kernel/signal.c
> index 42b67d2cea37..f802c82c7bcc 100644
> --- a/kernel/signal.c
> +++ b/kernel/signal.c
> @@ -3984,6 +3984,16 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
>  	if (oact)
>  		*oact = *k;
>  
> +	/*
> +	 * Clear unknown flag bits in order to allow userspace to detect missing
> +	 * support for flag bits and to allow the kernel to use non-uapi bits
> +	 * internally.
> +	 */
> +	if (act)
> +		act->sa.sa_flags &= UAPI_SA_FLAGS;
> +	if (oact)
> +		oact->sa.sa_flags &= UAPI_SA_FLAGS;
> +

Seems reasonable.

[...]

Cheers
---Dave

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 4/7] signal: define the SA_UNSUPPORTED bit in sa_flags
  2020-08-22  5:10   ` Peter Collingbourne
@ 2020-09-08 15:13     ` Dave Martin
  -1 siblings, 0 replies; 59+ messages in thread
From: Dave Martin @ 2020-09-08 15:13 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Will Deacon, Oleg Nesterov, Eric W. Biederman,
	James E.J. Bottomley, linux-parisc, Andrey Konovalov,
	Kevin Brodsky, David Spickett, Linux ARM, Richard Henderson

On Fri, Aug 21, 2020 at 10:10:14PM -0700, Peter Collingbourne wrote:

Nit: no statement of the chage being made (other than in the subject
line).

> This bit will never be supported in the uapi. The purpose of this flag
> bit is to allow userspace to distinguish an old kernel that does not
> clear unknown sa_flags bits from a kernel that supports every flag bit.
> 
> In other words, if userspace finds that this bit remains set in
> oldact.sa_flags, it means that the kernel cannot be trusted to have
> cleared unknown flag bits from sa_flags, so no assumptions about flag
> bit support can be made.

This isn't quite right?  After a single sigaction() call, oact will
contain the sa_flags for the previously registered handler.  So a
second sigaction() call would be needed to find out the newly effective
sa_flags.

> 
> Signed-off-by: Peter Collingbourne <pcc@google.com>
> ---
> View this change in Gerrit: https://linux-review.googlesource.com/q/Ic2501ad150a3a79c1cf27fb8c99be342e9dffbcb
> 
>  include/uapi/asm-generic/signal-defs.h | 7 +++++++
>  kernel/signal.c                        | 6 ++++++
>  2 files changed, 13 insertions(+)
> 
> diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
> index 319628058a53..e853cbe8722d 100644
> --- a/include/uapi/asm-generic/signal-defs.h
> +++ b/include/uapi/asm-generic/signal-defs.h
> @@ -14,6 +14,12 @@
>   * SA_RESTART flag to get restarting signals (which were the default long ago)
>   * SA_NODEFER prevents the current signal from being masked in the handler.
>   * SA_RESETHAND clears the handler when the signal is delivered.
> + * SA_UNSUPPORTED is a flag bit that will never be supported. Kernels from
> + * before the introduction of SA_UNSUPPORTED did not clear unknown bits from
> + * sa_flags when read using the oldact argument to sigaction and rt_sigaction,
> + * so this bit allows flag bit support to be detected from userspace while
> + * allowing an old kernel to be distinguished from a kernel that supports every
> + * flag bit.
>   *
>   * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
>   * Unix names RESETHAND and NODEFER respectively.
> @@ -42,6 +48,7 @@
>  #ifndef SA_RESETHAND
>  #define SA_RESETHAND	0x80000000
>  #endif
> +#define SA_UNSUPPORTED	0x00000400

I guess people may debate which bit is chosen, but your consolidation
of these definitions should help to reduce the possibility of future
collisions.  This bit appears unused for now, so I guess I don't have a
strong opinion.

>  #define SA_NOMASK	SA_NODEFER
>  #define SA_ONESHOT	SA_RESETHAND
> diff --git a/kernel/signal.c b/kernel/signal.c
> index f802c82c7bcc..c80e70bde11d 100644
> --- a/kernel/signal.c
> +++ b/kernel/signal.c
> @@ -3984,6 +3984,12 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
>  	if (oact)
>  		*oact = *k;
>  
> +	/*
> +	 * Make sure that we never accidentally claim to support SA_UNSUPPORTED,
> +	 * e.g. by having an architecture use the bit in their uapi.
> +	 */
> +	BUILD_BUG_ON(UAPI_SA_FLAGS & SA_UNSUPPORTED);
> +

Seems reasonable.

With the above rewording in the commit message to clarify that a second
sigaction() is needed:

Reviewed-by: Dave Martin <Dave.Martin@arm.com>

[...]

Cheers
---Dave

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 4/7] signal: define the SA_UNSUPPORTED bit in sa_flags
@ 2020-09-08 15:13     ` Dave Martin
  0 siblings, 0 replies; 59+ messages in thread
From: Dave Martin @ 2020-09-08 15:13 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Linux ARM, linux-parisc, Catalin Marinas, Kevin Brodsky,
	Oleg Nesterov, James E.J. Bottomley, Kostya Serebryany,
	Eric W. Biederman, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Will Deacon, Evgenii Stepanov,
	Richard Henderson

On Fri, Aug 21, 2020 at 10:10:14PM -0700, Peter Collingbourne wrote:

Nit: no statement of the chage being made (other than in the subject
line).

> This bit will never be supported in the uapi. The purpose of this flag
> bit is to allow userspace to distinguish an old kernel that does not
> clear unknown sa_flags bits from a kernel that supports every flag bit.
> 
> In other words, if userspace finds that this bit remains set in
> oldact.sa_flags, it means that the kernel cannot be trusted to have
> cleared unknown flag bits from sa_flags, so no assumptions about flag
> bit support can be made.

This isn't quite right?  After a single sigaction() call, oact will
contain the sa_flags for the previously registered handler.  So a
second sigaction() call would be needed to find out the newly effective
sa_flags.

> 
> Signed-off-by: Peter Collingbourne <pcc@google.com>
> ---
> View this change in Gerrit: https://linux-review.googlesource.com/q/Ic2501ad150a3a79c1cf27fb8c99be342e9dffbcb
> 
>  include/uapi/asm-generic/signal-defs.h | 7 +++++++
>  kernel/signal.c                        | 6 ++++++
>  2 files changed, 13 insertions(+)
> 
> diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
> index 319628058a53..e853cbe8722d 100644
> --- a/include/uapi/asm-generic/signal-defs.h
> +++ b/include/uapi/asm-generic/signal-defs.h
> @@ -14,6 +14,12 @@
>   * SA_RESTART flag to get restarting signals (which were the default long ago)
>   * SA_NODEFER prevents the current signal from being masked in the handler.
>   * SA_RESETHAND clears the handler when the signal is delivered.
> + * SA_UNSUPPORTED is a flag bit that will never be supported. Kernels from
> + * before the introduction of SA_UNSUPPORTED did not clear unknown bits from
> + * sa_flags when read using the oldact argument to sigaction and rt_sigaction,
> + * so this bit allows flag bit support to be detected from userspace while
> + * allowing an old kernel to be distinguished from a kernel that supports every
> + * flag bit.
>   *
>   * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
>   * Unix names RESETHAND and NODEFER respectively.
> @@ -42,6 +48,7 @@
>  #ifndef SA_RESETHAND
>  #define SA_RESETHAND	0x80000000
>  #endif
> +#define SA_UNSUPPORTED	0x00000400

I guess people may debate which bit is chosen, but your consolidation
of these definitions should help to reduce the possibility of future
collisions.  This bit appears unused for now, so I guess I don't have a
strong opinion.

>  #define SA_NOMASK	SA_NODEFER
>  #define SA_ONESHOT	SA_RESETHAND
> diff --git a/kernel/signal.c b/kernel/signal.c
> index f802c82c7bcc..c80e70bde11d 100644
> --- a/kernel/signal.c
> +++ b/kernel/signal.c
> @@ -3984,6 +3984,12 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
>  	if (oact)
>  		*oact = *k;
>  
> +	/*
> +	 * Make sure that we never accidentally claim to support SA_UNSUPPORTED,
> +	 * e.g. by having an architecture use the bit in their uapi.
> +	 */
> +	BUILD_BUG_ON(UAPI_SA_FLAGS & SA_UNSUPPORTED);
> +

Seems reasonable.

With the above rewording in the commit message to clarify that a second
sigaction() is needed:

Reviewed-by: Dave Martin <Dave.Martin@arm.com>

[...]

Cheers
---Dave

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 5/7] signal: deduplicate code dealing with common _sigfault fields
  2020-08-22  5:10   ` Peter Collingbourne
@ 2020-09-08 15:13     ` Dave Martin
  -1 siblings, 0 replies; 59+ messages in thread
From: Dave Martin @ 2020-09-08 15:13 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Will Deacon, Oleg Nesterov, Eric W. Biederman,
	James E.J. Bottomley, linux-parisc, Andrey Konovalov,
	Kevin Brodsky, David Spickett, Linux ARM, Richard Henderson

On Fri, Aug 21, 2020 at 10:10:15PM -0700, Peter Collingbourne wrote:
> We're about to add more common _sigfault fields, so deduplicate the
> existing code for initializing _sigfault fields in {send,force}_sig_*,
> and for copying _sigfault fields in copy_siginfo_to_external32 and
> post_copy_siginfo_from_user32, to reduce the number of places that
> will need to be updated by upcoming changes.
> 
> Signed-off-by: Peter Collingbourne <pcc@google.com>
> ---
> View this change in Gerrit: https://linux-review.googlesource.com/q/I4f56174e1b7b2bf4a3c8139e6879cbfd52750a24
> 
>  include/linux/signal.h |  13 ++++++
>  kernel/signal.c        | 101 ++++++++++++++++-------------------------
>  2 files changed, 53 insertions(+), 61 deletions(-)
> 
> diff --git a/include/linux/signal.h b/include/linux/signal.h
> index 6bb1a3f0258c..3edbf54493ee 100644
> --- a/include/linux/signal.h
> +++ b/include/linux/signal.h
> @@ -50,6 +50,19 @@ enum siginfo_layout {
>  
>  enum siginfo_layout siginfo_layout(unsigned sig, int si_code);
>  
> +static inline bool siginfo_layout_is_fault(enum siginfo_layout layout)
> +{
> +	switch (layout) {
> +	case SIL_FAULT:
> +	case SIL_FAULT_MCEERR:
> +	case SIL_FAULT_BNDERR:
> +	case SIL_FAULT_PKUERR:
> +		return true;
> +	default:
> +		return false;
> +	}
> +}
> +
>  /*
>   * Define some primitives to manipulate sigset_t.
>   */
> diff --git a/kernel/signal.c b/kernel/signal.c
> index c80e70bde11d..4ee9dc03f20f 100644
> --- a/kernel/signal.c
> +++ b/kernel/signal.c
> @@ -1649,6 +1649,15 @@ void force_sigsegv(int sig)
>  	force_sig(SIGSEGV);
>  }
>  
> +static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
> +				       int code, void __user *addr)
> +{
> +	info->si_signo = sig;
> +	info->si_errno = 0;
> +	info->si_code = code;
> +	info->si_addr = addr;
> +}
> +
>  int force_sig_fault_to_task(int sig, int code, void __user *addr
>  	___ARCH_SI_TRAPNO(int trapno)
>  	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
> @@ -1657,10 +1666,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
>  	struct kernel_siginfo info;
>  
>  	clear_siginfo(&info);
> -	info.si_signo = sig;
> -	info.si_errno = 0;
> -	info.si_code  = code;
> -	info.si_addr  = addr;
> +	set_sigfault_common_fields(&info, sig, code, addr);
>  #ifdef __ARCH_SI_TRAPNO
>  	info.si_trapno = trapno;
>  #endif
> @@ -1689,10 +1695,7 @@ int send_sig_fault(int sig, int code, void __user *addr
>  	struct kernel_siginfo info;
>  
>  	clear_siginfo(&info);
> -	info.si_signo = sig;
> -	info.si_errno = 0;
> -	info.si_code  = code;
> -	info.si_addr  = addr;
> +	set_sigfault_common_fields(&info, sig, code, addr);
>  #ifdef __ARCH_SI_TRAPNO
>  	info.si_trapno = trapno;
>  #endif
> @@ -1710,10 +1713,7 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
>  
>  	WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
>  	clear_siginfo(&info);
> -	info.si_signo = SIGBUS;
> -	info.si_errno = 0;
> -	info.si_code = code;
> -	info.si_addr = addr;
> +	set_sigfault_common_fields(&info, SIGBUS, code, addr);
>  	info.si_addr_lsb = lsb;
>  	return force_sig_info(&info);
>  }
> @@ -1724,10 +1724,7 @@ int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *
>  
>  	WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
>  	clear_siginfo(&info);
> -	info.si_signo = SIGBUS;
> -	info.si_errno = 0;
> -	info.si_code = code;
> -	info.si_addr = addr;
> +	set_sigfault_common_fields(&info, SIGBUS, code, addr);
>  	info.si_addr_lsb = lsb;
>  	return send_sig_info(info.si_signo, &info, t);
>  }
> @@ -1738,10 +1735,7 @@ int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
>  	struct kernel_siginfo info;
>  
>  	clear_siginfo(&info);
> -	info.si_signo = SIGSEGV;
> -	info.si_errno = 0;
> -	info.si_code  = SEGV_BNDERR;
> -	info.si_addr  = addr;
> +	set_sigfault_common_fields(&info, SIGSEGV, SEGV_BNDERR, addr);
>  	info.si_lower = lower;
>  	info.si_upper = upper;
>  	return force_sig_info(&info);
> @@ -1753,10 +1747,7 @@ int force_sig_pkuerr(void __user *addr, u32 pkey)
>  	struct kernel_siginfo info;
>  
>  	clear_siginfo(&info);
> -	info.si_signo = SIGSEGV;
> -	info.si_errno = 0;
> -	info.si_code  = SEGV_PKUERR;
> -	info.si_addr  = addr;
> +	set_sigfault_common_fields(&info, SIGSEGV, SEGV_PKUERR, addr);
>  	info.si_pkey  = pkey;
>  	return force_sig_info(&info);
>  }
> @@ -1770,10 +1761,8 @@ int force_sig_ptrace_errno_trap(int errno, void __user *addr)
>  	struct kernel_siginfo info;
>  
>  	clear_siginfo(&info);
> -	info.si_signo = SIGTRAP;
> +	set_sigfault_common_fields(&info, SIGTRAP, TRAP_HWBKPT, addr);
>  	info.si_errno = errno;
> -	info.si_code  = TRAP_HWBKPT;
> -	info.si_addr  = addr;
>  	return force_sig_info(&info);
>  }
>  
> @@ -3266,12 +3255,23 @@ int copy_siginfo_from_user(kernel_siginfo_t *to, const siginfo_t __user *from)
>  void copy_siginfo_to_external32(struct compat_siginfo *to,
>  		const struct kernel_siginfo *from)
>  {
> +	enum siginfo_layout layout =
> +		siginfo_layout(from->si_signo, from->si_code);
> +
>  	memset(to, 0, sizeof(*to));
>  
>  	to->si_signo = from->si_signo;
>  	to->si_errno = from->si_errno;
>  	to->si_code  = from->si_code;
> -	switch(siginfo_layout(from->si_signo, from->si_code)) {
> +
> +	if (siginfo_layout_is_fault(layout)) {
> +		to->si_addr = ptr_to_compat(from->si_addr);
> +#ifdef __ARCH_SI_TRAPNO
> +		to->si_trapno = from->si_trapno;
> +#endif
> +	}
> +
> +	switch (layout) {

I find the code flow slightly awkward with this change, because the
fault signal fields are populated partly in the if() above and partly
in the switch().  Previously, only the universal stuff was done outside.

Would this be easier on future maintainers if we pulled the common
stuff out into a helper and then called it from the appropriate switch
cases?  The compiler will probably output some duplicated code in that
case (depending on how clever it is at undoing the duplication), but
the amount of affected code is small.


>  	case SIL_KILL:
>  		to->si_pid = from->si_pid;
>  		to->si_uid = from->si_uid;
> @@ -3286,31 +3286,15 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
>  		to->si_fd   = from->si_fd;
>  		break;
>  	case SIL_FAULT:
> -		to->si_addr = ptr_to_compat(from->si_addr);
> -#ifdef __ARCH_SI_TRAPNO
> -		to->si_trapno = from->si_trapno;
> -#endif
>  		break;
>  	case SIL_FAULT_MCEERR:
> -		to->si_addr = ptr_to_compat(from->si_addr);
> -#ifdef __ARCH_SI_TRAPNO
> -		to->si_trapno = from->si_trapno;
> -#endif
>  		to->si_addr_lsb = from->si_addr_lsb;
>  		break;
>  	case SIL_FAULT_BNDERR:
> -		to->si_addr = ptr_to_compat(from->si_addr);
> -#ifdef __ARCH_SI_TRAPNO
> -		to->si_trapno = from->si_trapno;
> -#endif
>  		to->si_lower = ptr_to_compat(from->si_lower);
>  		to->si_upper = ptr_to_compat(from->si_upper);
>  		break;
>  	case SIL_FAULT_PKUERR:
> -		to->si_addr = ptr_to_compat(from->si_addr);
> -#ifdef __ARCH_SI_TRAPNO
> -		to->si_trapno = from->si_trapno;
> -#endif
>  		to->si_pkey = from->si_pkey;
>  		break;
>  	case SIL_CHLD:
> @@ -3347,11 +3331,22 @@ int __copy_siginfo_to_user32(struct compat_siginfo __user *to,
>  static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
>  					 const struct compat_siginfo *from)
>  {
> +	enum siginfo_layout layout =
> +		siginfo_layout(from->si_signo, from->si_code);
> +
>  	clear_siginfo(to);
>  	to->si_signo = from->si_signo;
>  	to->si_errno = from->si_errno;
>  	to->si_code  = from->si_code;
> -	switch(siginfo_layout(from->si_signo, from->si_code)) {
> +
> +	if (siginfo_layout_is_fault(layout)) {
> +		to->si_addr = compat_ptr(from->si_addr);
> +#ifdef __ARCH_SI_TRAPNO
> +		to->si_trapno = from->si_trapno;
> +#endif
> +	}
> +
> +	switch (layout) {

Same comment as for copy_siginfo_to_external32()?

[...]

Otherwise, looks reasonable.

Cheers
---Dave

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 5/7] signal: deduplicate code dealing with common _sigfault fields
@ 2020-09-08 15:13     ` Dave Martin
  0 siblings, 0 replies; 59+ messages in thread
From: Dave Martin @ 2020-09-08 15:13 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Linux ARM, linux-parisc, Catalin Marinas, Kevin Brodsky,
	Oleg Nesterov, James E.J. Bottomley, Kostya Serebryany,
	Eric W. Biederman, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Will Deacon, Evgenii Stepanov,
	Richard Henderson

On Fri, Aug 21, 2020 at 10:10:15PM -0700, Peter Collingbourne wrote:
> We're about to add more common _sigfault fields, so deduplicate the
> existing code for initializing _sigfault fields in {send,force}_sig_*,
> and for copying _sigfault fields in copy_siginfo_to_external32 and
> post_copy_siginfo_from_user32, to reduce the number of places that
> will need to be updated by upcoming changes.
> 
> Signed-off-by: Peter Collingbourne <pcc@google.com>
> ---
> View this change in Gerrit: https://linux-review.googlesource.com/q/I4f56174e1b7b2bf4a3c8139e6879cbfd52750a24
> 
>  include/linux/signal.h |  13 ++++++
>  kernel/signal.c        | 101 ++++++++++++++++-------------------------
>  2 files changed, 53 insertions(+), 61 deletions(-)
> 
> diff --git a/include/linux/signal.h b/include/linux/signal.h
> index 6bb1a3f0258c..3edbf54493ee 100644
> --- a/include/linux/signal.h
> +++ b/include/linux/signal.h
> @@ -50,6 +50,19 @@ enum siginfo_layout {
>  
>  enum siginfo_layout siginfo_layout(unsigned sig, int si_code);
>  
> +static inline bool siginfo_layout_is_fault(enum siginfo_layout layout)
> +{
> +	switch (layout) {
> +	case SIL_FAULT:
> +	case SIL_FAULT_MCEERR:
> +	case SIL_FAULT_BNDERR:
> +	case SIL_FAULT_PKUERR:
> +		return true;
> +	default:
> +		return false;
> +	}
> +}
> +
>  /*
>   * Define some primitives to manipulate sigset_t.
>   */
> diff --git a/kernel/signal.c b/kernel/signal.c
> index c80e70bde11d..4ee9dc03f20f 100644
> --- a/kernel/signal.c
> +++ b/kernel/signal.c
> @@ -1649,6 +1649,15 @@ void force_sigsegv(int sig)
>  	force_sig(SIGSEGV);
>  }
>  
> +static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
> +				       int code, void __user *addr)
> +{
> +	info->si_signo = sig;
> +	info->si_errno = 0;
> +	info->si_code = code;
> +	info->si_addr = addr;
> +}
> +
>  int force_sig_fault_to_task(int sig, int code, void __user *addr
>  	___ARCH_SI_TRAPNO(int trapno)
>  	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
> @@ -1657,10 +1666,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
>  	struct kernel_siginfo info;
>  
>  	clear_siginfo(&info);
> -	info.si_signo = sig;
> -	info.si_errno = 0;
> -	info.si_code  = code;
> -	info.si_addr  = addr;
> +	set_sigfault_common_fields(&info, sig, code, addr);
>  #ifdef __ARCH_SI_TRAPNO
>  	info.si_trapno = trapno;
>  #endif
> @@ -1689,10 +1695,7 @@ int send_sig_fault(int sig, int code, void __user *addr
>  	struct kernel_siginfo info;
>  
>  	clear_siginfo(&info);
> -	info.si_signo = sig;
> -	info.si_errno = 0;
> -	info.si_code  = code;
> -	info.si_addr  = addr;
> +	set_sigfault_common_fields(&info, sig, code, addr);
>  #ifdef __ARCH_SI_TRAPNO
>  	info.si_trapno = trapno;
>  #endif
> @@ -1710,10 +1713,7 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
>  
>  	WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
>  	clear_siginfo(&info);
> -	info.si_signo = SIGBUS;
> -	info.si_errno = 0;
> -	info.si_code = code;
> -	info.si_addr = addr;
> +	set_sigfault_common_fields(&info, SIGBUS, code, addr);
>  	info.si_addr_lsb = lsb;
>  	return force_sig_info(&info);
>  }
> @@ -1724,10 +1724,7 @@ int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *
>  
>  	WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
>  	clear_siginfo(&info);
> -	info.si_signo = SIGBUS;
> -	info.si_errno = 0;
> -	info.si_code = code;
> -	info.si_addr = addr;
> +	set_sigfault_common_fields(&info, SIGBUS, code, addr);
>  	info.si_addr_lsb = lsb;
>  	return send_sig_info(info.si_signo, &info, t);
>  }
> @@ -1738,10 +1735,7 @@ int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
>  	struct kernel_siginfo info;
>  
>  	clear_siginfo(&info);
> -	info.si_signo = SIGSEGV;
> -	info.si_errno = 0;
> -	info.si_code  = SEGV_BNDERR;
> -	info.si_addr  = addr;
> +	set_sigfault_common_fields(&info, SIGSEGV, SEGV_BNDERR, addr);
>  	info.si_lower = lower;
>  	info.si_upper = upper;
>  	return force_sig_info(&info);
> @@ -1753,10 +1747,7 @@ int force_sig_pkuerr(void __user *addr, u32 pkey)
>  	struct kernel_siginfo info;
>  
>  	clear_siginfo(&info);
> -	info.si_signo = SIGSEGV;
> -	info.si_errno = 0;
> -	info.si_code  = SEGV_PKUERR;
> -	info.si_addr  = addr;
> +	set_sigfault_common_fields(&info, SIGSEGV, SEGV_PKUERR, addr);
>  	info.si_pkey  = pkey;
>  	return force_sig_info(&info);
>  }
> @@ -1770,10 +1761,8 @@ int force_sig_ptrace_errno_trap(int errno, void __user *addr)
>  	struct kernel_siginfo info;
>  
>  	clear_siginfo(&info);
> -	info.si_signo = SIGTRAP;
> +	set_sigfault_common_fields(&info, SIGTRAP, TRAP_HWBKPT, addr);
>  	info.si_errno = errno;
> -	info.si_code  = TRAP_HWBKPT;
> -	info.si_addr  = addr;
>  	return force_sig_info(&info);
>  }
>  
> @@ -3266,12 +3255,23 @@ int copy_siginfo_from_user(kernel_siginfo_t *to, const siginfo_t __user *from)
>  void copy_siginfo_to_external32(struct compat_siginfo *to,
>  		const struct kernel_siginfo *from)
>  {
> +	enum siginfo_layout layout =
> +		siginfo_layout(from->si_signo, from->si_code);
> +
>  	memset(to, 0, sizeof(*to));
>  
>  	to->si_signo = from->si_signo;
>  	to->si_errno = from->si_errno;
>  	to->si_code  = from->si_code;
> -	switch(siginfo_layout(from->si_signo, from->si_code)) {
> +
> +	if (siginfo_layout_is_fault(layout)) {
> +		to->si_addr = ptr_to_compat(from->si_addr);
> +#ifdef __ARCH_SI_TRAPNO
> +		to->si_trapno = from->si_trapno;
> +#endif
> +	}
> +
> +	switch (layout) {

I find the code flow slightly awkward with this change, because the
fault signal fields are populated partly in the if() above and partly
in the switch().  Previously, only the universal stuff was done outside.

Would this be easier on future maintainers if we pulled the common
stuff out into a helper and then called it from the appropriate switch
cases?  The compiler will probably output some duplicated code in that
case (depending on how clever it is at undoing the duplication), but
the amount of affected code is small.


>  	case SIL_KILL:
>  		to->si_pid = from->si_pid;
>  		to->si_uid = from->si_uid;
> @@ -3286,31 +3286,15 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
>  		to->si_fd   = from->si_fd;
>  		break;
>  	case SIL_FAULT:
> -		to->si_addr = ptr_to_compat(from->si_addr);
> -#ifdef __ARCH_SI_TRAPNO
> -		to->si_trapno = from->si_trapno;
> -#endif
>  		break;
>  	case SIL_FAULT_MCEERR:
> -		to->si_addr = ptr_to_compat(from->si_addr);
> -#ifdef __ARCH_SI_TRAPNO
> -		to->si_trapno = from->si_trapno;
> -#endif
>  		to->si_addr_lsb = from->si_addr_lsb;
>  		break;
>  	case SIL_FAULT_BNDERR:
> -		to->si_addr = ptr_to_compat(from->si_addr);
> -#ifdef __ARCH_SI_TRAPNO
> -		to->si_trapno = from->si_trapno;
> -#endif
>  		to->si_lower = ptr_to_compat(from->si_lower);
>  		to->si_upper = ptr_to_compat(from->si_upper);
>  		break;
>  	case SIL_FAULT_PKUERR:
> -		to->si_addr = ptr_to_compat(from->si_addr);
> -#ifdef __ARCH_SI_TRAPNO
> -		to->si_trapno = from->si_trapno;
> -#endif
>  		to->si_pkey = from->si_pkey;
>  		break;
>  	case SIL_CHLD:
> @@ -3347,11 +3331,22 @@ int __copy_siginfo_to_user32(struct compat_siginfo __user *to,
>  static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
>  					 const struct compat_siginfo *from)
>  {
> +	enum siginfo_layout layout =
> +		siginfo_layout(from->si_signo, from->si_code);
> +
>  	clear_siginfo(to);
>  	to->si_signo = from->si_signo;
>  	to->si_errno = from->si_errno;
>  	to->si_code  = from->si_code;
> -	switch(siginfo_layout(from->si_signo, from->si_code)) {
> +
> +	if (siginfo_layout_is_fault(layout)) {
> +		to->si_addr = compat_ptr(from->si_addr);
> +#ifdef __ARCH_SI_TRAPNO
> +		to->si_trapno = from->si_trapno;
> +#endif
> +	}
> +
> +	switch (layout) {

Same comment as for copy_siginfo_to_external32()?

[...]

Otherwise, looks reasonable.

Cheers
---Dave

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 6/7] signal: define the field siginfo.si_xflags
  2020-08-22  5:10   ` Peter Collingbourne
@ 2020-09-08 15:13     ` Dave Martin
  -1 siblings, 0 replies; 59+ messages in thread
From: Dave Martin @ 2020-09-08 15:13 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Will Deacon, Oleg Nesterov, Eric W. Biederman,
	James E.J. Bottomley, linux-parisc, Andrey Konovalov,
	Kevin Brodsky, David Spickett, Linux ARM, Richard Henderson

On Fri, Aug 21, 2020 at 10:10:16PM -0700, Peter Collingbourne wrote:

[ Add a new siginfo member sa_xflags, for fault signals. ]

> This field will contain flags that may be used by signal handlers to
> determine whether other fields in the _sigfault portion of siginfo are
> valid. An example use case is the following patch, which introduces
> the si_addr_ignored_bits{,_mask} fields.
> 
> A new sigcontext flag, SA_XFLAGS, is introduced in order to allow
> a signal handler to require the kernel to set the field (but note
> that the field will be set anyway if the kernel supports the flag,
> regardless of its value). In combination with the previous patches,
> this allows a userspace program to determine whether the kernel will
> set the field.
> 
> It is possible for an si_xflags-unaware program to cause a signal
> handler in an si_xflags-aware program to be called with a provided
> siginfo data structure by using one of the following syscalls:
> 
> - ptrace(PTRACE_SETSIGINFO)
> - pidfd_send_signal
> - rt_sigqueueinfo
> - rt_tgsigqueueinfo
> 
> So we need to prevent the si_xflags-unaware program from causing an
> uninitialized read of si_xflags in the si_xflags-aware program when
> it uses one of these syscalls.
> 
> The last three cases can be handled by observing that each of these
> syscalls fails if si_code >= 0, so we define si_xflags to only be
> valid if si_code >= 0.

I would say >.  0 is SI_USER, and the fact that those other interfaces
reject SI_USER seems inconsistent or a bug.

We can always relax the rule later.

Since si_xflags only makes sense for "real" fault signals, it would
never be applicable in combination with SI_USER.  Or am I missing
something?

Either way, I think this is just a documentation ossue in practice.

> 
> There is no such check on si_code in ptrace(PTRACE_SETSIGINFO), so
> we make ptrace(PTRACE_SETSIGINFO) clear the si_xflags field if it
> detects that the signal would use the _sigfault layout, and introduce
> a new ptrace request type, PTRACE_SETSIGINFO2, that a si_xflags-aware
> program may use to opt out of this behavior.

Will we need to introduce PTRACE_SETSIGINFO3, 4 etc., every time a new
field comes up?

I wonder whether we should make this more flexible, say accepting some
flags argument to say which fields the caller understands (and so
doesn't want clobbered).  Maybe we can (ab)use the sa_flags bit
definitions for indicating which extensions the caller understands.

> It is also possible for the kernel to inject a signal specified to
> use _sigfault by calling force_sig (e.g. there are numerous calls to
> force_sig(SIGSEGV)). In this case si_code is set to SI_KERNEL and the
> _kill union member is used, so document that si_code must be < SI_KERNEL.

Ack.  I'm still wondering if some of those SIGSEGV/SI_KERNEL instances
should be changed to one of the standard SIGSEGV codes, but either way,
having si_xflags validity require si_code < SI_KERNEL seems appropriate.


> Ideally this field could have just been named si_flags, but that
> name was already taken by ia64, so a different name was chosen.
> 
> Alternatively, we may consider making ia64's si_flags a generic field
> and having it appear at the end of _sigfault (in the same place as
> this patch has si_xflags) on non-ia64, keeping it in the same place
> on ia64. ia64's si_flags is a 32-bit field with only one flag bit
> allocated, so we would have 31 bits to use if we do this.

Hmm, that might be an idea.

It would mean that x86 would have different rules from other
architectures regarding how to know when the field is valid, which might
lull x86-first projects into a false sense of security.  Perhaps we could
refuse to expose any of the arch-independent flags in si_flags unless
explicitly requested via SA_XFLAGS, but that would be a departure from
what this series implements today.

So maybe it's simpler to keep the two fields separate, unless somebody
objects.

> 
> Signed-off-by: Peter Collingbourne <pcc@google.com>
> ---
> View this change in Gerrit: https://linux-review.googlesource.com/q/Ide155ce29366c3eab2a944ae4c51205982e5b8b2
> 
> v10:
> - make the new field compatible with the various ways
>   that a siginfo can be injected from another process
> - eliminate some duplication by adding a refactoring patch
>   before this one
> 
>  arch/powerpc/platforms/powernv/vas-fault.c |  1 +
>  arch/x86/kernel/signal_compat.c            |  4 +--
>  include/linux/compat.h                     |  2 ++
>  include/linux/signal_types.h               |  2 +-
>  include/uapi/asm-generic/siginfo.h         |  4 +++
>  include/uapi/asm-generic/signal-defs.h     |  4 +++
>  include/uapi/linux/ptrace.h                |  2 ++
>  kernel/ptrace.c                            | 29 ++++++++++++++++++++++
>  kernel/signal.c                            |  3 +++
>  9 files changed, 48 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/powerpc/platforms/powernv/vas-fault.c b/arch/powerpc/platforms/powernv/vas-fault.c
> index 3d21fce254b7..3bbb335561f5 100644
> --- a/arch/powerpc/platforms/powernv/vas-fault.c
> +++ b/arch/powerpc/platforms/powernv/vas-fault.c
> @@ -154,6 +154,7 @@ static void update_csb(struct vas_window *window,
>  	info.si_errno = EFAULT;
>  	info.si_code = SEGV_MAPERR;
>  	info.si_addr = csb_addr;
> +	info.si_xflags = 0;
>  
>  	/*
>  	 * process will be polling on csb.flags after request is sent to
> diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
> index c599013ae8cb..6b99f0c8a068 100644
> --- a/arch/x86/kernel/signal_compat.c
> +++ b/arch/x86/kernel/signal_compat.c
> @@ -121,8 +121,8 @@ static inline void signal_compat_build_tests(void)
>  #endif
>  
>  	CHECK_CSI_OFFSET(_sigfault);
> -	CHECK_CSI_SIZE  (_sigfault, 4*sizeof(int));
> -	CHECK_SI_SIZE   (_sigfault, 8*sizeof(int));
> +	CHECK_CSI_SIZE  (_sigfault, 8*sizeof(int));
> +	CHECK_SI_SIZE   (_sigfault, 16*sizeof(int));

(Yuk, but at least you make this no worse.)

>  
>  	BUILD_BUG_ON(offsetof(siginfo_t, si_addr) != 0x10);
>  	BUILD_BUG_ON(offsetof(compat_siginfo_t, si_addr) != 0x0C);
> diff --git a/include/linux/compat.h b/include/linux/compat.h
> index d38c4d7e83bd..55d4228dfd88 100644
> --- a/include/linux/compat.h
> +++ b/include/linux/compat.h
> @@ -231,7 +231,9 @@ typedef struct compat_siginfo {
>  					char _dummy_pkey[__COMPAT_ADDR_BND_PKEY_PAD];
>  					u32 _pkey;
>  				} _addr_pkey;
> +				compat_uptr_t _pad[6];
>  			};
> +			compat_uptr_t _xflags;

Should we have the same type here for native and compat?

I don't have a very strong opinion on this, but currently native on
64-bit arches will have 32 extra bits in _xflags that can never be used
(or have to be defined differently for compat).


>  		} _sigfault;
>  
>  		/* SIGPOLL */
> diff --git a/include/linux/signal_types.h b/include/linux/signal_types.h
> index a7887ad84d36..75ca861d982a 100644
> --- a/include/linux/signal_types.h
> +++ b/include/linux/signal_types.h
> @@ -78,6 +78,6 @@ struct ksignal {
>  
>  #define UAPI_SA_FLAGS                                                          \
>  	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
> -	 SA_NODEFER | SA_RESETHAND | __ARCH_UAPI_SA_FLAGS)
> +	 SA_NODEFER | SA_RESETHAND | SA_XFLAGS | __ARCH_UAPI_SA_FLAGS)
>  
>  #endif /* _LINUX_SIGNAL_TYPES_H */
> diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
> index cb3d6c267181..1fbd88d64f38 100644
> --- a/include/uapi/asm-generic/siginfo.h
> +++ b/include/uapi/asm-generic/siginfo.h
> @@ -91,7 +91,9 @@ union __sifields {
>  				char _dummy_pkey[__ADDR_BND_PKEY_PAD];
>  				__u32 _pkey;
>  			} _addr_pkey;
> +			void *_pad[6];

6?

Obviously we'll need something here, but I'm curious as to where this
value came from.

(Same for compat.)

>  		};
> +		unsigned long _xflags;
>  	} _sigfault;
>  
>  	/* SIGPOLL */
> @@ -152,6 +154,8 @@ typedef struct siginfo {
>  #define si_trapno	_sifields._sigfault._trapno
>  #endif
>  #define si_addr_lsb	_sifields._sigfault._addr_lsb
> +/* si_xflags is only valid if 0 <= si_code < SI_KERNEL */
> +#define si_xflags	_sifields._sigfault._xflags
>  #define si_lower	_sifields._sigfault._addr_bnd._lower
>  #define si_upper	_sifields._sigfault._addr_bnd._upper
>  #define si_pkey		_sifields._sigfault._addr_pkey._pkey
> diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
> index e853cbe8722d..bdbe1fe7a779 100644
> --- a/include/uapi/asm-generic/signal-defs.h
> +++ b/include/uapi/asm-generic/signal-defs.h
> @@ -20,6 +20,9 @@
>   * so this bit allows flag bit support to be detected from userspace while
>   * allowing an old kernel to be distinguished from a kernel that supports every
>   * flag bit.
> + * SA_XFLAGS indicates that the signal handler requires the siginfo.si_xflags
> + * field to be valid. Note that if the kernel supports SA_XFLAGS, the field will

Maybe "valid for fault signals (SIGSEGV etc.)"

[...]

Otherwise, this looks sensible overall to me.

Cheers
---Dave

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 6/7] signal: define the field siginfo.si_xflags
@ 2020-09-08 15:13     ` Dave Martin
  0 siblings, 0 replies; 59+ messages in thread
From: Dave Martin @ 2020-09-08 15:13 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Linux ARM, linux-parisc, Catalin Marinas, Kevin Brodsky,
	Oleg Nesterov, James E.J. Bottomley, Kostya Serebryany,
	Eric W. Biederman, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Will Deacon, Evgenii Stepanov,
	Richard Henderson

On Fri, Aug 21, 2020 at 10:10:16PM -0700, Peter Collingbourne wrote:

[ Add a new siginfo member sa_xflags, for fault signals. ]

> This field will contain flags that may be used by signal handlers to
> determine whether other fields in the _sigfault portion of siginfo are
> valid. An example use case is the following patch, which introduces
> the si_addr_ignored_bits{,_mask} fields.
> 
> A new sigcontext flag, SA_XFLAGS, is introduced in order to allow
> a signal handler to require the kernel to set the field (but note
> that the field will be set anyway if the kernel supports the flag,
> regardless of its value). In combination with the previous patches,
> this allows a userspace program to determine whether the kernel will
> set the field.
> 
> It is possible for an si_xflags-unaware program to cause a signal
> handler in an si_xflags-aware program to be called with a provided
> siginfo data structure by using one of the following syscalls:
> 
> - ptrace(PTRACE_SETSIGINFO)
> - pidfd_send_signal
> - rt_sigqueueinfo
> - rt_tgsigqueueinfo
> 
> So we need to prevent the si_xflags-unaware program from causing an
> uninitialized read of si_xflags in the si_xflags-aware program when
> it uses one of these syscalls.
> 
> The last three cases can be handled by observing that each of these
> syscalls fails if si_code >= 0, so we define si_xflags to only be
> valid if si_code >= 0.

I would say >.  0 is SI_USER, and the fact that those other interfaces
reject SI_USER seems inconsistent or a bug.

We can always relax the rule later.

Since si_xflags only makes sense for "real" fault signals, it would
never be applicable in combination with SI_USER.  Or am I missing
something?

Either way, I think this is just a documentation ossue in practice.

> 
> There is no such check on si_code in ptrace(PTRACE_SETSIGINFO), so
> we make ptrace(PTRACE_SETSIGINFO) clear the si_xflags field if it
> detects that the signal would use the _sigfault layout, and introduce
> a new ptrace request type, PTRACE_SETSIGINFO2, that a si_xflags-aware
> program may use to opt out of this behavior.

Will we need to introduce PTRACE_SETSIGINFO3, 4 etc., every time a new
field comes up?

I wonder whether we should make this more flexible, say accepting some
flags argument to say which fields the caller understands (and so
doesn't want clobbered).  Maybe we can (ab)use the sa_flags bit
definitions for indicating which extensions the caller understands.

> It is also possible for the kernel to inject a signal specified to
> use _sigfault by calling force_sig (e.g. there are numerous calls to
> force_sig(SIGSEGV)). In this case si_code is set to SI_KERNEL and the
> _kill union member is used, so document that si_code must be < SI_KERNEL.

Ack.  I'm still wondering if some of those SIGSEGV/SI_KERNEL instances
should be changed to one of the standard SIGSEGV codes, but either way,
having si_xflags validity require si_code < SI_KERNEL seems appropriate.


> Ideally this field could have just been named si_flags, but that
> name was already taken by ia64, so a different name was chosen.
> 
> Alternatively, we may consider making ia64's si_flags a generic field
> and having it appear at the end of _sigfault (in the same place as
> this patch has si_xflags) on non-ia64, keeping it in the same place
> on ia64. ia64's si_flags is a 32-bit field with only one flag bit
> allocated, so we would have 31 bits to use if we do this.

Hmm, that might be an idea.

It would mean that x86 would have different rules from other
architectures regarding how to know when the field is valid, which might
lull x86-first projects into a false sense of security.  Perhaps we could
refuse to expose any of the arch-independent flags in si_flags unless
explicitly requested via SA_XFLAGS, but that would be a departure from
what this series implements today.

So maybe it's simpler to keep the two fields separate, unless somebody
objects.

> 
> Signed-off-by: Peter Collingbourne <pcc@google.com>
> ---
> View this change in Gerrit: https://linux-review.googlesource.com/q/Ide155ce29366c3eab2a944ae4c51205982e5b8b2
> 
> v10:
> - make the new field compatible with the various ways
>   that a siginfo can be injected from another process
> - eliminate some duplication by adding a refactoring patch
>   before this one
> 
>  arch/powerpc/platforms/powernv/vas-fault.c |  1 +
>  arch/x86/kernel/signal_compat.c            |  4 +--
>  include/linux/compat.h                     |  2 ++
>  include/linux/signal_types.h               |  2 +-
>  include/uapi/asm-generic/siginfo.h         |  4 +++
>  include/uapi/asm-generic/signal-defs.h     |  4 +++
>  include/uapi/linux/ptrace.h                |  2 ++
>  kernel/ptrace.c                            | 29 ++++++++++++++++++++++
>  kernel/signal.c                            |  3 +++
>  9 files changed, 48 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/powerpc/platforms/powernv/vas-fault.c b/arch/powerpc/platforms/powernv/vas-fault.c
> index 3d21fce254b7..3bbb335561f5 100644
> --- a/arch/powerpc/platforms/powernv/vas-fault.c
> +++ b/arch/powerpc/platforms/powernv/vas-fault.c
> @@ -154,6 +154,7 @@ static void update_csb(struct vas_window *window,
>  	info.si_errno = EFAULT;
>  	info.si_code = SEGV_MAPERR;
>  	info.si_addr = csb_addr;
> +	info.si_xflags = 0;
>  
>  	/*
>  	 * process will be polling on csb.flags after request is sent to
> diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
> index c599013ae8cb..6b99f0c8a068 100644
> --- a/arch/x86/kernel/signal_compat.c
> +++ b/arch/x86/kernel/signal_compat.c
> @@ -121,8 +121,8 @@ static inline void signal_compat_build_tests(void)
>  #endif
>  
>  	CHECK_CSI_OFFSET(_sigfault);
> -	CHECK_CSI_SIZE  (_sigfault, 4*sizeof(int));
> -	CHECK_SI_SIZE   (_sigfault, 8*sizeof(int));
> +	CHECK_CSI_SIZE  (_sigfault, 8*sizeof(int));
> +	CHECK_SI_SIZE   (_sigfault, 16*sizeof(int));

(Yuk, but at least you make this no worse.)

>  
>  	BUILD_BUG_ON(offsetof(siginfo_t, si_addr) != 0x10);
>  	BUILD_BUG_ON(offsetof(compat_siginfo_t, si_addr) != 0x0C);
> diff --git a/include/linux/compat.h b/include/linux/compat.h
> index d38c4d7e83bd..55d4228dfd88 100644
> --- a/include/linux/compat.h
> +++ b/include/linux/compat.h
> @@ -231,7 +231,9 @@ typedef struct compat_siginfo {
>  					char _dummy_pkey[__COMPAT_ADDR_BND_PKEY_PAD];
>  					u32 _pkey;
>  				} _addr_pkey;
> +				compat_uptr_t _pad[6];
>  			};
> +			compat_uptr_t _xflags;

Should we have the same type here for native and compat?

I don't have a very strong opinion on this, but currently native on
64-bit arches will have 32 extra bits in _xflags that can never be used
(or have to be defined differently for compat).


>  		} _sigfault;
>  
>  		/* SIGPOLL */
> diff --git a/include/linux/signal_types.h b/include/linux/signal_types.h
> index a7887ad84d36..75ca861d982a 100644
> --- a/include/linux/signal_types.h
> +++ b/include/linux/signal_types.h
> @@ -78,6 +78,6 @@ struct ksignal {
>  
>  #define UAPI_SA_FLAGS                                                          \
>  	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
> -	 SA_NODEFER | SA_RESETHAND | __ARCH_UAPI_SA_FLAGS)
> +	 SA_NODEFER | SA_RESETHAND | SA_XFLAGS | __ARCH_UAPI_SA_FLAGS)
>  
>  #endif /* _LINUX_SIGNAL_TYPES_H */
> diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
> index cb3d6c267181..1fbd88d64f38 100644
> --- a/include/uapi/asm-generic/siginfo.h
> +++ b/include/uapi/asm-generic/siginfo.h
> @@ -91,7 +91,9 @@ union __sifields {
>  				char _dummy_pkey[__ADDR_BND_PKEY_PAD];
>  				__u32 _pkey;
>  			} _addr_pkey;
> +			void *_pad[6];

6?

Obviously we'll need something here, but I'm curious as to where this
value came from.

(Same for compat.)

>  		};
> +		unsigned long _xflags;
>  	} _sigfault;
>  
>  	/* SIGPOLL */
> @@ -152,6 +154,8 @@ typedef struct siginfo {
>  #define si_trapno	_sifields._sigfault._trapno
>  #endif
>  #define si_addr_lsb	_sifields._sigfault._addr_lsb
> +/* si_xflags is only valid if 0 <= si_code < SI_KERNEL */
> +#define si_xflags	_sifields._sigfault._xflags
>  #define si_lower	_sifields._sigfault._addr_bnd._lower
>  #define si_upper	_sifields._sigfault._addr_bnd._upper
>  #define si_pkey		_sifields._sigfault._addr_pkey._pkey
> diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
> index e853cbe8722d..bdbe1fe7a779 100644
> --- a/include/uapi/asm-generic/signal-defs.h
> +++ b/include/uapi/asm-generic/signal-defs.h
> @@ -20,6 +20,9 @@
>   * so this bit allows flag bit support to be detected from userspace while
>   * allowing an old kernel to be distinguished from a kernel that supports every
>   * flag bit.
> + * SA_XFLAGS indicates that the signal handler requires the siginfo.si_xflags
> + * field to be valid. Note that if the kernel supports SA_XFLAGS, the field will

Maybe "valid for fault signals (SIGSEGV etc.)"

[...]

Otherwise, this looks sensible overall to me.

Cheers
---Dave

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 7/7] arm64: expose FAR_EL1 tag bits in siginfo
  2020-08-22  5:10   ` Peter Collingbourne
@ 2020-09-08 15:13     ` Dave Martin
  -1 siblings, 0 replies; 59+ messages in thread
From: Dave Martin @ 2020-09-08 15:13 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Will Deacon, Oleg Nesterov, Eric W. Biederman,
	James E.J. Bottomley, linux-parisc, Andrey Konovalov,
	Kevin Brodsky, David Spickett, Linux ARM, Richard Henderson

On Fri, Aug 21, 2020 at 10:10:17PM -0700, Peter Collingbourne wrote:
> The kernel currently clears the tag bits (i.e. bits 56-63) in the fault
> address exposed via siginfo.si_addr and sigcontext.fault_address. However,
> the tag bits may be needed by tools in order to accurately diagnose
> memory errors, such as HWASan [1] or future tools based on the Memory
> Tagging Extension (MTE).
> 
> We should not stop clearing these bits in the existing fault address
> fields, because there may be existing userspace applications that are
> expecting the tag bits to be cleared. Instead, create a new pair of
> union fields in siginfo._sigfault, and store the tag bits of FAR_EL1
> there, together with a mask specifying which bits are valid.
> 
> A flag is added to si_xflags to allow userspace to determine whether
> the values in the fields are valid.
> 
> [1] http://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html
> 
> Signed-off-by: Peter Collingbourne <pcc@google.com>
> ---
> View this change in Gerrit: https://linux-review.googlesource.com/q/Ia8876bad8c798e0a32df7c2ce1256c4771c81446
> 
> v10:
> - rename the flag to SIXFLAG_ADDR_IGNORED_BITS
> - use an arch hook to specify which bits are ignored, instead
>   of passing them explicitly
> - while refactoring for the arch hook, noticed that my previous
>   patches missed a case involving cache maintenance instructions,
>   so expose the tag bits for that signal as well
> 
> v9:
> - make the ignored bits fields generic
> - add some new dependent patches that prepare us to store the
>   field in such a way that userspace can detect their presence
> 
> v8:
> - rebase onto 5.8rc2
> 
> v7:
> - switch to a new siginfo field instead of using sigcontext
> - merge the patch back into one since the other patches are now
>   unnecessary
> 
> v6:
> - move fault address and fault code into the kernel_siginfo data structure
> - split the patch in three since it was getting large and now has
>   generic and arch-specific parts
> 
> v5:
> - add padding to fault_addr_top_byte_context in order to ensure the correct
>   size and preserve sp alignment
> 
> v4:
> - expose only the tag bits in the context instead of the entire FAR_EL1
> - remove mention of the new context from the sigcontext.__reserved[] note
> 
> v3:
> - add documentation to tagged-pointers.rst
> - update comments in sigcontext.h
> 
> v2:
> - revert changes to hw_breakpoint.c
> - rename set_thread_esr to set_thread_far_esr
> 
>  Documentation/arm64/tagged-pointers.rst | 21 ++++++---
>  arch/arm64/include/asm/exception.h      |  2 +-
>  arch/arm64/include/asm/signal.h         | 17 +++++++
>  arch/arm64/include/asm/system_misc.h    |  2 +-
>  arch/arm64/include/asm/traps.h          |  6 +--
>  arch/arm64/kernel/debug-monitors.c      |  5 +--
>  arch/arm64/kernel/entry-common.c        |  2 -
>  arch/arm64/kernel/ptrace.c              |  7 +--
>  arch/arm64/kernel/sys_compat.c          |  5 +--
>  arch/arm64/kernel/traps.c               | 29 ++++++------
>  arch/arm64/mm/fault.c                   | 59 +++++++++++++------------
>  arch/x86/kernel/signal_compat.c         |  4 +-
>  include/linux/compat.h                  |  2 +
>  include/linux/signal.h                  |  8 ++++
>  include/uapi/asm-generic/siginfo.h      | 10 +++++
>  kernel/signal.c                         | 14 +++++-
>  16 files changed, 122 insertions(+), 71 deletions(-)
>  create mode 100644 arch/arm64/include/asm/signal.h
> 
> diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst
> index eab4323609b9..14273160b38b 100644
> --- a/Documentation/arm64/tagged-pointers.rst
> +++ b/Documentation/arm64/tagged-pointers.rst
> @@ -53,12 +53,21 @@ visibility.
>  Preserving tags
>  ---------------
>  
> -Non-zero tags are not preserved when delivering signals. This means that
> -signal handlers in applications making use of tags cannot rely on the
> -tag information for user virtual addresses being maintained for fields
> -inside siginfo_t. One exception to this rule is for signals raised in
> -response to watchpoint debug exceptions, where the tag information will
> -be preserved.
> +Non-zero tags are not preserved in the fault address fields
> +siginfo.si_addr or sigcontext.fault_address when delivering
> +signals. This means that signal handlers in applications making use
> +of tags cannot rely on the tag information for user virtual addresses
> +being maintained in these fields. One exception to this rule is for
> +signals raised in response to watchpoint debug exceptions, where the
> +tag information will be preserved.
> +
> +The fault address tag is preserved in the si_addr_ignored_bits field
> +of siginfo, which is set for signals raised in response to data aborts
> +and instruction aborts. The si_addr_ignored_bits_mask field indicates
> +which bits of the field are valid. The validity of these fields is
> +indicated by the SIXFLAG_ADDR_IGNORED_BITS flag in siginfo.si_xflags,
> +and the validity of si_xflags in turn is indicated by the kernel
> +indicating support for the sigaction.sa_flags flag SA_XFLAGS.
>  
>  The architecture prevents the use of a tagged PC, so the upper byte will
>  be set to a sign-extension of bit 55 on exception return.
> diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h
> index 7577a754d443..950d55dae948 100644
> --- a/arch/arm64/include/asm/exception.h
> +++ b/arch/arm64/include/asm/exception.h
> @@ -32,7 +32,7 @@ static inline u32 disr_to_esr(u64 disr)
>  }
>  
>  asmlinkage void enter_from_user_mode(void);
> -void do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs);
> +void do_mem_abort(unsigned long far, unsigned int esr, struct pt_regs *regs);
>  void do_undefinstr(struct pt_regs *regs);
>  void do_bti(struct pt_regs *regs);
>  asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr);

[...]

> diff --git a/include/linux/compat.h b/include/linux/compat.h
> index 55d4228dfd88..273146cf30fd 100644
> --- a/include/linux/compat.h
> +++ b/include/linux/compat.h
> @@ -234,6 +234,8 @@ typedef struct compat_siginfo {
>  				compat_uptr_t _pad[6];
>  			};
>  			compat_uptr_t _xflags;
> +			compat_uptr_t _addr_ignored_bits;
> +			compat_uptr_t _addr_ignored_bits_mask;
>  		} _sigfault;
>  
>  		/* SIGPOLL */
> diff --git a/include/linux/signal.h b/include/linux/signal.h
> index 3edbf54493ee..b4c473c12a9b 100644
> --- a/include/linux/signal.h
> +++ b/include/linux/signal.h
> @@ -480,4 +480,12 @@ struct seq_file;
>  extern void render_sigset_t(struct seq_file *, const char *, sigset_t *);
>  #endif

Can we have a comment here explaining what this helper needs to do, if
defined?

> +#ifndef arch_addr_ignored_bits_mask
> +static inline unsigned long arch_addr_ignored_bits_mask(unsigned long sig,
> +							unsigned long si_code)
> +{
> +	return 0;
> +}
> +#endif
> +
>  #endif /* _LINUX_SIGNAL_H */
> diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
> index 1fbd88d64f38..e314a38ce2d0 100644
> --- a/include/uapi/asm-generic/siginfo.h
> +++ b/include/uapi/asm-generic/siginfo.h
> @@ -94,6 +94,8 @@ union __sifields {
>  			void *_pad[6];
>  		};
>  		unsigned long _xflags;
> +		unsigned long _addr_ignored_bits;
> +		unsigned long _addr_ignored_bits_mask;
>  	} _sigfault;
>  
>  	/* SIGPOLL */
> @@ -156,6 +158,8 @@ typedef struct siginfo {
>  #define si_addr_lsb	_sifields._sigfault._addr_lsb
>  /* si_xflags is only valid if 0 <= si_code < SI_KERNEL */
>  #define si_xflags	_sifields._sigfault._xflags
> +#define si_addr_ignored_bits		_sifields._sigfault._addr_ignored_bits
> +#define si_addr_ignored_bits_mask	_sifields._sigfault._addr_ignored_bits_mask
>  #define si_lower	_sifields._sigfault._addr_bnd._lower
>  #define si_upper	_sifields._sigfault._addr_bnd._upper
>  #define si_pkey		_sifields._sigfault._addr_pkey._pkey
> @@ -296,6 +300,12 @@ typedef struct siginfo {
>  #define EMT_TAGOVF	1	/* tag overflow */
>  #define NSIGEMT		1
>  
> +/*
> + * SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT si_xflags
> + */
> +#define SIXFLAG_ADDR_IGNORED_BITS	1
> +/* si_addr_ignored_bits{,_mask} fields valid */
> +

I'm still uneasy about the "ignored bits" nomenclature, because the bits
aren't ignored, and because at the C language level above, they
generally _are_ considered part of the address.

I don't have a great suggestion for a new name, though.  If we just
consider the si_addr_ignored_bits to be attributes that accompany the
address, it might make sense to call it

	si_addr_attr_bits_mask

or similar.

That may or may not be considered to be less confusing.

>  /*
>   * sigevent definitions
>   * 
> diff --git a/kernel/signal.c b/kernel/signal.c
> index 4259903b95cb..29654652d3aa 100644
> --- a/kernel/signal.c
> +++ b/kernel/signal.c
> @@ -1652,11 +1652,17 @@ void force_sigsegv(int sig)
>  static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
>  				       int code, void __user *addr)
>  {
> +	unsigned long addr_long = (unsigned long)addr;
> +	unsigned long ignored_bits_mask =
> +		arch_addr_ignored_bits_mask(sig, code);
> +
>  	info->si_signo = sig;
>  	info->si_errno = 0;
>  	info->si_code = code;
> -	info->si_addr = addr;
> -	info->si_xflags = 0;
> +	info->si_addr = (void __user *)(addr_long & ~ignored_bits_mask);
> +	info->si_xflags = SIXFLAG_ADDR_IGNORED_BITS;
> +	info->si_addr_ignored_bits = addr_long & ignored_bits_mask;
> +	info->si_addr_ignored_bits_mask = ignored_bits_mask;

Could we report the ignored bits optionally?

i.e., if arch_addr_ignored_bits_mask() == 0, then we could perhaps leave
SIXFLAG_ADDR_IGNORED_BITS clear in si_xflags, and just set
si_addr_ignored_bits{,_mask} to zeros.

I can't decide myself whether this would be a good idea or not...

>  }
>  
>  int force_sig_fault_to_task(int sig, int code, void __user *addr
> @@ -3271,6 +3277,8 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
>  		to->si_trapno = from->si_trapno;
>  #endif
>  		to->si_xflags = from->si_xflags;
> +		to->si_addr_ignored_bits = from->si_addr_ignored_bits;
> +		to->si_addr_ignored_bits_mask = from->si_addr_ignored_bits_mask;

What happens if we're delivering a signal to a compat process?

It looks like we apply all the usual logic, but si_addr_ignored_bits and
si_addr_ignored_bits_mask simply get truncated.

That might be reasonable -- we don't care about bits that don't exist
for compat, irrespective of what they mean for native -- but it's
probably worth a comment.

>  	}
>  
>  	switch (layout) {
> @@ -3347,6 +3355,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
>  		to->si_trapno = from->si_trapno;
>  #endif
>  		to->si_xflags = from->si_xflags;
> +		to->si_addr_ignored_bits = from->si_addr_ignored_bits;
> +		to->si_addr_ignored_bits_mask = from->si_addr_ignored_bits_mask;

Otherwise, the patch looks reasonable.

Cheers
---Dave

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 7/7] arm64: expose FAR_EL1 tag bits in siginfo
@ 2020-09-08 15:13     ` Dave Martin
  0 siblings, 0 replies; 59+ messages in thread
From: Dave Martin @ 2020-09-08 15:13 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Linux ARM, linux-parisc, Catalin Marinas, Kevin Brodsky,
	Oleg Nesterov, James E.J. Bottomley, Kostya Serebryany,
	Eric W. Biederman, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Will Deacon, Evgenii Stepanov,
	Richard Henderson

On Fri, Aug 21, 2020 at 10:10:17PM -0700, Peter Collingbourne wrote:
> The kernel currently clears the tag bits (i.e. bits 56-63) in the fault
> address exposed via siginfo.si_addr and sigcontext.fault_address. However,
> the tag bits may be needed by tools in order to accurately diagnose
> memory errors, such as HWASan [1] or future tools based on the Memory
> Tagging Extension (MTE).
> 
> We should not stop clearing these bits in the existing fault address
> fields, because there may be existing userspace applications that are
> expecting the tag bits to be cleared. Instead, create a new pair of
> union fields in siginfo._sigfault, and store the tag bits of FAR_EL1
> there, together with a mask specifying which bits are valid.
> 
> A flag is added to si_xflags to allow userspace to determine whether
> the values in the fields are valid.
> 
> [1] http://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html
> 
> Signed-off-by: Peter Collingbourne <pcc@google.com>
> ---
> View this change in Gerrit: https://linux-review.googlesource.com/q/Ia8876bad8c798e0a32df7c2ce1256c4771c81446
> 
> v10:
> - rename the flag to SIXFLAG_ADDR_IGNORED_BITS
> - use an arch hook to specify which bits are ignored, instead
>   of passing them explicitly
> - while refactoring for the arch hook, noticed that my previous
>   patches missed a case involving cache maintenance instructions,
>   so expose the tag bits for that signal as well
> 
> v9:
> - make the ignored bits fields generic
> - add some new dependent patches that prepare us to store the
>   field in such a way that userspace can detect their presence
> 
> v8:
> - rebase onto 5.8rc2
> 
> v7:
> - switch to a new siginfo field instead of using sigcontext
> - merge the patch back into one since the other patches are now
>   unnecessary
> 
> v6:
> - move fault address and fault code into the kernel_siginfo data structure
> - split the patch in three since it was getting large and now has
>   generic and arch-specific parts
> 
> v5:
> - add padding to fault_addr_top_byte_context in order to ensure the correct
>   size and preserve sp alignment
> 
> v4:
> - expose only the tag bits in the context instead of the entire FAR_EL1
> - remove mention of the new context from the sigcontext.__reserved[] note
> 
> v3:
> - add documentation to tagged-pointers.rst
> - update comments in sigcontext.h
> 
> v2:
> - revert changes to hw_breakpoint.c
> - rename set_thread_esr to set_thread_far_esr
> 
>  Documentation/arm64/tagged-pointers.rst | 21 ++++++---
>  arch/arm64/include/asm/exception.h      |  2 +-
>  arch/arm64/include/asm/signal.h         | 17 +++++++
>  arch/arm64/include/asm/system_misc.h    |  2 +-
>  arch/arm64/include/asm/traps.h          |  6 +--
>  arch/arm64/kernel/debug-monitors.c      |  5 +--
>  arch/arm64/kernel/entry-common.c        |  2 -
>  arch/arm64/kernel/ptrace.c              |  7 +--
>  arch/arm64/kernel/sys_compat.c          |  5 +--
>  arch/arm64/kernel/traps.c               | 29 ++++++------
>  arch/arm64/mm/fault.c                   | 59 +++++++++++++------------
>  arch/x86/kernel/signal_compat.c         |  4 +-
>  include/linux/compat.h                  |  2 +
>  include/linux/signal.h                  |  8 ++++
>  include/uapi/asm-generic/siginfo.h      | 10 +++++
>  kernel/signal.c                         | 14 +++++-
>  16 files changed, 122 insertions(+), 71 deletions(-)
>  create mode 100644 arch/arm64/include/asm/signal.h
> 
> diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst
> index eab4323609b9..14273160b38b 100644
> --- a/Documentation/arm64/tagged-pointers.rst
> +++ b/Documentation/arm64/tagged-pointers.rst
> @@ -53,12 +53,21 @@ visibility.
>  Preserving tags
>  ---------------
>  
> -Non-zero tags are not preserved when delivering signals. This means that
> -signal handlers in applications making use of tags cannot rely on the
> -tag information for user virtual addresses being maintained for fields
> -inside siginfo_t. One exception to this rule is for signals raised in
> -response to watchpoint debug exceptions, where the tag information will
> -be preserved.
> +Non-zero tags are not preserved in the fault address fields
> +siginfo.si_addr or sigcontext.fault_address when delivering
> +signals. This means that signal handlers in applications making use
> +of tags cannot rely on the tag information for user virtual addresses
> +being maintained in these fields. One exception to this rule is for
> +signals raised in response to watchpoint debug exceptions, where the
> +tag information will be preserved.
> +
> +The fault address tag is preserved in the si_addr_ignored_bits field
> +of siginfo, which is set for signals raised in response to data aborts
> +and instruction aborts. The si_addr_ignored_bits_mask field indicates
> +which bits of the field are valid. The validity of these fields is
> +indicated by the SIXFLAG_ADDR_IGNORED_BITS flag in siginfo.si_xflags,
> +and the validity of si_xflags in turn is indicated by the kernel
> +indicating support for the sigaction.sa_flags flag SA_XFLAGS.
>  
>  The architecture prevents the use of a tagged PC, so the upper byte will
>  be set to a sign-extension of bit 55 on exception return.
> diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h
> index 7577a754d443..950d55dae948 100644
> --- a/arch/arm64/include/asm/exception.h
> +++ b/arch/arm64/include/asm/exception.h
> @@ -32,7 +32,7 @@ static inline u32 disr_to_esr(u64 disr)
>  }
>  
>  asmlinkage void enter_from_user_mode(void);
> -void do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs);
> +void do_mem_abort(unsigned long far, unsigned int esr, struct pt_regs *regs);
>  void do_undefinstr(struct pt_regs *regs);
>  void do_bti(struct pt_regs *regs);
>  asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr);

[...]

> diff --git a/include/linux/compat.h b/include/linux/compat.h
> index 55d4228dfd88..273146cf30fd 100644
> --- a/include/linux/compat.h
> +++ b/include/linux/compat.h
> @@ -234,6 +234,8 @@ typedef struct compat_siginfo {
>  				compat_uptr_t _pad[6];
>  			};
>  			compat_uptr_t _xflags;
> +			compat_uptr_t _addr_ignored_bits;
> +			compat_uptr_t _addr_ignored_bits_mask;
>  		} _sigfault;
>  
>  		/* SIGPOLL */
> diff --git a/include/linux/signal.h b/include/linux/signal.h
> index 3edbf54493ee..b4c473c12a9b 100644
> --- a/include/linux/signal.h
> +++ b/include/linux/signal.h
> @@ -480,4 +480,12 @@ struct seq_file;
>  extern void render_sigset_t(struct seq_file *, const char *, sigset_t *);
>  #endif

Can we have a comment here explaining what this helper needs to do, if
defined?

> +#ifndef arch_addr_ignored_bits_mask
> +static inline unsigned long arch_addr_ignored_bits_mask(unsigned long sig,
> +							unsigned long si_code)
> +{
> +	return 0;
> +}
> +#endif
> +
>  #endif /* _LINUX_SIGNAL_H */
> diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
> index 1fbd88d64f38..e314a38ce2d0 100644
> --- a/include/uapi/asm-generic/siginfo.h
> +++ b/include/uapi/asm-generic/siginfo.h
> @@ -94,6 +94,8 @@ union __sifields {
>  			void *_pad[6];
>  		};
>  		unsigned long _xflags;
> +		unsigned long _addr_ignored_bits;
> +		unsigned long _addr_ignored_bits_mask;
>  	} _sigfault;
>  
>  	/* SIGPOLL */
> @@ -156,6 +158,8 @@ typedef struct siginfo {
>  #define si_addr_lsb	_sifields._sigfault._addr_lsb
>  /* si_xflags is only valid if 0 <= si_code < SI_KERNEL */
>  #define si_xflags	_sifields._sigfault._xflags
> +#define si_addr_ignored_bits		_sifields._sigfault._addr_ignored_bits
> +#define si_addr_ignored_bits_mask	_sifields._sigfault._addr_ignored_bits_mask
>  #define si_lower	_sifields._sigfault._addr_bnd._lower
>  #define si_upper	_sifields._sigfault._addr_bnd._upper
>  #define si_pkey		_sifields._sigfault._addr_pkey._pkey
> @@ -296,6 +300,12 @@ typedef struct siginfo {
>  #define EMT_TAGOVF	1	/* tag overflow */
>  #define NSIGEMT		1
>  
> +/*
> + * SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT si_xflags
> + */
> +#define SIXFLAG_ADDR_IGNORED_BITS	1
> +/* si_addr_ignored_bits{,_mask} fields valid */
> +

I'm still uneasy about the "ignored bits" nomenclature, because the bits
aren't ignored, and because at the C language level above, they
generally _are_ considered part of the address.

I don't have a great suggestion for a new name, though.  If we just
consider the si_addr_ignored_bits to be attributes that accompany the
address, it might make sense to call it

	si_addr_attr_bits_mask

or similar.

That may or may not be considered to be less confusing.

>  /*
>   * sigevent definitions
>   * 
> diff --git a/kernel/signal.c b/kernel/signal.c
> index 4259903b95cb..29654652d3aa 100644
> --- a/kernel/signal.c
> +++ b/kernel/signal.c
> @@ -1652,11 +1652,17 @@ void force_sigsegv(int sig)
>  static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
>  				       int code, void __user *addr)
>  {
> +	unsigned long addr_long = (unsigned long)addr;
> +	unsigned long ignored_bits_mask =
> +		arch_addr_ignored_bits_mask(sig, code);
> +
>  	info->si_signo = sig;
>  	info->si_errno = 0;
>  	info->si_code = code;
> -	info->si_addr = addr;
> -	info->si_xflags = 0;
> +	info->si_addr = (void __user *)(addr_long & ~ignored_bits_mask);
> +	info->si_xflags = SIXFLAG_ADDR_IGNORED_BITS;
> +	info->si_addr_ignored_bits = addr_long & ignored_bits_mask;
> +	info->si_addr_ignored_bits_mask = ignored_bits_mask;

Could we report the ignored bits optionally?

i.e., if arch_addr_ignored_bits_mask() == 0, then we could perhaps leave
SIXFLAG_ADDR_IGNORED_BITS clear in si_xflags, and just set
si_addr_ignored_bits{,_mask} to zeros.

I can't decide myself whether this would be a good idea or not...

>  }
>  
>  int force_sig_fault_to_task(int sig, int code, void __user *addr
> @@ -3271,6 +3277,8 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
>  		to->si_trapno = from->si_trapno;
>  #endif
>  		to->si_xflags = from->si_xflags;
> +		to->si_addr_ignored_bits = from->si_addr_ignored_bits;
> +		to->si_addr_ignored_bits_mask = from->si_addr_ignored_bits_mask;

What happens if we're delivering a signal to a compat process?

It looks like we apply all the usual logic, but si_addr_ignored_bits and
si_addr_ignored_bits_mask simply get truncated.

That might be reasonable -- we don't care about bits that don't exist
for compat, irrespective of what they mean for native -- but it's
probably worth a comment.

>  	}
>  
>  	switch (layout) {
> @@ -3347,6 +3355,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
>  		to->si_trapno = from->si_trapno;
>  #endif
>  		to->si_xflags = from->si_xflags;
> +		to->si_addr_ignored_bits = from->si_addr_ignored_bits;
> +		to->si_addr_ignored_bits_mask = from->si_addr_ignored_bits_mask;

Otherwise, the patch looks reasonable.

Cheers
---Dave

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 2/7] arch: move SA_* definitions to generic headers
  2020-09-08 15:12     ` Dave Martin
@ 2020-10-03  1:14       ` Peter Collingbourne
  -1 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-10-03  1:14 UTC (permalink / raw)
  To: Dave Martin
  Cc: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Will Deacon, Oleg Nesterov, Eric W. Biederman,
	James E.J. Bottomley, Parisc List, Andrey Konovalov,
	Kevin Brodsky, David Spickett, Linux ARM, Richard Henderson

On Tue, Sep 8, 2020 at 8:12 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Fri, Aug 21, 2020 at 10:10:12PM -0700, Peter Collingbourne wrote:
> > Most architectures with the exception of alpha, mips, parisc and
> > sparc use the same values for these flags. Move their definitions into
> > asm-generic/signal-defs.h and allow the architectures with non-standard
> > values to override them. Also, document the non-standard flag values
> > in order to make it easier to add new generic flags in the future.
> >
> > Signed-off-by: Peter Collingbourne <pcc@google.com>
>
> While this looks reasonable, I've just realised that you strip the "U"
> from some arches' definitions here.
>
> So, on powerpc and x86, this changes the type of flags other than
> SA_RESETHAND from unsigned int to int.
>
> While I can't see this breaking any sensible use of these flags, there's
> a chance that there is software relying on this distinction by
> accident.

While it's true that it's technically possible that making these
signed could change semantics, I'm having trouble seeing a realistic
way in which software could be relying on this. Can you see one? I can
think of cases like if the code does something like left shifts one of
the flag bits into the sign bit (technically undefined behavior) and
then right shifts it back (in C this would need to all be done in a
single expression without storing to a variable; in C++ I suppose you
could use auto to preserve the signedness in a variable's type). For
example:

int x = (SA_NODEFER << 1) >> 1;

would give a different value to x if we made SA_NODEFER signed. But I
wouldn't really expect software to be doing this sort of thing even
accidentally, or much more than or'ing the flags together and
assigning them to a variable, or passing them as a parameter, or some
other operation which would fix the type.

I believe that the kernel's uapi guarantee applies at the binary
level, not at the source level. If that were not the case, I think we
would not be allowed to add any new declaration to an existing .h file
for fear of conflicting with a user program's identically spelled
declaration. And that seems more likely to me than software that would
do this sort of thing.

> I wonder whether it's worth doing something like
>
>         #ifdef ARCH_WANT_STRICTLY_UNSIGNED_SA_FLAGS
>         #define __SA_FLAG_VAL(x) x ## U
>         #else
>         #define __SA_FLAG_VAL(x) x
>         #endif
>
>         #ifndef SA_NOCLDSTOP
>         #define SA_NOCLDSTOP __SA_FLAG_VAL(0x00000001)
>         #endif
>
>         /* ... */

If we do this I would mildly prefer to keep the existing #defines in
the arch-specific headers as if the arch had different flag values, as
this would leave the arch-specific legacy cruft in the arch-specific
headers where it belongs.

> Mind you, the historical situation also has issues, e.g. because
> sa_flags in struct sigaction is an int, assigning
>
>         struct sigaction sa;
>
>         sa.sa_flags = SA_RESETHAND;
>
> implies an overflow and so isn't portably safe (at least in theory).  I
> guess we are getting away with it today.  Preserving the situation by
> keeping the "U"s where appropriate would at least avoid making the
> situation worse.

I believe that the result of this assignment (involving an unsigned to
signed conversion) is implementation defined and not undefined (which
would be problematic). And in all the implementations that matter, as
well as the C++ standard starting with C++20, this is a no-op cast
assuming two's complement. I'm not sure what this has to do with
making the constants signed because, as you pointed out, SA_RESETHAND
would remain unsigned despite the absence of 'U' because its value
does not fit in an int.

Peter

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 2/7] arch: move SA_* definitions to generic headers
@ 2020-10-03  1:14       ` Peter Collingbourne
  0 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-10-03  1:14 UTC (permalink / raw)
  To: Dave Martin
  Cc: Linux ARM, Parisc List, Catalin Marinas, Kevin Brodsky,
	Oleg Nesterov, James E.J. Bottomley, Kostya Serebryany,
	Eric W. Biederman, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Will Deacon, Evgenii Stepanov,
	Richard Henderson

On Tue, Sep 8, 2020 at 8:12 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Fri, Aug 21, 2020 at 10:10:12PM -0700, Peter Collingbourne wrote:
> > Most architectures with the exception of alpha, mips, parisc and
> > sparc use the same values for these flags. Move their definitions into
> > asm-generic/signal-defs.h and allow the architectures with non-standard
> > values to override them. Also, document the non-standard flag values
> > in order to make it easier to add new generic flags in the future.
> >
> > Signed-off-by: Peter Collingbourne <pcc@google.com>
>
> While this looks reasonable, I've just realised that you strip the "U"
> from some arches' definitions here.
>
> So, on powerpc and x86, this changes the type of flags other than
> SA_RESETHAND from unsigned int to int.
>
> While I can't see this breaking any sensible use of these flags, there's
> a chance that there is software relying on this distinction by
> accident.

While it's true that it's technically possible that making these
signed could change semantics, I'm having trouble seeing a realistic
way in which software could be relying on this. Can you see one? I can
think of cases like if the code does something like left shifts one of
the flag bits into the sign bit (technically undefined behavior) and
then right shifts it back (in C this would need to all be done in a
single expression without storing to a variable; in C++ I suppose you
could use auto to preserve the signedness in a variable's type). For
example:

int x = (SA_NODEFER << 1) >> 1;

would give a different value to x if we made SA_NODEFER signed. But I
wouldn't really expect software to be doing this sort of thing even
accidentally, or much more than or'ing the flags together and
assigning them to a variable, or passing them as a parameter, or some
other operation which would fix the type.

I believe that the kernel's uapi guarantee applies at the binary
level, not at the source level. If that were not the case, I think we
would not be allowed to add any new declaration to an existing .h file
for fear of conflicting with a user program's identically spelled
declaration. And that seems more likely to me than software that would
do this sort of thing.

> I wonder whether it's worth doing something like
>
>         #ifdef ARCH_WANT_STRICTLY_UNSIGNED_SA_FLAGS
>         #define __SA_FLAG_VAL(x) x ## U
>         #else
>         #define __SA_FLAG_VAL(x) x
>         #endif
>
>         #ifndef SA_NOCLDSTOP
>         #define SA_NOCLDSTOP __SA_FLAG_VAL(0x00000001)
>         #endif
>
>         /* ... */

If we do this I would mildly prefer to keep the existing #defines in
the arch-specific headers as if the arch had different flag values, as
this would leave the arch-specific legacy cruft in the arch-specific
headers where it belongs.

> Mind you, the historical situation also has issues, e.g. because
> sa_flags in struct sigaction is an int, assigning
>
>         struct sigaction sa;
>
>         sa.sa_flags = SA_RESETHAND;
>
> implies an overflow and so isn't portably safe (at least in theory).  I
> guess we are getting away with it today.  Preserving the situation by
> keeping the "U"s where appropriate would at least avoid making the
> situation worse.

I believe that the result of this assignment (involving an unsigned to
signed conversion) is implementation defined and not undefined (which
would be problematic). And in all the implementations that matter, as
well as the C++ standard starting with C++20, this is a no-op cast
assuming two's complement. I'm not sure what this has to do with
making the constants signed because, as you pointed out, SA_RESETHAND
would remain unsigned despite the absence of 'U' because its value
does not fit in an int.

Peter

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 1/7] parisc: start using signal-defs.h
  2020-08-30 17:07   ` Helge Deller
@ 2020-10-03  1:22     ` Peter Collingbourne
  2020-10-03 10:04       ` Helge Deller
  0 siblings, 1 reply; 59+ messages in thread
From: Peter Collingbourne @ 2020-10-03  1:22 UTC (permalink / raw)
  To: Helge Deller; +Cc: James E.J. Bottomley, Richard Henderson, Parisc List

On Sun, Aug 30, 2020 at 10:07 AM Helge Deller <deller@gmx.de> wrote:
>
> On 22.08.20 07:10, Peter Collingbourne wrote:
> > We currently include signal-defs.h on all architectures except parisc.
> > Make parisc fall in line. This will make maintenance easier once the
> > flag bits are moved here.
>
> The patch is basically OK, but....
>
> > Signed-off-by: Peter Collingbourne <pcc@google.com>
> > ---
> > View this change in Gerrit: https://linux-review.googlesource.com/q/If03a5135fb514fe96548fb74610e6c3586a04064
> >
> >  arch/parisc/include/uapi/asm/signal.h  | 9 +--------
> >  include/uapi/asm-generic/signal-defs.h | 6 ++++++
> >  2 files changed, 7 insertions(+), 8 deletions(-)
> >
> > diff --git a/arch/parisc/include/uapi/asm/signal.h b/arch/parisc/include/uapi/asm/signal.h
> > index d38563a394f2..92a1c7ea44b4 100644
> > --- a/arch/parisc/include/uapi/asm/signal.h
> > +++ b/arch/parisc/include/uapi/asm/signal.h
> > @@ -69,14 +69,7 @@
> >  #define MINSIGSTKSZ  2048
> >  #define SIGSTKSZ     8192
> >
> > -
> > -#define SIG_BLOCK          0 /* for blocking signals */
> > -#define SIG_UNBLOCK        1 /* for unblocking signals */
> > -#define SIG_SETMASK        2 /* for setting the signal mask */
> > -
> > -#define SIG_DFL      ((__sighandler_t)0)     /* default signal handling */
> > -#define SIG_IGN      ((__sighandler_t)1)     /* ignore signal */
> > -#define SIG_ERR      ((__sighandler_t)-1)    /* error return from signal */
> > +#include <asm/signal-defs.h>
> >
> >  # ifndef __ASSEMBLY__
> >
> > diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
> > index e9304c95ceea..ecdf6312bfa5 100644
> > --- a/include/uapi/asm-generic/signal-defs.h
> > +++ b/include/uapi/asm-generic/signal-defs.h
> > @@ -15,8 +15,14 @@
> >  #endif
> >
> >  #ifndef __ASSEMBLY__
>
> > +#ifndef __hppa__
> > +/*
> > + * These have a special definition on parisc, see:
> > + * arch/parisc/include/uapi/asm/signal.h
> > + */
> >  typedef void __signalfn_t(int);
> >  typedef __signalfn_t __user *__sighandler_t;
>
> please drop this special-case/#ifdef for hppa/parisc.
> Instead please drop the typedef in arch/parisc/include/uapi/asm/signal.h,
> same as you did for the other architectures.
>
> I've committed this patch to my tree, which will collide with yours:
>  https://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux.git/commit/?h=for-next
> If you like I can drop mine, and you fix it up on your side.
> Just let me know.
>
> Other than that you can add:
> Acked-by: Helge Deller <deller@gmx.de>
>
> Thanks!

Thanks for the review and apologies for the delay in getting back to
you. I've picked up your patch from your for-next branch into my
series before this change, and removed the special case for hppa. I
also build tested my series on hppa which revealed a typo in the
#include directive which I fixed. The new patch looks like this and it
will be included in v11 which I will try to send out soon.

diff --git a/arch/parisc/include/uapi/asm/signal.h
b/arch/parisc/include/uapi/asm/signal.h
index f1fd4fa880d7..e67b1bfb82ba 100644
--- a/arch/parisc/include/uapi/asm/signal.h
+++ b/arch/parisc/include/uapi/asm/signal.h
@@ -69,14 +69,7 @@
 #define MINSIGSTKSZ    2048
 #define SIGSTKSZ       8192

-
-#define SIG_BLOCK          0   /* for blocking signals */
-#define SIG_UNBLOCK        1   /* for unblocking signals */
-#define SIG_SETMASK        2   /* for setting the signal mask */
-
-#define SIG_DFL        ((__sighandler_t)0)     /* default signal handling */
-#define SIG_IGN        ((__sighandler_t)1)     /* ignore signal */
-#define SIG_ERR        ((__sighandler_t)-1)    /* error return from signal */
+#include <asm-generic/signal-defs.h>

 # ifndef __ASSEMBLY__

@@ -85,10 +78,6 @@
 /* Avoid too many header ordering problems.  */
 struct siginfo;

-/* Type of a signal handler.  */
-typedef void __signalfn_t(int);
-typedef __signalfn_t __user *__sighandler_t;
-
 typedef struct sigaltstack {
        void __user *ss_sp;
        int ss_flags;

Peter

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 1/7] parisc: start using signal-defs.h
  2020-10-03  1:22     ` Peter Collingbourne
@ 2020-10-03 10:04       ` Helge Deller
  0 siblings, 0 replies; 59+ messages in thread
From: Helge Deller @ 2020-10-03 10:04 UTC (permalink / raw)
  To: Peter Collingbourne; +Cc: James E.J. Bottomley, Richard Henderson, Parisc List

On 10/3/20 3:22 AM, Peter Collingbourne wrote:
> On Sun, Aug 30, 2020 at 10:07 AM Helge Deller <deller@gmx.de> wrote:
>>
>> On 22.08.20 07:10, Peter Collingbourne wrote:
>>> We currently include signal-defs.h on all architectures except parisc.
>>> Make parisc fall in line. This will make maintenance easier once the
>>> flag bits are moved here.
>>
>> The patch is basically OK, but....
>>
>>> Signed-off-by: Peter Collingbourne <pcc@google.com>
>>> ---
>>> View this change in Gerrit: https://linux-review.googlesource.com/q/If03a5135fb514fe96548fb74610e6c3586a04064
>>>
>>>  arch/parisc/include/uapi/asm/signal.h  | 9 +--------
>>>  include/uapi/asm-generic/signal-defs.h | 6 ++++++
>>>  2 files changed, 7 insertions(+), 8 deletions(-)
>>>
>>> diff --git a/arch/parisc/include/uapi/asm/signal.h b/arch/parisc/include/uapi/asm/signal.h
>>> index d38563a394f2..92a1c7ea44b4 100644
>>> --- a/arch/parisc/include/uapi/asm/signal.h
>>> +++ b/arch/parisc/include/uapi/asm/signal.h
>>> @@ -69,14 +69,7 @@
>>>  #define MINSIGSTKSZ  2048
>>>  #define SIGSTKSZ     8192
>>>
>>> -
>>> -#define SIG_BLOCK          0 /* for blocking signals */
>>> -#define SIG_UNBLOCK        1 /* for unblocking signals */
>>> -#define SIG_SETMASK        2 /* for setting the signal mask */
>>> -
>>> -#define SIG_DFL      ((__sighandler_t)0)     /* default signal handling */
>>> -#define SIG_IGN      ((__sighandler_t)1)     /* ignore signal */
>>> -#define SIG_ERR      ((__sighandler_t)-1)    /* error return from signal */
>>> +#include <asm/signal-defs.h>
>>>
>>>  # ifndef __ASSEMBLY__
>>>
>>> diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
>>> index e9304c95ceea..ecdf6312bfa5 100644
>>> --- a/include/uapi/asm-generic/signal-defs.h
>>> +++ b/include/uapi/asm-generic/signal-defs.h
>>> @@ -15,8 +15,14 @@
>>>  #endif
>>>
>>>  #ifndef __ASSEMBLY__
>>
>>> +#ifndef __hppa__
>>> +/*
>>> + * These have a special definition on parisc, see:
>>> + * arch/parisc/include/uapi/asm/signal.h
>>> + */
>>>  typedef void __signalfn_t(int);
>>>  typedef __signalfn_t __user *__sighandler_t;
>>
>> please drop this special-case/#ifdef for hppa/parisc.
>> Instead please drop the typedef in arch/parisc/include/uapi/asm/signal.h,
>> same as you did for the other architectures.
>>
>> I've committed this patch to my tree, which will collide with yours:
>>  https://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux.git/commit/?h=for-next
>> If you like I can drop mine, and you fix it up on your side.
>> Just let me know.
>>
>> Other than that you can add:
>> Acked-by: Helge Deller <deller@gmx.de>
>>
>> Thanks!
>
> Thanks for the review and apologies for the delay in getting back to
> you. I've picked up your patch from your for-next branch into my
> series before this change, and removed the special case for hppa. I
> also build tested my series on hppa which revealed a typo in the
> #include directive which I fixed. The new patch looks like this and it
> will be included in v11 which I will try to send out soon.

Thanks!
Ok, I've now dropped my patch from my for-next series.

Helge


> diff --git a/arch/parisc/include/uapi/asm/signal.h
> b/arch/parisc/include/uapi/asm/signal.h
> index f1fd4fa880d7..e67b1bfb82ba 100644
> --- a/arch/parisc/include/uapi/asm/signal.h
> +++ b/arch/parisc/include/uapi/asm/signal.h
> @@ -69,14 +69,7 @@
>  #define MINSIGSTKSZ    2048
>  #define SIGSTKSZ       8192
>
> -
> -#define SIG_BLOCK          0   /* for blocking signals */
> -#define SIG_UNBLOCK        1   /* for unblocking signals */
> -#define SIG_SETMASK        2   /* for setting the signal mask */
> -
> -#define SIG_DFL        ((__sighandler_t)0)     /* default signal handling */
> -#define SIG_IGN        ((__sighandler_t)1)     /* ignore signal */
> -#define SIG_ERR        ((__sighandler_t)-1)    /* error return from signal */
> +#include <asm-generic/signal-defs.h>
>
>  # ifndef __ASSEMBLY__
>
> @@ -85,10 +78,6 @@
>  /* Avoid too many header ordering problems.  */
>  struct siginfo;
>
> -/* Type of a signal handler.  */
> -typedef void __signalfn_t(int);
> -typedef __signalfn_t __user *__sighandler_t;
> -
>  typedef struct sigaltstack {
>         void __user *ss_sp;
>         int ss_flags;
>
> Peter
>


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 2/7] arch: move SA_* definitions to generic headers
  2020-10-03  1:14       ` Peter Collingbourne
@ 2020-10-05 11:06         ` Dave Martin
  -1 siblings, 0 replies; 59+ messages in thread
From: Dave Martin @ 2020-10-05 11:06 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Linux ARM, Parisc List, Catalin Marinas, Kevin Brodsky,
	Oleg Nesterov, James E.J. Bottomley, Kostya Serebryany,
	Eric W. Biederman, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Will Deacon, Evgenii Stepanov,
	Richard Henderson

On Fri, Oct 02, 2020 at 06:14:01PM -0700, Peter Collingbourne wrote:
> On Tue, Sep 8, 2020 at 8:12 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Fri, Aug 21, 2020 at 10:10:12PM -0700, Peter Collingbourne wrote:
> > > Most architectures with the exception of alpha, mips, parisc and
> > > sparc use the same values for these flags. Move their definitions into
> > > asm-generic/signal-defs.h and allow the architectures with non-standard
> > > values to override them. Also, document the non-standard flag values
> > > in order to make it easier to add new generic flags in the future.
> > >
> > > Signed-off-by: Peter Collingbourne <pcc@google.com>
> >
> > While this looks reasonable, I've just realised that you strip the "U"
> > from some arches' definitions here.
> >
> > So, on powerpc and x86, this changes the type of flags other than
> > SA_RESETHAND from unsigned int to int.
> >
> > While I can't see this breaking any sensible use of these flags, there's
> > a chance that there is software relying on this distinction by
> > accident.
> 
> While it's true that it's technically possible that making these
> signed could change semantics, I'm having trouble seeing a realistic
> way in which software could be relying on this. Can you see one? I can
> think of cases like if the code does something like left shifts one of
> the flag bits into the sign bit (technically undefined behavior) and
> then right shifts it back (in C this would need to all be done in a
> single expression without storing to a variable; in C++ I suppose you
> could use auto to preserve the signedness in a variable's type). For
> example:
> 
> int x = (SA_NODEFER << 1) >> 1;
> 
> would give a different value to x if we made SA_NODEFER signed. But I
> wouldn't really expect software to be doing this sort of thing even
> accidentally, or much more than or'ing the flags together and
> assigning them to a variable, or passing them as a parameter, or some
> other operation which would fix the type.

I couldn't come up with a very good, non-contrived example I admit.

> I believe that the kernel's uapi guarantee applies at the binary
> level, not at the source level. If that were not the case, I think we
> would not be allowed to add any new declaration to an existing .h file
> for fear of conflicting with a user program's identically spelled
> declaration. And that seems more likely to me than software that would
> do this sort of thing.

The behaviour of source code making legitimate use of the kernel headers
still shouldn't be changed without good reason, especially if the change
could lead to subtle bugs that the compiler won't detect.

However this doesn't mean that decrufting unintentional inconsistencies
in the headers is a bad idea ... and see my response below.

> > I wonder whether it's worth doing something like
> >
> >         #ifdef ARCH_WANT_STRICTLY_UNSIGNED_SA_FLAGS
> >         #define __SA_FLAG_VAL(x) x ## U
> >         #else
> >         #define __SA_FLAG_VAL(x) x
> >         #endif
> >
> >         #ifndef SA_NOCLDSTOP
> >         #define SA_NOCLDSTOP __SA_FLAG_VAL(0x00000001)
> >         #endif
> >
> >         /* ... */
> 
> If we do this I would mildly prefer to keep the existing #defines in
> the arch-specific headers as if the arch had different flag values, as
> this would leave the arch-specific legacy cruft in the arch-specific
> headers where it belongs.
> 
> > Mind you, the historical situation also has issues, e.g. because
> > sa_flags in struct sigaction is an int, assigning
> >
> >         struct sigaction sa;
> >
> >         sa.sa_flags = SA_RESETHAND;
> >
> > implies an overflow and so isn't portably safe (at least in theory).  I
> > guess we are getting away with it today.  Preserving the situation by
> > keeping the "U"s where appropriate would at least avoid making the
> > situation worse.
> 
> I believe that the result of this assignment (involving an unsigned to
> signed conversion) is implementation defined and not undefined (which
> would be problematic). And in all the implementations that matter, as
> well as the C++ standard starting with C++20, this is a no-op cast
> assuming two's complement. I'm not sure what this has to do with
> making the constants signed because, as you pointed out, SA_RESETHAND
> would remain unsigned despite the absence of 'U' because its value
> does not fit in an int.


I generally agree with your analysis here, and yes, the de facto langue
does define the behaviour for signed integer overflow in practice, even
if the C standards demur on this issue.


I actually got my argument a little backwards: the problem here is not
that SA_RESETHAND unexpectedly becomes a (negative) int, but that the
other values become ints: but those nonetheless remain positive because
they aren't big enough to alias the sign bit.

So the main way for things to go wrong seems to be if the values are
shifted up, as you observe.  But (a) that is a strange thing to do, and
(b) there is an obvious need for a cast if doing things like:

#define ENCODE_SIGNAL(int sig, int flags) ((u64)(flags) << 8 | (sig))

Code lacking the cast would already be wrong, since SA_RESETHAND etc.
would simply get shifted off.


I think it's worth drawing attention to the issue in the commit message,
but if nobody else objects then I guess I am not too concerned about the
change.

Cheers
---Dave

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 2/7] arch: move SA_* definitions to generic headers
@ 2020-10-05 11:06         ` Dave Martin
  0 siblings, 0 replies; 59+ messages in thread
From: Dave Martin @ 2020-10-05 11:06 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Parisc List, Catalin Marinas, Kevin Brodsky, Oleg Nesterov,
	Evgenii Stepanov, James E.J. Bottomley, Kostya Serebryany,
	Eric W. Biederman, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Will Deacon, Linux ARM, Richard Henderson

On Fri, Oct 02, 2020 at 06:14:01PM -0700, Peter Collingbourne wrote:
> On Tue, Sep 8, 2020 at 8:12 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Fri, Aug 21, 2020 at 10:10:12PM -0700, Peter Collingbourne wrote:
> > > Most architectures with the exception of alpha, mips, parisc and
> > > sparc use the same values for these flags. Move their definitions into
> > > asm-generic/signal-defs.h and allow the architectures with non-standard
> > > values to override them. Also, document the non-standard flag values
> > > in order to make it easier to add new generic flags in the future.
> > >
> > > Signed-off-by: Peter Collingbourne <pcc@google.com>
> >
> > While this looks reasonable, I've just realised that you strip the "U"
> > from some arches' definitions here.
> >
> > So, on powerpc and x86, this changes the type of flags other than
> > SA_RESETHAND from unsigned int to int.
> >
> > While I can't see this breaking any sensible use of these flags, there's
> > a chance that there is software relying on this distinction by
> > accident.
> 
> While it's true that it's technically possible that making these
> signed could change semantics, I'm having trouble seeing a realistic
> way in which software could be relying on this. Can you see one? I can
> think of cases like if the code does something like left shifts one of
> the flag bits into the sign bit (technically undefined behavior) and
> then right shifts it back (in C this would need to all be done in a
> single expression without storing to a variable; in C++ I suppose you
> could use auto to preserve the signedness in a variable's type). For
> example:
> 
> int x = (SA_NODEFER << 1) >> 1;
> 
> would give a different value to x if we made SA_NODEFER signed. But I
> wouldn't really expect software to be doing this sort of thing even
> accidentally, or much more than or'ing the flags together and
> assigning them to a variable, or passing them as a parameter, or some
> other operation which would fix the type.

I couldn't come up with a very good, non-contrived example I admit.

> I believe that the kernel's uapi guarantee applies at the binary
> level, not at the source level. If that were not the case, I think we
> would not be allowed to add any new declaration to an existing .h file
> for fear of conflicting with a user program's identically spelled
> declaration. And that seems more likely to me than software that would
> do this sort of thing.

The behaviour of source code making legitimate use of the kernel headers
still shouldn't be changed without good reason, especially if the change
could lead to subtle bugs that the compiler won't detect.

However this doesn't mean that decrufting unintentional inconsistencies
in the headers is a bad idea ... and see my response below.

> > I wonder whether it's worth doing something like
> >
> >         #ifdef ARCH_WANT_STRICTLY_UNSIGNED_SA_FLAGS
> >         #define __SA_FLAG_VAL(x) x ## U
> >         #else
> >         #define __SA_FLAG_VAL(x) x
> >         #endif
> >
> >         #ifndef SA_NOCLDSTOP
> >         #define SA_NOCLDSTOP __SA_FLAG_VAL(0x00000001)
> >         #endif
> >
> >         /* ... */
> 
> If we do this I would mildly prefer to keep the existing #defines in
> the arch-specific headers as if the arch had different flag values, as
> this would leave the arch-specific legacy cruft in the arch-specific
> headers where it belongs.
> 
> > Mind you, the historical situation also has issues, e.g. because
> > sa_flags in struct sigaction is an int, assigning
> >
> >         struct sigaction sa;
> >
> >         sa.sa_flags = SA_RESETHAND;
> >
> > implies an overflow and so isn't portably safe (at least in theory).  I
> > guess we are getting away with it today.  Preserving the situation by
> > keeping the "U"s where appropriate would at least avoid making the
> > situation worse.
> 
> I believe that the result of this assignment (involving an unsigned to
> signed conversion) is implementation defined and not undefined (which
> would be problematic). And in all the implementations that matter, as
> well as the C++ standard starting with C++20, this is a no-op cast
> assuming two's complement. I'm not sure what this has to do with
> making the constants signed because, as you pointed out, SA_RESETHAND
> would remain unsigned despite the absence of 'U' because its value
> does not fit in an int.


I generally agree with your analysis here, and yes, the de facto langue
does define the behaviour for signed integer overflow in practice, even
if the C standards demur on this issue.


I actually got my argument a little backwards: the problem here is not
that SA_RESETHAND unexpectedly becomes a (negative) int, but that the
other values become ints: but those nonetheless remain positive because
they aren't big enough to alias the sign bit.

So the main way for things to go wrong seems to be if the values are
shifted up, as you observe.  But (a) that is a strange thing to do, and
(b) there is an obvious need for a cast if doing things like:

#define ENCODE_SIGNAL(int sig, int flags) ((u64)(flags) << 8 | (sig))

Code lacking the cast would already be wrong, since SA_RESETHAND etc.
would simply get shifted off.


I think it's worth drawing attention to the issue in the commit message,
but if nobody else objects then I guess I am not too concerned about the
change.

Cheers
---Dave

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 5/7] signal: deduplicate code dealing with common _sigfault fields
  2020-09-08 15:13     ` Dave Martin
@ 2020-10-06  5:07       ` Peter Collingbourne
  -1 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-10-06  5:07 UTC (permalink / raw)
  To: Dave Martin
  Cc: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Will Deacon, Oleg Nesterov, Eric W. Biederman,
	James E.J. Bottomley, Parisc List, Andrey Konovalov,
	Kevin Brodsky, David Spickett, Linux ARM, Richard Henderson

On Tue, Sep 8, 2020 at 8:13 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Fri, Aug 21, 2020 at 10:10:15PM -0700, Peter Collingbourne wrote:
> > We're about to add more common _sigfault fields, so deduplicate the
> > existing code for initializing _sigfault fields in {send,force}_sig_*,
> > and for copying _sigfault fields in copy_siginfo_to_external32 and
> > post_copy_siginfo_from_user32, to reduce the number of places that
> > will need to be updated by upcoming changes.
> >
> > Signed-off-by: Peter Collingbourne <pcc@google.com>
> > ---
> > View this change in Gerrit: https://linux-review.googlesource.com/q/I4f56174e1b7b2bf4a3c8139e6879cbfd52750a24
> >
> >  include/linux/signal.h |  13 ++++++
> >  kernel/signal.c        | 101 ++++++++++++++++-------------------------
> >  2 files changed, 53 insertions(+), 61 deletions(-)
> >
> > diff --git a/include/linux/signal.h b/include/linux/signal.h
> > index 6bb1a3f0258c..3edbf54493ee 100644
> > --- a/include/linux/signal.h
> > +++ b/include/linux/signal.h
> > @@ -50,6 +50,19 @@ enum siginfo_layout {
> >
> >  enum siginfo_layout siginfo_layout(unsigned sig, int si_code);
> >
> > +static inline bool siginfo_layout_is_fault(enum siginfo_layout layout)
> > +{
> > +     switch (layout) {
> > +     case SIL_FAULT:
> > +     case SIL_FAULT_MCEERR:
> > +     case SIL_FAULT_BNDERR:
> > +     case SIL_FAULT_PKUERR:
> > +             return true;
> > +     default:
> > +             return false;
> > +     }
> > +}
> > +
> >  /*
> >   * Define some primitives to manipulate sigset_t.
> >   */
> > diff --git a/kernel/signal.c b/kernel/signal.c
> > index c80e70bde11d..4ee9dc03f20f 100644
> > --- a/kernel/signal.c
> > +++ b/kernel/signal.c
> > @@ -1649,6 +1649,15 @@ void force_sigsegv(int sig)
> >       force_sig(SIGSEGV);
> >  }
> >
> > +static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
> > +                                    int code, void __user *addr)
> > +{
> > +     info->si_signo = sig;
> > +     info->si_errno = 0;
> > +     info->si_code = code;
> > +     info->si_addr = addr;
> > +}
> > +
> >  int force_sig_fault_to_task(int sig, int code, void __user *addr
> >       ___ARCH_SI_TRAPNO(int trapno)
> >       ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
> > @@ -1657,10 +1666,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
> >       struct kernel_siginfo info;
> >
> >       clear_siginfo(&info);
> > -     info.si_signo = sig;
> > -     info.si_errno = 0;
> > -     info.si_code  = code;
> > -     info.si_addr  = addr;
> > +     set_sigfault_common_fields(&info, sig, code, addr);
> >  #ifdef __ARCH_SI_TRAPNO
> >       info.si_trapno = trapno;
> >  #endif
> > @@ -1689,10 +1695,7 @@ int send_sig_fault(int sig, int code, void __user *addr
> >       struct kernel_siginfo info;
> >
> >       clear_siginfo(&info);
> > -     info.si_signo = sig;
> > -     info.si_errno = 0;
> > -     info.si_code  = code;
> > -     info.si_addr  = addr;
> > +     set_sigfault_common_fields(&info, sig, code, addr);
> >  #ifdef __ARCH_SI_TRAPNO
> >       info.si_trapno = trapno;
> >  #endif
> > @@ -1710,10 +1713,7 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
> >
> >       WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
> >       clear_siginfo(&info);
> > -     info.si_signo = SIGBUS;
> > -     info.si_errno = 0;
> > -     info.si_code = code;
> > -     info.si_addr = addr;
> > +     set_sigfault_common_fields(&info, SIGBUS, code, addr);
> >       info.si_addr_lsb = lsb;
> >       return force_sig_info(&info);
> >  }
> > @@ -1724,10 +1724,7 @@ int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *
> >
> >       WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
> >       clear_siginfo(&info);
> > -     info.si_signo = SIGBUS;
> > -     info.si_errno = 0;
> > -     info.si_code = code;
> > -     info.si_addr = addr;
> > +     set_sigfault_common_fields(&info, SIGBUS, code, addr);
> >       info.si_addr_lsb = lsb;
> >       return send_sig_info(info.si_signo, &info, t);
> >  }
> > @@ -1738,10 +1735,7 @@ int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
> >       struct kernel_siginfo info;
> >
> >       clear_siginfo(&info);
> > -     info.si_signo = SIGSEGV;
> > -     info.si_errno = 0;
> > -     info.si_code  = SEGV_BNDERR;
> > -     info.si_addr  = addr;
> > +     set_sigfault_common_fields(&info, SIGSEGV, SEGV_BNDERR, addr);
> >       info.si_lower = lower;
> >       info.si_upper = upper;
> >       return force_sig_info(&info);
> > @@ -1753,10 +1747,7 @@ int force_sig_pkuerr(void __user *addr, u32 pkey)
> >       struct kernel_siginfo info;
> >
> >       clear_siginfo(&info);
> > -     info.si_signo = SIGSEGV;
> > -     info.si_errno = 0;
> > -     info.si_code  = SEGV_PKUERR;
> > -     info.si_addr  = addr;
> > +     set_sigfault_common_fields(&info, SIGSEGV, SEGV_PKUERR, addr);
> >       info.si_pkey  = pkey;
> >       return force_sig_info(&info);
> >  }
> > @@ -1770,10 +1761,8 @@ int force_sig_ptrace_errno_trap(int errno, void __user *addr)
> >       struct kernel_siginfo info;
> >
> >       clear_siginfo(&info);
> > -     info.si_signo = SIGTRAP;
> > +     set_sigfault_common_fields(&info, SIGTRAP, TRAP_HWBKPT, addr);
> >       info.si_errno = errno;
> > -     info.si_code  = TRAP_HWBKPT;
> > -     info.si_addr  = addr;
> >       return force_sig_info(&info);
> >  }
> >
> > @@ -3266,12 +3255,23 @@ int copy_siginfo_from_user(kernel_siginfo_t *to, const siginfo_t __user *from)
> >  void copy_siginfo_to_external32(struct compat_siginfo *to,
> >               const struct kernel_siginfo *from)
> >  {
> > +     enum siginfo_layout layout =
> > +             siginfo_layout(from->si_signo, from->si_code);
> > +
> >       memset(to, 0, sizeof(*to));
> >
> >       to->si_signo = from->si_signo;
> >       to->si_errno = from->si_errno;
> >       to->si_code  = from->si_code;
> > -     switch(siginfo_layout(from->si_signo, from->si_code)) {
> > +
> > +     if (siginfo_layout_is_fault(layout)) {
> > +             to->si_addr = ptr_to_compat(from->si_addr);
> > +#ifdef __ARCH_SI_TRAPNO
> > +             to->si_trapno = from->si_trapno;
> > +#endif
> > +     }
> > +
> > +     switch (layout) {
>
> I find the code flow slightly awkward with this change, because the
> fault signal fields are populated partly in the if() above and partly
> in the switch().  Previously, only the universal stuff was done outside.
>
> Would this be easier on future maintainers if we pulled the common
> stuff out into a helper and then called it from the appropriate switch
> cases?  The compiler will probably output some duplicated code in that
> case (depending on how clever it is at undoing the duplication), but
> the amount of affected code is small.

I'm not sure about that. One advantage of the current code structure
is that we end up with siginfo_layout_is_fault containing our single
canonical list of layouts that use the sigfault union member. With
your proposed code structure, the only caller of
siginfo_layout_is_fault would be the code that the next patch adds to
kernel/ptrace.c, which needs to know which layouts use sigfault so
that it can clear si_xflags, and that could relatively easily get out
of sync by accident since it's dealing with a less common case.

That being said, perhaps we could say that a caller of
ptrace(PTRACE_SETSIGINFO) is by definition old, so it wouldn't be
using that API to send signals with new siginfo layouts. That would
preclude a client from upgrading its knowledge of si_xflags
independently of its knowledge of new layouts though, and there would
be nothing preventing a new caller of siginfo_layout_is_fault being
added that would be exposed to new user code.

Peter

> >       case SIL_KILL:
> >               to->si_pid = from->si_pid;
> >               to->si_uid = from->si_uid;
> > @@ -3286,31 +3286,15 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
> >               to->si_fd   = from->si_fd;
> >               break;
> >       case SIL_FAULT:
> > -             to->si_addr = ptr_to_compat(from->si_addr);
> > -#ifdef __ARCH_SI_TRAPNO
> > -             to->si_trapno = from->si_trapno;
> > -#endif
> >               break;
> >       case SIL_FAULT_MCEERR:
> > -             to->si_addr = ptr_to_compat(from->si_addr);
> > -#ifdef __ARCH_SI_TRAPNO
> > -             to->si_trapno = from->si_trapno;
> > -#endif
> >               to->si_addr_lsb = from->si_addr_lsb;
> >               break;
> >       case SIL_FAULT_BNDERR:
> > -             to->si_addr = ptr_to_compat(from->si_addr);
> > -#ifdef __ARCH_SI_TRAPNO
> > -             to->si_trapno = from->si_trapno;
> > -#endif
> >               to->si_lower = ptr_to_compat(from->si_lower);
> >               to->si_upper = ptr_to_compat(from->si_upper);
> >               break;
> >       case SIL_FAULT_PKUERR:
> > -             to->si_addr = ptr_to_compat(from->si_addr);
> > -#ifdef __ARCH_SI_TRAPNO
> > -             to->si_trapno = from->si_trapno;
> > -#endif
> >               to->si_pkey = from->si_pkey;
> >               break;
> >       case SIL_CHLD:
> > @@ -3347,11 +3331,22 @@ int __copy_siginfo_to_user32(struct compat_siginfo __user *to,
> >  static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> >                                        const struct compat_siginfo *from)
> >  {
> > +     enum siginfo_layout layout =
> > +             siginfo_layout(from->si_signo, from->si_code);
> > +
> >       clear_siginfo(to);
> >       to->si_signo = from->si_signo;
> >       to->si_errno = from->si_errno;
> >       to->si_code  = from->si_code;
> > -     switch(siginfo_layout(from->si_signo, from->si_code)) {
> > +
> > +     if (siginfo_layout_is_fault(layout)) {
> > +             to->si_addr = compat_ptr(from->si_addr);
> > +#ifdef __ARCH_SI_TRAPNO
> > +             to->si_trapno = from->si_trapno;
> > +#endif
> > +     }
> > +
> > +     switch (layout) {
>
> Same comment as for copy_siginfo_to_external32()?
>
> [...]
>
> Otherwise, looks reasonable.
>
> Cheers
> ---Dave

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 5/7] signal: deduplicate code dealing with common _sigfault fields
@ 2020-10-06  5:07       ` Peter Collingbourne
  0 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-10-06  5:07 UTC (permalink / raw)
  To: Dave Martin
  Cc: Linux ARM, Parisc List, Catalin Marinas, Kevin Brodsky,
	Oleg Nesterov, James E.J. Bottomley, Kostya Serebryany,
	Eric W. Biederman, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Will Deacon, Evgenii Stepanov,
	Richard Henderson

On Tue, Sep 8, 2020 at 8:13 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Fri, Aug 21, 2020 at 10:10:15PM -0700, Peter Collingbourne wrote:
> > We're about to add more common _sigfault fields, so deduplicate the
> > existing code for initializing _sigfault fields in {send,force}_sig_*,
> > and for copying _sigfault fields in copy_siginfo_to_external32 and
> > post_copy_siginfo_from_user32, to reduce the number of places that
> > will need to be updated by upcoming changes.
> >
> > Signed-off-by: Peter Collingbourne <pcc@google.com>
> > ---
> > View this change in Gerrit: https://linux-review.googlesource.com/q/I4f56174e1b7b2bf4a3c8139e6879cbfd52750a24
> >
> >  include/linux/signal.h |  13 ++++++
> >  kernel/signal.c        | 101 ++++++++++++++++-------------------------
> >  2 files changed, 53 insertions(+), 61 deletions(-)
> >
> > diff --git a/include/linux/signal.h b/include/linux/signal.h
> > index 6bb1a3f0258c..3edbf54493ee 100644
> > --- a/include/linux/signal.h
> > +++ b/include/linux/signal.h
> > @@ -50,6 +50,19 @@ enum siginfo_layout {
> >
> >  enum siginfo_layout siginfo_layout(unsigned sig, int si_code);
> >
> > +static inline bool siginfo_layout_is_fault(enum siginfo_layout layout)
> > +{
> > +     switch (layout) {
> > +     case SIL_FAULT:
> > +     case SIL_FAULT_MCEERR:
> > +     case SIL_FAULT_BNDERR:
> > +     case SIL_FAULT_PKUERR:
> > +             return true;
> > +     default:
> > +             return false;
> > +     }
> > +}
> > +
> >  /*
> >   * Define some primitives to manipulate sigset_t.
> >   */
> > diff --git a/kernel/signal.c b/kernel/signal.c
> > index c80e70bde11d..4ee9dc03f20f 100644
> > --- a/kernel/signal.c
> > +++ b/kernel/signal.c
> > @@ -1649,6 +1649,15 @@ void force_sigsegv(int sig)
> >       force_sig(SIGSEGV);
> >  }
> >
> > +static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
> > +                                    int code, void __user *addr)
> > +{
> > +     info->si_signo = sig;
> > +     info->si_errno = 0;
> > +     info->si_code = code;
> > +     info->si_addr = addr;
> > +}
> > +
> >  int force_sig_fault_to_task(int sig, int code, void __user *addr
> >       ___ARCH_SI_TRAPNO(int trapno)
> >       ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
> > @@ -1657,10 +1666,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
> >       struct kernel_siginfo info;
> >
> >       clear_siginfo(&info);
> > -     info.si_signo = sig;
> > -     info.si_errno = 0;
> > -     info.si_code  = code;
> > -     info.si_addr  = addr;
> > +     set_sigfault_common_fields(&info, sig, code, addr);
> >  #ifdef __ARCH_SI_TRAPNO
> >       info.si_trapno = trapno;
> >  #endif
> > @@ -1689,10 +1695,7 @@ int send_sig_fault(int sig, int code, void __user *addr
> >       struct kernel_siginfo info;
> >
> >       clear_siginfo(&info);
> > -     info.si_signo = sig;
> > -     info.si_errno = 0;
> > -     info.si_code  = code;
> > -     info.si_addr  = addr;
> > +     set_sigfault_common_fields(&info, sig, code, addr);
> >  #ifdef __ARCH_SI_TRAPNO
> >       info.si_trapno = trapno;
> >  #endif
> > @@ -1710,10 +1713,7 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
> >
> >       WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
> >       clear_siginfo(&info);
> > -     info.si_signo = SIGBUS;
> > -     info.si_errno = 0;
> > -     info.si_code = code;
> > -     info.si_addr = addr;
> > +     set_sigfault_common_fields(&info, SIGBUS, code, addr);
> >       info.si_addr_lsb = lsb;
> >       return force_sig_info(&info);
> >  }
> > @@ -1724,10 +1724,7 @@ int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *
> >
> >       WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
> >       clear_siginfo(&info);
> > -     info.si_signo = SIGBUS;
> > -     info.si_errno = 0;
> > -     info.si_code = code;
> > -     info.si_addr = addr;
> > +     set_sigfault_common_fields(&info, SIGBUS, code, addr);
> >       info.si_addr_lsb = lsb;
> >       return send_sig_info(info.si_signo, &info, t);
> >  }
> > @@ -1738,10 +1735,7 @@ int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
> >       struct kernel_siginfo info;
> >
> >       clear_siginfo(&info);
> > -     info.si_signo = SIGSEGV;
> > -     info.si_errno = 0;
> > -     info.si_code  = SEGV_BNDERR;
> > -     info.si_addr  = addr;
> > +     set_sigfault_common_fields(&info, SIGSEGV, SEGV_BNDERR, addr);
> >       info.si_lower = lower;
> >       info.si_upper = upper;
> >       return force_sig_info(&info);
> > @@ -1753,10 +1747,7 @@ int force_sig_pkuerr(void __user *addr, u32 pkey)
> >       struct kernel_siginfo info;
> >
> >       clear_siginfo(&info);
> > -     info.si_signo = SIGSEGV;
> > -     info.si_errno = 0;
> > -     info.si_code  = SEGV_PKUERR;
> > -     info.si_addr  = addr;
> > +     set_sigfault_common_fields(&info, SIGSEGV, SEGV_PKUERR, addr);
> >       info.si_pkey  = pkey;
> >       return force_sig_info(&info);
> >  }
> > @@ -1770,10 +1761,8 @@ int force_sig_ptrace_errno_trap(int errno, void __user *addr)
> >       struct kernel_siginfo info;
> >
> >       clear_siginfo(&info);
> > -     info.si_signo = SIGTRAP;
> > +     set_sigfault_common_fields(&info, SIGTRAP, TRAP_HWBKPT, addr);
> >       info.si_errno = errno;
> > -     info.si_code  = TRAP_HWBKPT;
> > -     info.si_addr  = addr;
> >       return force_sig_info(&info);
> >  }
> >
> > @@ -3266,12 +3255,23 @@ int copy_siginfo_from_user(kernel_siginfo_t *to, const siginfo_t __user *from)
> >  void copy_siginfo_to_external32(struct compat_siginfo *to,
> >               const struct kernel_siginfo *from)
> >  {
> > +     enum siginfo_layout layout =
> > +             siginfo_layout(from->si_signo, from->si_code);
> > +
> >       memset(to, 0, sizeof(*to));
> >
> >       to->si_signo = from->si_signo;
> >       to->si_errno = from->si_errno;
> >       to->si_code  = from->si_code;
> > -     switch(siginfo_layout(from->si_signo, from->si_code)) {
> > +
> > +     if (siginfo_layout_is_fault(layout)) {
> > +             to->si_addr = ptr_to_compat(from->si_addr);
> > +#ifdef __ARCH_SI_TRAPNO
> > +             to->si_trapno = from->si_trapno;
> > +#endif
> > +     }
> > +
> > +     switch (layout) {
>
> I find the code flow slightly awkward with this change, because the
> fault signal fields are populated partly in the if() above and partly
> in the switch().  Previously, only the universal stuff was done outside.
>
> Would this be easier on future maintainers if we pulled the common
> stuff out into a helper and then called it from the appropriate switch
> cases?  The compiler will probably output some duplicated code in that
> case (depending on how clever it is at undoing the duplication), but
> the amount of affected code is small.

I'm not sure about that. One advantage of the current code structure
is that we end up with siginfo_layout_is_fault containing our single
canonical list of layouts that use the sigfault union member. With
your proposed code structure, the only caller of
siginfo_layout_is_fault would be the code that the next patch adds to
kernel/ptrace.c, which needs to know which layouts use sigfault so
that it can clear si_xflags, and that could relatively easily get out
of sync by accident since it's dealing with a less common case.

That being said, perhaps we could say that a caller of
ptrace(PTRACE_SETSIGINFO) is by definition old, so it wouldn't be
using that API to send signals with new siginfo layouts. That would
preclude a client from upgrading its knowledge of si_xflags
independently of its knowledge of new layouts though, and there would
be nothing preventing a new caller of siginfo_layout_is_fault being
added that would be exposed to new user code.

Peter

> >       case SIL_KILL:
> >               to->si_pid = from->si_pid;
> >               to->si_uid = from->si_uid;
> > @@ -3286,31 +3286,15 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
> >               to->si_fd   = from->si_fd;
> >               break;
> >       case SIL_FAULT:
> > -             to->si_addr = ptr_to_compat(from->si_addr);
> > -#ifdef __ARCH_SI_TRAPNO
> > -             to->si_trapno = from->si_trapno;
> > -#endif
> >               break;
> >       case SIL_FAULT_MCEERR:
> > -             to->si_addr = ptr_to_compat(from->si_addr);
> > -#ifdef __ARCH_SI_TRAPNO
> > -             to->si_trapno = from->si_trapno;
> > -#endif
> >               to->si_addr_lsb = from->si_addr_lsb;
> >               break;
> >       case SIL_FAULT_BNDERR:
> > -             to->si_addr = ptr_to_compat(from->si_addr);
> > -#ifdef __ARCH_SI_TRAPNO
> > -             to->si_trapno = from->si_trapno;
> > -#endif
> >               to->si_lower = ptr_to_compat(from->si_lower);
> >               to->si_upper = ptr_to_compat(from->si_upper);
> >               break;
> >       case SIL_FAULT_PKUERR:
> > -             to->si_addr = ptr_to_compat(from->si_addr);
> > -#ifdef __ARCH_SI_TRAPNO
> > -             to->si_trapno = from->si_trapno;
> > -#endif
> >               to->si_pkey = from->si_pkey;
> >               break;
> >       case SIL_CHLD:
> > @@ -3347,11 +3331,22 @@ int __copy_siginfo_to_user32(struct compat_siginfo __user *to,
> >  static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> >                                        const struct compat_siginfo *from)
> >  {
> > +     enum siginfo_layout layout =
> > +             siginfo_layout(from->si_signo, from->si_code);
> > +
> >       clear_siginfo(to);
> >       to->si_signo = from->si_signo;
> >       to->si_errno = from->si_errno;
> >       to->si_code  = from->si_code;
> > -     switch(siginfo_layout(from->si_signo, from->si_code)) {
> > +
> > +     if (siginfo_layout_is_fault(layout)) {
> > +             to->si_addr = compat_ptr(from->si_addr);
> > +#ifdef __ARCH_SI_TRAPNO
> > +             to->si_trapno = from->si_trapno;
> > +#endif
> > +     }
> > +
> > +     switch (layout) {
>
> Same comment as for copy_siginfo_to_external32()?
>
> [...]
>
> Otherwise, looks reasonable.
>
> Cheers
> ---Dave

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 5/7] signal: deduplicate code dealing with common _sigfault fields
  2020-10-06  5:07       ` Peter Collingbourne
@ 2020-10-07  8:56         ` Dave Martin
  -1 siblings, 0 replies; 59+ messages in thread
From: Dave Martin @ 2020-10-07  8:56 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Linux ARM, Parisc List, Catalin Marinas, Kevin Brodsky,
	Oleg Nesterov, James E.J. Bottomley, Kostya Serebryany,
	Eric W. Biederman, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Will Deacon, Evgenii Stepanov,
	Richard Henderson

On Mon, Oct 05, 2020 at 10:07:01PM -0700, Peter Collingbourne wrote:
> On Tue, Sep 8, 2020 at 8:13 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Fri, Aug 21, 2020 at 10:10:15PM -0700, Peter Collingbourne wrote:
> > > We're about to add more common _sigfault fields, so deduplicate the
> > > existing code for initializing _sigfault fields in {send,force}_sig_*,
> > > and for copying _sigfault fields in copy_siginfo_to_external32 and
> > > post_copy_siginfo_from_user32, to reduce the number of places that
> > > will need to be updated by upcoming changes.
> > >
> > > Signed-off-by: Peter Collingbourne <pcc@google.com>
> > > ---
> > > View this change in Gerrit: https://linux-review.googlesource.com/q/I4f56174e1b7b2bf4a3c8139e6879cbfd52750a24
> > >
> > >  include/linux/signal.h |  13 ++++++
> > >  kernel/signal.c        | 101 ++++++++++++++++-------------------------
> > >  2 files changed, 53 insertions(+), 61 deletions(-)
> > >
> > > diff --git a/include/linux/signal.h b/include/linux/signal.h
> > > index 6bb1a3f0258c..3edbf54493ee 100644
> > > --- a/include/linux/signal.h
> > > +++ b/include/linux/signal.h
> > > @@ -50,6 +50,19 @@ enum siginfo_layout {
> > >
> > >  enum siginfo_layout siginfo_layout(unsigned sig, int si_code);
> > >
> > > +static inline bool siginfo_layout_is_fault(enum siginfo_layout layout)
> > > +{
> > > +     switch (layout) {
> > > +     case SIL_FAULT:
> > > +     case SIL_FAULT_MCEERR:
> > > +     case SIL_FAULT_BNDERR:
> > > +     case SIL_FAULT_PKUERR:
> > > +             return true;
> > > +     default:
> > > +             return false;
> > > +     }
> > > +}
> > > +
> > >  /*
> > >   * Define some primitives to manipulate sigset_t.
> > >   */
> > > diff --git a/kernel/signal.c b/kernel/signal.c
> > > index c80e70bde11d..4ee9dc03f20f 100644
> > > --- a/kernel/signal.c
> > > +++ b/kernel/signal.c
> > > @@ -1649,6 +1649,15 @@ void force_sigsegv(int sig)
> > >       force_sig(SIGSEGV);
> > >  }
> > >
> > > +static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
> > > +                                    int code, void __user *addr)
> > > +{
> > > +     info->si_signo = sig;
> > > +     info->si_errno = 0;
> > > +     info->si_code = code;
> > > +     info->si_addr = addr;
> > > +}
> > > +
> > >  int force_sig_fault_to_task(int sig, int code, void __user *addr
> > >       ___ARCH_SI_TRAPNO(int trapno)
> > >       ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
> > > @@ -1657,10 +1666,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
> > >       struct kernel_siginfo info;
> > >
> > >       clear_siginfo(&info);
> > > -     info.si_signo = sig;
> > > -     info.si_errno = 0;
> > > -     info.si_code  = code;
> > > -     info.si_addr  = addr;
> > > +     set_sigfault_common_fields(&info, sig, code, addr);
> > >  #ifdef __ARCH_SI_TRAPNO
> > >       info.si_trapno = trapno;
> > >  #endif
> > > @@ -1689,10 +1695,7 @@ int send_sig_fault(int sig, int code, void __user *addr
> > >       struct kernel_siginfo info;
> > >
> > >       clear_siginfo(&info);
> > > -     info.si_signo = sig;
> > > -     info.si_errno = 0;
> > > -     info.si_code  = code;
> > > -     info.si_addr  = addr;
> > > +     set_sigfault_common_fields(&info, sig, code, addr);
> > >  #ifdef __ARCH_SI_TRAPNO
> > >       info.si_trapno = trapno;
> > >  #endif
> > > @@ -1710,10 +1713,7 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
> > >
> > >       WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
> > >       clear_siginfo(&info);
> > > -     info.si_signo = SIGBUS;
> > > -     info.si_errno = 0;
> > > -     info.si_code = code;
> > > -     info.si_addr = addr;
> > > +     set_sigfault_common_fields(&info, SIGBUS, code, addr);
> > >       info.si_addr_lsb = lsb;
> > >       return force_sig_info(&info);
> > >  }
> > > @@ -1724,10 +1724,7 @@ int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *
> > >
> > >       WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
> > >       clear_siginfo(&info);
> > > -     info.si_signo = SIGBUS;
> > > -     info.si_errno = 0;
> > > -     info.si_code = code;
> > > -     info.si_addr = addr;
> > > +     set_sigfault_common_fields(&info, SIGBUS, code, addr);
> > >       info.si_addr_lsb = lsb;
> > >       return send_sig_info(info.si_signo, &info, t);
> > >  }
> > > @@ -1738,10 +1735,7 @@ int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
> > >       struct kernel_siginfo info;
> > >
> > >       clear_siginfo(&info);
> > > -     info.si_signo = SIGSEGV;
> > > -     info.si_errno = 0;
> > > -     info.si_code  = SEGV_BNDERR;
> > > -     info.si_addr  = addr;
> > > +     set_sigfault_common_fields(&info, SIGSEGV, SEGV_BNDERR, addr);
> > >       info.si_lower = lower;
> > >       info.si_upper = upper;
> > >       return force_sig_info(&info);
> > > @@ -1753,10 +1747,7 @@ int force_sig_pkuerr(void __user *addr, u32 pkey)
> > >       struct kernel_siginfo info;
> > >
> > >       clear_siginfo(&info);
> > > -     info.si_signo = SIGSEGV;
> > > -     info.si_errno = 0;
> > > -     info.si_code  = SEGV_PKUERR;
> > > -     info.si_addr  = addr;
> > > +     set_sigfault_common_fields(&info, SIGSEGV, SEGV_PKUERR, addr);
> > >       info.si_pkey  = pkey;
> > >       return force_sig_info(&info);
> > >  }
> > > @@ -1770,10 +1761,8 @@ int force_sig_ptrace_errno_trap(int errno, void __user *addr)
> > >       struct kernel_siginfo info;
> > >
> > >       clear_siginfo(&info);
> > > -     info.si_signo = SIGTRAP;
> > > +     set_sigfault_common_fields(&info, SIGTRAP, TRAP_HWBKPT, addr);
> > >       info.si_errno = errno;
> > > -     info.si_code  = TRAP_HWBKPT;
> > > -     info.si_addr  = addr;
> > >       return force_sig_info(&info);
> > >  }
> > >
> > > @@ -3266,12 +3255,23 @@ int copy_siginfo_from_user(kernel_siginfo_t *to, const siginfo_t __user *from)
> > >  void copy_siginfo_to_external32(struct compat_siginfo *to,
> > >               const struct kernel_siginfo *from)
> > >  {
> > > +     enum siginfo_layout layout =
> > > +             siginfo_layout(from->si_signo, from->si_code);
> > > +
> > >       memset(to, 0, sizeof(*to));
> > >
> > >       to->si_signo = from->si_signo;
> > >       to->si_errno = from->si_errno;
> > >       to->si_code  = from->si_code;
> > > -     switch(siginfo_layout(from->si_signo, from->si_code)) {
> > > +
> > > +     if (siginfo_layout_is_fault(layout)) {
> > > +             to->si_addr = ptr_to_compat(from->si_addr);
> > > +#ifdef __ARCH_SI_TRAPNO
> > > +             to->si_trapno = from->si_trapno;
> > > +#endif
> > > +     }
> > > +
> > > +     switch (layout) {
> >
> > I find the code flow slightly awkward with this change, because the
> > fault signal fields are populated partly in the if() above and partly
> > in the switch().  Previously, only the universal stuff was done outside.
> >
> > Would this be easier on future maintainers if we pulled the common
> > stuff out into a helper and then called it from the appropriate switch
> > cases?  The compiler will probably output some duplicated code in that
> > case (depending on how clever it is at undoing the duplication), but
> > the amount of affected code is small.
> 
> I'm not sure about that. One advantage of the current code structure
> is that we end up with siginfo_layout_is_fault containing our single
> canonical list of layouts that use the sigfault union member. With
> your proposed code structure, the only caller of
> siginfo_layout_is_fault would be the code that the next patch adds to
> kernel/ptrace.c, which needs to know which layouts use sigfault so
> that it can clear si_xflags, and that could relatively easily get out
> of sync by accident since it's dealing with a less common case.
> 
> That being said, perhaps we could say that a caller of
> ptrace(PTRACE_SETSIGINFO) is by definition old, so it wouldn't be
> using that API to send signals with new siginfo layouts. That would
> preclude a client from upgrading its knowledge of si_xflags
> independently of its knowledge of new layouts though, and there would
> be nothing preventing a new caller of siginfo_layout_is_fault being
> added that would be exposed to new user code.

OK, I guess I don't have a strong view on this for now.

I suppose that clear_siginfo() could be moved into
set_sigfault_common_fields() (perhaps warranting a rename to
init_sigfault() or similar).

But that's just one line per case, so probably not worth getting excited
about.  There is also some virtue in keeping the clear_siginfo()
explicit everywhere, so that people are reminded about the need for it.

Anyway, that's not essential.

[...]

Cheers
---Dave

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 5/7] signal: deduplicate code dealing with common _sigfault fields
@ 2020-10-07  8:56         ` Dave Martin
  0 siblings, 0 replies; 59+ messages in thread
From: Dave Martin @ 2020-10-07  8:56 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Parisc List, Catalin Marinas, Kevin Brodsky, Oleg Nesterov,
	Evgenii Stepanov, James E.J. Bottomley, Kostya Serebryany,
	Eric W. Biederman, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Will Deacon, Linux ARM, Richard Henderson

On Mon, Oct 05, 2020 at 10:07:01PM -0700, Peter Collingbourne wrote:
> On Tue, Sep 8, 2020 at 8:13 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Fri, Aug 21, 2020 at 10:10:15PM -0700, Peter Collingbourne wrote:
> > > We're about to add more common _sigfault fields, so deduplicate the
> > > existing code for initializing _sigfault fields in {send,force}_sig_*,
> > > and for copying _sigfault fields in copy_siginfo_to_external32 and
> > > post_copy_siginfo_from_user32, to reduce the number of places that
> > > will need to be updated by upcoming changes.
> > >
> > > Signed-off-by: Peter Collingbourne <pcc@google.com>
> > > ---
> > > View this change in Gerrit: https://linux-review.googlesource.com/q/I4f56174e1b7b2bf4a3c8139e6879cbfd52750a24
> > >
> > >  include/linux/signal.h |  13 ++++++
> > >  kernel/signal.c        | 101 ++++++++++++++++-------------------------
> > >  2 files changed, 53 insertions(+), 61 deletions(-)
> > >
> > > diff --git a/include/linux/signal.h b/include/linux/signal.h
> > > index 6bb1a3f0258c..3edbf54493ee 100644
> > > --- a/include/linux/signal.h
> > > +++ b/include/linux/signal.h
> > > @@ -50,6 +50,19 @@ enum siginfo_layout {
> > >
> > >  enum siginfo_layout siginfo_layout(unsigned sig, int si_code);
> > >
> > > +static inline bool siginfo_layout_is_fault(enum siginfo_layout layout)
> > > +{
> > > +     switch (layout) {
> > > +     case SIL_FAULT:
> > > +     case SIL_FAULT_MCEERR:
> > > +     case SIL_FAULT_BNDERR:
> > > +     case SIL_FAULT_PKUERR:
> > > +             return true;
> > > +     default:
> > > +             return false;
> > > +     }
> > > +}
> > > +
> > >  /*
> > >   * Define some primitives to manipulate sigset_t.
> > >   */
> > > diff --git a/kernel/signal.c b/kernel/signal.c
> > > index c80e70bde11d..4ee9dc03f20f 100644
> > > --- a/kernel/signal.c
> > > +++ b/kernel/signal.c
> > > @@ -1649,6 +1649,15 @@ void force_sigsegv(int sig)
> > >       force_sig(SIGSEGV);
> > >  }
> > >
> > > +static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
> > > +                                    int code, void __user *addr)
> > > +{
> > > +     info->si_signo = sig;
> > > +     info->si_errno = 0;
> > > +     info->si_code = code;
> > > +     info->si_addr = addr;
> > > +}
> > > +
> > >  int force_sig_fault_to_task(int sig, int code, void __user *addr
> > >       ___ARCH_SI_TRAPNO(int trapno)
> > >       ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
> > > @@ -1657,10 +1666,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
> > >       struct kernel_siginfo info;
> > >
> > >       clear_siginfo(&info);
> > > -     info.si_signo = sig;
> > > -     info.si_errno = 0;
> > > -     info.si_code  = code;
> > > -     info.si_addr  = addr;
> > > +     set_sigfault_common_fields(&info, sig, code, addr);
> > >  #ifdef __ARCH_SI_TRAPNO
> > >       info.si_trapno = trapno;
> > >  #endif
> > > @@ -1689,10 +1695,7 @@ int send_sig_fault(int sig, int code, void __user *addr
> > >       struct kernel_siginfo info;
> > >
> > >       clear_siginfo(&info);
> > > -     info.si_signo = sig;
> > > -     info.si_errno = 0;
> > > -     info.si_code  = code;
> > > -     info.si_addr  = addr;
> > > +     set_sigfault_common_fields(&info, sig, code, addr);
> > >  #ifdef __ARCH_SI_TRAPNO
> > >       info.si_trapno = trapno;
> > >  #endif
> > > @@ -1710,10 +1713,7 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
> > >
> > >       WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
> > >       clear_siginfo(&info);
> > > -     info.si_signo = SIGBUS;
> > > -     info.si_errno = 0;
> > > -     info.si_code = code;
> > > -     info.si_addr = addr;
> > > +     set_sigfault_common_fields(&info, SIGBUS, code, addr);
> > >       info.si_addr_lsb = lsb;
> > >       return force_sig_info(&info);
> > >  }
> > > @@ -1724,10 +1724,7 @@ int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *
> > >
> > >       WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
> > >       clear_siginfo(&info);
> > > -     info.si_signo = SIGBUS;
> > > -     info.si_errno = 0;
> > > -     info.si_code = code;
> > > -     info.si_addr = addr;
> > > +     set_sigfault_common_fields(&info, SIGBUS, code, addr);
> > >       info.si_addr_lsb = lsb;
> > >       return send_sig_info(info.si_signo, &info, t);
> > >  }
> > > @@ -1738,10 +1735,7 @@ int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
> > >       struct kernel_siginfo info;
> > >
> > >       clear_siginfo(&info);
> > > -     info.si_signo = SIGSEGV;
> > > -     info.si_errno = 0;
> > > -     info.si_code  = SEGV_BNDERR;
> > > -     info.si_addr  = addr;
> > > +     set_sigfault_common_fields(&info, SIGSEGV, SEGV_BNDERR, addr);
> > >       info.si_lower = lower;
> > >       info.si_upper = upper;
> > >       return force_sig_info(&info);
> > > @@ -1753,10 +1747,7 @@ int force_sig_pkuerr(void __user *addr, u32 pkey)
> > >       struct kernel_siginfo info;
> > >
> > >       clear_siginfo(&info);
> > > -     info.si_signo = SIGSEGV;
> > > -     info.si_errno = 0;
> > > -     info.si_code  = SEGV_PKUERR;
> > > -     info.si_addr  = addr;
> > > +     set_sigfault_common_fields(&info, SIGSEGV, SEGV_PKUERR, addr);
> > >       info.si_pkey  = pkey;
> > >       return force_sig_info(&info);
> > >  }
> > > @@ -1770,10 +1761,8 @@ int force_sig_ptrace_errno_trap(int errno, void __user *addr)
> > >       struct kernel_siginfo info;
> > >
> > >       clear_siginfo(&info);
> > > -     info.si_signo = SIGTRAP;
> > > +     set_sigfault_common_fields(&info, SIGTRAP, TRAP_HWBKPT, addr);
> > >       info.si_errno = errno;
> > > -     info.si_code  = TRAP_HWBKPT;
> > > -     info.si_addr  = addr;
> > >       return force_sig_info(&info);
> > >  }
> > >
> > > @@ -3266,12 +3255,23 @@ int copy_siginfo_from_user(kernel_siginfo_t *to, const siginfo_t __user *from)
> > >  void copy_siginfo_to_external32(struct compat_siginfo *to,
> > >               const struct kernel_siginfo *from)
> > >  {
> > > +     enum siginfo_layout layout =
> > > +             siginfo_layout(from->si_signo, from->si_code);
> > > +
> > >       memset(to, 0, sizeof(*to));
> > >
> > >       to->si_signo = from->si_signo;
> > >       to->si_errno = from->si_errno;
> > >       to->si_code  = from->si_code;
> > > -     switch(siginfo_layout(from->si_signo, from->si_code)) {
> > > +
> > > +     if (siginfo_layout_is_fault(layout)) {
> > > +             to->si_addr = ptr_to_compat(from->si_addr);
> > > +#ifdef __ARCH_SI_TRAPNO
> > > +             to->si_trapno = from->si_trapno;
> > > +#endif
> > > +     }
> > > +
> > > +     switch (layout) {
> >
> > I find the code flow slightly awkward with this change, because the
> > fault signal fields are populated partly in the if() above and partly
> > in the switch().  Previously, only the universal stuff was done outside.
> >
> > Would this be easier on future maintainers if we pulled the common
> > stuff out into a helper and then called it from the appropriate switch
> > cases?  The compiler will probably output some duplicated code in that
> > case (depending on how clever it is at undoing the duplication), but
> > the amount of affected code is small.
> 
> I'm not sure about that. One advantage of the current code structure
> is that we end up with siginfo_layout_is_fault containing our single
> canonical list of layouts that use the sigfault union member. With
> your proposed code structure, the only caller of
> siginfo_layout_is_fault would be the code that the next patch adds to
> kernel/ptrace.c, which needs to know which layouts use sigfault so
> that it can clear si_xflags, and that could relatively easily get out
> of sync by accident since it's dealing with a less common case.
> 
> That being said, perhaps we could say that a caller of
> ptrace(PTRACE_SETSIGINFO) is by definition old, so it wouldn't be
> using that API to send signals with new siginfo layouts. That would
> preclude a client from upgrading its knowledge of si_xflags
> independently of its knowledge of new layouts though, and there would
> be nothing preventing a new caller of siginfo_layout_is_fault being
> added that would be exposed to new user code.

OK, I guess I don't have a strong view on this for now.

I suppose that clear_siginfo() could be moved into
set_sigfault_common_fields() (perhaps warranting a rename to
init_sigfault() or similar).

But that's just one line per case, so probably not worth getting excited
about.  There is also some virtue in keeping the clear_siginfo()
explicit everywhere, so that people are reminded about the need for it.

Anyway, that's not essential.

[...]

Cheers
---Dave

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 6/7] signal: define the field siginfo.si_xflags
  2020-09-08 15:13     ` Dave Martin
@ 2020-10-08  2:11       ` Peter Collingbourne
  -1 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-10-08  2:11 UTC (permalink / raw)
  To: Dave Martin
  Cc: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Will Deacon, Oleg Nesterov, Eric W. Biederman,
	James E.J. Bottomley, Parisc List, Andrey Konovalov,
	Kevin Brodsky, David Spickett, Linux ARM, Richard Henderson

On Tue, Sep 8, 2020 at 8:13 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Fri, Aug 21, 2020 at 10:10:16PM -0700, Peter Collingbourne wrote:
>
> [ Add a new siginfo member sa_xflags, for fault signals. ]

Will fix.

> > This field will contain flags that may be used by signal handlers to
> > determine whether other fields in the _sigfault portion of siginfo are
> > valid. An example use case is the following patch, which introduces
> > the si_addr_ignored_bits{,_mask} fields.
> >
> > A new sigcontext flag, SA_XFLAGS, is introduced in order to allow
> > a signal handler to require the kernel to set the field (but note
> > that the field will be set anyway if the kernel supports the flag,
> > regardless of its value). In combination with the previous patches,
> > this allows a userspace program to determine whether the kernel will
> > set the field.
> >
> > It is possible for an si_xflags-unaware program to cause a signal
> > handler in an si_xflags-aware program to be called with a provided
> > siginfo data structure by using one of the following syscalls:
> >
> > - ptrace(PTRACE_SETSIGINFO)
> > - pidfd_send_signal
> > - rt_sigqueueinfo
> > - rt_tgsigqueueinfo
> >
> > So we need to prevent the si_xflags-unaware program from causing an
> > uninitialized read of si_xflags in the si_xflags-aware program when
> > it uses one of these syscalls.
> >
> > The last three cases can be handled by observing that each of these
> > syscalls fails if si_code >= 0, so we define si_xflags to only be
> > valid if si_code >= 0.
>
> I would say >.  0 is SI_USER, and the fact that those other interfaces
> reject SI_USER seems inconsistent or a bug.
>
> We can always relax the rule later.
>
> Since si_xflags only makes sense for "real" fault signals, it would
> never be applicable in combination with SI_USER.  Or am I missing
> something?
>
> Either way, I think this is just a documentation ossue in practice.

I think you're right. kill(2) and tgkill(2) set si_code to SI_USER, so
excluding SI_USER seems to be necessary to avoid an invalid read via
either of these syscalls. I will update the comment to say > 0.

> >
> > There is no such check on si_code in ptrace(PTRACE_SETSIGINFO), so
> > we make ptrace(PTRACE_SETSIGINFO) clear the si_xflags field if it
> > detects that the signal would use the _sigfault layout, and introduce
> > a new ptrace request type, PTRACE_SETSIGINFO2, that a si_xflags-aware
> > program may use to opt out of this behavior.
>
> Will we need to introduce PTRACE_SETSIGINFO3, 4 etc., every time a new
> field comes up?
>
> I wonder whether we should make this more flexible, say accepting some
> flags argument to say which fields the caller understands (and so
> doesn't want clobbered).  Maybe we can (ab)use the sa_flags bit
> definitions for indicating which extensions the caller understands.

I'd be okay with adding a flags argument here, to be passed via the
addr argument to PTRACE_SETSIGINFO2. (Confusingly, in some of the
ptrace request types including the ones that deal with siginfo "data"
is the argument that takes an address and "addr" is the one that takes
something else! My new request type will do the same to make things
consistently confusing.)

I guess we would only require a new "out of band" signaling mechanism
if we were adding a field to a different union member (presumably a
flags field to support the kind of future expansion that we anticipate
for sigfault), since for sigfault we may indicate presence of new
fields using si_xflags. Presumably such a field would come at the same
time as a new SA_* bit for detecting its presence, so I suppose that
we could use the sa_flags bits here as well. I'm not entirely
comfortable with that though because the other SA_* bits wouldn't make
sense to be passed as an argument here (and because of the
architecture dependence that made it so hard to find free SA_* bits to
add, we would be unnecessarily restricted in the number of bits that
we could easily add here), and in the future someone may come up with
a reason to pass a new flag here that wouldn't correspond to an SA_*
bit. So I would mildly prefer a new set of bit definitions.

It's unfortunate that the addr argument for PTRACE_SETSIGINFO was
specified to be ignored rather than causing an error for non-zero
values, as otherwise we could have used it as the flags argument to
the existing request type and avoided adding a new one. Of course,
this is the same issue that has caused us so much grief with
sigaction. But for the new request type we can do things properly and
require addr to have only recognized bits set.

> > It is also possible for the kernel to inject a signal specified to
> > use _sigfault by calling force_sig (e.g. there are numerous calls to
> > force_sig(SIGSEGV)). In this case si_code is set to SI_KERNEL and the
> > _kill union member is used, so document that si_code must be < SI_KERNEL.
>
> Ack.  I'm still wondering if some of those SIGSEGV/SI_KERNEL instances
> should be changed to one of the standard SIGSEGV codes, but either way,
> having si_xflags validity require si_code < SI_KERNEL seems appropriate.
>
>
> > Ideally this field could have just been named si_flags, but that
> > name was already taken by ia64, so a different name was chosen.
> >
> > Alternatively, we may consider making ia64's si_flags a generic field
> > and having it appear at the end of _sigfault (in the same place as
> > this patch has si_xflags) on non-ia64, keeping it in the same place
> > on ia64. ia64's si_flags is a 32-bit field with only one flag bit
> > allocated, so we would have 31 bits to use if we do this.
>
> Hmm, that might be an idea.
>
> It would mean that x86 would have different rules from other
> architectures regarding how to know when the field is valid, which might
> lull x86-first projects into a false sense of security.  Perhaps we could

ia64 is Itanium, not x86. And ia64 is almost dead (I heard that gcc
was planning to remove support some time next year [1], which I expect
would be followed soon after by dropping kernel support). So I
wouldn't expect there to be a lot of ia64-first projects out there.

[1] https://www.phoronix.com/scan.php?page=news_item&px=Intel-IA-64-GCC-Deprecation

> refuse to expose any of the arch-independent flags in si_flags unless
> explicitly requested via SA_XFLAGS, but that would be a departure from
> what this series implements today.
>
> So maybe it's simpler to keep the two fields separate, unless somebody
> objects.

Notwithstanding the above, I would be mildly in favor of keeping them
separate in order to avoid the complexity implied by entangling them,
since it's complex enough to add fields here as it is.

> >
> > Signed-off-by: Peter Collingbourne <pcc@google.com>
> > ---
> > View this change in Gerrit: https://linux-review.googlesource.com/q/Ide155ce29366c3eab2a944ae4c51205982e5b8b2
> >
> > v10:
> > - make the new field compatible with the various ways
> >   that a siginfo can be injected from another process
> > - eliminate some duplication by adding a refactoring patch
> >   before this one
> >
> >  arch/powerpc/platforms/powernv/vas-fault.c |  1 +
> >  arch/x86/kernel/signal_compat.c            |  4 +--
> >  include/linux/compat.h                     |  2 ++
> >  include/linux/signal_types.h               |  2 +-
> >  include/uapi/asm-generic/siginfo.h         |  4 +++
> >  include/uapi/asm-generic/signal-defs.h     |  4 +++
> >  include/uapi/linux/ptrace.h                |  2 ++
> >  kernel/ptrace.c                            | 29 ++++++++++++++++++++++
> >  kernel/signal.c                            |  3 +++
> >  9 files changed, 48 insertions(+), 3 deletions(-)
> >
> > diff --git a/arch/powerpc/platforms/powernv/vas-fault.c b/arch/powerpc/platforms/powernv/vas-fault.c
> > index 3d21fce254b7..3bbb335561f5 100644
> > --- a/arch/powerpc/platforms/powernv/vas-fault.c
> > +++ b/arch/powerpc/platforms/powernv/vas-fault.c
> > @@ -154,6 +154,7 @@ static void update_csb(struct vas_window *window,
> >       info.si_errno = EFAULT;
> >       info.si_code = SEGV_MAPERR;
> >       info.si_addr = csb_addr;
> > +     info.si_xflags = 0;
> >
> >       /*
> >        * process will be polling on csb.flags after request is sent to
> > diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
> > index c599013ae8cb..6b99f0c8a068 100644
> > --- a/arch/x86/kernel/signal_compat.c
> > +++ b/arch/x86/kernel/signal_compat.c
> > @@ -121,8 +121,8 @@ static inline void signal_compat_build_tests(void)
> >  #endif
> >
> >       CHECK_CSI_OFFSET(_sigfault);
> > -     CHECK_CSI_SIZE  (_sigfault, 4*sizeof(int));
> > -     CHECK_SI_SIZE   (_sigfault, 8*sizeof(int));
> > +     CHECK_CSI_SIZE  (_sigfault, 8*sizeof(int));
> > +     CHECK_SI_SIZE   (_sigfault, 16*sizeof(int));
>
> (Yuk, but at least you make this no worse.)
>
> >
> >       BUILD_BUG_ON(offsetof(siginfo_t, si_addr) != 0x10);
> >       BUILD_BUG_ON(offsetof(compat_siginfo_t, si_addr) != 0x0C);
> > diff --git a/include/linux/compat.h b/include/linux/compat.h
> > index d38c4d7e83bd..55d4228dfd88 100644
> > --- a/include/linux/compat.h
> > +++ b/include/linux/compat.h
> > @@ -231,7 +231,9 @@ typedef struct compat_siginfo {
> >                                       char _dummy_pkey[__COMPAT_ADDR_BND_PKEY_PAD];
> >                                       u32 _pkey;
> >                               } _addr_pkey;
> > +                             compat_uptr_t _pad[6];
> >                       };
> > +                     compat_uptr_t _xflags;
>
> Should we have the same type here for native and compat?
>
> I don't have a very strong opinion on this, but currently native on
> 64-bit arches will have 32 extra bits in _xflags that can never be used
> (or have to be defined differently for compat).

Good point. I will make this a u64 (although I think 32 bits will
probably be more than enough, the distance between si_xflags and
si_addr_ignored_bits will be 8 bytes on 64-bit architectures due to
alignment so we may as well make all of the bits available).

> >               } _sigfault;
> >
> >               /* SIGPOLL */
> > diff --git a/include/linux/signal_types.h b/include/linux/signal_types.h
> > index a7887ad84d36..75ca861d982a 100644
> > --- a/include/linux/signal_types.h
> > +++ b/include/linux/signal_types.h
> > @@ -78,6 +78,6 @@ struct ksignal {
> >
> >  #define UAPI_SA_FLAGS                                                          \
> >       (SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
> > -      SA_NODEFER | SA_RESETHAND | __ARCH_UAPI_SA_FLAGS)
> > +      SA_NODEFER | SA_RESETHAND | SA_XFLAGS | __ARCH_UAPI_SA_FLAGS)
> >
> >  #endif /* _LINUX_SIGNAL_TYPES_H */
> > diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
> > index cb3d6c267181..1fbd88d64f38 100644
> > --- a/include/uapi/asm-generic/siginfo.h
> > +++ b/include/uapi/asm-generic/siginfo.h
> > @@ -91,7 +91,9 @@ union __sifields {
> >                               char _dummy_pkey[__ADDR_BND_PKEY_PAD];
> >                               __u32 _pkey;
> >                       } _addr_pkey;
> > +                     void *_pad[6];
>
> 6?
>
> Obviously we'll need something here, but I'm curious as to where this
> value came from.
>
> (Same for compat.)

I think it came from Eric's suggestion in [1], i.e. 2 words from the
existing fields plus the 4 words of padding suggested by Eric.

[1] https://www.spinics.net/lists/arm-kernel/msg808618.html

> >               };
> > +             unsigned long _xflags;
> >       } _sigfault;
> >
> >       /* SIGPOLL */
> > @@ -152,6 +154,8 @@ typedef struct siginfo {
> >  #define si_trapno    _sifields._sigfault._trapno
> >  #endif
> >  #define si_addr_lsb  _sifields._sigfault._addr_lsb
> > +/* si_xflags is only valid if 0 <= si_code < SI_KERNEL */
> > +#define si_xflags    _sifields._sigfault._xflags
> >  #define si_lower     _sifields._sigfault._addr_bnd._lower
> >  #define si_upper     _sifields._sigfault._addr_bnd._upper
> >  #define si_pkey              _sifields._sigfault._addr_pkey._pkey
> > diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
> > index e853cbe8722d..bdbe1fe7a779 100644
> > --- a/include/uapi/asm-generic/signal-defs.h
> > +++ b/include/uapi/asm-generic/signal-defs.h
> > @@ -20,6 +20,9 @@
> >   * so this bit allows flag bit support to be detected from userspace while
> >   * allowing an old kernel to be distinguished from a kernel that supports every
> >   * flag bit.
> > + * SA_XFLAGS indicates that the signal handler requires the siginfo.si_xflags
> > + * field to be valid. Note that if the kernel supports SA_XFLAGS, the field will
>
> Maybe "valid for fault signals (SIGSEGV etc.)"

Will add.

> [...]
>
> Otherwise, this looks sensible overall to me.

Thanks for the review. (And apologies for being slow to respond to
your reviews. I got preempted by another task right after sending out
v10 and only now did I get a chance to get back to this.)

Peter

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 6/7] signal: define the field siginfo.si_xflags
@ 2020-10-08  2:11       ` Peter Collingbourne
  0 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-10-08  2:11 UTC (permalink / raw)
  To: Dave Martin
  Cc: Linux ARM, Parisc List, Catalin Marinas, Kevin Brodsky,
	Oleg Nesterov, James E.J. Bottomley, Kostya Serebryany,
	Eric W. Biederman, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Will Deacon, Evgenii Stepanov,
	Richard Henderson

On Tue, Sep 8, 2020 at 8:13 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Fri, Aug 21, 2020 at 10:10:16PM -0700, Peter Collingbourne wrote:
>
> [ Add a new siginfo member sa_xflags, for fault signals. ]

Will fix.

> > This field will contain flags that may be used by signal handlers to
> > determine whether other fields in the _sigfault portion of siginfo are
> > valid. An example use case is the following patch, which introduces
> > the si_addr_ignored_bits{,_mask} fields.
> >
> > A new sigcontext flag, SA_XFLAGS, is introduced in order to allow
> > a signal handler to require the kernel to set the field (but note
> > that the field will be set anyway if the kernel supports the flag,
> > regardless of its value). In combination with the previous patches,
> > this allows a userspace program to determine whether the kernel will
> > set the field.
> >
> > It is possible for an si_xflags-unaware program to cause a signal
> > handler in an si_xflags-aware program to be called with a provided
> > siginfo data structure by using one of the following syscalls:
> >
> > - ptrace(PTRACE_SETSIGINFO)
> > - pidfd_send_signal
> > - rt_sigqueueinfo
> > - rt_tgsigqueueinfo
> >
> > So we need to prevent the si_xflags-unaware program from causing an
> > uninitialized read of si_xflags in the si_xflags-aware program when
> > it uses one of these syscalls.
> >
> > The last three cases can be handled by observing that each of these
> > syscalls fails if si_code >= 0, so we define si_xflags to only be
> > valid if si_code >= 0.
>
> I would say >.  0 is SI_USER, and the fact that those other interfaces
> reject SI_USER seems inconsistent or a bug.
>
> We can always relax the rule later.
>
> Since si_xflags only makes sense for "real" fault signals, it would
> never be applicable in combination with SI_USER.  Or am I missing
> something?
>
> Either way, I think this is just a documentation ossue in practice.

I think you're right. kill(2) and tgkill(2) set si_code to SI_USER, so
excluding SI_USER seems to be necessary to avoid an invalid read via
either of these syscalls. I will update the comment to say > 0.

> >
> > There is no such check on si_code in ptrace(PTRACE_SETSIGINFO), so
> > we make ptrace(PTRACE_SETSIGINFO) clear the si_xflags field if it
> > detects that the signal would use the _sigfault layout, and introduce
> > a new ptrace request type, PTRACE_SETSIGINFO2, that a si_xflags-aware
> > program may use to opt out of this behavior.
>
> Will we need to introduce PTRACE_SETSIGINFO3, 4 etc., every time a new
> field comes up?
>
> I wonder whether we should make this more flexible, say accepting some
> flags argument to say which fields the caller understands (and so
> doesn't want clobbered).  Maybe we can (ab)use the sa_flags bit
> definitions for indicating which extensions the caller understands.

I'd be okay with adding a flags argument here, to be passed via the
addr argument to PTRACE_SETSIGINFO2. (Confusingly, in some of the
ptrace request types including the ones that deal with siginfo "data"
is the argument that takes an address and "addr" is the one that takes
something else! My new request type will do the same to make things
consistently confusing.)

I guess we would only require a new "out of band" signaling mechanism
if we were adding a field to a different union member (presumably a
flags field to support the kind of future expansion that we anticipate
for sigfault), since for sigfault we may indicate presence of new
fields using si_xflags. Presumably such a field would come at the same
time as a new SA_* bit for detecting its presence, so I suppose that
we could use the sa_flags bits here as well. I'm not entirely
comfortable with that though because the other SA_* bits wouldn't make
sense to be passed as an argument here (and because of the
architecture dependence that made it so hard to find free SA_* bits to
add, we would be unnecessarily restricted in the number of bits that
we could easily add here), and in the future someone may come up with
a reason to pass a new flag here that wouldn't correspond to an SA_*
bit. So I would mildly prefer a new set of bit definitions.

It's unfortunate that the addr argument for PTRACE_SETSIGINFO was
specified to be ignored rather than causing an error for non-zero
values, as otherwise we could have used it as the flags argument to
the existing request type and avoided adding a new one. Of course,
this is the same issue that has caused us so much grief with
sigaction. But for the new request type we can do things properly and
require addr to have only recognized bits set.

> > It is also possible for the kernel to inject a signal specified to
> > use _sigfault by calling force_sig (e.g. there are numerous calls to
> > force_sig(SIGSEGV)). In this case si_code is set to SI_KERNEL and the
> > _kill union member is used, so document that si_code must be < SI_KERNEL.
>
> Ack.  I'm still wondering if some of those SIGSEGV/SI_KERNEL instances
> should be changed to one of the standard SIGSEGV codes, but either way,
> having si_xflags validity require si_code < SI_KERNEL seems appropriate.
>
>
> > Ideally this field could have just been named si_flags, but that
> > name was already taken by ia64, so a different name was chosen.
> >
> > Alternatively, we may consider making ia64's si_flags a generic field
> > and having it appear at the end of _sigfault (in the same place as
> > this patch has si_xflags) on non-ia64, keeping it in the same place
> > on ia64. ia64's si_flags is a 32-bit field with only one flag bit
> > allocated, so we would have 31 bits to use if we do this.
>
> Hmm, that might be an idea.
>
> It would mean that x86 would have different rules from other
> architectures regarding how to know when the field is valid, which might
> lull x86-first projects into a false sense of security.  Perhaps we could

ia64 is Itanium, not x86. And ia64 is almost dead (I heard that gcc
was planning to remove support some time next year [1], which I expect
would be followed soon after by dropping kernel support). So I
wouldn't expect there to be a lot of ia64-first projects out there.

[1] https://www.phoronix.com/scan.php?page=news_item&px=Intel-IA-64-GCC-Deprecation

> refuse to expose any of the arch-independent flags in si_flags unless
> explicitly requested via SA_XFLAGS, but that would be a departure from
> what this series implements today.
>
> So maybe it's simpler to keep the two fields separate, unless somebody
> objects.

Notwithstanding the above, I would be mildly in favor of keeping them
separate in order to avoid the complexity implied by entangling them,
since it's complex enough to add fields here as it is.

> >
> > Signed-off-by: Peter Collingbourne <pcc@google.com>
> > ---
> > View this change in Gerrit: https://linux-review.googlesource.com/q/Ide155ce29366c3eab2a944ae4c51205982e5b8b2
> >
> > v10:
> > - make the new field compatible with the various ways
> >   that a siginfo can be injected from another process
> > - eliminate some duplication by adding a refactoring patch
> >   before this one
> >
> >  arch/powerpc/platforms/powernv/vas-fault.c |  1 +
> >  arch/x86/kernel/signal_compat.c            |  4 +--
> >  include/linux/compat.h                     |  2 ++
> >  include/linux/signal_types.h               |  2 +-
> >  include/uapi/asm-generic/siginfo.h         |  4 +++
> >  include/uapi/asm-generic/signal-defs.h     |  4 +++
> >  include/uapi/linux/ptrace.h                |  2 ++
> >  kernel/ptrace.c                            | 29 ++++++++++++++++++++++
> >  kernel/signal.c                            |  3 +++
> >  9 files changed, 48 insertions(+), 3 deletions(-)
> >
> > diff --git a/arch/powerpc/platforms/powernv/vas-fault.c b/arch/powerpc/platforms/powernv/vas-fault.c
> > index 3d21fce254b7..3bbb335561f5 100644
> > --- a/arch/powerpc/platforms/powernv/vas-fault.c
> > +++ b/arch/powerpc/platforms/powernv/vas-fault.c
> > @@ -154,6 +154,7 @@ static void update_csb(struct vas_window *window,
> >       info.si_errno = EFAULT;
> >       info.si_code = SEGV_MAPERR;
> >       info.si_addr = csb_addr;
> > +     info.si_xflags = 0;
> >
> >       /*
> >        * process will be polling on csb.flags after request is sent to
> > diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
> > index c599013ae8cb..6b99f0c8a068 100644
> > --- a/arch/x86/kernel/signal_compat.c
> > +++ b/arch/x86/kernel/signal_compat.c
> > @@ -121,8 +121,8 @@ static inline void signal_compat_build_tests(void)
> >  #endif
> >
> >       CHECK_CSI_OFFSET(_sigfault);
> > -     CHECK_CSI_SIZE  (_sigfault, 4*sizeof(int));
> > -     CHECK_SI_SIZE   (_sigfault, 8*sizeof(int));
> > +     CHECK_CSI_SIZE  (_sigfault, 8*sizeof(int));
> > +     CHECK_SI_SIZE   (_sigfault, 16*sizeof(int));
>
> (Yuk, but at least you make this no worse.)
>
> >
> >       BUILD_BUG_ON(offsetof(siginfo_t, si_addr) != 0x10);
> >       BUILD_BUG_ON(offsetof(compat_siginfo_t, si_addr) != 0x0C);
> > diff --git a/include/linux/compat.h b/include/linux/compat.h
> > index d38c4d7e83bd..55d4228dfd88 100644
> > --- a/include/linux/compat.h
> > +++ b/include/linux/compat.h
> > @@ -231,7 +231,9 @@ typedef struct compat_siginfo {
> >                                       char _dummy_pkey[__COMPAT_ADDR_BND_PKEY_PAD];
> >                                       u32 _pkey;
> >                               } _addr_pkey;
> > +                             compat_uptr_t _pad[6];
> >                       };
> > +                     compat_uptr_t _xflags;
>
> Should we have the same type here for native and compat?
>
> I don't have a very strong opinion on this, but currently native on
> 64-bit arches will have 32 extra bits in _xflags that can never be used
> (or have to be defined differently for compat).

Good point. I will make this a u64 (although I think 32 bits will
probably be more than enough, the distance between si_xflags and
si_addr_ignored_bits will be 8 bytes on 64-bit architectures due to
alignment so we may as well make all of the bits available).

> >               } _sigfault;
> >
> >               /* SIGPOLL */
> > diff --git a/include/linux/signal_types.h b/include/linux/signal_types.h
> > index a7887ad84d36..75ca861d982a 100644
> > --- a/include/linux/signal_types.h
> > +++ b/include/linux/signal_types.h
> > @@ -78,6 +78,6 @@ struct ksignal {
> >
> >  #define UAPI_SA_FLAGS                                                          \
> >       (SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
> > -      SA_NODEFER | SA_RESETHAND | __ARCH_UAPI_SA_FLAGS)
> > +      SA_NODEFER | SA_RESETHAND | SA_XFLAGS | __ARCH_UAPI_SA_FLAGS)
> >
> >  #endif /* _LINUX_SIGNAL_TYPES_H */
> > diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
> > index cb3d6c267181..1fbd88d64f38 100644
> > --- a/include/uapi/asm-generic/siginfo.h
> > +++ b/include/uapi/asm-generic/siginfo.h
> > @@ -91,7 +91,9 @@ union __sifields {
> >                               char _dummy_pkey[__ADDR_BND_PKEY_PAD];
> >                               __u32 _pkey;
> >                       } _addr_pkey;
> > +                     void *_pad[6];
>
> 6?
>
> Obviously we'll need something here, but I'm curious as to where this
> value came from.
>
> (Same for compat.)

I think it came from Eric's suggestion in [1], i.e. 2 words from the
existing fields plus the 4 words of padding suggested by Eric.

[1] https://www.spinics.net/lists/arm-kernel/msg808618.html

> >               };
> > +             unsigned long _xflags;
> >       } _sigfault;
> >
> >       /* SIGPOLL */
> > @@ -152,6 +154,8 @@ typedef struct siginfo {
> >  #define si_trapno    _sifields._sigfault._trapno
> >  #endif
> >  #define si_addr_lsb  _sifields._sigfault._addr_lsb
> > +/* si_xflags is only valid if 0 <= si_code < SI_KERNEL */
> > +#define si_xflags    _sifields._sigfault._xflags
> >  #define si_lower     _sifields._sigfault._addr_bnd._lower
> >  #define si_upper     _sifields._sigfault._addr_bnd._upper
> >  #define si_pkey              _sifields._sigfault._addr_pkey._pkey
> > diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
> > index e853cbe8722d..bdbe1fe7a779 100644
> > --- a/include/uapi/asm-generic/signal-defs.h
> > +++ b/include/uapi/asm-generic/signal-defs.h
> > @@ -20,6 +20,9 @@
> >   * so this bit allows flag bit support to be detected from userspace while
> >   * allowing an old kernel to be distinguished from a kernel that supports every
> >   * flag bit.
> > + * SA_XFLAGS indicates that the signal handler requires the siginfo.si_xflags
> > + * field to be valid. Note that if the kernel supports SA_XFLAGS, the field will
>
> Maybe "valid for fault signals (SIGSEGV etc.)"

Will add.

> [...]
>
> Otherwise, this looks sensible overall to me.

Thanks for the review. (And apologies for being slow to respond to
your reviews. I got preempted by another task right after sending out
v10 and only now did I get a chance to get back to this.)

Peter

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 4/7] signal: define the SA_UNSUPPORTED bit in sa_flags
  2020-09-08 15:13     ` Dave Martin
@ 2020-10-08  2:21       ` Peter Collingbourne
  -1 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-10-08  2:21 UTC (permalink / raw)
  To: Dave Martin
  Cc: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Will Deacon, Oleg Nesterov, Eric W. Biederman,
	James E.J. Bottomley, Parisc List, Andrey Konovalov,
	Kevin Brodsky, David Spickett, Linux ARM, Richard Henderson

On Tue, Sep 8, 2020 at 8:13 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Fri, Aug 21, 2020 at 10:10:14PM -0700, Peter Collingbourne wrote:
>
> Nit: no statement of the chage being made (other than in the subject
> line).

Will fix.

> > This bit will never be supported in the uapi. The purpose of this flag
> > bit is to allow userspace to distinguish an old kernel that does not
> > clear unknown sa_flags bits from a kernel that supports every flag bit.
> >
> > In other words, if userspace finds that this bit remains set in
> > oldact.sa_flags, it means that the kernel cannot be trusted to have
> > cleared unknown flag bits from sa_flags, so no assumptions about flag
> > bit support can be made.
>
> This isn't quite right?  After a single sigaction() call, oact will
> contain the sa_flags for the previously registered handler.  So a
> second sigaction() call would be needed to find out the newly effective
> sa_flags.

You're right, this is unclear to say the least. In v11 I will reword like so:

    In other words, if userspace does something like:

      act.sa_flags |= SA_UNSUPPORTED;
      sigaction(SIGSEGV, &act, 0);
      sigaction(SIGSEGV, 0, &oldact);

    and finds that SA_UNSUPPORTED remains set in oldact.sa_flags, it means
    that the kernel cannot be trusted to have cleared unknown flag bits
    from sa_flags, so no assumptions about flag bit support can be made.

> >
> > Signed-off-by: Peter Collingbourne <pcc@google.com>
> > ---
> > View this change in Gerrit: https://linux-review.googlesource.com/q/Ic2501ad150a3a79c1cf27fb8c99be342e9dffbcb
> >
> >  include/uapi/asm-generic/signal-defs.h | 7 +++++++
> >  kernel/signal.c                        | 6 ++++++
> >  2 files changed, 13 insertions(+)
> >
> > diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
> > index 319628058a53..e853cbe8722d 100644
> > --- a/include/uapi/asm-generic/signal-defs.h
> > +++ b/include/uapi/asm-generic/signal-defs.h
> > @@ -14,6 +14,12 @@
> >   * SA_RESTART flag to get restarting signals (which were the default long ago)
> >   * SA_NODEFER prevents the current signal from being masked in the handler.
> >   * SA_RESETHAND clears the handler when the signal is delivered.
> > + * SA_UNSUPPORTED is a flag bit that will never be supported. Kernels from
> > + * before the introduction of SA_UNSUPPORTED did not clear unknown bits from
> > + * sa_flags when read using the oldact argument to sigaction and rt_sigaction,
> > + * so this bit allows flag bit support to be detected from userspace while
> > + * allowing an old kernel to be distinguished from a kernel that supports every
> > + * flag bit.
> >   *
> >   * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
> >   * Unix names RESETHAND and NODEFER respectively.
> > @@ -42,6 +48,7 @@
> >  #ifndef SA_RESETHAND
> >  #define SA_RESETHAND 0x80000000
> >  #endif
> > +#define SA_UNSUPPORTED       0x00000400
>
> I guess people may debate which bit is chosen, but your consolidation
> of these definitions should help to reduce the possibility of future
> collisions.  This bit appears unused for now, so I guess I don't have a
> strong opinion.
>
> >  #define SA_NOMASK    SA_NODEFER
> >  #define SA_ONESHOT   SA_RESETHAND
> > diff --git a/kernel/signal.c b/kernel/signal.c
> > index f802c82c7bcc..c80e70bde11d 100644
> > --- a/kernel/signal.c
> > +++ b/kernel/signal.c
> > @@ -3984,6 +3984,12 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
> >       if (oact)
> >               *oact = *k;
> >
> > +     /*
> > +      * Make sure that we never accidentally claim to support SA_UNSUPPORTED,
> > +      * e.g. by having an architecture use the bit in their uapi.
> > +      */
> > +     BUILD_BUG_ON(UAPI_SA_FLAGS & SA_UNSUPPORTED);
> > +
>
> Seems reasonable.
>
> With the above rewording in the commit message to clarify that a second
> sigaction() is needed:
>
> Reviewed-by: Dave Martin <Dave.Martin@arm.com>

Thanks for the review.

Peter

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 4/7] signal: define the SA_UNSUPPORTED bit in sa_flags
@ 2020-10-08  2:21       ` Peter Collingbourne
  0 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-10-08  2:21 UTC (permalink / raw)
  To: Dave Martin
  Cc: Linux ARM, Parisc List, Catalin Marinas, Kevin Brodsky,
	Oleg Nesterov, James E.J. Bottomley, Kostya Serebryany,
	Eric W. Biederman, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Will Deacon, Evgenii Stepanov,
	Richard Henderson

On Tue, Sep 8, 2020 at 8:13 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Fri, Aug 21, 2020 at 10:10:14PM -0700, Peter Collingbourne wrote:
>
> Nit: no statement of the chage being made (other than in the subject
> line).

Will fix.

> > This bit will never be supported in the uapi. The purpose of this flag
> > bit is to allow userspace to distinguish an old kernel that does not
> > clear unknown sa_flags bits from a kernel that supports every flag bit.
> >
> > In other words, if userspace finds that this bit remains set in
> > oldact.sa_flags, it means that the kernel cannot be trusted to have
> > cleared unknown flag bits from sa_flags, so no assumptions about flag
> > bit support can be made.
>
> This isn't quite right?  After a single sigaction() call, oact will
> contain the sa_flags for the previously registered handler.  So a
> second sigaction() call would be needed to find out the newly effective
> sa_flags.

You're right, this is unclear to say the least. In v11 I will reword like so:

    In other words, if userspace does something like:

      act.sa_flags |= SA_UNSUPPORTED;
      sigaction(SIGSEGV, &act, 0);
      sigaction(SIGSEGV, 0, &oldact);

    and finds that SA_UNSUPPORTED remains set in oldact.sa_flags, it means
    that the kernel cannot be trusted to have cleared unknown flag bits
    from sa_flags, so no assumptions about flag bit support can be made.

> >
> > Signed-off-by: Peter Collingbourne <pcc@google.com>
> > ---
> > View this change in Gerrit: https://linux-review.googlesource.com/q/Ic2501ad150a3a79c1cf27fb8c99be342e9dffbcb
> >
> >  include/uapi/asm-generic/signal-defs.h | 7 +++++++
> >  kernel/signal.c                        | 6 ++++++
> >  2 files changed, 13 insertions(+)
> >
> > diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
> > index 319628058a53..e853cbe8722d 100644
> > --- a/include/uapi/asm-generic/signal-defs.h
> > +++ b/include/uapi/asm-generic/signal-defs.h
> > @@ -14,6 +14,12 @@
> >   * SA_RESTART flag to get restarting signals (which were the default long ago)
> >   * SA_NODEFER prevents the current signal from being masked in the handler.
> >   * SA_RESETHAND clears the handler when the signal is delivered.
> > + * SA_UNSUPPORTED is a flag bit that will never be supported. Kernels from
> > + * before the introduction of SA_UNSUPPORTED did not clear unknown bits from
> > + * sa_flags when read using the oldact argument to sigaction and rt_sigaction,
> > + * so this bit allows flag bit support to be detected from userspace while
> > + * allowing an old kernel to be distinguished from a kernel that supports every
> > + * flag bit.
> >   *
> >   * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
> >   * Unix names RESETHAND and NODEFER respectively.
> > @@ -42,6 +48,7 @@
> >  #ifndef SA_RESETHAND
> >  #define SA_RESETHAND 0x80000000
> >  #endif
> > +#define SA_UNSUPPORTED       0x00000400
>
> I guess people may debate which bit is chosen, but your consolidation
> of these definitions should help to reduce the possibility of future
> collisions.  This bit appears unused for now, so I guess I don't have a
> strong opinion.
>
> >  #define SA_NOMASK    SA_NODEFER
> >  #define SA_ONESHOT   SA_RESETHAND
> > diff --git a/kernel/signal.c b/kernel/signal.c
> > index f802c82c7bcc..c80e70bde11d 100644
> > --- a/kernel/signal.c
> > +++ b/kernel/signal.c
> > @@ -3984,6 +3984,12 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
> >       if (oact)
> >               *oact = *k;
> >
> > +     /*
> > +      * Make sure that we never accidentally claim to support SA_UNSUPPORTED,
> > +      * e.g. by having an architecture use the bit in their uapi.
> > +      */
> > +     BUILD_BUG_ON(UAPI_SA_FLAGS & SA_UNSUPPORTED);
> > +
>
> Seems reasonable.
>
> With the above rewording in the commit message to clarify that a second
> sigaction() is needed:
>
> Reviewed-by: Dave Martin <Dave.Martin@arm.com>

Thanks for the review.

Peter

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 3/7] signal: clear non-uapi flag bits when passing/returning sa_flags
  2020-09-08 15:12     ` Dave Martin
@ 2020-10-08  2:23       ` Peter Collingbourne
  -1 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-10-08  2:23 UTC (permalink / raw)
  To: Dave Martin
  Cc: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Will Deacon, Oleg Nesterov, Eric W. Biederman,
	James E.J. Bottomley, Parisc List, Andrey Konovalov,
	Kevin Brodsky, David Spickett, Linux ARM, Richard Henderson

On Tue, Sep 8, 2020 at 8:12 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Fri, Aug 21, 2020 at 10:10:13PM -0700, Peter Collingbourne wrote:
> > Previously we were not clearing non-uapi flag bits in
> > sigaction.sa_flags when storing the userspace-provided sa_flags or
> > when returning them via oldact. Start doing so.
> >
> > This allows userspace to detect missing support for flag bits and
> > allows the kernel to use non-uapi bits internally, as we are already
> > doing in arch/x86 for two flag bits. Now that this change is in
> > place, we no longer need the code in arch/x86 that was hiding these
> > bits from userspace, so remove it.
> >
> > This is technically a userspace-visible behavior change for sigaction, as
> > the unknown bits returned via oldact.sa_flags are no longer set. However,
> > we are free to define the behavior for unknown bits exactly because
> > their behavior is currently undefined, so for now we can define the
> > meaning of each of them to be "clear the bit in oldact.sa_flags unless
> > the bit becomes known in the future". Furthermore, this behavior is
> > consistent with OpenBSD [1], illumos [2] and XNU [3] (FreeBSD [4] and
> > NetBSD [5] fail the syscall if unknown bits are set). So there is some
> > precedent for this behavior in other kernels, and in particular in XNU,
> > which is probably the most popular kernel among those that I looked at,
> > which means that this change is less likely to be a compatibility issue.
> >
> > Link: [1] https://github.com/openbsd/src/blob/f634a6a4b5bf832e9c1de77f7894ae2625e74484/sys/kern/kern_sig.c#L278
> > Link: [2] https://github.com/illumos/illumos-gate/blob/76f19f5fdc974fe5be5c82a556e43a4df93f1de1/usr/src/uts/common/syscall/sigaction.c#L86
> > Link: [3] https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/kern/kern_sig.c#L480
> > Link: [4] https://github.com/freebsd/freebsd/blob/eded70c37057857c6e23fae51f86b8f8f43cd2d0/sys/kern/kern_sig.c#L699
> > Link: [5] https://github.com/NetBSD/src/blob/3365779becdcedfca206091a645a0e8e22b2946e/sys/kern/sys_sig.c#L473
> > Signed-off-by: Peter Collingbourne <pcc@google.com>
> > ---
> > View this change in Gerrit: https://linux-review.googlesource.com/q/I35aab6f5be932505d90f3b3450c083b4db1eca86
> >
> > v10:
> > - rename SA_UAPI_FLAGS -> UAPI_SA_FLAGS
> > - refactor how we define it to avoid mentioning flags more
> >   than once
> >
> >  arch/arm/include/asm/signal.h    |  2 ++
> >  arch/parisc/include/asm/signal.h |  2 ++
> >  arch/x86/kernel/signal_compat.c  |  7 -------
> >  include/linux/signal_types.h     | 12 ++++++++++++
> >  kernel/signal.c                  | 10 ++++++++++
> >  5 files changed, 26 insertions(+), 7 deletions(-)
> >
> > diff --git a/arch/arm/include/asm/signal.h b/arch/arm/include/asm/signal.h
> > index 65530a042009..430be7774402 100644
> > --- a/arch/arm/include/asm/signal.h
> > +++ b/arch/arm/include/asm/signal.h
> > @@ -17,6 +17,8 @@ typedef struct {
> >       unsigned long sig[_NSIG_WORDS];
> >  } sigset_t;
> >
> > +#define __ARCH_UAPI_SA_FLAGS (SA_THIRTYTWO | SA_RESTORER)
> > +
> >  #define __ARCH_HAS_SA_RESTORER
> >
> >  #include <asm/sigcontext.h>
> > diff --git a/arch/parisc/include/asm/signal.h b/arch/parisc/include/asm/signal.h
> > index 715c96ba2ec8..30dd1e43ef88 100644
> > --- a/arch/parisc/include/asm/signal.h
> > +++ b/arch/parisc/include/asm/signal.h
> > @@ -21,6 +21,8 @@ typedef struct {
> >       unsigned long sig[_NSIG_WORDS];
> >  } sigset_t;
> >
> > +#define __ARCH_UAPI_SA_FLAGS _SA_SIGGFAULT
> > +
> >  #include <asm/sigcontext.h>
> >
> >  #endif /* !__ASSEMBLY */
> > diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
> > index 9ccbf0576cd0..c599013ae8cb 100644
> > --- a/arch/x86/kernel/signal_compat.c
> > +++ b/arch/x86/kernel/signal_compat.c
> > @@ -165,16 +165,9 @@ void sigaction_compat_abi(struct k_sigaction *act, struct k_sigaction *oact)
> >  {
> >       signal_compat_build_tests();
> >
> > -     /* Don't leak in-kernel non-uapi flags to user-space */
> > -     if (oact)
> > -             oact->sa.sa_flags &= ~(SA_IA32_ABI | SA_X32_ABI);
> > -
> >       if (!act)
> >               return;
> >
> > -     /* Don't let flags to be set from userspace */
> > -     act->sa.sa_flags &= ~(SA_IA32_ABI | SA_X32_ABI);
> > -
> >       if (in_ia32_syscall())
> >               act->sa.sa_flags |= SA_IA32_ABI;
> >       if (in_x32_syscall())
> > diff --git a/include/linux/signal_types.h b/include/linux/signal_types.h
> > index f8a90ae9c6ec..a7887ad84d36 100644
> > --- a/include/linux/signal_types.h
> > +++ b/include/linux/signal_types.h
> > @@ -68,4 +68,16 @@ struct ksignal {
> >       int sig;
> >  };
> >
> > +#ifndef __ARCH_UAPI_SA_FLAGS
> > +#ifdef SA_RESTORER
> > +#define __ARCH_UAPI_SA_FLAGS SA_RESTORER
> > +#else
> > +#define __ARCH_UAPI_SA_FLAGS 0
> > +#endif
> > +#endif
> > +
> > +#define UAPI_SA_FLAGS                                                          \
> > +     (SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
> > +      SA_NODEFER | SA_RESETHAND | __ARCH_UAPI_SA_FLAGS)
> > +
>
> Part of me wants this to be closer to the common flag definitions.  But
> we don't really want to define this in the UAPI headers.

Agreed on keeping this out of uapi, otherwise I would have defined this inline.

> Unless you can think of another good place to put it, this is probably
> OK as-is.

Ack.

Peter

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 3/7] signal: clear non-uapi flag bits when passing/returning sa_flags
@ 2020-10-08  2:23       ` Peter Collingbourne
  0 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-10-08  2:23 UTC (permalink / raw)
  To: Dave Martin
  Cc: Linux ARM, Parisc List, Catalin Marinas, Kevin Brodsky,
	Oleg Nesterov, James E.J. Bottomley, Kostya Serebryany,
	Eric W. Biederman, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Will Deacon, Evgenii Stepanov,
	Richard Henderson

On Tue, Sep 8, 2020 at 8:12 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Fri, Aug 21, 2020 at 10:10:13PM -0700, Peter Collingbourne wrote:
> > Previously we were not clearing non-uapi flag bits in
> > sigaction.sa_flags when storing the userspace-provided sa_flags or
> > when returning them via oldact. Start doing so.
> >
> > This allows userspace to detect missing support for flag bits and
> > allows the kernel to use non-uapi bits internally, as we are already
> > doing in arch/x86 for two flag bits. Now that this change is in
> > place, we no longer need the code in arch/x86 that was hiding these
> > bits from userspace, so remove it.
> >
> > This is technically a userspace-visible behavior change for sigaction, as
> > the unknown bits returned via oldact.sa_flags are no longer set. However,
> > we are free to define the behavior for unknown bits exactly because
> > their behavior is currently undefined, so for now we can define the
> > meaning of each of them to be "clear the bit in oldact.sa_flags unless
> > the bit becomes known in the future". Furthermore, this behavior is
> > consistent with OpenBSD [1], illumos [2] and XNU [3] (FreeBSD [4] and
> > NetBSD [5] fail the syscall if unknown bits are set). So there is some
> > precedent for this behavior in other kernels, and in particular in XNU,
> > which is probably the most popular kernel among those that I looked at,
> > which means that this change is less likely to be a compatibility issue.
> >
> > Link: [1] https://github.com/openbsd/src/blob/f634a6a4b5bf832e9c1de77f7894ae2625e74484/sys/kern/kern_sig.c#L278
> > Link: [2] https://github.com/illumos/illumos-gate/blob/76f19f5fdc974fe5be5c82a556e43a4df93f1de1/usr/src/uts/common/syscall/sigaction.c#L86
> > Link: [3] https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/kern/kern_sig.c#L480
> > Link: [4] https://github.com/freebsd/freebsd/blob/eded70c37057857c6e23fae51f86b8f8f43cd2d0/sys/kern/kern_sig.c#L699
> > Link: [5] https://github.com/NetBSD/src/blob/3365779becdcedfca206091a645a0e8e22b2946e/sys/kern/sys_sig.c#L473
> > Signed-off-by: Peter Collingbourne <pcc@google.com>
> > ---
> > View this change in Gerrit: https://linux-review.googlesource.com/q/I35aab6f5be932505d90f3b3450c083b4db1eca86
> >
> > v10:
> > - rename SA_UAPI_FLAGS -> UAPI_SA_FLAGS
> > - refactor how we define it to avoid mentioning flags more
> >   than once
> >
> >  arch/arm/include/asm/signal.h    |  2 ++
> >  arch/parisc/include/asm/signal.h |  2 ++
> >  arch/x86/kernel/signal_compat.c  |  7 -------
> >  include/linux/signal_types.h     | 12 ++++++++++++
> >  kernel/signal.c                  | 10 ++++++++++
> >  5 files changed, 26 insertions(+), 7 deletions(-)
> >
> > diff --git a/arch/arm/include/asm/signal.h b/arch/arm/include/asm/signal.h
> > index 65530a042009..430be7774402 100644
> > --- a/arch/arm/include/asm/signal.h
> > +++ b/arch/arm/include/asm/signal.h
> > @@ -17,6 +17,8 @@ typedef struct {
> >       unsigned long sig[_NSIG_WORDS];
> >  } sigset_t;
> >
> > +#define __ARCH_UAPI_SA_FLAGS (SA_THIRTYTWO | SA_RESTORER)
> > +
> >  #define __ARCH_HAS_SA_RESTORER
> >
> >  #include <asm/sigcontext.h>
> > diff --git a/arch/parisc/include/asm/signal.h b/arch/parisc/include/asm/signal.h
> > index 715c96ba2ec8..30dd1e43ef88 100644
> > --- a/arch/parisc/include/asm/signal.h
> > +++ b/arch/parisc/include/asm/signal.h
> > @@ -21,6 +21,8 @@ typedef struct {
> >       unsigned long sig[_NSIG_WORDS];
> >  } sigset_t;
> >
> > +#define __ARCH_UAPI_SA_FLAGS _SA_SIGGFAULT
> > +
> >  #include <asm/sigcontext.h>
> >
> >  #endif /* !__ASSEMBLY */
> > diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
> > index 9ccbf0576cd0..c599013ae8cb 100644
> > --- a/arch/x86/kernel/signal_compat.c
> > +++ b/arch/x86/kernel/signal_compat.c
> > @@ -165,16 +165,9 @@ void sigaction_compat_abi(struct k_sigaction *act, struct k_sigaction *oact)
> >  {
> >       signal_compat_build_tests();
> >
> > -     /* Don't leak in-kernel non-uapi flags to user-space */
> > -     if (oact)
> > -             oact->sa.sa_flags &= ~(SA_IA32_ABI | SA_X32_ABI);
> > -
> >       if (!act)
> >               return;
> >
> > -     /* Don't let flags to be set from userspace */
> > -     act->sa.sa_flags &= ~(SA_IA32_ABI | SA_X32_ABI);
> > -
> >       if (in_ia32_syscall())
> >               act->sa.sa_flags |= SA_IA32_ABI;
> >       if (in_x32_syscall())
> > diff --git a/include/linux/signal_types.h b/include/linux/signal_types.h
> > index f8a90ae9c6ec..a7887ad84d36 100644
> > --- a/include/linux/signal_types.h
> > +++ b/include/linux/signal_types.h
> > @@ -68,4 +68,16 @@ struct ksignal {
> >       int sig;
> >  };
> >
> > +#ifndef __ARCH_UAPI_SA_FLAGS
> > +#ifdef SA_RESTORER
> > +#define __ARCH_UAPI_SA_FLAGS SA_RESTORER
> > +#else
> > +#define __ARCH_UAPI_SA_FLAGS 0
> > +#endif
> > +#endif
> > +
> > +#define UAPI_SA_FLAGS                                                          \
> > +     (SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
> > +      SA_NODEFER | SA_RESETHAND | __ARCH_UAPI_SA_FLAGS)
> > +
>
> Part of me wants this to be closer to the common flag definitions.  But
> we don't really want to define this in the UAPI headers.

Agreed on keeping this out of uapi, otherwise I would have defined this inline.

> Unless you can think of another good place to put it, this is probably
> OK as-is.

Ack.

Peter

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 7/7] arm64: expose FAR_EL1 tag bits in siginfo
  2020-09-08 15:13     ` Dave Martin
@ 2020-10-08  2:54       ` Peter Collingbourne
  -1 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-10-08  2:54 UTC (permalink / raw)
  To: Dave Martin
  Cc: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Will Deacon, Oleg Nesterov, Eric W. Biederman,
	James E.J. Bottomley, Parisc List, Andrey Konovalov,
	Kevin Brodsky, David Spickett, Linux ARM, Richard Henderson

On Tue, Sep 8, 2020 at 8:13 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Fri, Aug 21, 2020 at 10:10:17PM -0700, Peter Collingbourne wrote:
> > The kernel currently clears the tag bits (i.e. bits 56-63) in the fault
> > address exposed via siginfo.si_addr and sigcontext.fault_address. However,
> > the tag bits may be needed by tools in order to accurately diagnose
> > memory errors, such as HWASan [1] or future tools based on the Memory
> > Tagging Extension (MTE).
> >
> > We should not stop clearing these bits in the existing fault address
> > fields, because there may be existing userspace applications that are
> > expecting the tag bits to be cleared. Instead, create a new pair of
> > union fields in siginfo._sigfault, and store the tag bits of FAR_EL1
> > there, together with a mask specifying which bits are valid.
> >
> > A flag is added to si_xflags to allow userspace to determine whether
> > the values in the fields are valid.
> >
> > [1] http://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html
> >
> > Signed-off-by: Peter Collingbourne <pcc@google.com>
> > ---
> > View this change in Gerrit: https://linux-review.googlesource.com/q/Ia8876bad8c798e0a32df7c2ce1256c4771c81446
> >
> > v10:
> > - rename the flag to SIXFLAG_ADDR_IGNORED_BITS
> > - use an arch hook to specify which bits are ignored, instead
> >   of passing them explicitly
> > - while refactoring for the arch hook, noticed that my previous
> >   patches missed a case involving cache maintenance instructions,
> >   so expose the tag bits for that signal as well
> >
> > v9:
> > - make the ignored bits fields generic
> > - add some new dependent patches that prepare us to store the
> >   field in such a way that userspace can detect their presence
> >
> > v8:
> > - rebase onto 5.8rc2
> >
> > v7:
> > - switch to a new siginfo field instead of using sigcontext
> > - merge the patch back into one since the other patches are now
> >   unnecessary
> >
> > v6:
> > - move fault address and fault code into the kernel_siginfo data structure
> > - split the patch in three since it was getting large and now has
> >   generic and arch-specific parts
> >
> > v5:
> > - add padding to fault_addr_top_byte_context in order to ensure the correct
> >   size and preserve sp alignment
> >
> > v4:
> > - expose only the tag bits in the context instead of the entire FAR_EL1
> > - remove mention of the new context from the sigcontext.__reserved[] note
> >
> > v3:
> > - add documentation to tagged-pointers.rst
> > - update comments in sigcontext.h
> >
> > v2:
> > - revert changes to hw_breakpoint.c
> > - rename set_thread_esr to set_thread_far_esr
> >
> >  Documentation/arm64/tagged-pointers.rst | 21 ++++++---
> >  arch/arm64/include/asm/exception.h      |  2 +-
> >  arch/arm64/include/asm/signal.h         | 17 +++++++
> >  arch/arm64/include/asm/system_misc.h    |  2 +-
> >  arch/arm64/include/asm/traps.h          |  6 +--
> >  arch/arm64/kernel/debug-monitors.c      |  5 +--
> >  arch/arm64/kernel/entry-common.c        |  2 -
> >  arch/arm64/kernel/ptrace.c              |  7 +--
> >  arch/arm64/kernel/sys_compat.c          |  5 +--
> >  arch/arm64/kernel/traps.c               | 29 ++++++------
> >  arch/arm64/mm/fault.c                   | 59 +++++++++++++------------
> >  arch/x86/kernel/signal_compat.c         |  4 +-
> >  include/linux/compat.h                  |  2 +
> >  include/linux/signal.h                  |  8 ++++
> >  include/uapi/asm-generic/siginfo.h      | 10 +++++
> >  kernel/signal.c                         | 14 +++++-
> >  16 files changed, 122 insertions(+), 71 deletions(-)
> >  create mode 100644 arch/arm64/include/asm/signal.h
> >
> > diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst
> > index eab4323609b9..14273160b38b 100644
> > --- a/Documentation/arm64/tagged-pointers.rst
> > +++ b/Documentation/arm64/tagged-pointers.rst
> > @@ -53,12 +53,21 @@ visibility.
> >  Preserving tags
> >  ---------------
> >
> > -Non-zero tags are not preserved when delivering signals. This means that
> > -signal handlers in applications making use of tags cannot rely on the
> > -tag information for user virtual addresses being maintained for fields
> > -inside siginfo_t. One exception to this rule is for signals raised in
> > -response to watchpoint debug exceptions, where the tag information will
> > -be preserved.
> > +Non-zero tags are not preserved in the fault address fields
> > +siginfo.si_addr or sigcontext.fault_address when delivering
> > +signals. This means that signal handlers in applications making use
> > +of tags cannot rely on the tag information for user virtual addresses
> > +being maintained in these fields. One exception to this rule is for
> > +signals raised in response to watchpoint debug exceptions, where the
> > +tag information will be preserved.
> > +
> > +The fault address tag is preserved in the si_addr_ignored_bits field
> > +of siginfo, which is set for signals raised in response to data aborts
> > +and instruction aborts. The si_addr_ignored_bits_mask field indicates
> > +which bits of the field are valid. The validity of these fields is
> > +indicated by the SIXFLAG_ADDR_IGNORED_BITS flag in siginfo.si_xflags,
> > +and the validity of si_xflags in turn is indicated by the kernel
> > +indicating support for the sigaction.sa_flags flag SA_XFLAGS.
> >
> >  The architecture prevents the use of a tagged PC, so the upper byte will
> >  be set to a sign-extension of bit 55 on exception return.
> > diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h
> > index 7577a754d443..950d55dae948 100644
> > --- a/arch/arm64/include/asm/exception.h
> > +++ b/arch/arm64/include/asm/exception.h
> > @@ -32,7 +32,7 @@ static inline u32 disr_to_esr(u64 disr)
> >  }
> >
> >  asmlinkage void enter_from_user_mode(void);
> > -void do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs);
> > +void do_mem_abort(unsigned long far, unsigned int esr, struct pt_regs *regs);
> >  void do_undefinstr(struct pt_regs *regs);
> >  void do_bti(struct pt_regs *regs);
> >  asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr);
>
> [...]
>
> > diff --git a/include/linux/compat.h b/include/linux/compat.h
> > index 55d4228dfd88..273146cf30fd 100644
> > --- a/include/linux/compat.h
> > +++ b/include/linux/compat.h
> > @@ -234,6 +234,8 @@ typedef struct compat_siginfo {
> >                               compat_uptr_t _pad[6];
> >                       };
> >                       compat_uptr_t _xflags;
> > +                     compat_uptr_t _addr_ignored_bits;
> > +                     compat_uptr_t _addr_ignored_bits_mask;
> >               } _sigfault;
> >
> >               /* SIGPOLL */
> > diff --git a/include/linux/signal.h b/include/linux/signal.h
> > index 3edbf54493ee..b4c473c12a9b 100644
> > --- a/include/linux/signal.h
> > +++ b/include/linux/signal.h
> > @@ -480,4 +480,12 @@ struct seq_file;
> >  extern void render_sigset_t(struct seq_file *, const char *, sigset_t *);
> >  #endif
>
> Can we have a comment here explaining what this helper needs to do, if
> defined?

Will add.

> > +#ifndef arch_addr_ignored_bits_mask
> > +static inline unsigned long arch_addr_ignored_bits_mask(unsigned long sig,
> > +                                                     unsigned long si_code)
> > +{
> > +     return 0;
> > +}
> > +#endif
> > +
> >  #endif /* _LINUX_SIGNAL_H */
> > diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
> > index 1fbd88d64f38..e314a38ce2d0 100644
> > --- a/include/uapi/asm-generic/siginfo.h
> > +++ b/include/uapi/asm-generic/siginfo.h
> > @@ -94,6 +94,8 @@ union __sifields {
> >                       void *_pad[6];
> >               };
> >               unsigned long _xflags;
> > +             unsigned long _addr_ignored_bits;
> > +             unsigned long _addr_ignored_bits_mask;
> >       } _sigfault;
> >
> >       /* SIGPOLL */
> > @@ -156,6 +158,8 @@ typedef struct siginfo {
> >  #define si_addr_lsb  _sifields._sigfault._addr_lsb
> >  /* si_xflags is only valid if 0 <= si_code < SI_KERNEL */
> >  #define si_xflags    _sifields._sigfault._xflags
> > +#define si_addr_ignored_bits         _sifields._sigfault._addr_ignored_bits
> > +#define si_addr_ignored_bits_mask    _sifields._sigfault._addr_ignored_bits_mask
> >  #define si_lower     _sifields._sigfault._addr_bnd._lower
> >  #define si_upper     _sifields._sigfault._addr_bnd._upper
> >  #define si_pkey              _sifields._sigfault._addr_pkey._pkey
> > @@ -296,6 +300,12 @@ typedef struct siginfo {
> >  #define EMT_TAGOVF   1       /* tag overflow */
> >  #define NSIGEMT              1
> >
> > +/*
> > + * SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT si_xflags
> > + */
> > +#define SIXFLAG_ADDR_IGNORED_BITS    1
> > +/* si_addr_ignored_bits{,_mask} fields valid */
> > +
>
> I'm still uneasy about the "ignored bits" nomenclature, because the bits
> aren't ignored, and because at the C language level above, they
> generally _are_ considered part of the address.
>
> I don't have a great suggestion for a new name, though.  If we just
> consider the si_addr_ignored_bits to be attributes that accompany the
> address, it might make sense to call it
>
>         si_addr_attr_bits_mask
>
> or similar.
>
> That may or may not be considered to be less confusing.

Hmm, I wasn't entirely comfortable with "ignored" either because, as
you point out, once MTE arrives some of the bits won't be ignored any
more. Maybe since folks who are going to be working with these bits
will probably be at least a little familiar with their use on arm64
with MTE and the tagged address ABI, we should just borrow the
nomenclature from arm64 and call it:

  si_addr_tag_bits
  si_addr_tag_bits_mask
  SIXFLAG_ADDR_TAG_BITS

> >  /*
> >   * sigevent definitions
> >   *
> > diff --git a/kernel/signal.c b/kernel/signal.c
> > index 4259903b95cb..29654652d3aa 100644
> > --- a/kernel/signal.c
> > +++ b/kernel/signal.c
> > @@ -1652,11 +1652,17 @@ void force_sigsegv(int sig)
> >  static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
> >                                      int code, void __user *addr)
> >  {
> > +     unsigned long addr_long = (unsigned long)addr;
> > +     unsigned long ignored_bits_mask =
> > +             arch_addr_ignored_bits_mask(sig, code);
> > +
> >       info->si_signo = sig;
> >       info->si_errno = 0;
> >       info->si_code = code;
> > -     info->si_addr = addr;
> > -     info->si_xflags = 0;
> > +     info->si_addr = (void __user *)(addr_long & ~ignored_bits_mask);
> > +     info->si_xflags = SIXFLAG_ADDR_IGNORED_BITS;
> > +     info->si_addr_ignored_bits = addr_long & ignored_bits_mask;
> > +     info->si_addr_ignored_bits_mask = ignored_bits_mask;
>
> Could we report the ignored bits optionally?
>
> i.e., if arch_addr_ignored_bits_mask() == 0, then we could perhaps leave
> SIXFLAG_ADDR_IGNORED_BITS clear in si_xflags, and just set
> si_addr_ignored_bits{,_mask} to zeros.
>
> I can't decide myself whether this would be a good idea or not...

Since having the bit clear should be equivalent from the user's point
of view to having it set with the mask equal to 0, I think I would
favor the solution that would make the kernel code simpler, i.e. what
I have implemented.

> >  }
> >
> >  int force_sig_fault_to_task(int sig, int code, void __user *addr
> > @@ -3271,6 +3277,8 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
> >               to->si_trapno = from->si_trapno;
> >  #endif
> >               to->si_xflags = from->si_xflags;
> > +             to->si_addr_ignored_bits = from->si_addr_ignored_bits;
> > +             to->si_addr_ignored_bits_mask = from->si_addr_ignored_bits_mask;
>
> What happens if we're delivering a signal to a compat process?
>
> It looks like we apply all the usual logic, but si_addr_ignored_bits and
> si_addr_ignored_bits_mask simply get truncated.
>
> That might be reasonable -- we don't care about bits that don't exist
> for compat, irrespective of what they mean for native -- but it's
> probably worth a comment.

If the signal originates from a compat process then I would expect the
addresses involved in the fault to be 32 bits wide, so I would not
expect there to be any truncation in practice. The situation is the
same for si_addr I think. I can leave a comment here.

> >       }
> >
> >       switch (layout) {
> > @@ -3347,6 +3355,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> >               to->si_trapno = from->si_trapno;
> >  #endif
> >               to->si_xflags = from->si_xflags;
> > +             to->si_addr_ignored_bits = from->si_addr_ignored_bits;
> > +             to->si_addr_ignored_bits_mask = from->si_addr_ignored_bits_mask;
>
> Otherwise, the patch looks reasonable.

Thanks for the review.

Peter

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 7/7] arm64: expose FAR_EL1 tag bits in siginfo
@ 2020-10-08  2:54       ` Peter Collingbourne
  0 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-10-08  2:54 UTC (permalink / raw)
  To: Dave Martin
  Cc: Linux ARM, Parisc List, Catalin Marinas, Kevin Brodsky,
	Oleg Nesterov, James E.J. Bottomley, Kostya Serebryany,
	Eric W. Biederman, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Will Deacon, Evgenii Stepanov,
	Richard Henderson

On Tue, Sep 8, 2020 at 8:13 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Fri, Aug 21, 2020 at 10:10:17PM -0700, Peter Collingbourne wrote:
> > The kernel currently clears the tag bits (i.e. bits 56-63) in the fault
> > address exposed via siginfo.si_addr and sigcontext.fault_address. However,
> > the tag bits may be needed by tools in order to accurately diagnose
> > memory errors, such as HWASan [1] or future tools based on the Memory
> > Tagging Extension (MTE).
> >
> > We should not stop clearing these bits in the existing fault address
> > fields, because there may be existing userspace applications that are
> > expecting the tag bits to be cleared. Instead, create a new pair of
> > union fields in siginfo._sigfault, and store the tag bits of FAR_EL1
> > there, together with a mask specifying which bits are valid.
> >
> > A flag is added to si_xflags to allow userspace to determine whether
> > the values in the fields are valid.
> >
> > [1] http://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html
> >
> > Signed-off-by: Peter Collingbourne <pcc@google.com>
> > ---
> > View this change in Gerrit: https://linux-review.googlesource.com/q/Ia8876bad8c798e0a32df7c2ce1256c4771c81446
> >
> > v10:
> > - rename the flag to SIXFLAG_ADDR_IGNORED_BITS
> > - use an arch hook to specify which bits are ignored, instead
> >   of passing them explicitly
> > - while refactoring for the arch hook, noticed that my previous
> >   patches missed a case involving cache maintenance instructions,
> >   so expose the tag bits for that signal as well
> >
> > v9:
> > - make the ignored bits fields generic
> > - add some new dependent patches that prepare us to store the
> >   field in such a way that userspace can detect their presence
> >
> > v8:
> > - rebase onto 5.8rc2
> >
> > v7:
> > - switch to a new siginfo field instead of using sigcontext
> > - merge the patch back into one since the other patches are now
> >   unnecessary
> >
> > v6:
> > - move fault address and fault code into the kernel_siginfo data structure
> > - split the patch in three since it was getting large and now has
> >   generic and arch-specific parts
> >
> > v5:
> > - add padding to fault_addr_top_byte_context in order to ensure the correct
> >   size and preserve sp alignment
> >
> > v4:
> > - expose only the tag bits in the context instead of the entire FAR_EL1
> > - remove mention of the new context from the sigcontext.__reserved[] note
> >
> > v3:
> > - add documentation to tagged-pointers.rst
> > - update comments in sigcontext.h
> >
> > v2:
> > - revert changes to hw_breakpoint.c
> > - rename set_thread_esr to set_thread_far_esr
> >
> >  Documentation/arm64/tagged-pointers.rst | 21 ++++++---
> >  arch/arm64/include/asm/exception.h      |  2 +-
> >  arch/arm64/include/asm/signal.h         | 17 +++++++
> >  arch/arm64/include/asm/system_misc.h    |  2 +-
> >  arch/arm64/include/asm/traps.h          |  6 +--
> >  arch/arm64/kernel/debug-monitors.c      |  5 +--
> >  arch/arm64/kernel/entry-common.c        |  2 -
> >  arch/arm64/kernel/ptrace.c              |  7 +--
> >  arch/arm64/kernel/sys_compat.c          |  5 +--
> >  arch/arm64/kernel/traps.c               | 29 ++++++------
> >  arch/arm64/mm/fault.c                   | 59 +++++++++++++------------
> >  arch/x86/kernel/signal_compat.c         |  4 +-
> >  include/linux/compat.h                  |  2 +
> >  include/linux/signal.h                  |  8 ++++
> >  include/uapi/asm-generic/siginfo.h      | 10 +++++
> >  kernel/signal.c                         | 14 +++++-
> >  16 files changed, 122 insertions(+), 71 deletions(-)
> >  create mode 100644 arch/arm64/include/asm/signal.h
> >
> > diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst
> > index eab4323609b9..14273160b38b 100644
> > --- a/Documentation/arm64/tagged-pointers.rst
> > +++ b/Documentation/arm64/tagged-pointers.rst
> > @@ -53,12 +53,21 @@ visibility.
> >  Preserving tags
> >  ---------------
> >
> > -Non-zero tags are not preserved when delivering signals. This means that
> > -signal handlers in applications making use of tags cannot rely on the
> > -tag information for user virtual addresses being maintained for fields
> > -inside siginfo_t. One exception to this rule is for signals raised in
> > -response to watchpoint debug exceptions, where the tag information will
> > -be preserved.
> > +Non-zero tags are not preserved in the fault address fields
> > +siginfo.si_addr or sigcontext.fault_address when delivering
> > +signals. This means that signal handlers in applications making use
> > +of tags cannot rely on the tag information for user virtual addresses
> > +being maintained in these fields. One exception to this rule is for
> > +signals raised in response to watchpoint debug exceptions, where the
> > +tag information will be preserved.
> > +
> > +The fault address tag is preserved in the si_addr_ignored_bits field
> > +of siginfo, which is set for signals raised in response to data aborts
> > +and instruction aborts. The si_addr_ignored_bits_mask field indicates
> > +which bits of the field are valid. The validity of these fields is
> > +indicated by the SIXFLAG_ADDR_IGNORED_BITS flag in siginfo.si_xflags,
> > +and the validity of si_xflags in turn is indicated by the kernel
> > +indicating support for the sigaction.sa_flags flag SA_XFLAGS.
> >
> >  The architecture prevents the use of a tagged PC, so the upper byte will
> >  be set to a sign-extension of bit 55 on exception return.
> > diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h
> > index 7577a754d443..950d55dae948 100644
> > --- a/arch/arm64/include/asm/exception.h
> > +++ b/arch/arm64/include/asm/exception.h
> > @@ -32,7 +32,7 @@ static inline u32 disr_to_esr(u64 disr)
> >  }
> >
> >  asmlinkage void enter_from_user_mode(void);
> > -void do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs);
> > +void do_mem_abort(unsigned long far, unsigned int esr, struct pt_regs *regs);
> >  void do_undefinstr(struct pt_regs *regs);
> >  void do_bti(struct pt_regs *regs);
> >  asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr);
>
> [...]
>
> > diff --git a/include/linux/compat.h b/include/linux/compat.h
> > index 55d4228dfd88..273146cf30fd 100644
> > --- a/include/linux/compat.h
> > +++ b/include/linux/compat.h
> > @@ -234,6 +234,8 @@ typedef struct compat_siginfo {
> >                               compat_uptr_t _pad[6];
> >                       };
> >                       compat_uptr_t _xflags;
> > +                     compat_uptr_t _addr_ignored_bits;
> > +                     compat_uptr_t _addr_ignored_bits_mask;
> >               } _sigfault;
> >
> >               /* SIGPOLL */
> > diff --git a/include/linux/signal.h b/include/linux/signal.h
> > index 3edbf54493ee..b4c473c12a9b 100644
> > --- a/include/linux/signal.h
> > +++ b/include/linux/signal.h
> > @@ -480,4 +480,12 @@ struct seq_file;
> >  extern void render_sigset_t(struct seq_file *, const char *, sigset_t *);
> >  #endif
>
> Can we have a comment here explaining what this helper needs to do, if
> defined?

Will add.

> > +#ifndef arch_addr_ignored_bits_mask
> > +static inline unsigned long arch_addr_ignored_bits_mask(unsigned long sig,
> > +                                                     unsigned long si_code)
> > +{
> > +     return 0;
> > +}
> > +#endif
> > +
> >  #endif /* _LINUX_SIGNAL_H */
> > diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
> > index 1fbd88d64f38..e314a38ce2d0 100644
> > --- a/include/uapi/asm-generic/siginfo.h
> > +++ b/include/uapi/asm-generic/siginfo.h
> > @@ -94,6 +94,8 @@ union __sifields {
> >                       void *_pad[6];
> >               };
> >               unsigned long _xflags;
> > +             unsigned long _addr_ignored_bits;
> > +             unsigned long _addr_ignored_bits_mask;
> >       } _sigfault;
> >
> >       /* SIGPOLL */
> > @@ -156,6 +158,8 @@ typedef struct siginfo {
> >  #define si_addr_lsb  _sifields._sigfault._addr_lsb
> >  /* si_xflags is only valid if 0 <= si_code < SI_KERNEL */
> >  #define si_xflags    _sifields._sigfault._xflags
> > +#define si_addr_ignored_bits         _sifields._sigfault._addr_ignored_bits
> > +#define si_addr_ignored_bits_mask    _sifields._sigfault._addr_ignored_bits_mask
> >  #define si_lower     _sifields._sigfault._addr_bnd._lower
> >  #define si_upper     _sifields._sigfault._addr_bnd._upper
> >  #define si_pkey              _sifields._sigfault._addr_pkey._pkey
> > @@ -296,6 +300,12 @@ typedef struct siginfo {
> >  #define EMT_TAGOVF   1       /* tag overflow */
> >  #define NSIGEMT              1
> >
> > +/*
> > + * SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT si_xflags
> > + */
> > +#define SIXFLAG_ADDR_IGNORED_BITS    1
> > +/* si_addr_ignored_bits{,_mask} fields valid */
> > +
>
> I'm still uneasy about the "ignored bits" nomenclature, because the bits
> aren't ignored, and because at the C language level above, they
> generally _are_ considered part of the address.
>
> I don't have a great suggestion for a new name, though.  If we just
> consider the si_addr_ignored_bits to be attributes that accompany the
> address, it might make sense to call it
>
>         si_addr_attr_bits_mask
>
> or similar.
>
> That may or may not be considered to be less confusing.

Hmm, I wasn't entirely comfortable with "ignored" either because, as
you point out, once MTE arrives some of the bits won't be ignored any
more. Maybe since folks who are going to be working with these bits
will probably be at least a little familiar with their use on arm64
with MTE and the tagged address ABI, we should just borrow the
nomenclature from arm64 and call it:

  si_addr_tag_bits
  si_addr_tag_bits_mask
  SIXFLAG_ADDR_TAG_BITS

> >  /*
> >   * sigevent definitions
> >   *
> > diff --git a/kernel/signal.c b/kernel/signal.c
> > index 4259903b95cb..29654652d3aa 100644
> > --- a/kernel/signal.c
> > +++ b/kernel/signal.c
> > @@ -1652,11 +1652,17 @@ void force_sigsegv(int sig)
> >  static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
> >                                      int code, void __user *addr)
> >  {
> > +     unsigned long addr_long = (unsigned long)addr;
> > +     unsigned long ignored_bits_mask =
> > +             arch_addr_ignored_bits_mask(sig, code);
> > +
> >       info->si_signo = sig;
> >       info->si_errno = 0;
> >       info->si_code = code;
> > -     info->si_addr = addr;
> > -     info->si_xflags = 0;
> > +     info->si_addr = (void __user *)(addr_long & ~ignored_bits_mask);
> > +     info->si_xflags = SIXFLAG_ADDR_IGNORED_BITS;
> > +     info->si_addr_ignored_bits = addr_long & ignored_bits_mask;
> > +     info->si_addr_ignored_bits_mask = ignored_bits_mask;
>
> Could we report the ignored bits optionally?
>
> i.e., if arch_addr_ignored_bits_mask() == 0, then we could perhaps leave
> SIXFLAG_ADDR_IGNORED_BITS clear in si_xflags, and just set
> si_addr_ignored_bits{,_mask} to zeros.
>
> I can't decide myself whether this would be a good idea or not...

Since having the bit clear should be equivalent from the user's point
of view to having it set with the mask equal to 0, I think I would
favor the solution that would make the kernel code simpler, i.e. what
I have implemented.

> >  }
> >
> >  int force_sig_fault_to_task(int sig, int code, void __user *addr
> > @@ -3271,6 +3277,8 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
> >               to->si_trapno = from->si_trapno;
> >  #endif
> >               to->si_xflags = from->si_xflags;
> > +             to->si_addr_ignored_bits = from->si_addr_ignored_bits;
> > +             to->si_addr_ignored_bits_mask = from->si_addr_ignored_bits_mask;
>
> What happens if we're delivering a signal to a compat process?
>
> It looks like we apply all the usual logic, but si_addr_ignored_bits and
> si_addr_ignored_bits_mask simply get truncated.
>
> That might be reasonable -- we don't care about bits that don't exist
> for compat, irrespective of what they mean for native -- but it's
> probably worth a comment.

If the signal originates from a compat process then I would expect the
addresses involved in the fault to be 32 bits wide, so I would not
expect there to be any truncation in practice. The situation is the
same for si_addr I think. I can leave a comment here.

> >       }
> >
> >       switch (layout) {
> > @@ -3347,6 +3355,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> >               to->si_trapno = from->si_trapno;
> >  #endif
> >               to->si_xflags = from->si_xflags;
> > +             to->si_addr_ignored_bits = from->si_addr_ignored_bits;
> > +             to->si_addr_ignored_bits_mask = from->si_addr_ignored_bits_mask;
>
> Otherwise, the patch looks reasonable.

Thanks for the review.

Peter

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 6/7] signal: define the field siginfo.si_xflags
  2020-10-08  2:11       ` Peter Collingbourne
@ 2020-10-09 18:19         ` Peter Collingbourne
  -1 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-10-09 18:19 UTC (permalink / raw)
  To: Dave Martin
  Cc: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Will Deacon, Oleg Nesterov, Eric W. Biederman,
	James E.J. Bottomley, Parisc List, Andrey Konovalov,
	Kevin Brodsky, David Spickett, Linux ARM, Richard Henderson

On Wed, Oct 7, 2020 at 7:11 PM Peter Collingbourne <pcc@google.com> wrote:
>
> On Tue, Sep 8, 2020 at 8:13 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Fri, Aug 21, 2020 at 10:10:16PM -0700, Peter Collingbourne wrote:
> >
> > [ Add a new siginfo member sa_xflags, for fault signals. ]
>
> Will fix.
>
> > > This field will contain flags that may be used by signal handlers to
> > > determine whether other fields in the _sigfault portion of siginfo are
> > > valid. An example use case is the following patch, which introduces
> > > the si_addr_ignored_bits{,_mask} fields.
> > >
> > > A new sigcontext flag, SA_XFLAGS, is introduced in order to allow
> > > a signal handler to require the kernel to set the field (but note
> > > that the field will be set anyway if the kernel supports the flag,
> > > regardless of its value). In combination with the previous patches,
> > > this allows a userspace program to determine whether the kernel will
> > > set the field.
> > >
> > > It is possible for an si_xflags-unaware program to cause a signal
> > > handler in an si_xflags-aware program to be called with a provided
> > > siginfo data structure by using one of the following syscalls:
> > >
> > > - ptrace(PTRACE_SETSIGINFO)
> > > - pidfd_send_signal
> > > - rt_sigqueueinfo
> > > - rt_tgsigqueueinfo
> > >
> > > So we need to prevent the si_xflags-unaware program from causing an
> > > uninitialized read of si_xflags in the si_xflags-aware program when
> > > it uses one of these syscalls.
> > >
> > > The last three cases can be handled by observing that each of these
> > > syscalls fails if si_code >= 0, so we define si_xflags to only be
> > > valid if si_code >= 0.
> >
> > I would say >.  0 is SI_USER, and the fact that those other interfaces
> > reject SI_USER seems inconsistent or a bug.
> >
> > We can always relax the rule later.
> >
> > Since si_xflags only makes sense for "real" fault signals, it would
> > never be applicable in combination with SI_USER.  Or am I missing
> > something?
> >
> > Either way, I think this is just a documentation ossue in practice.
>
> I think you're right. kill(2) and tgkill(2) set si_code to SI_USER, so
> excluding SI_USER seems to be necessary to avoid an invalid read via
> either of these syscalls. I will update the comment to say > 0.
>
> > >
> > > There is no such check on si_code in ptrace(PTRACE_SETSIGINFO), so
> > > we make ptrace(PTRACE_SETSIGINFO) clear the si_xflags field if it
> > > detects that the signal would use the _sigfault layout, and introduce
> > > a new ptrace request type, PTRACE_SETSIGINFO2, that a si_xflags-aware
> > > program may use to opt out of this behavior.
> >
> > Will we need to introduce PTRACE_SETSIGINFO3, 4 etc., every time a new
> > field comes up?
> >
> > I wonder whether we should make this more flexible, say accepting some
> > flags argument to say which fields the caller understands (and so
> > doesn't want clobbered).  Maybe we can (ab)use the sa_flags bit
> > definitions for indicating which extensions the caller understands.
>
> I'd be okay with adding a flags argument here, to be passed via the
> addr argument to PTRACE_SETSIGINFO2. (Confusingly, in some of the
> ptrace request types including the ones that deal with siginfo "data"
> is the argument that takes an address and "addr" is the one that takes
> something else! My new request type will do the same to make things
> consistently confusing.)
>
> I guess we would only require a new "out of band" signaling mechanism
> if we were adding a field to a different union member (presumably a
> flags field to support the kind of future expansion that we anticipate
> for sigfault), since for sigfault we may indicate presence of new
> fields using si_xflags. Presumably such a field would come at the same
> time as a new SA_* bit for detecting its presence, so I suppose that
> we could use the sa_flags bits here as well. I'm not entirely
> comfortable with that though because the other SA_* bits wouldn't make
> sense to be passed as an argument here (and because of the
> architecture dependence that made it so hard to find free SA_* bits to
> add, we would be unnecessarily restricted in the number of bits that
> we could easily add here), and in the future someone may come up with
> a reason to pass a new flag here that wouldn't correspond to an SA_*
> bit. So I would mildly prefer a new set of bit definitions.
>
> It's unfortunate that the addr argument for PTRACE_SETSIGINFO was
> specified to be ignored rather than causing an error for non-zero
> values, as otherwise we could have used it as the flags argument to
> the existing request type and avoided adding a new one. Of course,
> this is the same issue that has caused us so much grief with
> sigaction. But for the new request type we can do things properly and
> require addr to have only recognized bits set.
>
> > > It is also possible for the kernel to inject a signal specified to
> > > use _sigfault by calling force_sig (e.g. there are numerous calls to
> > > force_sig(SIGSEGV)). In this case si_code is set to SI_KERNEL and the
> > > _kill union member is used, so document that si_code must be < SI_KERNEL.
> >
> > Ack.  I'm still wondering if some of those SIGSEGV/SI_KERNEL instances
> > should be changed to one of the standard SIGSEGV codes, but either way,
> > having si_xflags validity require si_code < SI_KERNEL seems appropriate.
> >
> >
> > > Ideally this field could have just been named si_flags, but that
> > > name was already taken by ia64, so a different name was chosen.
> > >
> > > Alternatively, we may consider making ia64's si_flags a generic field
> > > and having it appear at the end of _sigfault (in the same place as
> > > this patch has si_xflags) on non-ia64, keeping it in the same place
> > > on ia64. ia64's si_flags is a 32-bit field with only one flag bit
> > > allocated, so we would have 31 bits to use if we do this.
> >
> > Hmm, that might be an idea.
> >
> > It would mean that x86 would have different rules from other
> > architectures regarding how to know when the field is valid, which might
> > lull x86-first projects into a false sense of security.  Perhaps we could
>
> ia64 is Itanium, not x86. And ia64 is almost dead (I heard that gcc
> was planning to remove support some time next year [1], which I expect
> would be followed soon after by dropping kernel support). So I
> wouldn't expect there to be a lot of ia64-first projects out there.
>
> [1] https://www.phoronix.com/scan.php?page=news_item&px=Intel-IA-64-GCC-Deprecation
>
> > refuse to expose any of the arch-independent flags in si_flags unless
> > explicitly requested via SA_XFLAGS, but that would be a departure from
> > what this series implements today.
> >
> > So maybe it's simpler to keep the two fields separate, unless somebody
> > objects.
>
> Notwithstanding the above, I would be mildly in favor of keeping them
> separate in order to avoid the complexity implied by entangling them,
> since it's complex enough to add fields here as it is.
>
> > >
> > > Signed-off-by: Peter Collingbourne <pcc@google.com>
> > > ---
> > > View this change in Gerrit: https://linux-review.googlesource.com/q/Ide155ce29366c3eab2a944ae4c51205982e5b8b2
> > >
> > > v10:
> > > - make the new field compatible with the various ways
> > >   that a siginfo can be injected from another process
> > > - eliminate some duplication by adding a refactoring patch
> > >   before this one
> > >
> > >  arch/powerpc/platforms/powernv/vas-fault.c |  1 +
> > >  arch/x86/kernel/signal_compat.c            |  4 +--
> > >  include/linux/compat.h                     |  2 ++
> > >  include/linux/signal_types.h               |  2 +-
> > >  include/uapi/asm-generic/siginfo.h         |  4 +++
> > >  include/uapi/asm-generic/signal-defs.h     |  4 +++
> > >  include/uapi/linux/ptrace.h                |  2 ++
> > >  kernel/ptrace.c                            | 29 ++++++++++++++++++++++
> > >  kernel/signal.c                            |  3 +++
> > >  9 files changed, 48 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/arch/powerpc/platforms/powernv/vas-fault.c b/arch/powerpc/platforms/powernv/vas-fault.c
> > > index 3d21fce254b7..3bbb335561f5 100644
> > > --- a/arch/powerpc/platforms/powernv/vas-fault.c
> > > +++ b/arch/powerpc/platforms/powernv/vas-fault.c
> > > @@ -154,6 +154,7 @@ static void update_csb(struct vas_window *window,
> > >       info.si_errno = EFAULT;
> > >       info.si_code = SEGV_MAPERR;
> > >       info.si_addr = csb_addr;
> > > +     info.si_xflags = 0;
> > >
> > >       /*
> > >        * process will be polling on csb.flags after request is sent to
> > > diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
> > > index c599013ae8cb..6b99f0c8a068 100644
> > > --- a/arch/x86/kernel/signal_compat.c
> > > +++ b/arch/x86/kernel/signal_compat.c
> > > @@ -121,8 +121,8 @@ static inline void signal_compat_build_tests(void)
> > >  #endif
> > >
> > >       CHECK_CSI_OFFSET(_sigfault);
> > > -     CHECK_CSI_SIZE  (_sigfault, 4*sizeof(int));
> > > -     CHECK_SI_SIZE   (_sigfault, 8*sizeof(int));
> > > +     CHECK_CSI_SIZE  (_sigfault, 8*sizeof(int));
> > > +     CHECK_SI_SIZE   (_sigfault, 16*sizeof(int));
> >
> > (Yuk, but at least you make this no worse.)
> >
> > >
> > >       BUILD_BUG_ON(offsetof(siginfo_t, si_addr) != 0x10);
> > >       BUILD_BUG_ON(offsetof(compat_siginfo_t, si_addr) != 0x0C);
> > > diff --git a/include/linux/compat.h b/include/linux/compat.h
> > > index d38c4d7e83bd..55d4228dfd88 100644
> > > --- a/include/linux/compat.h
> > > +++ b/include/linux/compat.h
> > > @@ -231,7 +231,9 @@ typedef struct compat_siginfo {
> > >                                       char _dummy_pkey[__COMPAT_ADDR_BND_PKEY_PAD];
> > >                                       u32 _pkey;
> > >                               } _addr_pkey;
> > > +                             compat_uptr_t _pad[6];
> > >                       };
> > > +                     compat_uptr_t _xflags;
> >
> > Should we have the same type here for native and compat?
> >
> > I don't have a very strong opinion on this, but currently native on
> > 64-bit arches will have 32 extra bits in _xflags that can never be used
> > (or have to be defined differently for compat).
>
> Good point. I will make this a u64 (although I think 32 bits will
> probably be more than enough, the distance between si_xflags and
> si_addr_ignored_bits will be 8 bytes on 64-bit architectures due to
> alignment so we may as well make all of the bits available).

It turns out that we can't actually make this a u64 because on 32-bit
platforms this increases the alignment of the union to 8, which breaks
layout for the other fields in the union. In v12 I will make this a
u32 so that we don't end up with unusable bits.

Peter

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 6/7] signal: define the field siginfo.si_xflags
@ 2020-10-09 18:19         ` Peter Collingbourne
  0 siblings, 0 replies; 59+ messages in thread
From: Peter Collingbourne @ 2020-10-09 18:19 UTC (permalink / raw)
  To: Dave Martin
  Cc: Linux ARM, Parisc List, Catalin Marinas, Kevin Brodsky,
	Oleg Nesterov, James E.J. Bottomley, Kostya Serebryany,
	Eric W. Biederman, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Will Deacon, Evgenii Stepanov,
	Richard Henderson

On Wed, Oct 7, 2020 at 7:11 PM Peter Collingbourne <pcc@google.com> wrote:
>
> On Tue, Sep 8, 2020 at 8:13 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Fri, Aug 21, 2020 at 10:10:16PM -0700, Peter Collingbourne wrote:
> >
> > [ Add a new siginfo member sa_xflags, for fault signals. ]
>
> Will fix.
>
> > > This field will contain flags that may be used by signal handlers to
> > > determine whether other fields in the _sigfault portion of siginfo are
> > > valid. An example use case is the following patch, which introduces
> > > the si_addr_ignored_bits{,_mask} fields.
> > >
> > > A new sigcontext flag, SA_XFLAGS, is introduced in order to allow
> > > a signal handler to require the kernel to set the field (but note
> > > that the field will be set anyway if the kernel supports the flag,
> > > regardless of its value). In combination with the previous patches,
> > > this allows a userspace program to determine whether the kernel will
> > > set the field.
> > >
> > > It is possible for an si_xflags-unaware program to cause a signal
> > > handler in an si_xflags-aware program to be called with a provided
> > > siginfo data structure by using one of the following syscalls:
> > >
> > > - ptrace(PTRACE_SETSIGINFO)
> > > - pidfd_send_signal
> > > - rt_sigqueueinfo
> > > - rt_tgsigqueueinfo
> > >
> > > So we need to prevent the si_xflags-unaware program from causing an
> > > uninitialized read of si_xflags in the si_xflags-aware program when
> > > it uses one of these syscalls.
> > >
> > > The last three cases can be handled by observing that each of these
> > > syscalls fails if si_code >= 0, so we define si_xflags to only be
> > > valid if si_code >= 0.
> >
> > I would say >.  0 is SI_USER, and the fact that those other interfaces
> > reject SI_USER seems inconsistent or a bug.
> >
> > We can always relax the rule later.
> >
> > Since si_xflags only makes sense for "real" fault signals, it would
> > never be applicable in combination with SI_USER.  Or am I missing
> > something?
> >
> > Either way, I think this is just a documentation ossue in practice.
>
> I think you're right. kill(2) and tgkill(2) set si_code to SI_USER, so
> excluding SI_USER seems to be necessary to avoid an invalid read via
> either of these syscalls. I will update the comment to say > 0.
>
> > >
> > > There is no such check on si_code in ptrace(PTRACE_SETSIGINFO), so
> > > we make ptrace(PTRACE_SETSIGINFO) clear the si_xflags field if it
> > > detects that the signal would use the _sigfault layout, and introduce
> > > a new ptrace request type, PTRACE_SETSIGINFO2, that a si_xflags-aware
> > > program may use to opt out of this behavior.
> >
> > Will we need to introduce PTRACE_SETSIGINFO3, 4 etc., every time a new
> > field comes up?
> >
> > I wonder whether we should make this more flexible, say accepting some
> > flags argument to say which fields the caller understands (and so
> > doesn't want clobbered).  Maybe we can (ab)use the sa_flags bit
> > definitions for indicating which extensions the caller understands.
>
> I'd be okay with adding a flags argument here, to be passed via the
> addr argument to PTRACE_SETSIGINFO2. (Confusingly, in some of the
> ptrace request types including the ones that deal with siginfo "data"
> is the argument that takes an address and "addr" is the one that takes
> something else! My new request type will do the same to make things
> consistently confusing.)
>
> I guess we would only require a new "out of band" signaling mechanism
> if we were adding a field to a different union member (presumably a
> flags field to support the kind of future expansion that we anticipate
> for sigfault), since for sigfault we may indicate presence of new
> fields using si_xflags. Presumably such a field would come at the same
> time as a new SA_* bit for detecting its presence, so I suppose that
> we could use the sa_flags bits here as well. I'm not entirely
> comfortable with that though because the other SA_* bits wouldn't make
> sense to be passed as an argument here (and because of the
> architecture dependence that made it so hard to find free SA_* bits to
> add, we would be unnecessarily restricted in the number of bits that
> we could easily add here), and in the future someone may come up with
> a reason to pass a new flag here that wouldn't correspond to an SA_*
> bit. So I would mildly prefer a new set of bit definitions.
>
> It's unfortunate that the addr argument for PTRACE_SETSIGINFO was
> specified to be ignored rather than causing an error for non-zero
> values, as otherwise we could have used it as the flags argument to
> the existing request type and avoided adding a new one. Of course,
> this is the same issue that has caused us so much grief with
> sigaction. But for the new request type we can do things properly and
> require addr to have only recognized bits set.
>
> > > It is also possible for the kernel to inject a signal specified to
> > > use _sigfault by calling force_sig (e.g. there are numerous calls to
> > > force_sig(SIGSEGV)). In this case si_code is set to SI_KERNEL and the
> > > _kill union member is used, so document that si_code must be < SI_KERNEL.
> >
> > Ack.  I'm still wondering if some of those SIGSEGV/SI_KERNEL instances
> > should be changed to one of the standard SIGSEGV codes, but either way,
> > having si_xflags validity require si_code < SI_KERNEL seems appropriate.
> >
> >
> > > Ideally this field could have just been named si_flags, but that
> > > name was already taken by ia64, so a different name was chosen.
> > >
> > > Alternatively, we may consider making ia64's si_flags a generic field
> > > and having it appear at the end of _sigfault (in the same place as
> > > this patch has si_xflags) on non-ia64, keeping it in the same place
> > > on ia64. ia64's si_flags is a 32-bit field with only one flag bit
> > > allocated, so we would have 31 bits to use if we do this.
> >
> > Hmm, that might be an idea.
> >
> > It would mean that x86 would have different rules from other
> > architectures regarding how to know when the field is valid, which might
> > lull x86-first projects into a false sense of security.  Perhaps we could
>
> ia64 is Itanium, not x86. And ia64 is almost dead (I heard that gcc
> was planning to remove support some time next year [1], which I expect
> would be followed soon after by dropping kernel support). So I
> wouldn't expect there to be a lot of ia64-first projects out there.
>
> [1] https://www.phoronix.com/scan.php?page=news_item&px=Intel-IA-64-GCC-Deprecation
>
> > refuse to expose any of the arch-independent flags in si_flags unless
> > explicitly requested via SA_XFLAGS, but that would be a departure from
> > what this series implements today.
> >
> > So maybe it's simpler to keep the two fields separate, unless somebody
> > objects.
>
> Notwithstanding the above, I would be mildly in favor of keeping them
> separate in order to avoid the complexity implied by entangling them,
> since it's complex enough to add fields here as it is.
>
> > >
> > > Signed-off-by: Peter Collingbourne <pcc@google.com>
> > > ---
> > > View this change in Gerrit: https://linux-review.googlesource.com/q/Ide155ce29366c3eab2a944ae4c51205982e5b8b2
> > >
> > > v10:
> > > - make the new field compatible with the various ways
> > >   that a siginfo can be injected from another process
> > > - eliminate some duplication by adding a refactoring patch
> > >   before this one
> > >
> > >  arch/powerpc/platforms/powernv/vas-fault.c |  1 +
> > >  arch/x86/kernel/signal_compat.c            |  4 +--
> > >  include/linux/compat.h                     |  2 ++
> > >  include/linux/signal_types.h               |  2 +-
> > >  include/uapi/asm-generic/siginfo.h         |  4 +++
> > >  include/uapi/asm-generic/signal-defs.h     |  4 +++
> > >  include/uapi/linux/ptrace.h                |  2 ++
> > >  kernel/ptrace.c                            | 29 ++++++++++++++++++++++
> > >  kernel/signal.c                            |  3 +++
> > >  9 files changed, 48 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/arch/powerpc/platforms/powernv/vas-fault.c b/arch/powerpc/platforms/powernv/vas-fault.c
> > > index 3d21fce254b7..3bbb335561f5 100644
> > > --- a/arch/powerpc/platforms/powernv/vas-fault.c
> > > +++ b/arch/powerpc/platforms/powernv/vas-fault.c
> > > @@ -154,6 +154,7 @@ static void update_csb(struct vas_window *window,
> > >       info.si_errno = EFAULT;
> > >       info.si_code = SEGV_MAPERR;
> > >       info.si_addr = csb_addr;
> > > +     info.si_xflags = 0;
> > >
> > >       /*
> > >        * process will be polling on csb.flags after request is sent to
> > > diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
> > > index c599013ae8cb..6b99f0c8a068 100644
> > > --- a/arch/x86/kernel/signal_compat.c
> > > +++ b/arch/x86/kernel/signal_compat.c
> > > @@ -121,8 +121,8 @@ static inline void signal_compat_build_tests(void)
> > >  #endif
> > >
> > >       CHECK_CSI_OFFSET(_sigfault);
> > > -     CHECK_CSI_SIZE  (_sigfault, 4*sizeof(int));
> > > -     CHECK_SI_SIZE   (_sigfault, 8*sizeof(int));
> > > +     CHECK_CSI_SIZE  (_sigfault, 8*sizeof(int));
> > > +     CHECK_SI_SIZE   (_sigfault, 16*sizeof(int));
> >
> > (Yuk, but at least you make this no worse.)
> >
> > >
> > >       BUILD_BUG_ON(offsetof(siginfo_t, si_addr) != 0x10);
> > >       BUILD_BUG_ON(offsetof(compat_siginfo_t, si_addr) != 0x0C);
> > > diff --git a/include/linux/compat.h b/include/linux/compat.h
> > > index d38c4d7e83bd..55d4228dfd88 100644
> > > --- a/include/linux/compat.h
> > > +++ b/include/linux/compat.h
> > > @@ -231,7 +231,9 @@ typedef struct compat_siginfo {
> > >                                       char _dummy_pkey[__COMPAT_ADDR_BND_PKEY_PAD];
> > >                                       u32 _pkey;
> > >                               } _addr_pkey;
> > > +                             compat_uptr_t _pad[6];
> > >                       };
> > > +                     compat_uptr_t _xflags;
> >
> > Should we have the same type here for native and compat?
> >
> > I don't have a very strong opinion on this, but currently native on
> > 64-bit arches will have 32 extra bits in _xflags that can never be used
> > (or have to be defined differently for compat).
>
> Good point. I will make this a u64 (although I think 32 bits will
> probably be more than enough, the distance between si_xflags and
> si_addr_ignored_bits will be 8 bytes on 64-bit architectures due to
> alignment so we may as well make all of the bits available).

It turns out that we can't actually make this a u64 because on 32-bit
platforms this increases the alignment of the union to 8, which breaks
layout for the other fields in the union. In v12 I will make this a
u32 so that we don't end up with unusable bits.

Peter

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 4/7] signal: define the SA_UNSUPPORTED bit in sa_flags
  2020-10-08  2:21       ` Peter Collingbourne
@ 2020-10-12 13:37         ` Dave Martin
  -1 siblings, 0 replies; 59+ messages in thread
From: Dave Martin @ 2020-10-12 13:37 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Linux ARM, Parisc List, Catalin Marinas, Kevin Brodsky,
	Oleg Nesterov, James E.J. Bottomley, Kostya Serebryany,
	Eric W. Biederman, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Will Deacon, Evgenii Stepanov,
	Richard Henderson

On Wed, Oct 07, 2020 at 07:21:25PM -0700, Peter Collingbourne wrote:
> On Tue, Sep 8, 2020 at 8:13 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Fri, Aug 21, 2020 at 10:10:14PM -0700, Peter Collingbourne wrote:
> >
> > Nit: no statement of the chage being made (other than in the subject
> > line).
> 
> Will fix.
> 
> > > This bit will never be supported in the uapi. The purpose of this flag
> > > bit is to allow userspace to distinguish an old kernel that does not
> > > clear unknown sa_flags bits from a kernel that supports every flag bit.
> > >
> > > In other words, if userspace finds that this bit remains set in
> > > oldact.sa_flags, it means that the kernel cannot be trusted to have
> > > cleared unknown flag bits from sa_flags, so no assumptions about flag
> > > bit support can be made.
> >
> > This isn't quite right?  After a single sigaction() call, oact will
> > contain the sa_flags for the previously registered handler.  So a
> > second sigaction() call would be needed to find out the newly effective
> > sa_flags.
> 
> You're right, this is unclear to say the least. In v11 I will reword like so:
> 
>     In other words, if userspace does something like:
> 
>       act.sa_flags |= SA_UNSUPPORTED;
>       sigaction(SIGSEGV, &act, 0);
>       sigaction(SIGSEGV, 0, &oldact);
> 
>     and finds that SA_UNSUPPORTED remains set in oldact.sa_flags, it means
>     that the kernel cannot be trusted to have cleared unknown flag bits
>     from sa_flags, so no assumptions about flag bit support can be made.

Seems reasonable.  We'd need to make sure we're clear about which flags
this applies for, though.  The pre-existing flags can be assumed to be
supported irrespective of whether SA_UNSUPPORTED remains set.

Cheers
---Dave

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 4/7] signal: define the SA_UNSUPPORTED bit in sa_flags
@ 2020-10-12 13:37         ` Dave Martin
  0 siblings, 0 replies; 59+ messages in thread
From: Dave Martin @ 2020-10-12 13:37 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Parisc List, Catalin Marinas, Kevin Brodsky, Oleg Nesterov,
	Evgenii Stepanov, James E.J. Bottomley, Kostya Serebryany,
	Eric W. Biederman, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Will Deacon, Linux ARM, Richard Henderson

On Wed, Oct 07, 2020 at 07:21:25PM -0700, Peter Collingbourne wrote:
> On Tue, Sep 8, 2020 at 8:13 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Fri, Aug 21, 2020 at 10:10:14PM -0700, Peter Collingbourne wrote:
> >
> > Nit: no statement of the chage being made (other than in the subject
> > line).
> 
> Will fix.
> 
> > > This bit will never be supported in the uapi. The purpose of this flag
> > > bit is to allow userspace to distinguish an old kernel that does not
> > > clear unknown sa_flags bits from a kernel that supports every flag bit.
> > >
> > > In other words, if userspace finds that this bit remains set in
> > > oldact.sa_flags, it means that the kernel cannot be trusted to have
> > > cleared unknown flag bits from sa_flags, so no assumptions about flag
> > > bit support can be made.
> >
> > This isn't quite right?  After a single sigaction() call, oact will
> > contain the sa_flags for the previously registered handler.  So a
> > second sigaction() call would be needed to find out the newly effective
> > sa_flags.
> 
> You're right, this is unclear to say the least. In v11 I will reword like so:
> 
>     In other words, if userspace does something like:
> 
>       act.sa_flags |= SA_UNSUPPORTED;
>       sigaction(SIGSEGV, &act, 0);
>       sigaction(SIGSEGV, 0, &oldact);
> 
>     and finds that SA_UNSUPPORTED remains set in oldact.sa_flags, it means
>     that the kernel cannot be trusted to have cleared unknown flag bits
>     from sa_flags, so no assumptions about flag bit support can be made.

Seems reasonable.  We'd need to make sure we're clear about which flags
this applies for, though.  The pre-existing flags can be assumed to be
supported irrespective of whether SA_UNSUPPORTED remains set.

Cheers
---Dave

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 6/7] signal: define the field siginfo.si_xflags
  2020-10-08  2:11       ` Peter Collingbourne
@ 2020-10-12 13:55         ` Dave Martin
  -1 siblings, 0 replies; 59+ messages in thread
From: Dave Martin @ 2020-10-12 13:55 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Linux ARM, Parisc List, Catalin Marinas, Kevin Brodsky,
	Oleg Nesterov, James E.J. Bottomley, Kostya Serebryany,
	Eric W. Biederman, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Will Deacon, Evgenii Stepanov,
	Richard Henderson

On Wed, Oct 07, 2020 at 07:11:07PM -0700, Peter Collingbourne wrote:
> On Tue, Sep 8, 2020 at 8:13 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Fri, Aug 21, 2020 at 10:10:16PM -0700, Peter Collingbourne wrote:
> >
> > [ Add a new siginfo member sa_xflags, for fault signals. ]
> 
> Will fix.
> 
> > > This field will contain flags that may be used by signal handlers to
> > > determine whether other fields in the _sigfault portion of siginfo are
> > > valid. An example use case is the following patch, which introduces
> > > the si_addr_ignored_bits{,_mask} fields.
> > >
> > > A new sigcontext flag, SA_XFLAGS, is introduced in order to allow
> > > a signal handler to require the kernel to set the field (but note
> > > that the field will be set anyway if the kernel supports the flag,
> > > regardless of its value). In combination with the previous patches,
> > > this allows a userspace program to determine whether the kernel will
> > > set the field.
> > >
> > > It is possible for an si_xflags-unaware program to cause a signal
> > > handler in an si_xflags-aware program to be called with a provided
> > > siginfo data structure by using one of the following syscalls:
> > >
> > > - ptrace(PTRACE_SETSIGINFO)
> > > - pidfd_send_signal
> > > - rt_sigqueueinfo
> > > - rt_tgsigqueueinfo
> > >
> > > So we need to prevent the si_xflags-unaware program from causing an
> > > uninitialized read of si_xflags in the si_xflags-aware program when
> > > it uses one of these syscalls.
> > >
> > > The last three cases can be handled by observing that each of these
> > > syscalls fails if si_code >= 0, so we define si_xflags to only be
> > > valid if si_code >= 0.
> >
> > I would say >.  0 is SI_USER, and the fact that those other interfaces
> > reject SI_USER seems inconsistent or a bug.
> >
> > We can always relax the rule later.
> >
> > Since si_xflags only makes sense for "real" fault signals, it would
> > never be applicable in combination with SI_USER.  Or am I missing
> > something?
> >
> > Either way, I think this is just a documentation ossue in practice.
> 
> I think you're right. kill(2) and tgkill(2) set si_code to SI_USER, so
> excluding SI_USER seems to be necessary to avoid an invalid read via
> either of these syscalls. I will update the comment to say > 0.

OK, makes sense.


> > > There is no such check on si_code in ptrace(PTRACE_SETSIGINFO), so
> > > we make ptrace(PTRACE_SETSIGINFO) clear the si_xflags field if it
> > > detects that the signal would use the _sigfault layout, and introduce
> > > a new ptrace request type, PTRACE_SETSIGINFO2, that a si_xflags-aware
> > > program may use to opt out of this behavior.
> >
> > Will we need to introduce PTRACE_SETSIGINFO3, 4 etc., every time a new
> > field comes up?
> >
> > I wonder whether we should make this more flexible, say accepting some
> > flags argument to say which fields the caller understands (and so
> > doesn't want clobbered).  Maybe we can (ab)use the sa_flags bit
> > definitions for indicating which extensions the caller understands.
> 
> I'd be okay with adding a flags argument here, to be passed via the
> addr argument to PTRACE_SETSIGINFO2. (Confusingly, in some of the
> ptrace request types including the ones that deal with siginfo "data"
> is the argument that takes an address and "addr" is the one that takes
> something else! My new request type will do the same to make things
> consistently confusing.)

So long as we try to follow the existing pattern for similar ptrace
calls, I guess people will cope with it.

If we make the argument a struct pointer, we have the option to expand
it later if needed, provided that the initial definition of the struct
members provides a way to discover such extensions (i.e., the initial
struct needs space for a flag indicating this, or an indication of the
struct size, or similar).

> I guess we would only require a new "out of band" signaling mechanism
> if we were adding a field to a different union member (presumably a
> flags field to support the kind of future expansion that we anticipate
> for sigfault), since for sigfault we may indicate presence of new
> fields using si_xflags. Presumably such a field would come at the same
> time as a new SA_* bit for detecting its presence, so I suppose that
> we could use the sa_flags bits here as well. I'm not entirely
> comfortable with that though because the other SA_* bits wouldn't make
> sense to be passed as an argument here (and because of the
> architecture dependence that made it so hard to find free SA_* bits to
> add, we would be unnecessarily restricted in the number of bits that
> we could easily add here), and in the future someone may come up with
> a reason to pass a new flag here that wouldn't correspond to an SA_*
> bit. So I would mildly prefer a new set of bit definitions.

We don't need to use the sa_flags bit definitions here if that's likely
to be problematic.

I don't really have a strong opinion either way though.

> It's unfortunate that the addr argument for PTRACE_SETSIGINFO was
> specified to be ignored rather than causing an error for non-zero
> values, as otherwise we could have used it as the flags argument to
> the existing request type and avoided adding a new one. Of course,
> this is the same issue that has caused us so much grief with
> sigaction. But for the new request type we can do things properly and
> require addr to have only recognized bits set.

Ack

> > > It is also possible for the kernel to inject a signal specified to
> > > use _sigfault by calling force_sig (e.g. there are numerous calls to
> > > force_sig(SIGSEGV)). In this case si_code is set to SI_KERNEL and the
> > > _kill union member is used, so document that si_code must be < SI_KERNEL.
> >
> > Ack.  I'm still wondering if some of those SIGSEGV/SI_KERNEL instances
> > should be changed to one of the standard SIGSEGV codes, but either way,
> > having si_xflags validity require si_code < SI_KERNEL seems appropriate.
> >
> >
> > > Ideally this field could have just been named si_flags, but that
> > > name was already taken by ia64, so a different name was chosen.
> > >
> > > Alternatively, we may consider making ia64's si_flags a generic field
> > > and having it appear at the end of _sigfault (in the same place as
> > > this patch has si_xflags) on non-ia64, keeping it in the same place
> > > on ia64. ia64's si_flags is a 32-bit field with only one flag bit
> > > allocated, so we would have 31 bits to use if we do this.
> >
> > Hmm, that might be an idea.
> >
> > It would mean that x86 would have different rules from other
> > architectures regarding how to know when the field is valid, which might
> > lull x86-first projects into a false sense of security.  Perhaps we could
> 
> ia64 is Itanium, not x86. And ia64 is almost dead (I heard that gcc
> was planning to remove support some time next year [1], which I expect
> would be followed soon after by dropping kernel support). So I
> wouldn't expect there to be a lot of ia64-first projects out there.
> 
> [1] https://www.phoronix.com/scan.php?page=news_item&px=Intel-IA-64-GCC-Deprecation

Ack, I knew this but I guess I skim-read your text too quickly and only
saw the "64"...

> > refuse to expose any of the arch-independent flags in si_flags unless
> > explicitly requested via SA_XFLAGS, but that would be a departure from
> > what this series implements today.
> >
> > So maybe it's simpler to keep the two fields separate, unless somebody
> > objects.
> 
> Notwithstanding the above, I would be mildly in favor of keeping them
> separate in order to avoid the complexity implied by entangling them,
> since it's complex enough to add fields here as it is.
> 
> > >
> > > Signed-off-by: Peter Collingbourne <pcc@google.com>
> > > ---
> > > View this change in Gerrit: https://linux-review.googlesource.com/q/Ide155ce29366c3eab2a944ae4c51205982e5b8b2
> > >
> > > v10:
> > > - make the new field compatible with the various ways
> > >   that a siginfo can be injected from another process
> > > - eliminate some duplication by adding a refactoring patch
> > >   before this one
> > >
> > >  arch/powerpc/platforms/powernv/vas-fault.c |  1 +
> > >  arch/x86/kernel/signal_compat.c            |  4 +--
> > >  include/linux/compat.h                     |  2 ++
> > >  include/linux/signal_types.h               |  2 +-
> > >  include/uapi/asm-generic/siginfo.h         |  4 +++
> > >  include/uapi/asm-generic/signal-defs.h     |  4 +++
> > >  include/uapi/linux/ptrace.h                |  2 ++
> > >  kernel/ptrace.c                            | 29 ++++++++++++++++++++++
> > >  kernel/signal.c                            |  3 +++
> > >  9 files changed, 48 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/arch/powerpc/platforms/powernv/vas-fault.c b/arch/powerpc/platforms/powernv/vas-fault.c
> > > index 3d21fce254b7..3bbb335561f5 100644
> > > --- a/arch/powerpc/platforms/powernv/vas-fault.c
> > > +++ b/arch/powerpc/platforms/powernv/vas-fault.c
> > > @@ -154,6 +154,7 @@ static void update_csb(struct vas_window *window,
> > >       info.si_errno = EFAULT;
> > >       info.si_code = SEGV_MAPERR;
> > >       info.si_addr = csb_addr;
> > > +     info.si_xflags = 0;
> > >
> > >       /*
> > >        * process will be polling on csb.flags after request is sent to
> > > diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
> > > index c599013ae8cb..6b99f0c8a068 100644
> > > --- a/arch/x86/kernel/signal_compat.c
> > > +++ b/arch/x86/kernel/signal_compat.c
> > > @@ -121,8 +121,8 @@ static inline void signal_compat_build_tests(void)
> > >  #endif
> > >
> > >       CHECK_CSI_OFFSET(_sigfault);
> > > -     CHECK_CSI_SIZE  (_sigfault, 4*sizeof(int));
> > > -     CHECK_SI_SIZE   (_sigfault, 8*sizeof(int));
> > > +     CHECK_CSI_SIZE  (_sigfault, 8*sizeof(int));
> > > +     CHECK_SI_SIZE   (_sigfault, 16*sizeof(int));
> >
> > (Yuk, but at least you make this no worse.)
> >
> > >
> > >       BUILD_BUG_ON(offsetof(siginfo_t, si_addr) != 0x10);
> > >       BUILD_BUG_ON(offsetof(compat_siginfo_t, si_addr) != 0x0C);
> > > diff --git a/include/linux/compat.h b/include/linux/compat.h
> > > index d38c4d7e83bd..55d4228dfd88 100644
> > > --- a/include/linux/compat.h
> > > +++ b/include/linux/compat.h
> > > @@ -231,7 +231,9 @@ typedef struct compat_siginfo {
> > >                                       char _dummy_pkey[__COMPAT_ADDR_BND_PKEY_PAD];
> > >                                       u32 _pkey;
> > >                               } _addr_pkey;
> > > +                             compat_uptr_t _pad[6];
> > >                       };
> > > +                     compat_uptr_t _xflags;
> >
> > Should we have the same type here for native and compat?
> >
> > I don't have a very strong opinion on this, but currently native on
> > 64-bit arches will have 32 extra bits in _xflags that can never be used
> > (or have to be defined differently for compat).
> 
> Good point. I will make this a u64 (although I think 32 bits will
> probably be more than enough, the distance between si_xflags and
> si_addr_ignored_bits will be 8 bytes on 64-bit architectures due to
> alignment so we may as well make all of the bits available).

Ack

> > >               } _sigfault;
> > >
> > >               /* SIGPOLL */
> > > diff --git a/include/linux/signal_types.h b/include/linux/signal_types.h
> > > index a7887ad84d36..75ca861d982a 100644
> > > --- a/include/linux/signal_types.h
> > > +++ b/include/linux/signal_types.h
> > > @@ -78,6 +78,6 @@ struct ksignal {
> > >
> > >  #define UAPI_SA_FLAGS                                                          \
> > >       (SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
> > > -      SA_NODEFER | SA_RESETHAND | __ARCH_UAPI_SA_FLAGS)
> > > +      SA_NODEFER | SA_RESETHAND | SA_XFLAGS | __ARCH_UAPI_SA_FLAGS)
> > >
> > >  #endif /* _LINUX_SIGNAL_TYPES_H */
> > > diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
> > > index cb3d6c267181..1fbd88d64f38 100644
> > > --- a/include/uapi/asm-generic/siginfo.h
> > > +++ b/include/uapi/asm-generic/siginfo.h
> > > @@ -91,7 +91,9 @@ union __sifields {
> > >                               char _dummy_pkey[__ADDR_BND_PKEY_PAD];
> > >                               __u32 _pkey;
> > >                       } _addr_pkey;
> > > +                     void *_pad[6];
> >
> > 6?
> >
> > Obviously we'll need something here, but I'm curious as to where this
> > value came from.
> >
> > (Same for compat.)
> 
> I think it came from Eric's suggestion in [1], i.e. 2 words from the
> existing fields plus the 4 words of padding suggested by Eric.
> 
> [1] https://www.spinics.net/lists/arm-kernel/msg808618.html

So long as there's a reason for it, I guess I don't have a strong opinion.

> 
> > >               };
> > > +             unsigned long _xflags;
> > >       } _sigfault;
> > >
> > >       /* SIGPOLL */
> > > @@ -152,6 +154,8 @@ typedef struct siginfo {
> > >  #define si_trapno    _sifields._sigfault._trapno
> > >  #endif
> > >  #define si_addr_lsb  _sifields._sigfault._addr_lsb
> > > +/* si_xflags is only valid if 0 <= si_code < SI_KERNEL */
> > > +#define si_xflags    _sifields._sigfault._xflags
> > >  #define si_lower     _sifields._sigfault._addr_bnd._lower
> > >  #define si_upper     _sifields._sigfault._addr_bnd._upper
> > >  #define si_pkey              _sifields._sigfault._addr_pkey._pkey
> > > diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
> > > index e853cbe8722d..bdbe1fe7a779 100644
> > > --- a/include/uapi/asm-generic/signal-defs.h
> > > +++ b/include/uapi/asm-generic/signal-defs.h
> > > @@ -20,6 +20,9 @@
> > >   * so this bit allows flag bit support to be detected from userspace while
> > >   * allowing an old kernel to be distinguished from a kernel that supports every
> > >   * flag bit.
> > > + * SA_XFLAGS indicates that the signal handler requires the siginfo.si_xflags
> > > + * field to be valid. Note that if the kernel supports SA_XFLAGS, the field will
> >
> > Maybe "valid for fault signals (SIGSEGV etc.)"
> 
> Will add.
> 
> > [...]
> >
> > Otherwise, this looks sensible overall to me.
> 
> Thanks for the review. (And apologies for being slow to respond to
> your reviews. I got preempted by another task right after sending out
> v10 and only now did I get a chance to get back to this.)

No worries, I've had other stuff to do too...

Cheers
---Dave

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 6/7] signal: define the field siginfo.si_xflags
@ 2020-10-12 13:55         ` Dave Martin
  0 siblings, 0 replies; 59+ messages in thread
From: Dave Martin @ 2020-10-12 13:55 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Parisc List, Catalin Marinas, Kevin Brodsky, Oleg Nesterov,
	Evgenii Stepanov, James E.J. Bottomley, Kostya Serebryany,
	Eric W. Biederman, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Will Deacon, Linux ARM, Richard Henderson

On Wed, Oct 07, 2020 at 07:11:07PM -0700, Peter Collingbourne wrote:
> On Tue, Sep 8, 2020 at 8:13 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Fri, Aug 21, 2020 at 10:10:16PM -0700, Peter Collingbourne wrote:
> >
> > [ Add a new siginfo member sa_xflags, for fault signals. ]
> 
> Will fix.
> 
> > > This field will contain flags that may be used by signal handlers to
> > > determine whether other fields in the _sigfault portion of siginfo are
> > > valid. An example use case is the following patch, which introduces
> > > the si_addr_ignored_bits{,_mask} fields.
> > >
> > > A new sigcontext flag, SA_XFLAGS, is introduced in order to allow
> > > a signal handler to require the kernel to set the field (but note
> > > that the field will be set anyway if the kernel supports the flag,
> > > regardless of its value). In combination with the previous patches,
> > > this allows a userspace program to determine whether the kernel will
> > > set the field.
> > >
> > > It is possible for an si_xflags-unaware program to cause a signal
> > > handler in an si_xflags-aware program to be called with a provided
> > > siginfo data structure by using one of the following syscalls:
> > >
> > > - ptrace(PTRACE_SETSIGINFO)
> > > - pidfd_send_signal
> > > - rt_sigqueueinfo
> > > - rt_tgsigqueueinfo
> > >
> > > So we need to prevent the si_xflags-unaware program from causing an
> > > uninitialized read of si_xflags in the si_xflags-aware program when
> > > it uses one of these syscalls.
> > >
> > > The last three cases can be handled by observing that each of these
> > > syscalls fails if si_code >= 0, so we define si_xflags to only be
> > > valid if si_code >= 0.
> >
> > I would say >.  0 is SI_USER, and the fact that those other interfaces
> > reject SI_USER seems inconsistent or a bug.
> >
> > We can always relax the rule later.
> >
> > Since si_xflags only makes sense for "real" fault signals, it would
> > never be applicable in combination with SI_USER.  Or am I missing
> > something?
> >
> > Either way, I think this is just a documentation ossue in practice.
> 
> I think you're right. kill(2) and tgkill(2) set si_code to SI_USER, so
> excluding SI_USER seems to be necessary to avoid an invalid read via
> either of these syscalls. I will update the comment to say > 0.

OK, makes sense.


> > > There is no such check on si_code in ptrace(PTRACE_SETSIGINFO), so
> > > we make ptrace(PTRACE_SETSIGINFO) clear the si_xflags field if it
> > > detects that the signal would use the _sigfault layout, and introduce
> > > a new ptrace request type, PTRACE_SETSIGINFO2, that a si_xflags-aware
> > > program may use to opt out of this behavior.
> >
> > Will we need to introduce PTRACE_SETSIGINFO3, 4 etc., every time a new
> > field comes up?
> >
> > I wonder whether we should make this more flexible, say accepting some
> > flags argument to say which fields the caller understands (and so
> > doesn't want clobbered).  Maybe we can (ab)use the sa_flags bit
> > definitions for indicating which extensions the caller understands.
> 
> I'd be okay with adding a flags argument here, to be passed via the
> addr argument to PTRACE_SETSIGINFO2. (Confusingly, in some of the
> ptrace request types including the ones that deal with siginfo "data"
> is the argument that takes an address and "addr" is the one that takes
> something else! My new request type will do the same to make things
> consistently confusing.)

So long as we try to follow the existing pattern for similar ptrace
calls, I guess people will cope with it.

If we make the argument a struct pointer, we have the option to expand
it later if needed, provided that the initial definition of the struct
members provides a way to discover such extensions (i.e., the initial
struct needs space for a flag indicating this, or an indication of the
struct size, or similar).

> I guess we would only require a new "out of band" signaling mechanism
> if we were adding a field to a different union member (presumably a
> flags field to support the kind of future expansion that we anticipate
> for sigfault), since for sigfault we may indicate presence of new
> fields using si_xflags. Presumably such a field would come at the same
> time as a new SA_* bit for detecting its presence, so I suppose that
> we could use the sa_flags bits here as well. I'm not entirely
> comfortable with that though because the other SA_* bits wouldn't make
> sense to be passed as an argument here (and because of the
> architecture dependence that made it so hard to find free SA_* bits to
> add, we would be unnecessarily restricted in the number of bits that
> we could easily add here), and in the future someone may come up with
> a reason to pass a new flag here that wouldn't correspond to an SA_*
> bit. So I would mildly prefer a new set of bit definitions.

We don't need to use the sa_flags bit definitions here if that's likely
to be problematic.

I don't really have a strong opinion either way though.

> It's unfortunate that the addr argument for PTRACE_SETSIGINFO was
> specified to be ignored rather than causing an error for non-zero
> values, as otherwise we could have used it as the flags argument to
> the existing request type and avoided adding a new one. Of course,
> this is the same issue that has caused us so much grief with
> sigaction. But for the new request type we can do things properly and
> require addr to have only recognized bits set.

Ack

> > > It is also possible for the kernel to inject a signal specified to
> > > use _sigfault by calling force_sig (e.g. there are numerous calls to
> > > force_sig(SIGSEGV)). In this case si_code is set to SI_KERNEL and the
> > > _kill union member is used, so document that si_code must be < SI_KERNEL.
> >
> > Ack.  I'm still wondering if some of those SIGSEGV/SI_KERNEL instances
> > should be changed to one of the standard SIGSEGV codes, but either way,
> > having si_xflags validity require si_code < SI_KERNEL seems appropriate.
> >
> >
> > > Ideally this field could have just been named si_flags, but that
> > > name was already taken by ia64, so a different name was chosen.
> > >
> > > Alternatively, we may consider making ia64's si_flags a generic field
> > > and having it appear at the end of _sigfault (in the same place as
> > > this patch has si_xflags) on non-ia64, keeping it in the same place
> > > on ia64. ia64's si_flags is a 32-bit field with only one flag bit
> > > allocated, so we would have 31 bits to use if we do this.
> >
> > Hmm, that might be an idea.
> >
> > It would mean that x86 would have different rules from other
> > architectures regarding how to know when the field is valid, which might
> > lull x86-first projects into a false sense of security.  Perhaps we could
> 
> ia64 is Itanium, not x86. And ia64 is almost dead (I heard that gcc
> was planning to remove support some time next year [1], which I expect
> would be followed soon after by dropping kernel support). So I
> wouldn't expect there to be a lot of ia64-first projects out there.
> 
> [1] https://www.phoronix.com/scan.php?page=news_item&px=Intel-IA-64-GCC-Deprecation

Ack, I knew this but I guess I skim-read your text too quickly and only
saw the "64"...

> > refuse to expose any of the arch-independent flags in si_flags unless
> > explicitly requested via SA_XFLAGS, but that would be a departure from
> > what this series implements today.
> >
> > So maybe it's simpler to keep the two fields separate, unless somebody
> > objects.
> 
> Notwithstanding the above, I would be mildly in favor of keeping them
> separate in order to avoid the complexity implied by entangling them,
> since it's complex enough to add fields here as it is.
> 
> > >
> > > Signed-off-by: Peter Collingbourne <pcc@google.com>
> > > ---
> > > View this change in Gerrit: https://linux-review.googlesource.com/q/Ide155ce29366c3eab2a944ae4c51205982e5b8b2
> > >
> > > v10:
> > > - make the new field compatible with the various ways
> > >   that a siginfo can be injected from another process
> > > - eliminate some duplication by adding a refactoring patch
> > >   before this one
> > >
> > >  arch/powerpc/platforms/powernv/vas-fault.c |  1 +
> > >  arch/x86/kernel/signal_compat.c            |  4 +--
> > >  include/linux/compat.h                     |  2 ++
> > >  include/linux/signal_types.h               |  2 +-
> > >  include/uapi/asm-generic/siginfo.h         |  4 +++
> > >  include/uapi/asm-generic/signal-defs.h     |  4 +++
> > >  include/uapi/linux/ptrace.h                |  2 ++
> > >  kernel/ptrace.c                            | 29 ++++++++++++++++++++++
> > >  kernel/signal.c                            |  3 +++
> > >  9 files changed, 48 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/arch/powerpc/platforms/powernv/vas-fault.c b/arch/powerpc/platforms/powernv/vas-fault.c
> > > index 3d21fce254b7..3bbb335561f5 100644
> > > --- a/arch/powerpc/platforms/powernv/vas-fault.c
> > > +++ b/arch/powerpc/platforms/powernv/vas-fault.c
> > > @@ -154,6 +154,7 @@ static void update_csb(struct vas_window *window,
> > >       info.si_errno = EFAULT;
> > >       info.si_code = SEGV_MAPERR;
> > >       info.si_addr = csb_addr;
> > > +     info.si_xflags = 0;
> > >
> > >       /*
> > >        * process will be polling on csb.flags after request is sent to
> > > diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
> > > index c599013ae8cb..6b99f0c8a068 100644
> > > --- a/arch/x86/kernel/signal_compat.c
> > > +++ b/arch/x86/kernel/signal_compat.c
> > > @@ -121,8 +121,8 @@ static inline void signal_compat_build_tests(void)
> > >  #endif
> > >
> > >       CHECK_CSI_OFFSET(_sigfault);
> > > -     CHECK_CSI_SIZE  (_sigfault, 4*sizeof(int));
> > > -     CHECK_SI_SIZE   (_sigfault, 8*sizeof(int));
> > > +     CHECK_CSI_SIZE  (_sigfault, 8*sizeof(int));
> > > +     CHECK_SI_SIZE   (_sigfault, 16*sizeof(int));
> >
> > (Yuk, but at least you make this no worse.)
> >
> > >
> > >       BUILD_BUG_ON(offsetof(siginfo_t, si_addr) != 0x10);
> > >       BUILD_BUG_ON(offsetof(compat_siginfo_t, si_addr) != 0x0C);
> > > diff --git a/include/linux/compat.h b/include/linux/compat.h
> > > index d38c4d7e83bd..55d4228dfd88 100644
> > > --- a/include/linux/compat.h
> > > +++ b/include/linux/compat.h
> > > @@ -231,7 +231,9 @@ typedef struct compat_siginfo {
> > >                                       char _dummy_pkey[__COMPAT_ADDR_BND_PKEY_PAD];
> > >                                       u32 _pkey;
> > >                               } _addr_pkey;
> > > +                             compat_uptr_t _pad[6];
> > >                       };
> > > +                     compat_uptr_t _xflags;
> >
> > Should we have the same type here for native and compat?
> >
> > I don't have a very strong opinion on this, but currently native on
> > 64-bit arches will have 32 extra bits in _xflags that can never be used
> > (or have to be defined differently for compat).
> 
> Good point. I will make this a u64 (although I think 32 bits will
> probably be more than enough, the distance between si_xflags and
> si_addr_ignored_bits will be 8 bytes on 64-bit architectures due to
> alignment so we may as well make all of the bits available).

Ack

> > >               } _sigfault;
> > >
> > >               /* SIGPOLL */
> > > diff --git a/include/linux/signal_types.h b/include/linux/signal_types.h
> > > index a7887ad84d36..75ca861d982a 100644
> > > --- a/include/linux/signal_types.h
> > > +++ b/include/linux/signal_types.h
> > > @@ -78,6 +78,6 @@ struct ksignal {
> > >
> > >  #define UAPI_SA_FLAGS                                                          \
> > >       (SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
> > > -      SA_NODEFER | SA_RESETHAND | __ARCH_UAPI_SA_FLAGS)
> > > +      SA_NODEFER | SA_RESETHAND | SA_XFLAGS | __ARCH_UAPI_SA_FLAGS)
> > >
> > >  #endif /* _LINUX_SIGNAL_TYPES_H */
> > > diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
> > > index cb3d6c267181..1fbd88d64f38 100644
> > > --- a/include/uapi/asm-generic/siginfo.h
> > > +++ b/include/uapi/asm-generic/siginfo.h
> > > @@ -91,7 +91,9 @@ union __sifields {
> > >                               char _dummy_pkey[__ADDR_BND_PKEY_PAD];
> > >                               __u32 _pkey;
> > >                       } _addr_pkey;
> > > +                     void *_pad[6];
> >
> > 6?
> >
> > Obviously we'll need something here, but I'm curious as to where this
> > value came from.
> >
> > (Same for compat.)
> 
> I think it came from Eric's suggestion in [1], i.e. 2 words from the
> existing fields plus the 4 words of padding suggested by Eric.
> 
> [1] https://www.spinics.net/lists/arm-kernel/msg808618.html

So long as there's a reason for it, I guess I don't have a strong opinion.

> 
> > >               };
> > > +             unsigned long _xflags;
> > >       } _sigfault;
> > >
> > >       /* SIGPOLL */
> > > @@ -152,6 +154,8 @@ typedef struct siginfo {
> > >  #define si_trapno    _sifields._sigfault._trapno
> > >  #endif
> > >  #define si_addr_lsb  _sifields._sigfault._addr_lsb
> > > +/* si_xflags is only valid if 0 <= si_code < SI_KERNEL */
> > > +#define si_xflags    _sifields._sigfault._xflags
> > >  #define si_lower     _sifields._sigfault._addr_bnd._lower
> > >  #define si_upper     _sifields._sigfault._addr_bnd._upper
> > >  #define si_pkey              _sifields._sigfault._addr_pkey._pkey
> > > diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
> > > index e853cbe8722d..bdbe1fe7a779 100644
> > > --- a/include/uapi/asm-generic/signal-defs.h
> > > +++ b/include/uapi/asm-generic/signal-defs.h
> > > @@ -20,6 +20,9 @@
> > >   * so this bit allows flag bit support to be detected from userspace while
> > >   * allowing an old kernel to be distinguished from a kernel that supports every
> > >   * flag bit.
> > > + * SA_XFLAGS indicates that the signal handler requires the siginfo.si_xflags
> > > + * field to be valid. Note that if the kernel supports SA_XFLAGS, the field will
> >
> > Maybe "valid for fault signals (SIGSEGV etc.)"
> 
> Will add.
> 
> > [...]
> >
> > Otherwise, this looks sensible overall to me.
> 
> Thanks for the review. (And apologies for being slow to respond to
> your reviews. I got preempted by another task right after sending out
> v10 and only now did I get a chance to get back to this.)

No worries, I've had other stuff to do too...

Cheers
---Dave

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 6/7] signal: define the field siginfo.si_xflags
  2020-10-09 18:19         ` Peter Collingbourne
@ 2020-10-12 13:57           ` Dave Martin
  -1 siblings, 0 replies; 59+ messages in thread
From: Dave Martin @ 2020-10-12 13:57 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Linux ARM, Parisc List, Catalin Marinas, Kevin Brodsky,
	Oleg Nesterov, James E.J. Bottomley, Kostya Serebryany,
	Eric W. Biederman, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Will Deacon, Evgenii Stepanov,
	Richard Henderson

On Fri, Oct 09, 2020 at 11:19:55AM -0700, Peter Collingbourne wrote:
> On Wed, Oct 7, 2020 at 7:11 PM Peter Collingbourne <pcc@google.com> wrote:
> >
> > On Tue, Sep 8, 2020 at 8:13 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > >
> > > On Fri, Aug 21, 2020 at 10:10:16PM -0700, Peter Collingbourne wrote:

[...]

> > > > diff --git a/include/linux/compat.h b/include/linux/compat.h
> > > > index d38c4d7e83bd..55d4228dfd88 100644
> > > > --- a/include/linux/compat.h
> > > > +++ b/include/linux/compat.h
> > > > @@ -231,7 +231,9 @@ typedef struct compat_siginfo {
> > > >                                       char _dummy_pkey[__COMPAT_ADDR_BND_PKEY_PAD];
> > > >                                       u32 _pkey;
> > > >                               } _addr_pkey;
> > > > +                             compat_uptr_t _pad[6];
> > > >                       };
> > > > +                     compat_uptr_t _xflags;
> > >
> > > Should we have the same type here for native and compat?
> > >
> > > I don't have a very strong opinion on this, but currently native on
> > > 64-bit arches will have 32 extra bits in _xflags that can never be used
> > > (or have to be defined differently for compat).
> >
> > Good point. I will make this a u64 (although I think 32 bits will
> > probably be more than enough, the distance between si_xflags and
> > si_addr_ignored_bits will be 8 bytes on 64-bit architectures due to
> > alignment so we may as well make all of the bits available).
> 
> It turns out that we can't actually make this a u64 because on 32-bit
> platforms this increases the alignment of the union to 8, which breaks
> layout for the other fields in the union. In v12 I will make this a
> u32 so that we don't end up with unusable bits.

u32 seems fine to me.

If we need more bits later, we can always use one of the 32 xflags bits
to indicate that the new field(s) exist.

Cheers
---Dave

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 6/7] signal: define the field siginfo.si_xflags
@ 2020-10-12 13:57           ` Dave Martin
  0 siblings, 0 replies; 59+ messages in thread
From: Dave Martin @ 2020-10-12 13:57 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Parisc List, Catalin Marinas, Kevin Brodsky, Oleg Nesterov,
	Evgenii Stepanov, James E.J. Bottomley, Kostya Serebryany,
	Eric W. Biederman, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Will Deacon, Linux ARM, Richard Henderson

On Fri, Oct 09, 2020 at 11:19:55AM -0700, Peter Collingbourne wrote:
> On Wed, Oct 7, 2020 at 7:11 PM Peter Collingbourne <pcc@google.com> wrote:
> >
> > On Tue, Sep 8, 2020 at 8:13 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > >
> > > On Fri, Aug 21, 2020 at 10:10:16PM -0700, Peter Collingbourne wrote:

[...]

> > > > diff --git a/include/linux/compat.h b/include/linux/compat.h
> > > > index d38c4d7e83bd..55d4228dfd88 100644
> > > > --- a/include/linux/compat.h
> > > > +++ b/include/linux/compat.h
> > > > @@ -231,7 +231,9 @@ typedef struct compat_siginfo {
> > > >                                       char _dummy_pkey[__COMPAT_ADDR_BND_PKEY_PAD];
> > > >                                       u32 _pkey;
> > > >                               } _addr_pkey;
> > > > +                             compat_uptr_t _pad[6];
> > > >                       };
> > > > +                     compat_uptr_t _xflags;
> > >
> > > Should we have the same type here for native and compat?
> > >
> > > I don't have a very strong opinion on this, but currently native on
> > > 64-bit arches will have 32 extra bits in _xflags that can never be used
> > > (or have to be defined differently for compat).
> >
> > Good point. I will make this a u64 (although I think 32 bits will
> > probably be more than enough, the distance between si_xflags and
> > si_addr_ignored_bits will be 8 bytes on 64-bit architectures due to
> > alignment so we may as well make all of the bits available).
> 
> It turns out that we can't actually make this a u64 because on 32-bit
> platforms this increases the alignment of the union to 8, which breaks
> layout for the other fields in the union. In v12 I will make this a
> u32 so that we don't end up with unusable bits.

u32 seems fine to me.

If we need more bits later, we can always use one of the 32 xflags bits
to indicate that the new field(s) exist.

Cheers
---Dave

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 7/7] arm64: expose FAR_EL1 tag bits in siginfo
  2020-10-08  2:54       ` Peter Collingbourne
@ 2020-10-12 14:14         ` Dave Martin
  -1 siblings, 0 replies; 59+ messages in thread
From: Dave Martin @ 2020-10-12 14:14 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Linux ARM, Parisc List, Catalin Marinas, Kevin Brodsky,
	Oleg Nesterov, James E.J. Bottomley, Kostya Serebryany,
	Eric W. Biederman, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Will Deacon, Evgenii Stepanov,
	Richard Henderson

On Wed, Oct 07, 2020 at 07:54:46PM -0700, Peter Collingbourne wrote:
> On Tue, Sep 8, 2020 at 8:13 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Fri, Aug 21, 2020 at 10:10:17PM -0700, Peter Collingbourne wrote:
> > > The kernel currently clears the tag bits (i.e. bits 56-63) in the fault
> > > address exposed via siginfo.si_addr and sigcontext.fault_address. However,
> > > the tag bits may be needed by tools in order to accurately diagnose
> > > memory errors, such as HWASan [1] or future tools based on the Memory
> > > Tagging Extension (MTE).
> > >
> > > We should not stop clearing these bits in the existing fault address
> > > fields, because there may be existing userspace applications that are
> > > expecting the tag bits to be cleared. Instead, create a new pair of
> > > union fields in siginfo._sigfault, and store the tag bits of FAR_EL1
> > > there, together with a mask specifying which bits are valid.
> > >
> > > A flag is added to si_xflags to allow userspace to determine whether
> > > the values in the fields are valid.
> > >
> > > [1] http://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html
> > >
> > > Signed-off-by: Peter Collingbourne <pcc@google.com>
> > > ---
> > > View this change in Gerrit: https://linux-review.googlesource.com/q/Ia8876bad8c798e0a32df7c2ce1256c4771c81446
> > >
> > > v10:
> > > - rename the flag to SIXFLAG_ADDR_IGNORED_BITS
> > > - use an arch hook to specify which bits are ignored, instead
> > >   of passing them explicitly
> > > - while refactoring for the arch hook, noticed that my previous
> > >   patches missed a case involving cache maintenance instructions,
> > >   so expose the tag bits for that signal as well
> > >
> > > v9:
> > > - make the ignored bits fields generic
> > > - add some new dependent patches that prepare us to store the
> > >   field in such a way that userspace can detect their presence
> > >
> > > v8:
> > > - rebase onto 5.8rc2
> > >
> > > v7:
> > > - switch to a new siginfo field instead of using sigcontext
> > > - merge the patch back into one since the other patches are now
> > >   unnecessary
> > >
> > > v6:
> > > - move fault address and fault code into the kernel_siginfo data structure
> > > - split the patch in three since it was getting large and now has
> > >   generic and arch-specific parts
> > >
> > > v5:
> > > - add padding to fault_addr_top_byte_context in order to ensure the correct
> > >   size and preserve sp alignment
> > >
> > > v4:
> > > - expose only the tag bits in the context instead of the entire FAR_EL1
> > > - remove mention of the new context from the sigcontext.__reserved[] note
> > >
> > > v3:
> > > - add documentation to tagged-pointers.rst
> > > - update comments in sigcontext.h
> > >
> > > v2:
> > > - revert changes to hw_breakpoint.c
> > > - rename set_thread_esr to set_thread_far_esr
> > >
> > >  Documentation/arm64/tagged-pointers.rst | 21 ++++++---
> > >  arch/arm64/include/asm/exception.h      |  2 +-
> > >  arch/arm64/include/asm/signal.h         | 17 +++++++
> > >  arch/arm64/include/asm/system_misc.h    |  2 +-
> > >  arch/arm64/include/asm/traps.h          |  6 +--
> > >  arch/arm64/kernel/debug-monitors.c      |  5 +--
> > >  arch/arm64/kernel/entry-common.c        |  2 -
> > >  arch/arm64/kernel/ptrace.c              |  7 +--
> > >  arch/arm64/kernel/sys_compat.c          |  5 +--
> > >  arch/arm64/kernel/traps.c               | 29 ++++++------
> > >  arch/arm64/mm/fault.c                   | 59 +++++++++++++------------
> > >  arch/x86/kernel/signal_compat.c         |  4 +-
> > >  include/linux/compat.h                  |  2 +
> > >  include/linux/signal.h                  |  8 ++++
> > >  include/uapi/asm-generic/siginfo.h      | 10 +++++
> > >  kernel/signal.c                         | 14 +++++-
> > >  16 files changed, 122 insertions(+), 71 deletions(-)
> > >  create mode 100644 arch/arm64/include/asm/signal.h
> > >
> > > diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst
> > > index eab4323609b9..14273160b38b 100644
> > > --- a/Documentation/arm64/tagged-pointers.rst
> > > +++ b/Documentation/arm64/tagged-pointers.rst
> > > @@ -53,12 +53,21 @@ visibility.
> > >  Preserving tags
> > >  ---------------
> > >
> > > -Non-zero tags are not preserved when delivering signals. This means that
> > > -signal handlers in applications making use of tags cannot rely on the
> > > -tag information for user virtual addresses being maintained for fields
> > > -inside siginfo_t. One exception to this rule is for signals raised in
> > > -response to watchpoint debug exceptions, where the tag information will
> > > -be preserved.
> > > +Non-zero tags are not preserved in the fault address fields
> > > +siginfo.si_addr or sigcontext.fault_address when delivering
> > > +signals. This means that signal handlers in applications making use
> > > +of tags cannot rely on the tag information for user virtual addresses
> > > +being maintained in these fields. One exception to this rule is for
> > > +signals raised in response to watchpoint debug exceptions, where the
> > > +tag information will be preserved.
> > > +
> > > +The fault address tag is preserved in the si_addr_ignored_bits field
> > > +of siginfo, which is set for signals raised in response to data aborts
> > > +and instruction aborts. The si_addr_ignored_bits_mask field indicates
> > > +which bits of the field are valid. The validity of these fields is
> > > +indicated by the SIXFLAG_ADDR_IGNORED_BITS flag in siginfo.si_xflags,
> > > +and the validity of si_xflags in turn is indicated by the kernel
> > > +indicating support for the sigaction.sa_flags flag SA_XFLAGS.
> > >
> > >  The architecture prevents the use of a tagged PC, so the upper byte will
> > >  be set to a sign-extension of bit 55 on exception return.
> > > diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h
> > > index 7577a754d443..950d55dae948 100644
> > > --- a/arch/arm64/include/asm/exception.h
> > > +++ b/arch/arm64/include/asm/exception.h
> > > @@ -32,7 +32,7 @@ static inline u32 disr_to_esr(u64 disr)
> > >  }
> > >
> > >  asmlinkage void enter_from_user_mode(void);
> > > -void do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs);
> > > +void do_mem_abort(unsigned long far, unsigned int esr, struct pt_regs *regs);
> > >  void do_undefinstr(struct pt_regs *regs);
> > >  void do_bti(struct pt_regs *regs);
> > >  asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr);
> >
> > [...]
> >
> > > diff --git a/include/linux/compat.h b/include/linux/compat.h
> > > index 55d4228dfd88..273146cf30fd 100644
> > > --- a/include/linux/compat.h
> > > +++ b/include/linux/compat.h
> > > @@ -234,6 +234,8 @@ typedef struct compat_siginfo {
> > >                               compat_uptr_t _pad[6];
> > >                       };
> > >                       compat_uptr_t _xflags;
> > > +                     compat_uptr_t _addr_ignored_bits;
> > > +                     compat_uptr_t _addr_ignored_bits_mask;
> > >               } _sigfault;
> > >
> > >               /* SIGPOLL */
> > > diff --git a/include/linux/signal.h b/include/linux/signal.h
> > > index 3edbf54493ee..b4c473c12a9b 100644
> > > --- a/include/linux/signal.h
> > > +++ b/include/linux/signal.h
> > > @@ -480,4 +480,12 @@ struct seq_file;
> > >  extern void render_sigset_t(struct seq_file *, const char *, sigset_t *);
> > >  #endif
> >
> > Can we have a comment here explaining what this helper needs to do, if
> > defined?
> 
> Will add.
> 
> > > +#ifndef arch_addr_ignored_bits_mask
> > > +static inline unsigned long arch_addr_ignored_bits_mask(unsigned long sig,
> > > +                                                     unsigned long si_code)
> > > +{
> > > +     return 0;
> > > +}
> > > +#endif
> > > +
> > >  #endif /* _LINUX_SIGNAL_H */
> > > diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
> > > index 1fbd88d64f38..e314a38ce2d0 100644
> > > --- a/include/uapi/asm-generic/siginfo.h
> > > +++ b/include/uapi/asm-generic/siginfo.h
> > > @@ -94,6 +94,8 @@ union __sifields {
> > >                       void *_pad[6];
> > >               };
> > >               unsigned long _xflags;
> > > +             unsigned long _addr_ignored_bits;
> > > +             unsigned long _addr_ignored_bits_mask;
> > >       } _sigfault;
> > >
> > >       /* SIGPOLL */
> > > @@ -156,6 +158,8 @@ typedef struct siginfo {
> > >  #define si_addr_lsb  _sifields._sigfault._addr_lsb
> > >  /* si_xflags is only valid if 0 <= si_code < SI_KERNEL */
> > >  #define si_xflags    _sifields._sigfault._xflags
> > > +#define si_addr_ignored_bits         _sifields._sigfault._addr_ignored_bits
> > > +#define si_addr_ignored_bits_mask    _sifields._sigfault._addr_ignored_bits_mask
> > >  #define si_lower     _sifields._sigfault._addr_bnd._lower
> > >  #define si_upper     _sifields._sigfault._addr_bnd._upper
> > >  #define si_pkey              _sifields._sigfault._addr_pkey._pkey
> > > @@ -296,6 +300,12 @@ typedef struct siginfo {
> > >  #define EMT_TAGOVF   1       /* tag overflow */
> > >  #define NSIGEMT              1
> > >
> > > +/*
> > > + * SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT si_xflags
> > > + */
> > > +#define SIXFLAG_ADDR_IGNORED_BITS    1
> > > +/* si_addr_ignored_bits{,_mask} fields valid */
> > > +
> >
> > I'm still uneasy about the "ignored bits" nomenclature, because the bits
> > aren't ignored, and because at the C language level above, they
> > generally _are_ considered part of the address.
> >
> > I don't have a great suggestion for a new name, though.  If we just
> > consider the si_addr_ignored_bits to be attributes that accompany the
> > address, it might make sense to call it
> >
> >         si_addr_attr_bits_mask
> >
> > or similar.
> >
> > That may or may not be considered to be less confusing.
> 
> Hmm, I wasn't entirely comfortable with "ignored" either because, as
> you point out, once MTE arrives some of the bits won't be ignored any
> more. Maybe since folks who are going to be working with these bits
> will probably be at least a little familiar with their use on arm64
> with MTE and the tagged address ABI, we should just borrow the
> nomenclature from arm64 and call it:
> 
>   si_addr_tag_bits
>   si_addr_tag_bits_mask
>   SIXFLAG_ADDR_TAG_BITS

My view on this is that the affected bits are really not address bits.

They can be thrown away precisely because they never distinguish one
valid memory location from another valid memory location, nor an
unmapped address from a mapped address: i.e, they make no difference
to the vma (if any) the address maps to or the page within the vma, nor
the offset within page (down to some granularity not coarser than the
access size).

Addresses that differ only in these bits would either behave
identically, be at least partially coherent (in the case of attribute
flags that influence caching, for example), or would trigger some kind
of check failure.

That might motivate names such as

	si_addr_non_addr_bits
	si_addr_valid_bits
	si_addr_attr_bits


My line of reasoning might be a bit obscure though, so perhaps names of
this sort are not as helpful as I'd like to think.


> 
> > >  /*
> > >   * sigevent definitions
> > >   *
> > > diff --git a/kernel/signal.c b/kernel/signal.c
> > > index 4259903b95cb..29654652d3aa 100644
> > > --- a/kernel/signal.c
> > > +++ b/kernel/signal.c
> > > @@ -1652,11 +1652,17 @@ void force_sigsegv(int sig)
> > >  static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
> > >                                      int code, void __user *addr)
> > >  {
> > > +     unsigned long addr_long = (unsigned long)addr;
> > > +     unsigned long ignored_bits_mask =
> > > +             arch_addr_ignored_bits_mask(sig, code);
> > > +
> > >       info->si_signo = sig;
> > >       info->si_errno = 0;
> > >       info->si_code = code;
> > > -     info->si_addr = addr;
> > > -     info->si_xflags = 0;
> > > +     info->si_addr = (void __user *)(addr_long & ~ignored_bits_mask);
> > > +     info->si_xflags = SIXFLAG_ADDR_IGNORED_BITS;
> > > +     info->si_addr_ignored_bits = addr_long & ignored_bits_mask;
> > > +     info->si_addr_ignored_bits_mask = ignored_bits_mask;
> >
> > Could we report the ignored bits optionally?
> >
> > i.e., if arch_addr_ignored_bits_mask() == 0, then we could perhaps leave
> > SIXFLAG_ADDR_IGNORED_BITS clear in si_xflags, and just set
> > si_addr_ignored_bits{,_mask} to zeros.
> >
> > I can't decide myself whether this would be a good idea or not...
> 
> Since having the bit clear should be equivalent from the user's point
> of view to having it set with the mask equal to 0, I think I would
> favor the solution that would make the kernel code simpler, i.e. what
> I have implemented.

OK, that's reasonable.


> > >  }
> > >
> > >  int force_sig_fault_to_task(int sig, int code, void __user *addr
> > > @@ -3271,6 +3277,8 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
> > >               to->si_trapno = from->si_trapno;
> > >  #endif
> > >               to->si_xflags = from->si_xflags;
> > > +             to->si_addr_ignored_bits = from->si_addr_ignored_bits;
> > > +             to->si_addr_ignored_bits_mask = from->si_addr_ignored_bits_mask;
> >
> > What happens if we're delivering a signal to a compat process?
> >
> > It looks like we apply all the usual logic, but si_addr_ignored_bits and
> > si_addr_ignored_bits_mask simply get truncated.
> >
> > That might be reasonable -- we don't care about bits that don't exist
> > for compat, irrespective of what they mean for native -- but it's
> > probably worth a comment.
> 
> If the signal originates from a compat process then I would expect the
> addresses involved in the fault to be 32 bits wide, so I would not
> expect there to be any truncation in practice. The situation is the
> same for si_addr I think. I can leave a comment here.

OK, sounds fair.

We generally don't see 32-bit arches repurposing bits in the address,
since they tend to need all of them for addressing (unless, possibly,
when running some kind of low-footprint binary environment where
backwards compatibility isn't a concern -- not likely to be applicable
to Linux userspace).

> > >       }
> > >
> > >       switch (layout) {
> > > @@ -3347,6 +3355,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> > >               to->si_trapno = from->si_trapno;
> > >  #endif
> > >               to->si_xflags = from->si_xflags;
> > > +             to->si_addr_ignored_bits = from->si_addr_ignored_bits;
> > > +             to->si_addr_ignored_bits_mask = from->si_addr_ignored_bits_mask;
> >
> > Otherwise, the patch looks reasonable.
> 
> Thanks for the review.
> 
> Peter

Cheers
---Dave

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH v10 7/7] arm64: expose FAR_EL1 tag bits in siginfo
@ 2020-10-12 14:14         ` Dave Martin
  0 siblings, 0 replies; 59+ messages in thread
From: Dave Martin @ 2020-10-12 14:14 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Parisc List, Catalin Marinas, Kevin Brodsky, Oleg Nesterov,
	Evgenii Stepanov, James E.J. Bottomley, Kostya Serebryany,
	Eric W. Biederman, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Will Deacon, Linux ARM, Richard Henderson

On Wed, Oct 07, 2020 at 07:54:46PM -0700, Peter Collingbourne wrote:
> On Tue, Sep 8, 2020 at 8:13 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Fri, Aug 21, 2020 at 10:10:17PM -0700, Peter Collingbourne wrote:
> > > The kernel currently clears the tag bits (i.e. bits 56-63) in the fault
> > > address exposed via siginfo.si_addr and sigcontext.fault_address. However,
> > > the tag bits may be needed by tools in order to accurately diagnose
> > > memory errors, such as HWASan [1] or future tools based on the Memory
> > > Tagging Extension (MTE).
> > >
> > > We should not stop clearing these bits in the existing fault address
> > > fields, because there may be existing userspace applications that are
> > > expecting the tag bits to be cleared. Instead, create a new pair of
> > > union fields in siginfo._sigfault, and store the tag bits of FAR_EL1
> > > there, together with a mask specifying which bits are valid.
> > >
> > > A flag is added to si_xflags to allow userspace to determine whether
> > > the values in the fields are valid.
> > >
> > > [1] http://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html
> > >
> > > Signed-off-by: Peter Collingbourne <pcc@google.com>
> > > ---
> > > View this change in Gerrit: https://linux-review.googlesource.com/q/Ia8876bad8c798e0a32df7c2ce1256c4771c81446
> > >
> > > v10:
> > > - rename the flag to SIXFLAG_ADDR_IGNORED_BITS
> > > - use an arch hook to specify which bits are ignored, instead
> > >   of passing them explicitly
> > > - while refactoring for the arch hook, noticed that my previous
> > >   patches missed a case involving cache maintenance instructions,
> > >   so expose the tag bits for that signal as well
> > >
> > > v9:
> > > - make the ignored bits fields generic
> > > - add some new dependent patches that prepare us to store the
> > >   field in such a way that userspace can detect their presence
> > >
> > > v8:
> > > - rebase onto 5.8rc2
> > >
> > > v7:
> > > - switch to a new siginfo field instead of using sigcontext
> > > - merge the patch back into one since the other patches are now
> > >   unnecessary
> > >
> > > v6:
> > > - move fault address and fault code into the kernel_siginfo data structure
> > > - split the patch in three since it was getting large and now has
> > >   generic and arch-specific parts
> > >
> > > v5:
> > > - add padding to fault_addr_top_byte_context in order to ensure the correct
> > >   size and preserve sp alignment
> > >
> > > v4:
> > > - expose only the tag bits in the context instead of the entire FAR_EL1
> > > - remove mention of the new context from the sigcontext.__reserved[] note
> > >
> > > v3:
> > > - add documentation to tagged-pointers.rst
> > > - update comments in sigcontext.h
> > >
> > > v2:
> > > - revert changes to hw_breakpoint.c
> > > - rename set_thread_esr to set_thread_far_esr
> > >
> > >  Documentation/arm64/tagged-pointers.rst | 21 ++++++---
> > >  arch/arm64/include/asm/exception.h      |  2 +-
> > >  arch/arm64/include/asm/signal.h         | 17 +++++++
> > >  arch/arm64/include/asm/system_misc.h    |  2 +-
> > >  arch/arm64/include/asm/traps.h          |  6 +--
> > >  arch/arm64/kernel/debug-monitors.c      |  5 +--
> > >  arch/arm64/kernel/entry-common.c        |  2 -
> > >  arch/arm64/kernel/ptrace.c              |  7 +--
> > >  arch/arm64/kernel/sys_compat.c          |  5 +--
> > >  arch/arm64/kernel/traps.c               | 29 ++++++------
> > >  arch/arm64/mm/fault.c                   | 59 +++++++++++++------------
> > >  arch/x86/kernel/signal_compat.c         |  4 +-
> > >  include/linux/compat.h                  |  2 +
> > >  include/linux/signal.h                  |  8 ++++
> > >  include/uapi/asm-generic/siginfo.h      | 10 +++++
> > >  kernel/signal.c                         | 14 +++++-
> > >  16 files changed, 122 insertions(+), 71 deletions(-)
> > >  create mode 100644 arch/arm64/include/asm/signal.h
> > >
> > > diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst
> > > index eab4323609b9..14273160b38b 100644
> > > --- a/Documentation/arm64/tagged-pointers.rst
> > > +++ b/Documentation/arm64/tagged-pointers.rst
> > > @@ -53,12 +53,21 @@ visibility.
> > >  Preserving tags
> > >  ---------------
> > >
> > > -Non-zero tags are not preserved when delivering signals. This means that
> > > -signal handlers in applications making use of tags cannot rely on the
> > > -tag information for user virtual addresses being maintained for fields
> > > -inside siginfo_t. One exception to this rule is for signals raised in
> > > -response to watchpoint debug exceptions, where the tag information will
> > > -be preserved.
> > > +Non-zero tags are not preserved in the fault address fields
> > > +siginfo.si_addr or sigcontext.fault_address when delivering
> > > +signals. This means that signal handlers in applications making use
> > > +of tags cannot rely on the tag information for user virtual addresses
> > > +being maintained in these fields. One exception to this rule is for
> > > +signals raised in response to watchpoint debug exceptions, where the
> > > +tag information will be preserved.
> > > +
> > > +The fault address tag is preserved in the si_addr_ignored_bits field
> > > +of siginfo, which is set for signals raised in response to data aborts
> > > +and instruction aborts. The si_addr_ignored_bits_mask field indicates
> > > +which bits of the field are valid. The validity of these fields is
> > > +indicated by the SIXFLAG_ADDR_IGNORED_BITS flag in siginfo.si_xflags,
> > > +and the validity of si_xflags in turn is indicated by the kernel
> > > +indicating support for the sigaction.sa_flags flag SA_XFLAGS.
> > >
> > >  The architecture prevents the use of a tagged PC, so the upper byte will
> > >  be set to a sign-extension of bit 55 on exception return.
> > > diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h
> > > index 7577a754d443..950d55dae948 100644
> > > --- a/arch/arm64/include/asm/exception.h
> > > +++ b/arch/arm64/include/asm/exception.h
> > > @@ -32,7 +32,7 @@ static inline u32 disr_to_esr(u64 disr)
> > >  }
> > >
> > >  asmlinkage void enter_from_user_mode(void);
> > > -void do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs);
> > > +void do_mem_abort(unsigned long far, unsigned int esr, struct pt_regs *regs);
> > >  void do_undefinstr(struct pt_regs *regs);
> > >  void do_bti(struct pt_regs *regs);
> > >  asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr);
> >
> > [...]
> >
> > > diff --git a/include/linux/compat.h b/include/linux/compat.h
> > > index 55d4228dfd88..273146cf30fd 100644
> > > --- a/include/linux/compat.h
> > > +++ b/include/linux/compat.h
> > > @@ -234,6 +234,8 @@ typedef struct compat_siginfo {
> > >                               compat_uptr_t _pad[6];
> > >                       };
> > >                       compat_uptr_t _xflags;
> > > +                     compat_uptr_t _addr_ignored_bits;
> > > +                     compat_uptr_t _addr_ignored_bits_mask;
> > >               } _sigfault;
> > >
> > >               /* SIGPOLL */
> > > diff --git a/include/linux/signal.h b/include/linux/signal.h
> > > index 3edbf54493ee..b4c473c12a9b 100644
> > > --- a/include/linux/signal.h
> > > +++ b/include/linux/signal.h
> > > @@ -480,4 +480,12 @@ struct seq_file;
> > >  extern void render_sigset_t(struct seq_file *, const char *, sigset_t *);
> > >  #endif
> >
> > Can we have a comment here explaining what this helper needs to do, if
> > defined?
> 
> Will add.
> 
> > > +#ifndef arch_addr_ignored_bits_mask
> > > +static inline unsigned long arch_addr_ignored_bits_mask(unsigned long sig,
> > > +                                                     unsigned long si_code)
> > > +{
> > > +     return 0;
> > > +}
> > > +#endif
> > > +
> > >  #endif /* _LINUX_SIGNAL_H */
> > > diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
> > > index 1fbd88d64f38..e314a38ce2d0 100644
> > > --- a/include/uapi/asm-generic/siginfo.h
> > > +++ b/include/uapi/asm-generic/siginfo.h
> > > @@ -94,6 +94,8 @@ union __sifields {
> > >                       void *_pad[6];
> > >               };
> > >               unsigned long _xflags;
> > > +             unsigned long _addr_ignored_bits;
> > > +             unsigned long _addr_ignored_bits_mask;
> > >       } _sigfault;
> > >
> > >       /* SIGPOLL */
> > > @@ -156,6 +158,8 @@ typedef struct siginfo {
> > >  #define si_addr_lsb  _sifields._sigfault._addr_lsb
> > >  /* si_xflags is only valid if 0 <= si_code < SI_KERNEL */
> > >  #define si_xflags    _sifields._sigfault._xflags
> > > +#define si_addr_ignored_bits         _sifields._sigfault._addr_ignored_bits
> > > +#define si_addr_ignored_bits_mask    _sifields._sigfault._addr_ignored_bits_mask
> > >  #define si_lower     _sifields._sigfault._addr_bnd._lower
> > >  #define si_upper     _sifields._sigfault._addr_bnd._upper
> > >  #define si_pkey              _sifields._sigfault._addr_pkey._pkey
> > > @@ -296,6 +300,12 @@ typedef struct siginfo {
> > >  #define EMT_TAGOVF   1       /* tag overflow */
> > >  #define NSIGEMT              1
> > >
> > > +/*
> > > + * SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT si_xflags
> > > + */
> > > +#define SIXFLAG_ADDR_IGNORED_BITS    1
> > > +/* si_addr_ignored_bits{,_mask} fields valid */
> > > +
> >
> > I'm still uneasy about the "ignored bits" nomenclature, because the bits
> > aren't ignored, and because at the C language level above, they
> > generally _are_ considered part of the address.
> >
> > I don't have a great suggestion for a new name, though.  If we just
> > consider the si_addr_ignored_bits to be attributes that accompany the
> > address, it might make sense to call it
> >
> >         si_addr_attr_bits_mask
> >
> > or similar.
> >
> > That may or may not be considered to be less confusing.
> 
> Hmm, I wasn't entirely comfortable with "ignored" either because, as
> you point out, once MTE arrives some of the bits won't be ignored any
> more. Maybe since folks who are going to be working with these bits
> will probably be at least a little familiar with their use on arm64
> with MTE and the tagged address ABI, we should just borrow the
> nomenclature from arm64 and call it:
> 
>   si_addr_tag_bits
>   si_addr_tag_bits_mask
>   SIXFLAG_ADDR_TAG_BITS

My view on this is that the affected bits are really not address bits.

They can be thrown away precisely because they never distinguish one
valid memory location from another valid memory location, nor an
unmapped address from a mapped address: i.e, they make no difference
to the vma (if any) the address maps to or the page within the vma, nor
the offset within page (down to some granularity not coarser than the
access size).

Addresses that differ only in these bits would either behave
identically, be at least partially coherent (in the case of attribute
flags that influence caching, for example), or would trigger some kind
of check failure.

That might motivate names such as

	si_addr_non_addr_bits
	si_addr_valid_bits
	si_addr_attr_bits


My line of reasoning might be a bit obscure though, so perhaps names of
this sort are not as helpful as I'd like to think.


> 
> > >  /*
> > >   * sigevent definitions
> > >   *
> > > diff --git a/kernel/signal.c b/kernel/signal.c
> > > index 4259903b95cb..29654652d3aa 100644
> > > --- a/kernel/signal.c
> > > +++ b/kernel/signal.c
> > > @@ -1652,11 +1652,17 @@ void force_sigsegv(int sig)
> > >  static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
> > >                                      int code, void __user *addr)
> > >  {
> > > +     unsigned long addr_long = (unsigned long)addr;
> > > +     unsigned long ignored_bits_mask =
> > > +             arch_addr_ignored_bits_mask(sig, code);
> > > +
> > >       info->si_signo = sig;
> > >       info->si_errno = 0;
> > >       info->si_code = code;
> > > -     info->si_addr = addr;
> > > -     info->si_xflags = 0;
> > > +     info->si_addr = (void __user *)(addr_long & ~ignored_bits_mask);
> > > +     info->si_xflags = SIXFLAG_ADDR_IGNORED_BITS;
> > > +     info->si_addr_ignored_bits = addr_long & ignored_bits_mask;
> > > +     info->si_addr_ignored_bits_mask = ignored_bits_mask;
> >
> > Could we report the ignored bits optionally?
> >
> > i.e., if arch_addr_ignored_bits_mask() == 0, then we could perhaps leave
> > SIXFLAG_ADDR_IGNORED_BITS clear in si_xflags, and just set
> > si_addr_ignored_bits{,_mask} to zeros.
> >
> > I can't decide myself whether this would be a good idea or not...
> 
> Since having the bit clear should be equivalent from the user's point
> of view to having it set with the mask equal to 0, I think I would
> favor the solution that would make the kernel code simpler, i.e. what
> I have implemented.

OK, that's reasonable.


> > >  }
> > >
> > >  int force_sig_fault_to_task(int sig, int code, void __user *addr
> > > @@ -3271,6 +3277,8 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
> > >               to->si_trapno = from->si_trapno;
> > >  #endif
> > >               to->si_xflags = from->si_xflags;
> > > +             to->si_addr_ignored_bits = from->si_addr_ignored_bits;
> > > +             to->si_addr_ignored_bits_mask = from->si_addr_ignored_bits_mask;
> >
> > What happens if we're delivering a signal to a compat process?
> >
> > It looks like we apply all the usual logic, but si_addr_ignored_bits and
> > si_addr_ignored_bits_mask simply get truncated.
> >
> > That might be reasonable -- we don't care about bits that don't exist
> > for compat, irrespective of what they mean for native -- but it's
> > probably worth a comment.
> 
> If the signal originates from a compat process then I would expect the
> addresses involved in the fault to be 32 bits wide, so I would not
> expect there to be any truncation in practice. The situation is the
> same for si_addr I think. I can leave a comment here.

OK, sounds fair.

We generally don't see 32-bit arches repurposing bits in the address,
since they tend to need all of them for addressing (unless, possibly,
when running some kind of low-footprint binary environment where
backwards compatibility isn't a concern -- not likely to be applicable
to Linux userspace).

> > >       }
> > >
> > >       switch (layout) {
> > > @@ -3347,6 +3355,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> > >               to->si_trapno = from->si_trapno;
> > >  #endif
> > >               to->si_xflags = from->si_xflags;
> > > +             to->si_addr_ignored_bits = from->si_addr_ignored_bits;
> > > +             to->si_addr_ignored_bits_mask = from->si_addr_ignored_bits_mask;
> >
> > Otherwise, the patch looks reasonable.
> 
> Thanks for the review.
> 
> Peter

Cheers
---Dave

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 59+ messages in thread

end of thread, other threads:[~2020-10-12 14:16 UTC | newest]

Thread overview: 59+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-22  5:10 [PATCH v10 0/7] arm64: expose FAR_EL1 tag bits in siginfo Peter Collingbourne
2020-08-22  5:10 ` Peter Collingbourne
2020-08-22  5:10 ` [PATCH v10 1/7] parisc: start using signal-defs.h Peter Collingbourne
2020-08-22  5:10   ` Peter Collingbourne
2020-08-30 17:07   ` Helge Deller
2020-10-03  1:22     ` Peter Collingbourne
2020-10-03 10:04       ` Helge Deller
2020-09-08 15:12   ` Dave Martin
2020-09-08 15:12     ` Dave Martin
2020-08-22  5:10 ` [PATCH v10 2/7] arch: move SA_* definitions to generic headers Peter Collingbourne
2020-08-22  5:10   ` Peter Collingbourne
2020-09-08 15:12   ` Dave Martin
2020-09-08 15:12     ` Dave Martin
2020-10-03  1:14     ` Peter Collingbourne
2020-10-03  1:14       ` Peter Collingbourne
2020-10-05 11:06       ` Dave Martin
2020-10-05 11:06         ` Dave Martin
2020-08-22  5:10 ` [PATCH v10 3/7] signal: clear non-uapi flag bits when passing/returning sa_flags Peter Collingbourne
2020-08-22  5:10   ` Peter Collingbourne
2020-09-08 15:12   ` Dave Martin
2020-09-08 15:12     ` Dave Martin
2020-10-08  2:23     ` Peter Collingbourne
2020-10-08  2:23       ` Peter Collingbourne
2020-08-22  5:10 ` [PATCH v10 4/7] signal: define the SA_UNSUPPORTED bit in sa_flags Peter Collingbourne
2020-08-22  5:10   ` Peter Collingbourne
2020-09-08 15:13   ` Dave Martin
2020-09-08 15:13     ` Dave Martin
2020-10-08  2:21     ` Peter Collingbourne
2020-10-08  2:21       ` Peter Collingbourne
2020-10-12 13:37       ` Dave Martin
2020-10-12 13:37         ` Dave Martin
2020-08-22  5:10 ` [PATCH v10 5/7] signal: deduplicate code dealing with common _sigfault fields Peter Collingbourne
2020-08-22  5:10   ` Peter Collingbourne
2020-09-08 15:13   ` Dave Martin
2020-09-08 15:13     ` Dave Martin
2020-10-06  5:07     ` Peter Collingbourne
2020-10-06  5:07       ` Peter Collingbourne
2020-10-07  8:56       ` Dave Martin
2020-10-07  8:56         ` Dave Martin
2020-08-22  5:10 ` [PATCH v10 6/7] signal: define the field siginfo.si_xflags Peter Collingbourne
2020-08-22  5:10   ` Peter Collingbourne
2020-09-08 15:13   ` Dave Martin
2020-09-08 15:13     ` Dave Martin
2020-10-08  2:11     ` Peter Collingbourne
2020-10-08  2:11       ` Peter Collingbourne
2020-10-09 18:19       ` Peter Collingbourne
2020-10-09 18:19         ` Peter Collingbourne
2020-10-12 13:57         ` Dave Martin
2020-10-12 13:57           ` Dave Martin
2020-10-12 13:55       ` Dave Martin
2020-10-12 13:55         ` Dave Martin
2020-08-22  5:10 ` [PATCH v10 7/7] arm64: expose FAR_EL1 tag bits in siginfo Peter Collingbourne
2020-08-22  5:10   ` Peter Collingbourne
2020-09-08 15:13   ` Dave Martin
2020-09-08 15:13     ` Dave Martin
2020-10-08  2:54     ` Peter Collingbourne
2020-10-08  2:54       ` Peter Collingbourne
2020-10-12 14:14       ` Dave Martin
2020-10-12 14:14         ` Dave Martin

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.