All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v9 0/6] arm64: expose FAR_EL1 tag bits in siginfo
@ 2020-08-18  3:33 ` Peter Collingbourne
  0 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-18  3:33 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 (6):
  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: 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              |  5 ++
 arch/arm/include/uapi/asm/signal.h         | 28 +-------
 arch/arm64/include/asm/exception.h         |  2 +-
 arch/arm64/include/asm/traps.h             |  7 +-
 arch/arm64/kernel/debug-monitors.c         |  4 +-
 arch/arm64/kernel/entry-common.c           |  2 -
 arch/arm64/kernel/ptrace.c                 |  2 +-
 arch/arm64/kernel/traps.c                  | 15 +++--
 arch/arm64/mm/fault.c                      | 54 ++++++++-------
 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/mips/kernel/traps.c                   |  2 +-
 arch/parisc/include/asm/signal.h           |  4 ++
 arch/parisc/include/uapi/asm/signal.h      | 22 +------
 arch/parisc/kernel/ptrace.c                |  2 +-
 arch/parisc/mm/fault.c                     |  2 +-
 arch/powerpc/include/uapi/asm/signal.h     | 24 -------
 arch/powerpc/mm/fault.c                    |  2 +-
 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            |  7 --
 arch/x86/mm/fault.c                        |  3 +-
 arch/xtensa/include/uapi/asm/signal.h      | 24 -------
 include/linux/compat.h                     |  4 ++
 include/linux/sched/signal.h               | 12 +++-
 include/linux/signal_types.h               | 12 ++++
 include/uapi/asm-generic/siginfo.h         | 13 ++++
 include/uapi/asm-generic/signal-defs.h     | 64 ++++++++++++++++++
 include/uapi/asm-generic/signal.h          | 29 --------
 kernel/signal.c                            | 77 ++++++++++++++++++++--
 mm/memory-failure.c                        |  2 +-
 37 files changed, 261 insertions(+), 335 deletions(-)

-- 
2.28.0.220.ged08abb693-goog


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

* [PATCH v9 0/6] arm64: expose FAR_EL1 tag bits in siginfo
@ 2020-08-18  3:33 ` Peter Collingbourne
  0 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-18  3:33 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 (6):
  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: 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              |  5 ++
 arch/arm/include/uapi/asm/signal.h         | 28 +-------
 arch/arm64/include/asm/exception.h         |  2 +-
 arch/arm64/include/asm/traps.h             |  7 +-
 arch/arm64/kernel/debug-monitors.c         |  4 +-
 arch/arm64/kernel/entry-common.c           |  2 -
 arch/arm64/kernel/ptrace.c                 |  2 +-
 arch/arm64/kernel/traps.c                  | 15 +++--
 arch/arm64/mm/fault.c                      | 54 ++++++++-------
 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/mips/kernel/traps.c                   |  2 +-
 arch/parisc/include/asm/signal.h           |  4 ++
 arch/parisc/include/uapi/asm/signal.h      | 22 +------
 arch/parisc/kernel/ptrace.c                |  2 +-
 arch/parisc/mm/fault.c                     |  2 +-
 arch/powerpc/include/uapi/asm/signal.h     | 24 -------
 arch/powerpc/mm/fault.c                    |  2 +-
 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            |  7 --
 arch/x86/mm/fault.c                        |  3 +-
 arch/xtensa/include/uapi/asm/signal.h      | 24 -------
 include/linux/compat.h                     |  4 ++
 include/linux/sched/signal.h               | 12 +++-
 include/linux/signal_types.h               | 12 ++++
 include/uapi/asm-generic/siginfo.h         | 13 ++++
 include/uapi/asm-generic/signal-defs.h     | 64 ++++++++++++++++++
 include/uapi/asm-generic/signal.h          | 29 --------
 kernel/signal.c                            | 77 ++++++++++++++++++++--
 mm/memory-failure.c                        |  2 +-
 37 files changed, 261 insertions(+), 335 deletions(-)

-- 
2.28.0.220.ged08abb693-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] 66+ messages in thread

* [PATCH v9 1/6] parisc: start using signal-defs.h
  2020-08-18  3:33 ` Peter Collingbourne
@ 2020-08-18  3:33   ` Peter Collingbourne
  -1 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-18  3:33 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.220.ged08abb693-goog


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

* [PATCH v9 1/6] parisc: start using signal-defs.h
@ 2020-08-18  3:33   ` Peter Collingbourne
  0 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-18  3:33 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.220.ged08abb693-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] 66+ messages in thread

* [PATCH v9 2/6] arch: move SA_* definitions to generic headers
  2020-08-18  3:33 ` Peter Collingbourne
@ 2020-08-18  3:33   ` Peter Collingbourne
  -1 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-18  3:33 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

 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..91000b6b97e0 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_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.
+ */
+#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
+/*
+ * 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.
+ */
+
+#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.220.ged08abb693-goog


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

* [PATCH v9 2/6] arch: move SA_* definitions to generic headers
@ 2020-08-18  3:33   ` Peter Collingbourne
  0 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-18  3:33 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

 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..91000b6b97e0 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_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.
+ */
+#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
+/*
+ * 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.
+ */
+
+#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.220.ged08abb693-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] 66+ messages in thread

* [PATCH v9 3/6] signal: clear non-uapi flag bits when passing/returning sa_flags
  2020-08-18  3:33 ` Peter Collingbourne
@ 2020-08-18  3:33   ` Peter Collingbourne
  -1 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-18  3:33 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 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.

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

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

diff --git a/arch/arm/include/asm/signal.h b/arch/arm/include/asm/signal.h
index 65530a042009..d1070a783993 100644
--- a/arch/arm/include/asm/signal.h
+++ b/arch/arm/include/asm/signal.h
@@ -17,6 +17,10 @@ typedef struct {
 	unsigned long sig[_NSIG_WORDS];
 } sigset_t;
 
+#define SA_UAPI_FLAGS                                                          \
+	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_THIRTYTWO |             \
+	 SA_RESTORER | SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_RESETHAND)
+
 #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..ad06e14f6e8a 100644
--- a/arch/parisc/include/asm/signal.h
+++ b/arch/parisc/include/asm/signal.h
@@ -21,6 +21,10 @@ typedef struct {
 	unsigned long sig[_NSIG_WORDS];
 } sigset_t;
 
+#define SA_UAPI_FLAGS                                                          \
+	(SA_ONSTACK | SA_RESETHAND | SA_NOCLDSTOP | SA_SIGINFO | SA_NODEFER |  \
+	 SA_RESTART | SA_NOCLDWAIT | _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..e792f29b5846 100644
--- a/include/linux/signal_types.h
+++ b/include/linux/signal_types.h
@@ -68,4 +68,16 @@ struct ksignal {
 	int sig;
 };
 
+#ifndef SA_UAPI_FLAGS
+#ifdef SA_RESTORER
+#define SA_UAPI_FLAGS                                                          \
+	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
+	 SA_NODEFER | SA_RESETHAND | SA_RESTORER)
+#else
+#define SA_UAPI_FLAGS                                                          \
+	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
+	 SA_NODEFER | SA_RESETHAND)
+#endif
+#endif
+
 #endif /* _LINUX_SIGNAL_TYPES_H */
diff --git a/kernel/signal.c b/kernel/signal.c
index 42b67d2cea37..348b7981f1ff 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 &= SA_UAPI_FLAGS;
+	if (oact)
+		oact->sa.sa_flags &= SA_UAPI_FLAGS;
+
 	sigaction_compat_abi(act, oact);
 
 	if (act) {
-- 
2.28.0.220.ged08abb693-goog


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

* [PATCH v9 3/6] signal: clear non-uapi flag bits when passing/returning sa_flags
@ 2020-08-18  3:33   ` Peter Collingbourne
  0 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-18  3:33 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 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.

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

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

diff --git a/arch/arm/include/asm/signal.h b/arch/arm/include/asm/signal.h
index 65530a042009..d1070a783993 100644
--- a/arch/arm/include/asm/signal.h
+++ b/arch/arm/include/asm/signal.h
@@ -17,6 +17,10 @@ typedef struct {
 	unsigned long sig[_NSIG_WORDS];
 } sigset_t;
 
+#define SA_UAPI_FLAGS                                                          \
+	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_THIRTYTWO |             \
+	 SA_RESTORER | SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_RESETHAND)
+
 #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..ad06e14f6e8a 100644
--- a/arch/parisc/include/asm/signal.h
+++ b/arch/parisc/include/asm/signal.h
@@ -21,6 +21,10 @@ typedef struct {
 	unsigned long sig[_NSIG_WORDS];
 } sigset_t;
 
+#define SA_UAPI_FLAGS                                                          \
+	(SA_ONSTACK | SA_RESETHAND | SA_NOCLDSTOP | SA_SIGINFO | SA_NODEFER |  \
+	 SA_RESTART | SA_NOCLDWAIT | _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..e792f29b5846 100644
--- a/include/linux/signal_types.h
+++ b/include/linux/signal_types.h
@@ -68,4 +68,16 @@ struct ksignal {
 	int sig;
 };
 
+#ifndef SA_UAPI_FLAGS
+#ifdef SA_RESTORER
+#define SA_UAPI_FLAGS                                                          \
+	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
+	 SA_NODEFER | SA_RESETHAND | SA_RESTORER)
+#else
+#define SA_UAPI_FLAGS                                                          \
+	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
+	 SA_NODEFER | SA_RESETHAND)
+#endif
+#endif
+
 #endif /* _LINUX_SIGNAL_TYPES_H */
diff --git a/kernel/signal.c b/kernel/signal.c
index 42b67d2cea37..348b7981f1ff 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 &= SA_UAPI_FLAGS;
+	if (oact)
+		oact->sa.sa_flags &= SA_UAPI_FLAGS;
+
 	sigaction_compat_abi(act, oact);
 
 	if (act) {
-- 
2.28.0.220.ged08abb693-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] 66+ messages in thread

* [PATCH v9 4/6] signal: define the SA_UNSUPPORTED bit in sa_flags
  2020-08-18  3:33 ` Peter Collingbourne
@ 2020-08-18  3:33   ` Peter Collingbourne
  -1 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-18  3:33 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 91000b6b97e0..c30a9c1a77b2 100644
--- a/include/uapi/asm-generic/signal-defs.h
+++ b/include/uapi/asm-generic/signal-defs.h
@@ -13,6 +13,12 @@
  * 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_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 @@
  * 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.
  */
+#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 348b7981f1ff..664a6c31137e 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(SA_UAPI_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.220.ged08abb693-goog


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

* [PATCH v9 4/6] signal: define the SA_UNSUPPORTED bit in sa_flags
@ 2020-08-18  3:33   ` Peter Collingbourne
  0 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-18  3:33 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 91000b6b97e0..c30a9c1a77b2 100644
--- a/include/uapi/asm-generic/signal-defs.h
+++ b/include/uapi/asm-generic/signal-defs.h
@@ -13,6 +13,12 @@
  * 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_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 @@
  * 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.
  */
+#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 348b7981f1ff..664a6c31137e 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(SA_UAPI_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.220.ged08abb693-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] 66+ messages in thread

* [PATCH v9 5/6] signal: define the field siginfo.si_xflags
  2020-08-18  3:33 ` Peter Collingbourne
@ 2020-08-18  3:33   ` Peter Collingbourne
  -1 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-18  3:33 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.

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

 arch/arm/include/asm/signal.h              |  3 ++-
 arch/parisc/include/asm/signal.h           |  2 +-
 arch/powerpc/platforms/powernv/vas-fault.c |  1 +
 include/linux/compat.h                     |  2 ++
 include/linux/signal_types.h               |  4 ++--
 include/uapi/asm-generic/siginfo.h         |  3 +++
 include/uapi/asm-generic/signal-defs.h     |  4 ++++
 kernel/signal.c                            | 15 +++++++++++++++
 8 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/arch/arm/include/asm/signal.h b/arch/arm/include/asm/signal.h
index d1070a783993..6b2630dfe1df 100644
--- a/arch/arm/include/asm/signal.h
+++ b/arch/arm/include/asm/signal.h
@@ -19,7 +19,8 @@ typedef struct {
 
 #define SA_UAPI_FLAGS                                                          \
 	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_THIRTYTWO |             \
-	 SA_RESTORER | SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_RESETHAND)
+	 SA_RESTORER | SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_RESETHAND |   \
+	 SA_XFLAGS)
 
 #define __ARCH_HAS_SA_RESTORER
 
diff --git a/arch/parisc/include/asm/signal.h b/arch/parisc/include/asm/signal.h
index ad06e14f6e8a..3582bce44520 100644
--- a/arch/parisc/include/asm/signal.h
+++ b/arch/parisc/include/asm/signal.h
@@ -23,7 +23,7 @@ typedef struct {
 
 #define SA_UAPI_FLAGS                                                          \
 	(SA_ONSTACK | SA_RESETHAND | SA_NOCLDSTOP | SA_SIGINFO | SA_NODEFER |  \
-	 SA_RESTART | SA_NOCLDWAIT | _SA_SIGGFAULT)
+	 SA_RESTART | SA_NOCLDWAIT | _SA_SIGGFAULT | SA_XFLAGS)
 
 #include <asm/sigcontext.h>
 
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/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 e792f29b5846..cd3d08dde47a 100644
--- a/include/linux/signal_types.h
+++ b/include/linux/signal_types.h
@@ -72,11 +72,11 @@ struct ksignal {
 #ifdef SA_RESTORER
 #define SA_UAPI_FLAGS                                                          \
 	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
-	 SA_NODEFER | SA_RESETHAND | SA_RESTORER)
+	 SA_NODEFER | SA_RESETHAND | SA_RESTORER | SA_XFLAGS)
 #else
 #define SA_UAPI_FLAGS                                                          \
 	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
-	 SA_NODEFER | SA_RESETHAND)
+	 SA_NODEFER | SA_RESETHAND | SA_XFLAGS)
 #endif
 #endif
 
diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
index cb3d6c267181..413d804623c0 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,7 @@ typedef struct siginfo {
 #define si_trapno	_sifields._sigfault._trapno
 #endif
 #define si_addr_lsb	_sifields._sigfault._addr_lsb
+#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 c30a9c1a77b2..aeee6bb0763b 100644
--- a/include/uapi/asm-generic/signal-defs.h
+++ b/include/uapi/asm-generic/signal-defs.h
@@ -19,6 +19,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 @@
  * should be avoided for new generic flags: 3, 4, 5, 6, 7, 8, 9, 16, 24, 25, 26.
  */
 #define SA_UNSUPPORTED	0x00000400
+#define SA_XFLAGS	0x00000800
 
 #define SA_NOMASK	SA_NODEFER
 #define SA_ONESHOT	SA_RESETHAND
diff --git a/kernel/signal.c b/kernel/signal.c
index 664a6c31137e..72182eed1b8d 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1669,6 +1669,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
 	info.si_flags = flags;
 	info.si_isr = isr;
 #endif
+	info.si_xflags = 0;
 	return force_sig_info_to_task(&info, t);
 }
 
@@ -1701,6 +1702,7 @@ int send_sig_fault(int sig, int code, void __user *addr
 	info.si_flags = flags;
 	info.si_isr = isr;
 #endif
+	info.si_xflags = 0;
 	return send_sig_info(info.si_signo, &info, t);
 }
 
@@ -1715,6 +1717,7 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
 	info.si_code = code;
 	info.si_addr = addr;
 	info.si_addr_lsb = lsb;
+	info.si_xflags = 0;
 	return force_sig_info(&info);
 }
 
@@ -1729,6 +1732,7 @@ int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *
 	info.si_code = code;
 	info.si_addr = addr;
 	info.si_addr_lsb = lsb;
+	info.si_xflags = 0;
 	return send_sig_info(info.si_signo, &info, t);
 }
 EXPORT_SYMBOL(send_sig_mceerr);
@@ -1744,6 +1748,7 @@ int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
 	info.si_addr  = addr;
 	info.si_lower = lower;
 	info.si_upper = upper;
+	info.si_xflags = 0;
 	return force_sig_info(&info);
 }
 
@@ -1758,6 +1763,7 @@ int force_sig_pkuerr(void __user *addr, u32 pkey)
 	info.si_code  = SEGV_PKUERR;
 	info.si_addr  = addr;
 	info.si_pkey  = pkey;
+	info.si_xflags = 0;
 	return force_sig_info(&info);
 }
 #endif
@@ -1774,6 +1780,7 @@ int force_sig_ptrace_errno_trap(int errno, void __user *addr)
 	info.si_errno = errno;
 	info.si_code  = TRAP_HWBKPT;
 	info.si_addr  = addr;
+	info.si_xflags = 0;
 	return force_sig_info(&info);
 }
 
@@ -3290,6 +3297,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;
 		break;
 	case SIL_FAULT_MCEERR:
 		to->si_addr = ptr_to_compat(from->si_addr);
@@ -3297,6 +3305,7 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
 		to->si_trapno = from->si_trapno;
 #endif
 		to->si_addr_lsb = from->si_addr_lsb;
+		to->si_xflags = from->si_xflags;
 		break;
 	case SIL_FAULT_BNDERR:
 		to->si_addr = ptr_to_compat(from->si_addr);
@@ -3305,6 +3314,7 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
 #endif
 		to->si_lower = ptr_to_compat(from->si_lower);
 		to->si_upper = ptr_to_compat(from->si_upper);
+		to->si_xflags = from->si_xflags;
 		break;
 	case SIL_FAULT_PKUERR:
 		to->si_addr = ptr_to_compat(from->si_addr);
@@ -3312,6 +3322,7 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
 		to->si_trapno = from->si_trapno;
 #endif
 		to->si_pkey = from->si_pkey;
+		to->si_xflags = from->si_xflags;
 		break;
 	case SIL_CHLD:
 		to->si_pid = from->si_pid;
@@ -3370,6 +3381,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;
 		break;
 	case SIL_FAULT_MCEERR:
 		to->si_addr = compat_ptr(from->si_addr);
@@ -3377,6 +3389,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 		to->si_trapno = from->si_trapno;
 #endif
 		to->si_addr_lsb = from->si_addr_lsb;
+		to->si_xflags = from->si_xflags;
 		break;
 	case SIL_FAULT_BNDERR:
 		to->si_addr = compat_ptr(from->si_addr);
@@ -3385,6 +3398,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 #endif
 		to->si_lower = compat_ptr(from->si_lower);
 		to->si_upper = compat_ptr(from->si_upper);
+		to->si_xflags = from->si_xflags;
 		break;
 	case SIL_FAULT_PKUERR:
 		to->si_addr = compat_ptr(from->si_addr);
@@ -3392,6 +3406,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 		to->si_trapno = from->si_trapno;
 #endif
 		to->si_pkey = from->si_pkey;
+		to->si_xflags = from->si_xflags;
 		break;
 	case SIL_CHLD:
 		to->si_pid    = from->si_pid;
-- 
2.28.0.220.ged08abb693-goog


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

* [PATCH v9 5/6] signal: define the field siginfo.si_xflags
@ 2020-08-18  3:33   ` Peter Collingbourne
  0 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-18  3:33 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.

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

 arch/arm/include/asm/signal.h              |  3 ++-
 arch/parisc/include/asm/signal.h           |  2 +-
 arch/powerpc/platforms/powernv/vas-fault.c |  1 +
 include/linux/compat.h                     |  2 ++
 include/linux/signal_types.h               |  4 ++--
 include/uapi/asm-generic/siginfo.h         |  3 +++
 include/uapi/asm-generic/signal-defs.h     |  4 ++++
 kernel/signal.c                            | 15 +++++++++++++++
 8 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/arch/arm/include/asm/signal.h b/arch/arm/include/asm/signal.h
index d1070a783993..6b2630dfe1df 100644
--- a/arch/arm/include/asm/signal.h
+++ b/arch/arm/include/asm/signal.h
@@ -19,7 +19,8 @@ typedef struct {
 
 #define SA_UAPI_FLAGS                                                          \
 	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_THIRTYTWO |             \
-	 SA_RESTORER | SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_RESETHAND)
+	 SA_RESTORER | SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_RESETHAND |   \
+	 SA_XFLAGS)
 
 #define __ARCH_HAS_SA_RESTORER
 
diff --git a/arch/parisc/include/asm/signal.h b/arch/parisc/include/asm/signal.h
index ad06e14f6e8a..3582bce44520 100644
--- a/arch/parisc/include/asm/signal.h
+++ b/arch/parisc/include/asm/signal.h
@@ -23,7 +23,7 @@ typedef struct {
 
 #define SA_UAPI_FLAGS                                                          \
 	(SA_ONSTACK | SA_RESETHAND | SA_NOCLDSTOP | SA_SIGINFO | SA_NODEFER |  \
-	 SA_RESTART | SA_NOCLDWAIT | _SA_SIGGFAULT)
+	 SA_RESTART | SA_NOCLDWAIT | _SA_SIGGFAULT | SA_XFLAGS)
 
 #include <asm/sigcontext.h>
 
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/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 e792f29b5846..cd3d08dde47a 100644
--- a/include/linux/signal_types.h
+++ b/include/linux/signal_types.h
@@ -72,11 +72,11 @@ struct ksignal {
 #ifdef SA_RESTORER
 #define SA_UAPI_FLAGS                                                          \
 	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
-	 SA_NODEFER | SA_RESETHAND | SA_RESTORER)
+	 SA_NODEFER | SA_RESETHAND | SA_RESTORER | SA_XFLAGS)
 #else
 #define SA_UAPI_FLAGS                                                          \
 	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
-	 SA_NODEFER | SA_RESETHAND)
+	 SA_NODEFER | SA_RESETHAND | SA_XFLAGS)
 #endif
 #endif
 
diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
index cb3d6c267181..413d804623c0 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,7 @@ typedef struct siginfo {
 #define si_trapno	_sifields._sigfault._trapno
 #endif
 #define si_addr_lsb	_sifields._sigfault._addr_lsb
+#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 c30a9c1a77b2..aeee6bb0763b 100644
--- a/include/uapi/asm-generic/signal-defs.h
+++ b/include/uapi/asm-generic/signal-defs.h
@@ -19,6 +19,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 @@
  * should be avoided for new generic flags: 3, 4, 5, 6, 7, 8, 9, 16, 24, 25, 26.
  */
 #define SA_UNSUPPORTED	0x00000400
+#define SA_XFLAGS	0x00000800
 
 #define SA_NOMASK	SA_NODEFER
 #define SA_ONESHOT	SA_RESETHAND
diff --git a/kernel/signal.c b/kernel/signal.c
index 664a6c31137e..72182eed1b8d 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1669,6 +1669,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
 	info.si_flags = flags;
 	info.si_isr = isr;
 #endif
+	info.si_xflags = 0;
 	return force_sig_info_to_task(&info, t);
 }
 
@@ -1701,6 +1702,7 @@ int send_sig_fault(int sig, int code, void __user *addr
 	info.si_flags = flags;
 	info.si_isr = isr;
 #endif
+	info.si_xflags = 0;
 	return send_sig_info(info.si_signo, &info, t);
 }
 
@@ -1715,6 +1717,7 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
 	info.si_code = code;
 	info.si_addr = addr;
 	info.si_addr_lsb = lsb;
+	info.si_xflags = 0;
 	return force_sig_info(&info);
 }
 
@@ -1729,6 +1732,7 @@ int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *
 	info.si_code = code;
 	info.si_addr = addr;
 	info.si_addr_lsb = lsb;
+	info.si_xflags = 0;
 	return send_sig_info(info.si_signo, &info, t);
 }
 EXPORT_SYMBOL(send_sig_mceerr);
@@ -1744,6 +1748,7 @@ int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
 	info.si_addr  = addr;
 	info.si_lower = lower;
 	info.si_upper = upper;
+	info.si_xflags = 0;
 	return force_sig_info(&info);
 }
 
@@ -1758,6 +1763,7 @@ int force_sig_pkuerr(void __user *addr, u32 pkey)
 	info.si_code  = SEGV_PKUERR;
 	info.si_addr  = addr;
 	info.si_pkey  = pkey;
+	info.si_xflags = 0;
 	return force_sig_info(&info);
 }
 #endif
@@ -1774,6 +1780,7 @@ int force_sig_ptrace_errno_trap(int errno, void __user *addr)
 	info.si_errno = errno;
 	info.si_code  = TRAP_HWBKPT;
 	info.si_addr  = addr;
+	info.si_xflags = 0;
 	return force_sig_info(&info);
 }
 
@@ -3290,6 +3297,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;
 		break;
 	case SIL_FAULT_MCEERR:
 		to->si_addr = ptr_to_compat(from->si_addr);
@@ -3297,6 +3305,7 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
 		to->si_trapno = from->si_trapno;
 #endif
 		to->si_addr_lsb = from->si_addr_lsb;
+		to->si_xflags = from->si_xflags;
 		break;
 	case SIL_FAULT_BNDERR:
 		to->si_addr = ptr_to_compat(from->si_addr);
@@ -3305,6 +3314,7 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
 #endif
 		to->si_lower = ptr_to_compat(from->si_lower);
 		to->si_upper = ptr_to_compat(from->si_upper);
+		to->si_xflags = from->si_xflags;
 		break;
 	case SIL_FAULT_PKUERR:
 		to->si_addr = ptr_to_compat(from->si_addr);
@@ -3312,6 +3322,7 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
 		to->si_trapno = from->si_trapno;
 #endif
 		to->si_pkey = from->si_pkey;
+		to->si_xflags = from->si_xflags;
 		break;
 	case SIL_CHLD:
 		to->si_pid = from->si_pid;
@@ -3370,6 +3381,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;
 		break;
 	case SIL_FAULT_MCEERR:
 		to->si_addr = compat_ptr(from->si_addr);
@@ -3377,6 +3389,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 		to->si_trapno = from->si_trapno;
 #endif
 		to->si_addr_lsb = from->si_addr_lsb;
+		to->si_xflags = from->si_xflags;
 		break;
 	case SIL_FAULT_BNDERR:
 		to->si_addr = compat_ptr(from->si_addr);
@@ -3385,6 +3398,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 #endif
 		to->si_lower = compat_ptr(from->si_lower);
 		to->si_upper = compat_ptr(from->si_upper);
+		to->si_xflags = from->si_xflags;
 		break;
 	case SIL_FAULT_PKUERR:
 		to->si_addr = compat_ptr(from->si_addr);
@@ -3392,6 +3406,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 		to->si_trapno = from->si_trapno;
 #endif
 		to->si_pkey = from->si_pkey;
+		to->si_xflags = from->si_xflags;
 		break;
 	case SIL_CHLD:
 		to->si_pid    = from->si_pid;
-- 
2.28.0.220.ged08abb693-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] 66+ messages in thread

* [PATCH v9 6/6] arm64: expose FAR_EL1 tag bits in siginfo
  2020-08-18  3:33 ` Peter Collingbourne
@ 2020-08-18  3:33   ` Peter Collingbourne
  -1 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-18  3:33 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

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/traps.h          |  7 +++-
 arch/arm64/kernel/debug-monitors.c      |  4 +-
 arch/arm64/kernel/entry-common.c        |  2 -
 arch/arm64/kernel/ptrace.c              |  2 +-
 arch/arm64/kernel/traps.c               | 15 ++++---
 arch/arm64/mm/fault.c                   | 54 ++++++++++++++-----------
 arch/mips/kernel/traps.c                |  2 +-
 arch/parisc/kernel/ptrace.c             |  2 +-
 arch/parisc/mm/fault.c                  |  2 +-
 arch/powerpc/mm/fault.c                 |  2 +-
 arch/x86/mm/fault.c                     |  3 +-
 include/linux/compat.h                  |  2 +
 include/linux/sched/signal.h            | 12 +++++-
 include/uapi/asm-generic/siginfo.h      | 10 +++++
 kernel/signal.c                         | 50 +++++++++++++++++++----
 mm/memory-failure.c                     |  2 +-
 18 files changed, 136 insertions(+), 58 deletions(-)

diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst
index eab4323609b9..bd23039841a5 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 SI_XFLAG_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/traps.h b/arch/arm64/include/asm/traps.h
index cee5928e1b7d..8e4f6c5b97af 100644
--- a/arch/arm64/include/asm/traps.h
+++ b/arch/arm64/include/asm/traps.h
@@ -26,8 +26,11 @@ 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_fault(int signo, int code, void __user *addr,
+			   unsigned long far, unsigned char far_tb_mask,
+			   const char *str);
+void arm64_force_sig_mceerr(int code, void __user *addr, short lsb,
+			    unsigned long far, const char *str);
 void arm64_force_sig_ptrace_errno_trap(int errno, void __user *addr, const char *str);
 
 /*
diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
index 7310a4f7f993..bc9e02fbb710 100644
--- a/arch/arm64/kernel/debug-monitors.c
+++ b/arch/arm64/kernel/debug-monitors.c
@@ -235,8 +235,8 @@ static void send_user_sigtrap(int si_code)
 		local_irq_enable();
 
 	arm64_force_sig_fault(SIGTRAP, si_code,
-			     (void __user *)instruction_pointer(regs),
-			     "User debug trap");
+			      (void __user *)instruction_pointer(regs), 0, 0,
+			      "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..c73312064220 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -197,7 +197,7 @@ static void ptrace_hbptriggered(struct perf_event *bp,
 	}
 #endif
 	arm64_force_sig_fault(SIGTRAP, TRAP_HWBKPT,
-			      (void __user *)(bkpt->trigger),
+			      (void __user *)(bkpt->trigger), 0, 0,
 			      desc);
 }
 
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 13ebd5ca2070..c945c5cc1312 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -235,20 +235,25 @@ static void arm64_show_signal(int signo, const char *str)
 }
 
 void arm64_force_sig_fault(int signo, int code, void __user *addr,
+			   unsigned long far, unsigned char far_tb_mask,
 			   const char *str)
 {
+	unsigned long ignored_bits_mask = ((unsigned long)far_tb_mask) << 56;
+
 	arm64_show_signal(signo, str);
 	if (signo == SIGKILL)
 		force_sig(SIGKILL);
 	else
-		force_sig_fault(signo, code, addr);
+		force_sig_fault_with_ignored_bits(signo, code, addr,
+						  far & ignored_bits_mask,
+						  ignored_bits_mask);
 }
 
 void arm64_force_sig_mceerr(int code, void __user *addr, short lsb,
-			    const char *str)
+			    unsigned long far, const char *str)
 {
 	arm64_show_signal(SIGBUS, str);
-	force_sig_mceerr(code, addr, lsb);
+	force_sig_mceerr(code, addr, lsb, far & (0xffUL << 56), 0xffUL << 56);
 }
 
 void arm64_force_sig_ptrace_errno_trap(int errno, void __user *addr,
@@ -267,7 +272,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, addr, 0, 0, str);
 	} else {
 		die(str, regs, err);
 	}
@@ -829,7 +834,7 @@ void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr)
 	current->thread.fault_address = 0;
 	current->thread.fault_code = esr;
 
-	arm64_force_sig_fault(SIGILL, ILL_ILLOPC, pc,
+	arm64_force_sig_fault(SIGILL, ILL_ILLOPC, pc, 0, 0,
 			      "Bad EL0 synchronous exception");
 }
 
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index f07333e86c2f..82f05644417e 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.
@@ -394,7 +397,7 @@ static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *re
 
 		set_thread_esr(addr, esr);
 		arm64_force_sig_fault(inf->sig, inf->code, (void __user *)addr,
-				      inf->name);
+				      far, 0xff, inf->name);
 	} else {
 		__do_kernel_fault(addr, esr, regs);
 	}
@@ -446,7 +449,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 +457,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;
@@ -566,7 +570,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
 		 * this page fault.
 		 */
 		arm64_force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)addr,
-				      inf->name);
+				      far, 0xff, inf->name);
 	} else if (fault & (VM_FAULT_HWPOISON_LARGE | VM_FAULT_HWPOISON)) {
 		unsigned int lsb;
 
@@ -575,7 +579,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
 			lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault));
 
 		arm64_force_sig_mceerr(BUS_MCEERR_AR, (void __user *)addr, lsb,
-				       inf->name);
+				       far, inf->name);
 	} else {
 		/*
 		 * Something tried to access memory that isn't in our memory
@@ -583,8 +587,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);
+				      (void __user *)addr, far, 0xff, inf->name);
 	}
 
 	return 0;
@@ -594,30 +597,32 @@ 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;
@@ -635,7 +640,7 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
 	if (esr & ESR_ELx_FnV)
 		siaddr = NULL;
 	else
-		siaddr  = (void __user *)addr;
+		siaddr  = (void __user *)untagged_addr(far);
 	arm64_notify_die(inf->name, regs, inf->sig, inf->code, siaddr, esr);
 
 	return 0;
@@ -708,11 +713,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 +727,8 @@ 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,
+			 (void __user *)addr, esr);
 }
 NOKPROBE_SYMBOL(do_mem_abort);
 
@@ -735,8 +741,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,
+			 (void __user *)addr, esr);
 }
 NOKPROBE_SYMBOL(do_sp_pc_abort);
 
@@ -862,8 +868,8 @@ 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,
+				 (void __user *)pc, esr);
 	}
 
 	debug_exception_exit(regs);
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 38aa07ccdbcc..73a181c904b0 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -775,7 +775,7 @@ void force_fcr31_sig(unsigned long fcr31, void __user *fault_addr,
 	else if (fcr31 & FPU_CSR_INE_X)
 		si_code = FPE_FLTRES;
 
-	force_sig_fault_to_task(SIGFPE, si_code, fault_addr, tsk);
+	force_sig_fault_to_task(SIGFPE, si_code, fault_addr, 0, 0, tsk);
 }
 
 int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcr31)
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
index 2127974982df..62c8bb0d7d31 100644
--- a/arch/parisc/kernel/ptrace.c
+++ b/arch/parisc/kernel/ptrace.c
@@ -89,7 +89,7 @@ void user_enable_single_step(struct task_struct *task)
 		   parent know something happened. */
 		force_sig_fault_to_task(SIGTRAP, TRAP_TRACE,
 					(void __user *) (task_regs(task)->iaoq[0] & ~3),
-					task);
+					0, 0, task);
 		/* notify_parent(task, SIGCHLD); */
 		return;
 	}
diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
index 4bfe2da9fbe3..2a6064ea2dfc 100644
--- a/arch/parisc/mm/fault.c
+++ b/arch/parisc/mm/fault.c
@@ -400,7 +400,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
 				lsb = PAGE_SHIFT;
 
 			force_sig_mceerr(BUS_MCEERR_AR, (void __user *) address,
-					 lsb);
+					 lsb, 0, 0);
 			return;
 		}
 #endif
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 0add963a849b..4ffe2fb8e31a 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -152,7 +152,7 @@ static int do_sigbus(struct pt_regs *regs, unsigned long address,
 		if (fault & VM_FAULT_HWPOISON)
 			lsb = PAGE_SHIFT;
 
-		force_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb);
+		force_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb, 0, 0);
 		return 0;
 	}
 
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 35f1498e9832..a443eec157f6 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -898,7 +898,8 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address,
 			lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault));
 		if (fault & VM_FAULT_HWPOISON)
 			lsb = PAGE_SHIFT;
-		force_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb);
+		force_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb, 0,
+				 0);
 		return;
 	}
 #endif
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/sched/signal.h b/include/linux/sched/signal.h
index 1bad18a1d8ba..f62a014a5a4d 100644
--- a/include/linux/sched/signal.h
+++ b/include/linux/sched/signal.h
@@ -311,16 +311,24 @@ static inline void kernel_signal_stop(void)
 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)
-	, struct task_struct *t);
+	, unsigned long addr_ignored_bits, unsigned long addr_ignored_bits_mask,
+	struct task_struct *t);
 int force_sig_fault(int sig, int code, void __user *addr
 	___ARCH_SI_TRAPNO(int trapno)
 	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr));
+int force_sig_fault_with_ignored_bits(int sig, int code, void __user *addr
+	___ARCH_SI_TRAPNO(int trapno)
+	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
+	, unsigned long addr_ignored_bits,
+	unsigned long addr_ignored_bits_mask);
 int send_sig_fault(int sig, int code, void __user *addr
 	___ARCH_SI_TRAPNO(int trapno)
 	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
 	, struct task_struct *t);
 
-int force_sig_mceerr(int code, void __user *, short);
+int force_sig_mceerr(int code, void __user *addr, short addr_lsb,
+		     unsigned long addr_ignored_bits,
+		     unsigned long addr_ignored_bits_mask);
 int send_sig_mceerr(int code, void __user *, short, struct task_struct *);
 
 int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper);
diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
index 413d804623c0..1fc6482b0ad4 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 */
@@ -155,6 +157,8 @@ typedef struct siginfo {
 #endif
 #define si_addr_lsb	_sifields._sigfault._addr_lsb
 #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
@@ -295,6 +299,12 @@ typedef struct siginfo {
 #define EMT_TAGOVF	1	/* tag overflow */
 #define NSIGEMT		1
 
+/*
+ * SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT si_xflags
+ */
+#define SI_XFLAG_IGNORED_BITS	1
+/* si_addr_ignored_bits{,_mask} fields valid */
+
 /*
  * sigevent definitions
  * 
diff --git a/kernel/signal.c b/kernel/signal.c
index 72182eed1b8d..1f1e42adc57d 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1652,7 +1652,8 @@ void force_sigsegv(int sig)
 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)
-	, struct task_struct *t)
+	, unsigned long addr_ignored_bits, unsigned long addr_ignored_bits_mask,
+	struct task_struct *t)
 {
 	struct kernel_siginfo info;
 
@@ -1669,17 +1670,32 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
 	info.si_flags = flags;
 	info.si_isr = isr;
 #endif
-	info.si_xflags = 0;
+	info.si_xflags = SI_XFLAG_IGNORED_BITS;
+	info.si_addr_ignored_bits = addr_ignored_bits;
+	info.si_addr_ignored_bits_mask = addr_ignored_bits_mask;
 	return force_sig_info_to_task(&info, t);
 }
 
-int force_sig_fault(int sig, int code, void __user *addr
+int force_sig_fault_with_ignored_bits(int sig, int code, void __user *addr
 	___ARCH_SI_TRAPNO(int trapno)
-	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr))
+	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr),
+	unsigned long addr_ignored_bits, unsigned long addr_ignored_bits_mask)
 {
 	return force_sig_fault_to_task(sig, code, addr
 				       ___ARCH_SI_TRAPNO(trapno)
-				       ___ARCH_SI_IA64(imm, flags, isr), current);
+				       ___ARCH_SI_IA64(imm, flags, isr),
+				       addr_ignored_bits,
+				       addr_ignored_bits_mask, current);
+}
+
+int force_sig_fault(int sig, int code, void __user *addr
+	___ARCH_SI_TRAPNO(int trapno)
+	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr))
+{
+	return force_sig_fault_with_ignored_bits(sig, code, addr
+						 ___ARCH_SI_TRAPNO(trapno)
+						 ___ARCH_SI_IA64(imm, flags,
+								 isr), 0, 0);
 }
 
 int send_sig_fault(int sig, int code, void __user *addr
@@ -1706,7 +1722,9 @@ int send_sig_fault(int sig, int code, void __user *addr
 	return send_sig_info(info.si_signo, &info, t);
 }
 
-int force_sig_mceerr(int code, void __user *addr, short lsb)
+int force_sig_mceerr(int code, void __user *addr, short lsb,
+		     unsigned long addr_ignored_bits,
+		     unsigned long addr_ignored_bits_mask)
 {
 	struct kernel_siginfo info;
 
@@ -1717,7 +1735,9 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
 	info.si_code = code;
 	info.si_addr = addr;
 	info.si_addr_lsb = lsb;
-	info.si_xflags = 0;
+	info.si_xflags = SI_XFLAG_IGNORED_BITS;
+	info.si_addr_ignored_bits = addr_ignored_bits;
+	info.si_addr_ignored_bits_mask = addr_ignored_bits_mask;
 	return force_sig_info(&info);
 }
 
@@ -3298,6 +3318,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;
 		break;
 	case SIL_FAULT_MCEERR:
 		to->si_addr = ptr_to_compat(from->si_addr);
@@ -3306,6 +3328,8 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
 #endif
 		to->si_addr_lsb = from->si_addr_lsb;
 		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;
 		break;
 	case SIL_FAULT_BNDERR:
 		to->si_addr = ptr_to_compat(from->si_addr);
@@ -3315,6 +3339,8 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
 		to->si_lower = ptr_to_compat(from->si_lower);
 		to->si_upper = ptr_to_compat(from->si_upper);
 		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;
 		break;
 	case SIL_FAULT_PKUERR:
 		to->si_addr = ptr_to_compat(from->si_addr);
@@ -3323,6 +3349,8 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
 #endif
 		to->si_pkey = from->si_pkey;
 		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;
 		break;
 	case SIL_CHLD:
 		to->si_pid = from->si_pid;
@@ -3382,6 +3410,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;
 		break;
 	case SIL_FAULT_MCEERR:
 		to->si_addr = compat_ptr(from->si_addr);
@@ -3390,6 +3420,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 #endif
 		to->si_addr_lsb = from->si_addr_lsb;
 		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;
 		break;
 	case SIL_FAULT_BNDERR:
 		to->si_addr = compat_ptr(from->si_addr);
@@ -3399,6 +3431,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 		to->si_lower = compat_ptr(from->si_lower);
 		to->si_upper = compat_ptr(from->si_upper);
 		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;
 		break;
 	case SIL_FAULT_PKUERR:
 		to->si_addr = compat_ptr(from->si_addr);
@@ -3407,6 +3441,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 #endif
 		to->si_pkey = from->si_pkey;
 		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;
 		break;
 	case SIL_CHLD:
 		to->si_pid    = from->si_pid;
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index f1aa6433f404..e85e0bd4f0da 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -218,7 +218,7 @@ static int kill_proc(struct to_kill *tk, unsigned long pfn, int flags)
 	if (flags & MF_ACTION_REQUIRED) {
 		WARN_ON_ONCE(t != current);
 		ret = force_sig_mceerr(BUS_MCEERR_AR,
-					 (void __user *)tk->addr, addr_lsb);
+					 (void __user *)tk->addr, addr_lsb, 0, 0);
 	} else {
 		/*
 		 * Don't use force here, it's convenient if the signal
-- 
2.28.0.220.ged08abb693-goog


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

* [PATCH v9 6/6] arm64: expose FAR_EL1 tag bits in siginfo
@ 2020-08-18  3:33   ` Peter Collingbourne
  0 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-18  3:33 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

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/traps.h          |  7 +++-
 arch/arm64/kernel/debug-monitors.c      |  4 +-
 arch/arm64/kernel/entry-common.c        |  2 -
 arch/arm64/kernel/ptrace.c              |  2 +-
 arch/arm64/kernel/traps.c               | 15 ++++---
 arch/arm64/mm/fault.c                   | 54 ++++++++++++++-----------
 arch/mips/kernel/traps.c                |  2 +-
 arch/parisc/kernel/ptrace.c             |  2 +-
 arch/parisc/mm/fault.c                  |  2 +-
 arch/powerpc/mm/fault.c                 |  2 +-
 arch/x86/mm/fault.c                     |  3 +-
 include/linux/compat.h                  |  2 +
 include/linux/sched/signal.h            | 12 +++++-
 include/uapi/asm-generic/siginfo.h      | 10 +++++
 kernel/signal.c                         | 50 +++++++++++++++++++----
 mm/memory-failure.c                     |  2 +-
 18 files changed, 136 insertions(+), 58 deletions(-)

diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst
index eab4323609b9..bd23039841a5 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 SI_XFLAG_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/traps.h b/arch/arm64/include/asm/traps.h
index cee5928e1b7d..8e4f6c5b97af 100644
--- a/arch/arm64/include/asm/traps.h
+++ b/arch/arm64/include/asm/traps.h
@@ -26,8 +26,11 @@ 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_fault(int signo, int code, void __user *addr,
+			   unsigned long far, unsigned char far_tb_mask,
+			   const char *str);
+void arm64_force_sig_mceerr(int code, void __user *addr, short lsb,
+			    unsigned long far, const char *str);
 void arm64_force_sig_ptrace_errno_trap(int errno, void __user *addr, const char *str);
 
 /*
diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
index 7310a4f7f993..bc9e02fbb710 100644
--- a/arch/arm64/kernel/debug-monitors.c
+++ b/arch/arm64/kernel/debug-monitors.c
@@ -235,8 +235,8 @@ static void send_user_sigtrap(int si_code)
 		local_irq_enable();
 
 	arm64_force_sig_fault(SIGTRAP, si_code,
-			     (void __user *)instruction_pointer(regs),
-			     "User debug trap");
+			      (void __user *)instruction_pointer(regs), 0, 0,
+			      "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..c73312064220 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -197,7 +197,7 @@ static void ptrace_hbptriggered(struct perf_event *bp,
 	}
 #endif
 	arm64_force_sig_fault(SIGTRAP, TRAP_HWBKPT,
-			      (void __user *)(bkpt->trigger),
+			      (void __user *)(bkpt->trigger), 0, 0,
 			      desc);
 }
 
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 13ebd5ca2070..c945c5cc1312 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -235,20 +235,25 @@ static void arm64_show_signal(int signo, const char *str)
 }
 
 void arm64_force_sig_fault(int signo, int code, void __user *addr,
+			   unsigned long far, unsigned char far_tb_mask,
 			   const char *str)
 {
+	unsigned long ignored_bits_mask = ((unsigned long)far_tb_mask) << 56;
+
 	arm64_show_signal(signo, str);
 	if (signo == SIGKILL)
 		force_sig(SIGKILL);
 	else
-		force_sig_fault(signo, code, addr);
+		force_sig_fault_with_ignored_bits(signo, code, addr,
+						  far & ignored_bits_mask,
+						  ignored_bits_mask);
 }
 
 void arm64_force_sig_mceerr(int code, void __user *addr, short lsb,
-			    const char *str)
+			    unsigned long far, const char *str)
 {
 	arm64_show_signal(SIGBUS, str);
-	force_sig_mceerr(code, addr, lsb);
+	force_sig_mceerr(code, addr, lsb, far & (0xffUL << 56), 0xffUL << 56);
 }
 
 void arm64_force_sig_ptrace_errno_trap(int errno, void __user *addr,
@@ -267,7 +272,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, addr, 0, 0, str);
 	} else {
 		die(str, regs, err);
 	}
@@ -829,7 +834,7 @@ void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr)
 	current->thread.fault_address = 0;
 	current->thread.fault_code = esr;
 
-	arm64_force_sig_fault(SIGILL, ILL_ILLOPC, pc,
+	arm64_force_sig_fault(SIGILL, ILL_ILLOPC, pc, 0, 0,
 			      "Bad EL0 synchronous exception");
 }
 
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index f07333e86c2f..82f05644417e 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.
@@ -394,7 +397,7 @@ static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *re
 
 		set_thread_esr(addr, esr);
 		arm64_force_sig_fault(inf->sig, inf->code, (void __user *)addr,
-				      inf->name);
+				      far, 0xff, inf->name);
 	} else {
 		__do_kernel_fault(addr, esr, regs);
 	}
@@ -446,7 +449,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 +457,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;
@@ -566,7 +570,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
 		 * this page fault.
 		 */
 		arm64_force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)addr,
-				      inf->name);
+				      far, 0xff, inf->name);
 	} else if (fault & (VM_FAULT_HWPOISON_LARGE | VM_FAULT_HWPOISON)) {
 		unsigned int lsb;
 
@@ -575,7 +579,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
 			lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault));
 
 		arm64_force_sig_mceerr(BUS_MCEERR_AR, (void __user *)addr, lsb,
-				       inf->name);
+				       far, inf->name);
 	} else {
 		/*
 		 * Something tried to access memory that isn't in our memory
@@ -583,8 +587,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);
+				      (void __user *)addr, far, 0xff, inf->name);
 	}
 
 	return 0;
@@ -594,30 +597,32 @@ 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;
@@ -635,7 +640,7 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
 	if (esr & ESR_ELx_FnV)
 		siaddr = NULL;
 	else
-		siaddr  = (void __user *)addr;
+		siaddr  = (void __user *)untagged_addr(far);
 	arm64_notify_die(inf->name, regs, inf->sig, inf->code, siaddr, esr);
 
 	return 0;
@@ -708,11 +713,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 +727,8 @@ 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,
+			 (void __user *)addr, esr);
 }
 NOKPROBE_SYMBOL(do_mem_abort);
 
@@ -735,8 +741,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,
+			 (void __user *)addr, esr);
 }
 NOKPROBE_SYMBOL(do_sp_pc_abort);
 
@@ -862,8 +868,8 @@ 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,
+				 (void __user *)pc, esr);
 	}
 
 	debug_exception_exit(regs);
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 38aa07ccdbcc..73a181c904b0 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -775,7 +775,7 @@ void force_fcr31_sig(unsigned long fcr31, void __user *fault_addr,
 	else if (fcr31 & FPU_CSR_INE_X)
 		si_code = FPE_FLTRES;
 
-	force_sig_fault_to_task(SIGFPE, si_code, fault_addr, tsk);
+	force_sig_fault_to_task(SIGFPE, si_code, fault_addr, 0, 0, tsk);
 }
 
 int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcr31)
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
index 2127974982df..62c8bb0d7d31 100644
--- a/arch/parisc/kernel/ptrace.c
+++ b/arch/parisc/kernel/ptrace.c
@@ -89,7 +89,7 @@ void user_enable_single_step(struct task_struct *task)
 		   parent know something happened. */
 		force_sig_fault_to_task(SIGTRAP, TRAP_TRACE,
 					(void __user *) (task_regs(task)->iaoq[0] & ~3),
-					task);
+					0, 0, task);
 		/* notify_parent(task, SIGCHLD); */
 		return;
 	}
diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
index 4bfe2da9fbe3..2a6064ea2dfc 100644
--- a/arch/parisc/mm/fault.c
+++ b/arch/parisc/mm/fault.c
@@ -400,7 +400,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
 				lsb = PAGE_SHIFT;
 
 			force_sig_mceerr(BUS_MCEERR_AR, (void __user *) address,
-					 lsb);
+					 lsb, 0, 0);
 			return;
 		}
 #endif
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 0add963a849b..4ffe2fb8e31a 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -152,7 +152,7 @@ static int do_sigbus(struct pt_regs *regs, unsigned long address,
 		if (fault & VM_FAULT_HWPOISON)
 			lsb = PAGE_SHIFT;
 
-		force_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb);
+		force_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb, 0, 0);
 		return 0;
 	}
 
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 35f1498e9832..a443eec157f6 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -898,7 +898,8 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address,
 			lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault));
 		if (fault & VM_FAULT_HWPOISON)
 			lsb = PAGE_SHIFT;
-		force_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb);
+		force_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb, 0,
+				 0);
 		return;
 	}
 #endif
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/sched/signal.h b/include/linux/sched/signal.h
index 1bad18a1d8ba..f62a014a5a4d 100644
--- a/include/linux/sched/signal.h
+++ b/include/linux/sched/signal.h
@@ -311,16 +311,24 @@ static inline void kernel_signal_stop(void)
 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)
-	, struct task_struct *t);
+	, unsigned long addr_ignored_bits, unsigned long addr_ignored_bits_mask,
+	struct task_struct *t);
 int force_sig_fault(int sig, int code, void __user *addr
 	___ARCH_SI_TRAPNO(int trapno)
 	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr));
+int force_sig_fault_with_ignored_bits(int sig, int code, void __user *addr
+	___ARCH_SI_TRAPNO(int trapno)
+	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
+	, unsigned long addr_ignored_bits,
+	unsigned long addr_ignored_bits_mask);
 int send_sig_fault(int sig, int code, void __user *addr
 	___ARCH_SI_TRAPNO(int trapno)
 	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
 	, struct task_struct *t);
 
-int force_sig_mceerr(int code, void __user *, short);
+int force_sig_mceerr(int code, void __user *addr, short addr_lsb,
+		     unsigned long addr_ignored_bits,
+		     unsigned long addr_ignored_bits_mask);
 int send_sig_mceerr(int code, void __user *, short, struct task_struct *);
 
 int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper);
diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
index 413d804623c0..1fc6482b0ad4 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 */
@@ -155,6 +157,8 @@ typedef struct siginfo {
 #endif
 #define si_addr_lsb	_sifields._sigfault._addr_lsb
 #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
@@ -295,6 +299,12 @@ typedef struct siginfo {
 #define EMT_TAGOVF	1	/* tag overflow */
 #define NSIGEMT		1
 
+/*
+ * SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT si_xflags
+ */
+#define SI_XFLAG_IGNORED_BITS	1
+/* si_addr_ignored_bits{,_mask} fields valid */
+
 /*
  * sigevent definitions
  * 
diff --git a/kernel/signal.c b/kernel/signal.c
index 72182eed1b8d..1f1e42adc57d 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1652,7 +1652,8 @@ void force_sigsegv(int sig)
 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)
-	, struct task_struct *t)
+	, unsigned long addr_ignored_bits, unsigned long addr_ignored_bits_mask,
+	struct task_struct *t)
 {
 	struct kernel_siginfo info;
 
@@ -1669,17 +1670,32 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
 	info.si_flags = flags;
 	info.si_isr = isr;
 #endif
-	info.si_xflags = 0;
+	info.si_xflags = SI_XFLAG_IGNORED_BITS;
+	info.si_addr_ignored_bits = addr_ignored_bits;
+	info.si_addr_ignored_bits_mask = addr_ignored_bits_mask;
 	return force_sig_info_to_task(&info, t);
 }
 
-int force_sig_fault(int sig, int code, void __user *addr
+int force_sig_fault_with_ignored_bits(int sig, int code, void __user *addr
 	___ARCH_SI_TRAPNO(int trapno)
-	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr))
+	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr),
+	unsigned long addr_ignored_bits, unsigned long addr_ignored_bits_mask)
 {
 	return force_sig_fault_to_task(sig, code, addr
 				       ___ARCH_SI_TRAPNO(trapno)
-				       ___ARCH_SI_IA64(imm, flags, isr), current);
+				       ___ARCH_SI_IA64(imm, flags, isr),
+				       addr_ignored_bits,
+				       addr_ignored_bits_mask, current);
+}
+
+int force_sig_fault(int sig, int code, void __user *addr
+	___ARCH_SI_TRAPNO(int trapno)
+	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr))
+{
+	return force_sig_fault_with_ignored_bits(sig, code, addr
+						 ___ARCH_SI_TRAPNO(trapno)
+						 ___ARCH_SI_IA64(imm, flags,
+								 isr), 0, 0);
 }
 
 int send_sig_fault(int sig, int code, void __user *addr
@@ -1706,7 +1722,9 @@ int send_sig_fault(int sig, int code, void __user *addr
 	return send_sig_info(info.si_signo, &info, t);
 }
 
-int force_sig_mceerr(int code, void __user *addr, short lsb)
+int force_sig_mceerr(int code, void __user *addr, short lsb,
+		     unsigned long addr_ignored_bits,
+		     unsigned long addr_ignored_bits_mask)
 {
 	struct kernel_siginfo info;
 
@@ -1717,7 +1735,9 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
 	info.si_code = code;
 	info.si_addr = addr;
 	info.si_addr_lsb = lsb;
-	info.si_xflags = 0;
+	info.si_xflags = SI_XFLAG_IGNORED_BITS;
+	info.si_addr_ignored_bits = addr_ignored_bits;
+	info.si_addr_ignored_bits_mask = addr_ignored_bits_mask;
 	return force_sig_info(&info);
 }
 
@@ -3298,6 +3318,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;
 		break;
 	case SIL_FAULT_MCEERR:
 		to->si_addr = ptr_to_compat(from->si_addr);
@@ -3306,6 +3328,8 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
 #endif
 		to->si_addr_lsb = from->si_addr_lsb;
 		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;
 		break;
 	case SIL_FAULT_BNDERR:
 		to->si_addr = ptr_to_compat(from->si_addr);
@@ -3315,6 +3339,8 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
 		to->si_lower = ptr_to_compat(from->si_lower);
 		to->si_upper = ptr_to_compat(from->si_upper);
 		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;
 		break;
 	case SIL_FAULT_PKUERR:
 		to->si_addr = ptr_to_compat(from->si_addr);
@@ -3323,6 +3349,8 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
 #endif
 		to->si_pkey = from->si_pkey;
 		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;
 		break;
 	case SIL_CHLD:
 		to->si_pid = from->si_pid;
@@ -3382,6 +3410,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;
 		break;
 	case SIL_FAULT_MCEERR:
 		to->si_addr = compat_ptr(from->si_addr);
@@ -3390,6 +3420,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 #endif
 		to->si_addr_lsb = from->si_addr_lsb;
 		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;
 		break;
 	case SIL_FAULT_BNDERR:
 		to->si_addr = compat_ptr(from->si_addr);
@@ -3399,6 +3431,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 		to->si_lower = compat_ptr(from->si_lower);
 		to->si_upper = compat_ptr(from->si_upper);
 		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;
 		break;
 	case SIL_FAULT_PKUERR:
 		to->si_addr = compat_ptr(from->si_addr);
@@ -3407,6 +3441,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 #endif
 		to->si_pkey = from->si_pkey;
 		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;
 		break;
 	case SIL_CHLD:
 		to->si_pid    = from->si_pid;
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index f1aa6433f404..e85e0bd4f0da 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -218,7 +218,7 @@ static int kill_proc(struct to_kill *tk, unsigned long pfn, int flags)
 	if (flags & MF_ACTION_REQUIRED) {
 		WARN_ON_ONCE(t != current);
 		ret = force_sig_mceerr(BUS_MCEERR_AR,
-					 (void __user *)tk->addr, addr_lsb);
+					 (void __user *)tk->addr, addr_lsb, 0, 0);
 	} else {
 		/*
 		 * Don't use force here, it's convenient if the signal
-- 
2.28.0.220.ged08abb693-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] 66+ messages in thread

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

Hi Peter,

On Tue, Aug 18, 2020 at 5:39 AM Peter Collingbourne <pcc@google.com> 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>

Thanks for your patch!

>  arch/m68k/include/uapi/asm/signal.h    | 24 -------------

Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>

> --- 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_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.

Perhaps the order should match the order of the definitions below?
Then it becomes obvious SA_SIGINFO is not documented (it was on arm).

> + *
> + * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
> + * Unix names RESETHAND and NODEFER respectively.

I think moving this last comment below, just above the definitions of
SA_NOMASK and SA_ONESHOT, would make this easier to read.

> + */
> +#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
> +/*
> + * 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.

And I think this belongs to the previous comment block.

> + */
> +
> +#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

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

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

* Re: [PATCH v9 2/6] arch: move SA_* definitions to generic headers
@ 2020-08-19  7:13     ` Geert Uytterhoeven
  0 siblings, 0 replies; 66+ messages in thread
From: Geert Uytterhoeven @ 2020-08-19  7:13 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, Dave Martin, Evgenii Stepanov,
	Richard Henderson

Hi Peter,

On Tue, Aug 18, 2020 at 5:39 AM Peter Collingbourne <pcc@google.com> 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>

Thanks for your patch!

>  arch/m68k/include/uapi/asm/signal.h    | 24 -------------

Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>

> --- 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_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.

Perhaps the order should match the order of the definitions below?
Then it becomes obvious SA_SIGINFO is not documented (it was on arm).

> + *
> + * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
> + * Unix names RESETHAND and NODEFER respectively.

I think moving this last comment below, just above the definitions of
SA_NOMASK and SA_ONESHOT, would make this easier to read.

> + */
> +#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
> +/*
> + * 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.

And I think this belongs to the previous comment block.

> + */
> +
> +#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

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

_______________________________________________
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] 66+ messages in thread

* Re: [PATCH v9 2/6] arch: move SA_* definitions to generic headers
  2020-08-18  3:33   ` Peter Collingbourne
@ 2020-08-19 10:30     ` Dave Martin
  -1 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-19 10:30 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 Mon, Aug 17, 2020 at 08:33:47PM -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>
> ---
> View this change in Gerrit: https://linux-review.googlesource.com/q/Ia3849f18b8009bf41faca374e701cdca36974528
> 
>  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(-)

Nice diffstat!

> 
> 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

Can we add a placeholder for this in the common header?  We don't want
people accidentally defining a new generic flag that clashes with this.

> -#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

[...]

Otherwise, looks like a sensible cleanup.

Cheers
---Dave

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

* Re: [PATCH v9 2/6] arch: move SA_* definitions to generic headers
@ 2020-08-19 10:30     ` Dave Martin
  0 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-19 10:30 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 Mon, Aug 17, 2020 at 08:33:47PM -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>
> ---
> View this change in Gerrit: https://linux-review.googlesource.com/q/Ia3849f18b8009bf41faca374e701cdca36974528
> 
>  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(-)

Nice diffstat!

> 
> 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

Can we add a placeholder for this in the common header?  We don't want
people accidentally defining a new generic flag that clashes with this.

> -#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

[...]

Otherwise, looks like a sensible cleanup.

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] 66+ messages in thread

* Re: [PATCH v9 3/6] signal: clear non-uapi flag bits when passing/returning sa_flags
  2020-08-18  3:33   ` Peter Collingbourne
@ 2020-08-19 10:39     ` Dave Martin
  -1 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-19 10:39 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 Mon, Aug 17, 2020 at 08:33:48PM -0700, Peter Collingbourne wrote:

Nit: please say what the patch does.  Subject line should summarise
what is done, but should not add new information that is not present in
the description proper.

(Same for all the other patches.)

> 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.
> 
> Signed-off-by: Peter Collingbourne <pcc@google.com>
> ---
> View this change in Gerrit: https://linux-review.googlesource.com/q/I35aab6f5be932505d90f3b3450c083b4db1eca86
> 
>  arch/arm/include/asm/signal.h    |  4 ++++
>  arch/parisc/include/asm/signal.h |  4 ++++
>  arch/x86/kernel/signal_compat.c  |  7 -------
>  include/linux/signal_types.h     | 12 ++++++++++++
>  kernel/signal.c                  | 10 ++++++++++
>  5 files changed, 30 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/arm/include/asm/signal.h b/arch/arm/include/asm/signal.h
> index 65530a042009..d1070a783993 100644
> --- a/arch/arm/include/asm/signal.h
> +++ b/arch/arm/include/asm/signal.h
> @@ -17,6 +17,10 @@ typedef struct {
>  	unsigned long sig[_NSIG_WORDS];
>  } sigset_t;
>  
> +#define SA_UAPI_FLAGS                                                          \
> +	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_THIRTYTWO |             \
> +	 SA_RESTORER | SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_RESETHAND)
> +

I wonder whether all these per-arch definitions will tend to bitrot when
people add new common flags.

Can we have a common definition for the common bits, and just add the
extra arch-specific ones here?


Also, I wonder whether we should avoid the "SA_" prefix here.  Maybe
UAPI_SA_FLAGS?

>  #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..ad06e14f6e8a 100644
> --- a/arch/parisc/include/asm/signal.h
> +++ b/arch/parisc/include/asm/signal.h
> @@ -21,6 +21,10 @@ typedef struct {
>  	unsigned long sig[_NSIG_WORDS];
>  } sigset_t;
>  
> +#define SA_UAPI_FLAGS                                                          \
> +	(SA_ONSTACK | SA_RESETHAND | SA_NOCLDSTOP | SA_SIGINFO | SA_NODEFER |  \
> +	 SA_RESTART | SA_NOCLDWAIT | _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..e792f29b5846 100644
> --- a/include/linux/signal_types.h
> +++ b/include/linux/signal_types.h
> @@ -68,4 +68,16 @@ struct ksignal {
>  	int sig;
>  };
>  
> +#ifndef SA_UAPI_FLAGS
> +#ifdef SA_RESTORER
> +#define SA_UAPI_FLAGS                                                          \
> +	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
> +	 SA_NODEFER | SA_RESETHAND | SA_RESTORER)
> +#else
> +#define SA_UAPI_FLAGS                                                          \
> +	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
> +	 SA_NODEFER | SA_RESETHAND)
> +#endif
> +#endif
> +
>  #endif /* _LINUX_SIGNAL_TYPES_H */
> diff --git a/kernel/signal.c b/kernel/signal.c
> index 42b67d2cea37..348b7981f1ff 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 &= SA_UAPI_FLAGS;
> +	if (oact)
> +		oact->sa.sa_flags &= SA_UAPI_FLAGS;
> +

Seems reasonable.

Cheers
---Dave

>  	sigaction_compat_abi(act, oact);
>  
>  	if (act) {
> -- 
> 2.28.0.220.ged08abb693-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] 66+ messages in thread

* Re: [PATCH v9 3/6] signal: clear non-uapi flag bits when passing/returning sa_flags
@ 2020-08-19 10:39     ` Dave Martin
  0 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-19 10:39 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 Mon, Aug 17, 2020 at 08:33:48PM -0700, Peter Collingbourne wrote:

Nit: please say what the patch does.  Subject line should summarise
what is done, but should not add new information that is not present in
the description proper.

(Same for all the other patches.)

> 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.
> 
> Signed-off-by: Peter Collingbourne <pcc@google.com>
> ---
> View this change in Gerrit: https://linux-review.googlesource.com/q/I35aab6f5be932505d90f3b3450c083b4db1eca86
> 
>  arch/arm/include/asm/signal.h    |  4 ++++
>  arch/parisc/include/asm/signal.h |  4 ++++
>  arch/x86/kernel/signal_compat.c  |  7 -------
>  include/linux/signal_types.h     | 12 ++++++++++++
>  kernel/signal.c                  | 10 ++++++++++
>  5 files changed, 30 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/arm/include/asm/signal.h b/arch/arm/include/asm/signal.h
> index 65530a042009..d1070a783993 100644
> --- a/arch/arm/include/asm/signal.h
> +++ b/arch/arm/include/asm/signal.h
> @@ -17,6 +17,10 @@ typedef struct {
>  	unsigned long sig[_NSIG_WORDS];
>  } sigset_t;
>  
> +#define SA_UAPI_FLAGS                                                          \
> +	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_THIRTYTWO |             \
> +	 SA_RESTORER | SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_RESETHAND)
> +

I wonder whether all these per-arch definitions will tend to bitrot when
people add new common flags.

Can we have a common definition for the common bits, and just add the
extra arch-specific ones here?


Also, I wonder whether we should avoid the "SA_" prefix here.  Maybe
UAPI_SA_FLAGS?

>  #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..ad06e14f6e8a 100644
> --- a/arch/parisc/include/asm/signal.h
> +++ b/arch/parisc/include/asm/signal.h
> @@ -21,6 +21,10 @@ typedef struct {
>  	unsigned long sig[_NSIG_WORDS];
>  } sigset_t;
>  
> +#define SA_UAPI_FLAGS                                                          \
> +	(SA_ONSTACK | SA_RESETHAND | SA_NOCLDSTOP | SA_SIGINFO | SA_NODEFER |  \
> +	 SA_RESTART | SA_NOCLDWAIT | _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..e792f29b5846 100644
> --- a/include/linux/signal_types.h
> +++ b/include/linux/signal_types.h
> @@ -68,4 +68,16 @@ struct ksignal {
>  	int sig;
>  };
>  
> +#ifndef SA_UAPI_FLAGS
> +#ifdef SA_RESTORER
> +#define SA_UAPI_FLAGS                                                          \
> +	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
> +	 SA_NODEFER | SA_RESETHAND | SA_RESTORER)
> +#else
> +#define SA_UAPI_FLAGS                                                          \
> +	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
> +	 SA_NODEFER | SA_RESETHAND)
> +#endif
> +#endif
> +
>  #endif /* _LINUX_SIGNAL_TYPES_H */
> diff --git a/kernel/signal.c b/kernel/signal.c
> index 42b67d2cea37..348b7981f1ff 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 &= SA_UAPI_FLAGS;
> +	if (oact)
> +		oact->sa.sa_flags &= SA_UAPI_FLAGS;
> +

Seems reasonable.

Cheers
---Dave

>  	sigaction_compat_abi(act, oact);
>  
>  	if (act) {
> -- 
> 2.28.0.220.ged08abb693-goog
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

_______________________________________________
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] 66+ messages in thread

* Re: [PATCH v9 4/6] signal: define the SA_UNSUPPORTED bit in sa_flags
  2020-08-18  3:33   ` Peter Collingbourne
@ 2020-08-19 14:51     ` Dave Martin
  -1 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-19 14:51 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 Mon, Aug 17, 2020 at 08:33:49PM -0700, Peter Collingbourne wrote:
> 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 91000b6b97e0..c30a9c1a77b2 100644
> --- a/include/uapi/asm-generic/signal-defs.h
> +++ b/include/uapi/asm-generic/signal-defs.h
> @@ -13,6 +13,12 @@
>   * 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_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 @@
>   * 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.
>   */
> +#define SA_UNSUPPORTED	0x00000400

This concept confused me a bit initially, since in a sense this flag is
supported, just with a rather peculiar meaning.

Since the main (only) purpose of this bit will be to check whether
SA_XFLAGS is actually supported, I wonder whether it makes sense to weld
the two together, say:

#define SA_REQUEST_XFLAGS	0x00000c00
#define SA_XFLAGS_MASK		0x00000c00
#define SA_HAVE_XFLAGS		0x00000800

This is a departure from the current style of definitions though.

	sa.sa_flags |= SA_REQUEST_XFLAGS;
	sigaction(..., &sa, &sa);
	if ((sa.sa_flags & SA_XFLAGS_MASK) == SA_HAVE_XFLAGS)
		/* xflags available */


This would require some juggling of the way SA_UAPI_FLAGS works though.
Maybe not worth it, so long as the semantics get clearly documented.

[...]

Cheers
---Dave

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

* Re: [PATCH v9 4/6] signal: define the SA_UNSUPPORTED bit in sa_flags
@ 2020-08-19 14:51     ` Dave Martin
  0 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-19 14:51 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 Mon, Aug 17, 2020 at 08:33:49PM -0700, Peter Collingbourne wrote:
> 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 91000b6b97e0..c30a9c1a77b2 100644
> --- a/include/uapi/asm-generic/signal-defs.h
> +++ b/include/uapi/asm-generic/signal-defs.h
> @@ -13,6 +13,12 @@
>   * 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_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 @@
>   * 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.
>   */
> +#define SA_UNSUPPORTED	0x00000400

This concept confused me a bit initially, since in a sense this flag is
supported, just with a rather peculiar meaning.

Since the main (only) purpose of this bit will be to check whether
SA_XFLAGS is actually supported, I wonder whether it makes sense to weld
the two together, say:

#define SA_REQUEST_XFLAGS	0x00000c00
#define SA_XFLAGS_MASK		0x00000c00
#define SA_HAVE_XFLAGS		0x00000800

This is a departure from the current style of definitions though.

	sa.sa_flags |= SA_REQUEST_XFLAGS;
	sigaction(..., &sa, &sa);
	if ((sa.sa_flags & SA_XFLAGS_MASK) == SA_HAVE_XFLAGS)
		/* xflags available */


This would require some juggling of the way SA_UAPI_FLAGS works though.
Maybe not worth it, so long as the semantics get clearly documented.

[...]

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] 66+ messages in thread

* Re: [PATCH v9 5/6] signal: define the field siginfo.si_xflags
  2020-08-18  3:33   ` Peter Collingbourne
@ 2020-08-19 15:40     ` Dave Martin
  -1 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-19 15:40 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 Mon, Aug 17, 2020 at 08:33:50PM -0700, Peter Collingbourne wrote:
> 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.
> 
> 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.

For clarity, is the new si_xflags field supposed to be valid for all
signal types, or just certain signals and si_codes?

What happens for things like a rt_sigqueueinfo() from userspace?

> 
> Signed-off-by: Peter Collingbourne <pcc@google.com>
> ---
> View this change in Gerrit: https://linux-review.googlesource.com/q/Ide155ce29366c3eab2a944ae4c51205982e5b8b2
> 
>  arch/arm/include/asm/signal.h              |  3 ++-
>  arch/parisc/include/asm/signal.h           |  2 +-
>  arch/powerpc/platforms/powernv/vas-fault.c |  1 +
>  include/linux/compat.h                     |  2 ++
>  include/linux/signal_types.h               |  4 ++--
>  include/uapi/asm-generic/siginfo.h         |  3 +++
>  include/uapi/asm-generic/signal-defs.h     |  4 ++++
>  kernel/signal.c                            | 15 +++++++++++++++
>  8 files changed, 30 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm/include/asm/signal.h b/arch/arm/include/asm/signal.h
> index d1070a783993..6b2630dfe1df 100644
> --- a/arch/arm/include/asm/signal.h
> +++ b/arch/arm/include/asm/signal.h
> @@ -19,7 +19,8 @@ typedef struct {
>  
>  #define SA_UAPI_FLAGS                                                          \
>  	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_THIRTYTWO |             \
> -	 SA_RESTORER | SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_RESETHAND)
> +	 SA_RESTORER | SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_RESETHAND |   \
> +	 SA_XFLAGS)
>  
>  #define __ARCH_HAS_SA_RESTORER
>  
> diff --git a/arch/parisc/include/asm/signal.h b/arch/parisc/include/asm/signal.h
> index ad06e14f6e8a..3582bce44520 100644
> --- a/arch/parisc/include/asm/signal.h
> +++ b/arch/parisc/include/asm/signal.h
> @@ -23,7 +23,7 @@ typedef struct {
>  
>  #define SA_UAPI_FLAGS                                                          \
>  	(SA_ONSTACK | SA_RESETHAND | SA_NOCLDSTOP | SA_SIGINFO | SA_NODEFER |  \
> -	 SA_RESTART | SA_NOCLDWAIT | _SA_SIGGFAULT)
> +	 SA_RESTART | SA_NOCLDWAIT | _SA_SIGGFAULT | SA_XFLAGS)
>  
>  #include <asm/sigcontext.h>
>  
> 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/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 e792f29b5846..cd3d08dde47a 100644
> --- a/include/linux/signal_types.h
> +++ b/include/linux/signal_types.h
> @@ -72,11 +72,11 @@ struct ksignal {
>  #ifdef SA_RESTORER
>  #define SA_UAPI_FLAGS                                                          \
>  	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
> -	 SA_NODEFER | SA_RESETHAND | SA_RESTORER)
> +	 SA_NODEFER | SA_RESETHAND | SA_RESTORER | SA_XFLAGS)
>  #else
>  #define SA_UAPI_FLAGS                                                          \
>  	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
> -	 SA_NODEFER | SA_RESETHAND)
> +	 SA_NODEFER | SA_RESETHAND | SA_XFLAGS)
>  #endif
>  #endif
>  
> diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
> index cb3d6c267181..413d804623c0 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,7 @@ typedef struct siginfo {
>  #define si_trapno	_sifields._sigfault._trapno
>  #endif
>  #define si_addr_lsb	_sifields._sigfault._addr_lsb
> +#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 c30a9c1a77b2..aeee6bb0763b 100644
> --- a/include/uapi/asm-generic/signal-defs.h
> +++ b/include/uapi/asm-generic/signal-defs.h
> @@ -19,6 +19,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 @@
>   * should be avoided for new generic flags: 3, 4, 5, 6, 7, 8, 9, 16, 24, 25, 26.
>   */
>  #define SA_UNSUPPORTED	0x00000400
> +#define SA_XFLAGS	0x00000800
>  
>  #define SA_NOMASK	SA_NODEFER
>  #define SA_ONESHOT	SA_RESETHAND
> diff --git a/kernel/signal.c b/kernel/signal.c
> index 664a6c31137e..72182eed1b8d 100644
> --- a/kernel/signal.c
> +++ b/kernel/signal.c
> @@ -1669,6 +1669,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
>  	info.si_flags = flags;
>  	info.si_isr = isr;
>  #endif
> +	info.si_xflags = 0;
>  	return force_sig_info_to_task(&info, t);
>  }
>  
> @@ -1701,6 +1702,7 @@ int send_sig_fault(int sig, int code, void __user *addr
>  	info.si_flags = flags;
>  	info.si_isr = isr;
>  #endif
> +	info.si_xflags = 0;
>  	return send_sig_info(info.si_signo, &info, t);
>  }
>  
> @@ -1715,6 +1717,7 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
>  	info.si_code = code;
>  	info.si_addr = addr;
>  	info.si_addr_lsb = lsb;
> +	info.si_xflags = 0;
>  	return force_sig_info(&info);
>  }
>  
> @@ -1729,6 +1732,7 @@ int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *
>  	info.si_code = code;
>  	info.si_addr = addr;
>  	info.si_addr_lsb = lsb;
> +	info.si_xflags = 0;
>  	return send_sig_info(info.si_signo, &info, t);
>  }
>  EXPORT_SYMBOL(send_sig_mceerr);
> @@ -1744,6 +1748,7 @@ int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
>  	info.si_addr  = addr;
>  	info.si_lower = lower;
>  	info.si_upper = upper;
> +	info.si_xflags = 0;
>  	return force_sig_info(&info);
>  }
>  
> @@ -1758,6 +1763,7 @@ int force_sig_pkuerr(void __user *addr, u32 pkey)
>  	info.si_code  = SEGV_PKUERR;
>  	info.si_addr  = addr;
>  	info.si_pkey  = pkey;
> +	info.si_xflags = 0;
>  	return force_sig_info(&info);
>  }
>  #endif
> @@ -1774,6 +1780,7 @@ int force_sig_ptrace_errno_trap(int errno, void __user *addr)
>  	info.si_errno = errno;
>  	info.si_code  = TRAP_HWBKPT;
>  	info.si_addr  = addr;
> +	info.si_xflags = 0;
>  	return force_sig_info(&info);
>  }
>  
> @@ -3290,6 +3297,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;
>  		break;
>  	case SIL_FAULT_MCEERR:
>  		to->si_addr = ptr_to_compat(from->si_addr);
> @@ -3297,6 +3305,7 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
>  		to->si_trapno = from->si_trapno;
>  #endif
>  		to->si_addr_lsb = from->si_addr_lsb;
> +		to->si_xflags = from->si_xflags;
>  		break;
>  	case SIL_FAULT_BNDERR:
>  		to->si_addr = ptr_to_compat(from->si_addr);
> @@ -3305,6 +3314,7 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
>  #endif
>  		to->si_lower = ptr_to_compat(from->si_lower);
>  		to->si_upper = ptr_to_compat(from->si_upper);
> +		to->si_xflags = from->si_xflags;
>  		break;
>  	case SIL_FAULT_PKUERR:
>  		to->si_addr = ptr_to_compat(from->si_addr);
> @@ -3312,6 +3322,7 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
>  		to->si_trapno = from->si_trapno;
>  #endif
>  		to->si_pkey = from->si_pkey;
> +		to->si_xflags = from->si_xflags;
>  		break;
>  	case SIL_CHLD:
>  		to->si_pid = from->si_pid;
> @@ -3370,6 +3381,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;
>  		break;
>  	case SIL_FAULT_MCEERR:
>  		to->si_addr = compat_ptr(from->si_addr);
> @@ -3377,6 +3389,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
>  		to->si_trapno = from->si_trapno;
>  #endif
>  		to->si_addr_lsb = from->si_addr_lsb;
> +		to->si_xflags = from->si_xflags;
>  		break;
>  	case SIL_FAULT_BNDERR:
>  		to->si_addr = compat_ptr(from->si_addr);
> @@ -3385,6 +3398,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
>  #endif
>  		to->si_lower = compat_ptr(from->si_lower);
>  		to->si_upper = compat_ptr(from->si_upper);
> +		to->si_xflags = from->si_xflags;
>  		break;
>  	case SIL_FAULT_PKUERR:
>  		to->si_addr = compat_ptr(from->si_addr);
> @@ -3392,6 +3406,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
>  		to->si_trapno = from->si_trapno;
>  #endif
>  		to->si_pkey = from->si_pkey;
> +		to->si_xflags = from->si_xflags;

How did you figure out the list of places to make these changes?  I'm
not sure how to confirm that it's exhaustive.

It's a shame if we can't simply apply the change in one place.
Would the refactoring be too invasive to accomplish that?

Cheers
---Dave

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

* Re: [PATCH v9 5/6] signal: define the field siginfo.si_xflags
@ 2020-08-19 15:40     ` Dave Martin
  0 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-19 15:40 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 Mon, Aug 17, 2020 at 08:33:50PM -0700, Peter Collingbourne wrote:
> 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.
> 
> 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.

For clarity, is the new si_xflags field supposed to be valid for all
signal types, or just certain signals and si_codes?

What happens for things like a rt_sigqueueinfo() from userspace?

> 
> Signed-off-by: Peter Collingbourne <pcc@google.com>
> ---
> View this change in Gerrit: https://linux-review.googlesource.com/q/Ide155ce29366c3eab2a944ae4c51205982e5b8b2
> 
>  arch/arm/include/asm/signal.h              |  3 ++-
>  arch/parisc/include/asm/signal.h           |  2 +-
>  arch/powerpc/platforms/powernv/vas-fault.c |  1 +
>  include/linux/compat.h                     |  2 ++
>  include/linux/signal_types.h               |  4 ++--
>  include/uapi/asm-generic/siginfo.h         |  3 +++
>  include/uapi/asm-generic/signal-defs.h     |  4 ++++
>  kernel/signal.c                            | 15 +++++++++++++++
>  8 files changed, 30 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm/include/asm/signal.h b/arch/arm/include/asm/signal.h
> index d1070a783993..6b2630dfe1df 100644
> --- a/arch/arm/include/asm/signal.h
> +++ b/arch/arm/include/asm/signal.h
> @@ -19,7 +19,8 @@ typedef struct {
>  
>  #define SA_UAPI_FLAGS                                                          \
>  	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_THIRTYTWO |             \
> -	 SA_RESTORER | SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_RESETHAND)
> +	 SA_RESTORER | SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_RESETHAND |   \
> +	 SA_XFLAGS)
>  
>  #define __ARCH_HAS_SA_RESTORER
>  
> diff --git a/arch/parisc/include/asm/signal.h b/arch/parisc/include/asm/signal.h
> index ad06e14f6e8a..3582bce44520 100644
> --- a/arch/parisc/include/asm/signal.h
> +++ b/arch/parisc/include/asm/signal.h
> @@ -23,7 +23,7 @@ typedef struct {
>  
>  #define SA_UAPI_FLAGS                                                          \
>  	(SA_ONSTACK | SA_RESETHAND | SA_NOCLDSTOP | SA_SIGINFO | SA_NODEFER |  \
> -	 SA_RESTART | SA_NOCLDWAIT | _SA_SIGGFAULT)
> +	 SA_RESTART | SA_NOCLDWAIT | _SA_SIGGFAULT | SA_XFLAGS)
>  
>  #include <asm/sigcontext.h>
>  
> 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/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 e792f29b5846..cd3d08dde47a 100644
> --- a/include/linux/signal_types.h
> +++ b/include/linux/signal_types.h
> @@ -72,11 +72,11 @@ struct ksignal {
>  #ifdef SA_RESTORER
>  #define SA_UAPI_FLAGS                                                          \
>  	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
> -	 SA_NODEFER | SA_RESETHAND | SA_RESTORER)
> +	 SA_NODEFER | SA_RESETHAND | SA_RESTORER | SA_XFLAGS)
>  #else
>  #define SA_UAPI_FLAGS                                                          \
>  	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
> -	 SA_NODEFER | SA_RESETHAND)
> +	 SA_NODEFER | SA_RESETHAND | SA_XFLAGS)
>  #endif
>  #endif
>  
> diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
> index cb3d6c267181..413d804623c0 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,7 @@ typedef struct siginfo {
>  #define si_trapno	_sifields._sigfault._trapno
>  #endif
>  #define si_addr_lsb	_sifields._sigfault._addr_lsb
> +#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 c30a9c1a77b2..aeee6bb0763b 100644
> --- a/include/uapi/asm-generic/signal-defs.h
> +++ b/include/uapi/asm-generic/signal-defs.h
> @@ -19,6 +19,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 @@
>   * should be avoided for new generic flags: 3, 4, 5, 6, 7, 8, 9, 16, 24, 25, 26.
>   */
>  #define SA_UNSUPPORTED	0x00000400
> +#define SA_XFLAGS	0x00000800
>  
>  #define SA_NOMASK	SA_NODEFER
>  #define SA_ONESHOT	SA_RESETHAND
> diff --git a/kernel/signal.c b/kernel/signal.c
> index 664a6c31137e..72182eed1b8d 100644
> --- a/kernel/signal.c
> +++ b/kernel/signal.c
> @@ -1669,6 +1669,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
>  	info.si_flags = flags;
>  	info.si_isr = isr;
>  #endif
> +	info.si_xflags = 0;
>  	return force_sig_info_to_task(&info, t);
>  }
>  
> @@ -1701,6 +1702,7 @@ int send_sig_fault(int sig, int code, void __user *addr
>  	info.si_flags = flags;
>  	info.si_isr = isr;
>  #endif
> +	info.si_xflags = 0;
>  	return send_sig_info(info.si_signo, &info, t);
>  }
>  
> @@ -1715,6 +1717,7 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
>  	info.si_code = code;
>  	info.si_addr = addr;
>  	info.si_addr_lsb = lsb;
> +	info.si_xflags = 0;
>  	return force_sig_info(&info);
>  }
>  
> @@ -1729,6 +1732,7 @@ int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *
>  	info.si_code = code;
>  	info.si_addr = addr;
>  	info.si_addr_lsb = lsb;
> +	info.si_xflags = 0;
>  	return send_sig_info(info.si_signo, &info, t);
>  }
>  EXPORT_SYMBOL(send_sig_mceerr);
> @@ -1744,6 +1748,7 @@ int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
>  	info.si_addr  = addr;
>  	info.si_lower = lower;
>  	info.si_upper = upper;
> +	info.si_xflags = 0;
>  	return force_sig_info(&info);
>  }
>  
> @@ -1758,6 +1763,7 @@ int force_sig_pkuerr(void __user *addr, u32 pkey)
>  	info.si_code  = SEGV_PKUERR;
>  	info.si_addr  = addr;
>  	info.si_pkey  = pkey;
> +	info.si_xflags = 0;
>  	return force_sig_info(&info);
>  }
>  #endif
> @@ -1774,6 +1780,7 @@ int force_sig_ptrace_errno_trap(int errno, void __user *addr)
>  	info.si_errno = errno;
>  	info.si_code  = TRAP_HWBKPT;
>  	info.si_addr  = addr;
> +	info.si_xflags = 0;
>  	return force_sig_info(&info);
>  }
>  
> @@ -3290,6 +3297,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;
>  		break;
>  	case SIL_FAULT_MCEERR:
>  		to->si_addr = ptr_to_compat(from->si_addr);
> @@ -3297,6 +3305,7 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
>  		to->si_trapno = from->si_trapno;
>  #endif
>  		to->si_addr_lsb = from->si_addr_lsb;
> +		to->si_xflags = from->si_xflags;
>  		break;
>  	case SIL_FAULT_BNDERR:
>  		to->si_addr = ptr_to_compat(from->si_addr);
> @@ -3305,6 +3314,7 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
>  #endif
>  		to->si_lower = ptr_to_compat(from->si_lower);
>  		to->si_upper = ptr_to_compat(from->si_upper);
> +		to->si_xflags = from->si_xflags;
>  		break;
>  	case SIL_FAULT_PKUERR:
>  		to->si_addr = ptr_to_compat(from->si_addr);
> @@ -3312,6 +3322,7 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
>  		to->si_trapno = from->si_trapno;
>  #endif
>  		to->si_pkey = from->si_pkey;
> +		to->si_xflags = from->si_xflags;
>  		break;
>  	case SIL_CHLD:
>  		to->si_pid = from->si_pid;
> @@ -3370,6 +3381,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;
>  		break;
>  	case SIL_FAULT_MCEERR:
>  		to->si_addr = compat_ptr(from->si_addr);
> @@ -3377,6 +3389,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
>  		to->si_trapno = from->si_trapno;
>  #endif
>  		to->si_addr_lsb = from->si_addr_lsb;
> +		to->si_xflags = from->si_xflags;
>  		break;
>  	case SIL_FAULT_BNDERR:
>  		to->si_addr = compat_ptr(from->si_addr);
> @@ -3385,6 +3398,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
>  #endif
>  		to->si_lower = compat_ptr(from->si_lower);
>  		to->si_upper = compat_ptr(from->si_upper);
> +		to->si_xflags = from->si_xflags;
>  		break;
>  	case SIL_FAULT_PKUERR:
>  		to->si_addr = compat_ptr(from->si_addr);
> @@ -3392,6 +3406,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
>  		to->si_trapno = from->si_trapno;
>  #endif
>  		to->si_pkey = from->si_pkey;
> +		to->si_xflags = from->si_xflags;

How did you figure out the list of places to make these changes?  I'm
not sure how to confirm that it's exhaustive.

It's a shame if we can't simply apply the change in one place.
Would the refactoring be too invasive to accomplish that?

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] 66+ messages in thread

* Re: [PATCH v9 6/6] arm64: expose FAR_EL1 tag bits in siginfo
  2020-08-18  3:33   ` Peter Collingbourne
@ 2020-08-19 15:56     ` Dave Martin
  -1 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-19 15:56 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 Mon, Aug 17, 2020 at 08:33:51PM -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
> 
> 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/traps.h          |  7 +++-
>  arch/arm64/kernel/debug-monitors.c      |  4 +-
>  arch/arm64/kernel/entry-common.c        |  2 -
>  arch/arm64/kernel/ptrace.c              |  2 +-
>  arch/arm64/kernel/traps.c               | 15 ++++---
>  arch/arm64/mm/fault.c                   | 54 ++++++++++++++-----------
>  arch/mips/kernel/traps.c                |  2 +-
>  arch/parisc/kernel/ptrace.c             |  2 +-
>  arch/parisc/mm/fault.c                  |  2 +-
>  arch/powerpc/mm/fault.c                 |  2 +-
>  arch/x86/mm/fault.c                     |  3 +-
>  include/linux/compat.h                  |  2 +
>  include/linux/sched/signal.h            | 12 +++++-
>  include/uapi/asm-generic/siginfo.h      | 10 +++++
>  kernel/signal.c                         | 50 +++++++++++++++++++----
>  mm/memory-failure.c                     |  2 +-
>  18 files changed, 136 insertions(+), 58 deletions(-)
> 
> diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst
> index eab4323609b9..bd23039841a5 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 SI_XFLAG_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/traps.h b/arch/arm64/include/asm/traps.h
> index cee5928e1b7d..8e4f6c5b97af 100644
> --- a/arch/arm64/include/asm/traps.h
> +++ b/arch/arm64/include/asm/traps.h
> @@ -26,8 +26,11 @@ 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_fault(int signo, int code, void __user *addr,
> +			   unsigned long far, unsigned char far_tb_mask,
> +			   const char *str);
> +void arm64_force_sig_mceerr(int code, void __user *addr, short lsb,
> +			    unsigned long far, const char *str);
>  void arm64_force_sig_ptrace_errno_trap(int errno, void __user *addr, const char *str);
>  
>  /*
> diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
> index 7310a4f7f993..bc9e02fbb710 100644
> --- a/arch/arm64/kernel/debug-monitors.c
> +++ b/arch/arm64/kernel/debug-monitors.c
> @@ -235,8 +235,8 @@ static void send_user_sigtrap(int si_code)
>  		local_irq_enable();
>  
>  	arm64_force_sig_fault(SIGTRAP, si_code,
> -			     (void __user *)instruction_pointer(regs),
> -			     "User debug trap");
> +			      (void __user *)instruction_pointer(regs), 0, 0,
> +			      "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..c73312064220 100644
> --- a/arch/arm64/kernel/ptrace.c
> +++ b/arch/arm64/kernel/ptrace.c
> @@ -197,7 +197,7 @@ static void ptrace_hbptriggered(struct perf_event *bp,
>  	}
>  #endif
>  	arm64_force_sig_fault(SIGTRAP, TRAP_HWBKPT,
> -			      (void __user *)(bkpt->trigger),
> +			      (void __user *)(bkpt->trigger), 0, 0,
>  			      desc);
>  }
>  
> diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
> index 13ebd5ca2070..c945c5cc1312 100644
> --- a/arch/arm64/kernel/traps.c
> +++ b/arch/arm64/kernel/traps.c
> @@ -235,20 +235,25 @@ static void arm64_show_signal(int signo, const char *str)
>  }
>  
>  void arm64_force_sig_fault(int signo, int code, void __user *addr,
> +			   unsigned long far, unsigned char far_tb_mask,
>  			   const char *str)
>  {
> +	unsigned long ignored_bits_mask = ((unsigned long)far_tb_mask) << 56;
> +
>  	arm64_show_signal(signo, str);
>  	if (signo == SIGKILL)
>  		force_sig(SIGKILL);
>  	else
> -		force_sig_fault(signo, code, addr);
> +		force_sig_fault_with_ignored_bits(signo, code, addr,
> +						  far & ignored_bits_mask,
> +						  ignored_bits_mask);
>  }
>  
>  void arm64_force_sig_mceerr(int code, void __user *addr, short lsb,
> -			    const char *str)
> +			    unsigned long far, const char *str)
>  {
>  	arm64_show_signal(SIGBUS, str);
> -	force_sig_mceerr(code, addr, lsb);
> +	force_sig_mceerr(code, addr, lsb, far & (0xffUL << 56), 0xffUL << 56);
>  }
>  
>  void arm64_force_sig_ptrace_errno_trap(int errno, void __user *addr,
> @@ -267,7 +272,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, addr, 0, 0, str);
>  	} else {
>  		die(str, regs, err);
>  	}
> @@ -829,7 +834,7 @@ void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr)
>  	current->thread.fault_address = 0;
>  	current->thread.fault_code = esr;
>  
> -	arm64_force_sig_fault(SIGILL, ILL_ILLOPC, pc,
> +	arm64_force_sig_fault(SIGILL, ILL_ILLOPC, pc, 0, 0,
>  			      "Bad EL0 synchronous exception");
>  }
>  
> diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
> index f07333e86c2f..82f05644417e 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.
> @@ -394,7 +397,7 @@ static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *re
>  
>  		set_thread_esr(addr, esr);
>  		arm64_force_sig_fault(inf->sig, inf->code, (void __user *)addr,
> -				      inf->name);
> +				      far, 0xff, inf->name);
>  	} else {
>  		__do_kernel_fault(addr, esr, regs);
>  	}
> @@ -446,7 +449,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 +457,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;
> @@ -566,7 +570,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
>  		 * this page fault.
>  		 */
>  		arm64_force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)addr,
> -				      inf->name);
> +				      far, 0xff, inf->name);
>  	} else if (fault & (VM_FAULT_HWPOISON_LARGE | VM_FAULT_HWPOISON)) {
>  		unsigned int lsb;
>  
> @@ -575,7 +579,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
>  			lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault));
>  
>  		arm64_force_sig_mceerr(BUS_MCEERR_AR, (void __user *)addr, lsb,
> -				       inf->name);
> +				       far, inf->name);
>  	} else {
>  		/*
>  		 * Something tried to access memory that isn't in our memory
> @@ -583,8 +587,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);
> +				      (void __user *)addr, far, 0xff, inf->name);
>  	}
>  
>  	return 0;
> @@ -594,30 +597,32 @@ 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;
> @@ -635,7 +640,7 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
>  	if (esr & ESR_ELx_FnV)
>  		siaddr = NULL;
>  	else
> -		siaddr  = (void __user *)addr;
> +		siaddr  = (void __user *)untagged_addr(far);
>  	arm64_notify_die(inf->name, regs, inf->sig, inf->code, siaddr, esr);
>  
>  	return 0;
> @@ -708,11 +713,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 +727,8 @@ 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,
> +			 (void __user *)addr, esr);
>  }
>  NOKPROBE_SYMBOL(do_mem_abort);
>  
> @@ -735,8 +741,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,
> +			 (void __user *)addr, esr);
>  }
>  NOKPROBE_SYMBOL(do_sp_pc_abort);
>  
> @@ -862,8 +868,8 @@ 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,
> +				 (void __user *)pc, esr);
>  	}
>  
>  	debug_exception_exit(regs);
> diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
> index 38aa07ccdbcc..73a181c904b0 100644
> --- a/arch/mips/kernel/traps.c
> +++ b/arch/mips/kernel/traps.c
> @@ -775,7 +775,7 @@ void force_fcr31_sig(unsigned long fcr31, void __user *fault_addr,
>  	else if (fcr31 & FPU_CSR_INE_X)
>  		si_code = FPE_FLTRES;
>  
> -	force_sig_fault_to_task(SIGFPE, si_code, fault_addr, tsk);
> +	force_sig_fault_to_task(SIGFPE, si_code, fault_addr, 0, 0, tsk);
>  }
>  
>  int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcr31)
> diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
> index 2127974982df..62c8bb0d7d31 100644
> --- a/arch/parisc/kernel/ptrace.c
> +++ b/arch/parisc/kernel/ptrace.c
> @@ -89,7 +89,7 @@ void user_enable_single_step(struct task_struct *task)
>  		   parent know something happened. */
>  		force_sig_fault_to_task(SIGTRAP, TRAP_TRACE,
>  					(void __user *) (task_regs(task)->iaoq[0] & ~3),
> -					task);
> +					0, 0, task);
>  		/* notify_parent(task, SIGCHLD); */
>  		return;
>  	}
> diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
> index 4bfe2da9fbe3..2a6064ea2dfc 100644
> --- a/arch/parisc/mm/fault.c
> +++ b/arch/parisc/mm/fault.c
> @@ -400,7 +400,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
>  				lsb = PAGE_SHIFT;
>  
>  			force_sig_mceerr(BUS_MCEERR_AR, (void __user *) address,
> -					 lsb);
> +					 lsb, 0, 0);
>  			return;
>  		}
>  #endif
> diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
> index 0add963a849b..4ffe2fb8e31a 100644
> --- a/arch/powerpc/mm/fault.c
> +++ b/arch/powerpc/mm/fault.c
> @@ -152,7 +152,7 @@ static int do_sigbus(struct pt_regs *regs, unsigned long address,
>  		if (fault & VM_FAULT_HWPOISON)
>  			lsb = PAGE_SHIFT;
>  
> -		force_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb);
> +		force_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb, 0, 0);
>  		return 0;
>  	}
>  
> diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
> index 35f1498e9832..a443eec157f6 100644
> --- a/arch/x86/mm/fault.c
> +++ b/arch/x86/mm/fault.c
> @@ -898,7 +898,8 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address,
>  			lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault));
>  		if (fault & VM_FAULT_HWPOISON)
>  			lsb = PAGE_SHIFT;
> -		force_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb);
> +		force_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb, 0,
> +				 0);
>  		return;
>  	}
>  #endif
> 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/sched/signal.h b/include/linux/sched/signal.h
> index 1bad18a1d8ba..f62a014a5a4d 100644
> --- a/include/linux/sched/signal.h
> +++ b/include/linux/sched/signal.h
> @@ -311,16 +311,24 @@ static inline void kernel_signal_stop(void)
>  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)
> -	, struct task_struct *t);
> +	, unsigned long addr_ignored_bits, unsigned long addr_ignored_bits_mask,
> +	struct task_struct *t);
>  int force_sig_fault(int sig, int code, void __user *addr
>  	___ARCH_SI_TRAPNO(int trapno)
>  	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr));
> +int force_sig_fault_with_ignored_bits(int sig, int code, void __user *addr
> +	___ARCH_SI_TRAPNO(int trapno)
> +	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
> +	, unsigned long addr_ignored_bits,
> +	unsigned long addr_ignored_bits_mask);
>  int send_sig_fault(int sig, int code, void __user *addr
>  	___ARCH_SI_TRAPNO(int trapno)
>  	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
>  	, struct task_struct *t);
>  
> -int force_sig_mceerr(int code, void __user *, short);
> +int force_sig_mceerr(int code, void __user *addr, short addr_lsb,
> +		     unsigned long addr_ignored_bits,
> +		     unsigned long addr_ignored_bits_mask);
>  int send_sig_mceerr(int code, void __user *, short, struct task_struct *);
>  
>  int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper);
> diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
> index 413d804623c0..1fc6482b0ad4 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 */
> @@ -155,6 +157,8 @@ typedef struct siginfo {
>  #endif
>  #define si_addr_lsb	_sifields._sigfault._addr_lsb
>  #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
> @@ -295,6 +299,12 @@ typedef struct siginfo {
>  #define EMT_TAGOVF	1	/* tag overflow */
>  #define NSIGEMT		1
>  
> +/*
> + * SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT si_xflags
> + */
> +#define SI_XFLAG_IGNORED_BITS	1
> +/* si_addr_ignored_bits{,_mask} fields valid */
> +
>  /*
>   * sigevent definitions
>   * 
> diff --git a/kernel/signal.c b/kernel/signal.c
> index 72182eed1b8d..1f1e42adc57d 100644
> --- a/kernel/signal.c
> +++ b/kernel/signal.c
> @@ -1652,7 +1652,8 @@ void force_sigsegv(int sig)
>  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)
> -	, struct task_struct *t)
> +	, unsigned long addr_ignored_bits, unsigned long addr_ignored_bits_mask,
> +	struct task_struct *t)
>  {
>  	struct kernel_siginfo info;
>  
> @@ -1669,17 +1670,32 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
>  	info.si_flags = flags;
>  	info.si_isr = isr;
>  #endif
> -	info.si_xflags = 0;
> +	info.si_xflags = SI_XFLAG_IGNORED_BITS;
> +	info.si_addr_ignored_bits = addr_ignored_bits;
> +	info.si_addr_ignored_bits_mask = addr_ignored_bits_mask;
>  	return force_sig_info_to_task(&info, t);
>  }
>  
> -int force_sig_fault(int sig, int code, void __user *addr
> +int force_sig_fault_with_ignored_bits(int sig, int code, void __user *addr
>  	___ARCH_SI_TRAPNO(int trapno)
> -	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr))
> +	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr),
> +	unsigned long addr_ignored_bits, unsigned long addr_ignored_bits_mask)
>  {
>  	return force_sig_fault_to_task(sig, code, addr
>  				       ___ARCH_SI_TRAPNO(trapno)
> -				       ___ARCH_SI_IA64(imm, flags, isr), current);
> +				       ___ARCH_SI_IA64(imm, flags, isr),
> +				       addr_ignored_bits,
> +				       addr_ignored_bits_mask, current);
> +}
> +
> +int force_sig_fault(int sig, int code, void __user *addr
> +	___ARCH_SI_TRAPNO(int trapno)
> +	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr))
> +{
> +	return force_sig_fault_with_ignored_bits(sig, code, addr
> +						 ___ARCH_SI_TRAPNO(trapno)
> +						 ___ARCH_SI_IA64(imm, flags,
> +								 isr), 0, 0);
>  }
>  
>  int send_sig_fault(int sig, int code, void __user *addr
> @@ -1706,7 +1722,9 @@ int send_sig_fault(int sig, int code, void __user *addr
>  	return send_sig_info(info.si_signo, &info, t);
>  }
>  
> -int force_sig_mceerr(int code, void __user *addr, short lsb)
> +int force_sig_mceerr(int code, void __user *addr, short lsb,
> +		     unsigned long addr_ignored_bits,
> +		     unsigned long addr_ignored_bits_mask)

Rather than having to pass these extra arguments all over the place, can
we just pass the far for addr, and have an arch-specific hook for
splitting the ignored from non-ignored bits.  For now at least, I expect
that ignored bits mask to be constant for a given platform and kernel.

>  {
>  	struct kernel_siginfo info;
>  
> @@ -1717,7 +1735,9 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
>  	info.si_code = code;
>  	info.si_addr = addr;
>  	info.si_addr_lsb = lsb;
> -	info.si_xflags = 0;
> +	info.si_xflags = SI_XFLAG_IGNORED_BITS;

Maybe drop the first _, so that this becomes

	SIXFLAG_IGNORED_BITS

?  This may help to avoid anyone thinking this might be an si_code
value.  Maybe ..._IGNORED_ADDR_BITS would also help make it clearer what
this bit is referring to.


> +	info.si_addr_ignored_bits = addr_ignored_bits;
> +	info.si_addr_ignored_bits_mask = addr_ignored_bits_mask;
>  	return force_sig_info(&info);
>  }
>  
> @@ -3298,6 +3318,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;
>  		break;
>  	case SIL_FAULT_MCEERR:
>  		to->si_addr = ptr_to_compat(from->si_addr);
> @@ -3306,6 +3328,8 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
>  #endif
>  		to->si_addr_lsb = from->si_addr_lsb;
>  		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;
>  		break;
>  	case SIL_FAULT_BNDERR:
>  		to->si_addr = ptr_to_compat(from->si_addr);
> @@ -3315,6 +3339,8 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
>  		to->si_lower = ptr_to_compat(from->si_lower);
>  		to->si_upper = ptr_to_compat(from->si_upper);
>  		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;
>  		break;
>  	case SIL_FAULT_PKUERR:
>  		to->si_addr = ptr_to_compat(from->si_addr);
> @@ -3323,6 +3349,8 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
>  #endif
>  		to->si_pkey = from->si_pkey;
>  		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;
>  		break;>  	case SIL_CHLD:
>  		to->si_pid = from->si_pid;
> @@ -3382,6 +3410,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;
>  		break;
>  	case SIL_FAULT_MCEERR:
>  		to->si_addr = compat_ptr(from->si_addr);
> @@ -3390,6 +3420,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
>  #endif
>  		to->si_addr_lsb = from->si_addr_lsb;
>  		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;
>  		break;
>  	case SIL_FAULT_BNDERR:
>  		to->si_addr = compat_ptr(from->si_addr);
> @@ -3399,6 +3431,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
>  		to->si_lower = compat_ptr(from->si_lower);
>  		to->si_upper = compat_ptr(from->si_upper);
>  		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;
>  		break;
>  	case SIL_FAULT_PKUERR:
>  		to->si_addr = compat_ptr(from->si_addr);
> @@ -3407,6 +3441,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
>  #endif
>  		to->si_pkey = from->si_pkey;
>  		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;

Again, can you justify why this is exhaustive?  If there any way to
factor this so as to reduce the number of places we need to hack this
in?

[...]

Cheers
---Dave

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

* Re: [PATCH v9 6/6] arm64: expose FAR_EL1 tag bits in siginfo
@ 2020-08-19 15:56     ` Dave Martin
  0 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-19 15:56 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 Mon, Aug 17, 2020 at 08:33:51PM -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
> 
> 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/traps.h          |  7 +++-
>  arch/arm64/kernel/debug-monitors.c      |  4 +-
>  arch/arm64/kernel/entry-common.c        |  2 -
>  arch/arm64/kernel/ptrace.c              |  2 +-
>  arch/arm64/kernel/traps.c               | 15 ++++---
>  arch/arm64/mm/fault.c                   | 54 ++++++++++++++-----------
>  arch/mips/kernel/traps.c                |  2 +-
>  arch/parisc/kernel/ptrace.c             |  2 +-
>  arch/parisc/mm/fault.c                  |  2 +-
>  arch/powerpc/mm/fault.c                 |  2 +-
>  arch/x86/mm/fault.c                     |  3 +-
>  include/linux/compat.h                  |  2 +
>  include/linux/sched/signal.h            | 12 +++++-
>  include/uapi/asm-generic/siginfo.h      | 10 +++++
>  kernel/signal.c                         | 50 +++++++++++++++++++----
>  mm/memory-failure.c                     |  2 +-
>  18 files changed, 136 insertions(+), 58 deletions(-)
> 
> diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst
> index eab4323609b9..bd23039841a5 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 SI_XFLAG_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/traps.h b/arch/arm64/include/asm/traps.h
> index cee5928e1b7d..8e4f6c5b97af 100644
> --- a/arch/arm64/include/asm/traps.h
> +++ b/arch/arm64/include/asm/traps.h
> @@ -26,8 +26,11 @@ 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_fault(int signo, int code, void __user *addr,
> +			   unsigned long far, unsigned char far_tb_mask,
> +			   const char *str);
> +void arm64_force_sig_mceerr(int code, void __user *addr, short lsb,
> +			    unsigned long far, const char *str);
>  void arm64_force_sig_ptrace_errno_trap(int errno, void __user *addr, const char *str);
>  
>  /*
> diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
> index 7310a4f7f993..bc9e02fbb710 100644
> --- a/arch/arm64/kernel/debug-monitors.c
> +++ b/arch/arm64/kernel/debug-monitors.c
> @@ -235,8 +235,8 @@ static void send_user_sigtrap(int si_code)
>  		local_irq_enable();
>  
>  	arm64_force_sig_fault(SIGTRAP, si_code,
> -			     (void __user *)instruction_pointer(regs),
> -			     "User debug trap");
> +			      (void __user *)instruction_pointer(regs), 0, 0,
> +			      "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..c73312064220 100644
> --- a/arch/arm64/kernel/ptrace.c
> +++ b/arch/arm64/kernel/ptrace.c
> @@ -197,7 +197,7 @@ static void ptrace_hbptriggered(struct perf_event *bp,
>  	}
>  #endif
>  	arm64_force_sig_fault(SIGTRAP, TRAP_HWBKPT,
> -			      (void __user *)(bkpt->trigger),
> +			      (void __user *)(bkpt->trigger), 0, 0,
>  			      desc);
>  }
>  
> diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
> index 13ebd5ca2070..c945c5cc1312 100644
> --- a/arch/arm64/kernel/traps.c
> +++ b/arch/arm64/kernel/traps.c
> @@ -235,20 +235,25 @@ static void arm64_show_signal(int signo, const char *str)
>  }
>  
>  void arm64_force_sig_fault(int signo, int code, void __user *addr,
> +			   unsigned long far, unsigned char far_tb_mask,
>  			   const char *str)
>  {
> +	unsigned long ignored_bits_mask = ((unsigned long)far_tb_mask) << 56;
> +
>  	arm64_show_signal(signo, str);
>  	if (signo == SIGKILL)
>  		force_sig(SIGKILL);
>  	else
> -		force_sig_fault(signo, code, addr);
> +		force_sig_fault_with_ignored_bits(signo, code, addr,
> +						  far & ignored_bits_mask,
> +						  ignored_bits_mask);
>  }
>  
>  void arm64_force_sig_mceerr(int code, void __user *addr, short lsb,
> -			    const char *str)
> +			    unsigned long far, const char *str)
>  {
>  	arm64_show_signal(SIGBUS, str);
> -	force_sig_mceerr(code, addr, lsb);
> +	force_sig_mceerr(code, addr, lsb, far & (0xffUL << 56), 0xffUL << 56);
>  }
>  
>  void arm64_force_sig_ptrace_errno_trap(int errno, void __user *addr,
> @@ -267,7 +272,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, addr, 0, 0, str);
>  	} else {
>  		die(str, regs, err);
>  	}
> @@ -829,7 +834,7 @@ void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr)
>  	current->thread.fault_address = 0;
>  	current->thread.fault_code = esr;
>  
> -	arm64_force_sig_fault(SIGILL, ILL_ILLOPC, pc,
> +	arm64_force_sig_fault(SIGILL, ILL_ILLOPC, pc, 0, 0,
>  			      "Bad EL0 synchronous exception");
>  }
>  
> diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
> index f07333e86c2f..82f05644417e 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.
> @@ -394,7 +397,7 @@ static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *re
>  
>  		set_thread_esr(addr, esr);
>  		arm64_force_sig_fault(inf->sig, inf->code, (void __user *)addr,
> -				      inf->name);
> +				      far, 0xff, inf->name);
>  	} else {
>  		__do_kernel_fault(addr, esr, regs);
>  	}
> @@ -446,7 +449,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 +457,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;
> @@ -566,7 +570,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
>  		 * this page fault.
>  		 */
>  		arm64_force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)addr,
> -				      inf->name);
> +				      far, 0xff, inf->name);
>  	} else if (fault & (VM_FAULT_HWPOISON_LARGE | VM_FAULT_HWPOISON)) {
>  		unsigned int lsb;
>  
> @@ -575,7 +579,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
>  			lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault));
>  
>  		arm64_force_sig_mceerr(BUS_MCEERR_AR, (void __user *)addr, lsb,
> -				       inf->name);
> +				       far, inf->name);
>  	} else {
>  		/*
>  		 * Something tried to access memory that isn't in our memory
> @@ -583,8 +587,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);
> +				      (void __user *)addr, far, 0xff, inf->name);
>  	}
>  
>  	return 0;
> @@ -594,30 +597,32 @@ 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;
> @@ -635,7 +640,7 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
>  	if (esr & ESR_ELx_FnV)
>  		siaddr = NULL;
>  	else
> -		siaddr  = (void __user *)addr;
> +		siaddr  = (void __user *)untagged_addr(far);
>  	arm64_notify_die(inf->name, regs, inf->sig, inf->code, siaddr, esr);
>  
>  	return 0;
> @@ -708,11 +713,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 +727,8 @@ 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,
> +			 (void __user *)addr, esr);
>  }
>  NOKPROBE_SYMBOL(do_mem_abort);
>  
> @@ -735,8 +741,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,
> +			 (void __user *)addr, esr);
>  }
>  NOKPROBE_SYMBOL(do_sp_pc_abort);
>  
> @@ -862,8 +868,8 @@ 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,
> +				 (void __user *)pc, esr);
>  	}
>  
>  	debug_exception_exit(regs);
> diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
> index 38aa07ccdbcc..73a181c904b0 100644
> --- a/arch/mips/kernel/traps.c
> +++ b/arch/mips/kernel/traps.c
> @@ -775,7 +775,7 @@ void force_fcr31_sig(unsigned long fcr31, void __user *fault_addr,
>  	else if (fcr31 & FPU_CSR_INE_X)
>  		si_code = FPE_FLTRES;
>  
> -	force_sig_fault_to_task(SIGFPE, si_code, fault_addr, tsk);
> +	force_sig_fault_to_task(SIGFPE, si_code, fault_addr, 0, 0, tsk);
>  }
>  
>  int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcr31)
> diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
> index 2127974982df..62c8bb0d7d31 100644
> --- a/arch/parisc/kernel/ptrace.c
> +++ b/arch/parisc/kernel/ptrace.c
> @@ -89,7 +89,7 @@ void user_enable_single_step(struct task_struct *task)
>  		   parent know something happened. */
>  		force_sig_fault_to_task(SIGTRAP, TRAP_TRACE,
>  					(void __user *) (task_regs(task)->iaoq[0] & ~3),
> -					task);
> +					0, 0, task);
>  		/* notify_parent(task, SIGCHLD); */
>  		return;
>  	}
> diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
> index 4bfe2da9fbe3..2a6064ea2dfc 100644
> --- a/arch/parisc/mm/fault.c
> +++ b/arch/parisc/mm/fault.c
> @@ -400,7 +400,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
>  				lsb = PAGE_SHIFT;
>  
>  			force_sig_mceerr(BUS_MCEERR_AR, (void __user *) address,
> -					 lsb);
> +					 lsb, 0, 0);
>  			return;
>  		}
>  #endif
> diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
> index 0add963a849b..4ffe2fb8e31a 100644
> --- a/arch/powerpc/mm/fault.c
> +++ b/arch/powerpc/mm/fault.c
> @@ -152,7 +152,7 @@ static int do_sigbus(struct pt_regs *regs, unsigned long address,
>  		if (fault & VM_FAULT_HWPOISON)
>  			lsb = PAGE_SHIFT;
>  
> -		force_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb);
> +		force_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb, 0, 0);
>  		return 0;
>  	}
>  
> diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
> index 35f1498e9832..a443eec157f6 100644
> --- a/arch/x86/mm/fault.c
> +++ b/arch/x86/mm/fault.c
> @@ -898,7 +898,8 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address,
>  			lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault));
>  		if (fault & VM_FAULT_HWPOISON)
>  			lsb = PAGE_SHIFT;
> -		force_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb);
> +		force_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb, 0,
> +				 0);
>  		return;
>  	}
>  #endif
> 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/sched/signal.h b/include/linux/sched/signal.h
> index 1bad18a1d8ba..f62a014a5a4d 100644
> --- a/include/linux/sched/signal.h
> +++ b/include/linux/sched/signal.h
> @@ -311,16 +311,24 @@ static inline void kernel_signal_stop(void)
>  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)
> -	, struct task_struct *t);
> +	, unsigned long addr_ignored_bits, unsigned long addr_ignored_bits_mask,
> +	struct task_struct *t);
>  int force_sig_fault(int sig, int code, void __user *addr
>  	___ARCH_SI_TRAPNO(int trapno)
>  	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr));
> +int force_sig_fault_with_ignored_bits(int sig, int code, void __user *addr
> +	___ARCH_SI_TRAPNO(int trapno)
> +	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
> +	, unsigned long addr_ignored_bits,
> +	unsigned long addr_ignored_bits_mask);
>  int send_sig_fault(int sig, int code, void __user *addr
>  	___ARCH_SI_TRAPNO(int trapno)
>  	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
>  	, struct task_struct *t);
>  
> -int force_sig_mceerr(int code, void __user *, short);
> +int force_sig_mceerr(int code, void __user *addr, short addr_lsb,
> +		     unsigned long addr_ignored_bits,
> +		     unsigned long addr_ignored_bits_mask);
>  int send_sig_mceerr(int code, void __user *, short, struct task_struct *);
>  
>  int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper);
> diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
> index 413d804623c0..1fc6482b0ad4 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 */
> @@ -155,6 +157,8 @@ typedef struct siginfo {
>  #endif
>  #define si_addr_lsb	_sifields._sigfault._addr_lsb
>  #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
> @@ -295,6 +299,12 @@ typedef struct siginfo {
>  #define EMT_TAGOVF	1	/* tag overflow */
>  #define NSIGEMT		1
>  
> +/*
> + * SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT si_xflags
> + */
> +#define SI_XFLAG_IGNORED_BITS	1
> +/* si_addr_ignored_bits{,_mask} fields valid */
> +
>  /*
>   * sigevent definitions
>   * 
> diff --git a/kernel/signal.c b/kernel/signal.c
> index 72182eed1b8d..1f1e42adc57d 100644
> --- a/kernel/signal.c
> +++ b/kernel/signal.c
> @@ -1652,7 +1652,8 @@ void force_sigsegv(int sig)
>  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)
> -	, struct task_struct *t)
> +	, unsigned long addr_ignored_bits, unsigned long addr_ignored_bits_mask,
> +	struct task_struct *t)
>  {
>  	struct kernel_siginfo info;
>  
> @@ -1669,17 +1670,32 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
>  	info.si_flags = flags;
>  	info.si_isr = isr;
>  #endif
> -	info.si_xflags = 0;
> +	info.si_xflags = SI_XFLAG_IGNORED_BITS;
> +	info.si_addr_ignored_bits = addr_ignored_bits;
> +	info.si_addr_ignored_bits_mask = addr_ignored_bits_mask;
>  	return force_sig_info_to_task(&info, t);
>  }
>  
> -int force_sig_fault(int sig, int code, void __user *addr
> +int force_sig_fault_with_ignored_bits(int sig, int code, void __user *addr
>  	___ARCH_SI_TRAPNO(int trapno)
> -	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr))
> +	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr),
> +	unsigned long addr_ignored_bits, unsigned long addr_ignored_bits_mask)
>  {
>  	return force_sig_fault_to_task(sig, code, addr
>  				       ___ARCH_SI_TRAPNO(trapno)
> -				       ___ARCH_SI_IA64(imm, flags, isr), current);
> +				       ___ARCH_SI_IA64(imm, flags, isr),
> +				       addr_ignored_bits,
> +				       addr_ignored_bits_mask, current);
> +}
> +
> +int force_sig_fault(int sig, int code, void __user *addr
> +	___ARCH_SI_TRAPNO(int trapno)
> +	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr))
> +{
> +	return force_sig_fault_with_ignored_bits(sig, code, addr
> +						 ___ARCH_SI_TRAPNO(trapno)
> +						 ___ARCH_SI_IA64(imm, flags,
> +								 isr), 0, 0);
>  }
>  
>  int send_sig_fault(int sig, int code, void __user *addr
> @@ -1706,7 +1722,9 @@ int send_sig_fault(int sig, int code, void __user *addr
>  	return send_sig_info(info.si_signo, &info, t);
>  }
>  
> -int force_sig_mceerr(int code, void __user *addr, short lsb)
> +int force_sig_mceerr(int code, void __user *addr, short lsb,
> +		     unsigned long addr_ignored_bits,
> +		     unsigned long addr_ignored_bits_mask)

Rather than having to pass these extra arguments all over the place, can
we just pass the far for addr, and have an arch-specific hook for
splitting the ignored from non-ignored bits.  For now at least, I expect
that ignored bits mask to be constant for a given platform and kernel.

>  {
>  	struct kernel_siginfo info;
>  
> @@ -1717,7 +1735,9 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
>  	info.si_code = code;
>  	info.si_addr = addr;
>  	info.si_addr_lsb = lsb;
> -	info.si_xflags = 0;
> +	info.si_xflags = SI_XFLAG_IGNORED_BITS;

Maybe drop the first _, so that this becomes

	SIXFLAG_IGNORED_BITS

?  This may help to avoid anyone thinking this might be an si_code
value.  Maybe ..._IGNORED_ADDR_BITS would also help make it clearer what
this bit is referring to.


> +	info.si_addr_ignored_bits = addr_ignored_bits;
> +	info.si_addr_ignored_bits_mask = addr_ignored_bits_mask;
>  	return force_sig_info(&info);
>  }
>  
> @@ -3298,6 +3318,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;
>  		break;
>  	case SIL_FAULT_MCEERR:
>  		to->si_addr = ptr_to_compat(from->si_addr);
> @@ -3306,6 +3328,8 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
>  #endif
>  		to->si_addr_lsb = from->si_addr_lsb;
>  		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;
>  		break;
>  	case SIL_FAULT_BNDERR:
>  		to->si_addr = ptr_to_compat(from->si_addr);
> @@ -3315,6 +3339,8 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
>  		to->si_lower = ptr_to_compat(from->si_lower);
>  		to->si_upper = ptr_to_compat(from->si_upper);
>  		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;
>  		break;
>  	case SIL_FAULT_PKUERR:
>  		to->si_addr = ptr_to_compat(from->si_addr);
> @@ -3323,6 +3349,8 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
>  #endif
>  		to->si_pkey = from->si_pkey;
>  		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;
>  		break;>  	case SIL_CHLD:
>  		to->si_pid = from->si_pid;
> @@ -3382,6 +3410,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;
>  		break;
>  	case SIL_FAULT_MCEERR:
>  		to->si_addr = compat_ptr(from->si_addr);
> @@ -3390,6 +3420,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
>  #endif
>  		to->si_addr_lsb = from->si_addr_lsb;
>  		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;
>  		break;
>  	case SIL_FAULT_BNDERR:
>  		to->si_addr = compat_ptr(from->si_addr);
> @@ -3399,6 +3431,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
>  		to->si_lower = compat_ptr(from->si_lower);
>  		to->si_upper = compat_ptr(from->si_upper);
>  		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;
>  		break;
>  	case SIL_FAULT_PKUERR:
>  		to->si_addr = compat_ptr(from->si_addr);
> @@ -3407,6 +3441,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
>  #endif
>  		to->si_pkey = from->si_pkey;
>  		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;

Again, can you justify why this is exhaustive?  If there any way to
factor this so as to reduce the number of places we need to hack this
in?

[...]

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] 66+ messages in thread

* Re: [PATCH v9 2/6] arch: move SA_* definitions to generic headers
  2020-08-19 10:30     ` Dave Martin
@ 2020-08-19 21:35       ` Peter Collingbourne
  -1 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-19 21:35 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, linux-parisc, Andrey Konovalov,
	Kevin Brodsky, David Spickett, Linux ARM, Richard Henderson

On Wed, Aug 19, 2020 at 3:30 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Mon, Aug 17, 2020 at 08:33:47PM -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>
> > ---
> > View this change in Gerrit: https://linux-review.googlesource.com/q/Ia3849f18b8009bf41faca374e701cdca36974528
> >
> >  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(-)
>
> Nice diffstat!
>
> >
> > 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
>
> Can we add a placeholder for this in the common header?  We don't want
> people accidentally defining a new generic flag that clashes with this.

This flag (bit 25) is covered by the comment in
include/uapi/asm-generic/signal-defs.h that reads:

/*
 * 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.
 */

Peter

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

* Re: [PATCH v9 2/6] arch: move SA_* definitions to generic headers
@ 2020-08-19 21:35       ` Peter Collingbourne
  0 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-19 21:35 UTC (permalink / raw)
  To: Dave Martin
  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 Wed, Aug 19, 2020 at 3:30 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Mon, Aug 17, 2020 at 08:33:47PM -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>
> > ---
> > View this change in Gerrit: https://linux-review.googlesource.com/q/Ia3849f18b8009bf41faca374e701cdca36974528
> >
> >  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(-)
>
> Nice diffstat!
>
> >
> > 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
>
> Can we add a placeholder for this in the common header?  We don't want
> people accidentally defining a new generic flag that clashes with this.

This flag (bit 25) is covered by the comment in
include/uapi/asm-generic/signal-defs.h that reads:

/*
 * 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.
 */

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] 66+ messages in thread

* Re: [PATCH v9 2/6] arch: move SA_* definitions to generic headers
  2020-08-19  7:13     ` Geert Uytterhoeven
@ 2020-08-19 22:44       ` Peter Collingbourne
  -1 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-19 22:44 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, 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, Aug 19, 2020 at 12:14 AM Geert Uytterhoeven
<geert@linux-m68k.org> wrote:
>
> Hi Peter,
>
> On Tue, Aug 18, 2020 at 5:39 AM Peter Collingbourne <pcc@google.com> 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>
>
> Thanks for your patch!
>
> >  arch/m68k/include/uapi/asm/signal.h    | 24 -------------
>
> Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
>
> > --- 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_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.
>
> Perhaps the order should match the order of the definitions below?
> Then it becomes obvious SA_SIGINFO is not documented (it was on arm).

That makes sense. I'll copy the deleted arm comment for SA_SIGINFO here as well.

> > + *
> > + * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
> > + * Unix names RESETHAND and NODEFER respectively.
>
> I think moving this last comment below, just above the definitions of
> SA_NOMASK and SA_ONESHOT, would make this easier to read.
>
> > + */
> > +#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
> > +/*
> > + * 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.
>
> And I think this belongs to the previous comment block.

I put the comment block here to make it more likely that it will be
seen when adding new flags, but either location is fine with me.

Peter

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

* Re: [PATCH v9 2/6] arch: move SA_* definitions to generic headers
@ 2020-08-19 22:44       ` Peter Collingbourne
  0 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-19 22:44 UTC (permalink / raw)
  To: Geert Uytterhoeven
  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, Dave Martin, Evgenii Stepanov,
	Richard Henderson

On Wed, Aug 19, 2020 at 12:14 AM Geert Uytterhoeven
<geert@linux-m68k.org> wrote:
>
> Hi Peter,
>
> On Tue, Aug 18, 2020 at 5:39 AM Peter Collingbourne <pcc@google.com> 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>
>
> Thanks for your patch!
>
> >  arch/m68k/include/uapi/asm/signal.h    | 24 -------------
>
> Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
>
> > --- 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_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.
>
> Perhaps the order should match the order of the definitions below?
> Then it becomes obvious SA_SIGINFO is not documented (it was on arm).

That makes sense. I'll copy the deleted arm comment for SA_SIGINFO here as well.

> > + *
> > + * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
> > + * Unix names RESETHAND and NODEFER respectively.
>
> I think moving this last comment below, just above the definitions of
> SA_NOMASK and SA_ONESHOT, would make this easier to read.
>
> > + */
> > +#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
> > +/*
> > + * 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.
>
> And I think this belongs to the previous comment block.

I put the comment block here to make it more likely that it will be
seen when adding new flags, but either location is fine with me.

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] 66+ messages in thread

* Re: [PATCH v9 3/6] signal: clear non-uapi flag bits when passing/returning sa_flags
  2020-08-19 10:39     ` Dave Martin
@ 2020-08-19 23:39       ` Peter Collingbourne
  -1 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-19 23:39 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, Aug 19, 2020 at 3:39 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Mon, Aug 17, 2020 at 08:33:48PM -0700, Peter Collingbourne wrote:
>
> Nit: please say what the patch does.  Subject line should summarise
> what is done, but should not add new information that is not present in
> the description proper.
>
> (Same for all the other patches.)

Will do.

> > 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.
> >
> > Signed-off-by: Peter Collingbourne <pcc@google.com>
> > ---
> > View this change in Gerrit: https://linux-review.googlesource.com/q/I35aab6f5be932505d90f3b3450c083b4db1eca86
> >
> >  arch/arm/include/asm/signal.h    |  4 ++++
> >  arch/parisc/include/asm/signal.h |  4 ++++
> >  arch/x86/kernel/signal_compat.c  |  7 -------
> >  include/linux/signal_types.h     | 12 ++++++++++++
> >  kernel/signal.c                  | 10 ++++++++++
> >  5 files changed, 30 insertions(+), 7 deletions(-)
> >
> > diff --git a/arch/arm/include/asm/signal.h b/arch/arm/include/asm/signal.h
> > index 65530a042009..d1070a783993 100644
> > --- a/arch/arm/include/asm/signal.h
> > +++ b/arch/arm/include/asm/signal.h
> > @@ -17,6 +17,10 @@ typedef struct {
> >       unsigned long sig[_NSIG_WORDS];
> >  } sigset_t;
> >
> > +#define SA_UAPI_FLAGS                                                          \
> > +     (SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_THIRTYTWO |             \
> > +      SA_RESTORER | SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_RESETHAND)
> > +
>
> I wonder whether all these per-arch definitions will tend to bitrot when
> people add new common flags.
>
> Can we have a common definition for the common bits, and just add the
> extra arch-specific ones here?

I think so. We could have something like:

#define ARCH_UAPI_SA_FLAGS SA_THIRTYTWO

here. Then in signal_types.h we can do:

#ifndef ARCH_UAPI_SA_FLAGS
#define ARCH_UAPI_SA_FLAGS 0
#endif

#define UAPI_SA_FLAGS (... | ARCH_UAPI_SA_FLAGS)

I'll do that in v10.

> Also, I wonder whether we should avoid the "SA_" prefix here.  Maybe
> UAPI_SA_FLAGS?

Sounds good to me.

>
> >  #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..ad06e14f6e8a 100644
> > --- a/arch/parisc/include/asm/signal.h
> > +++ b/arch/parisc/include/asm/signal.h
> > @@ -21,6 +21,10 @@ typedef struct {
> >       unsigned long sig[_NSIG_WORDS];
> >  } sigset_t;
> >
> > +#define SA_UAPI_FLAGS                                                          \
> > +     (SA_ONSTACK | SA_RESETHAND | SA_NOCLDSTOP | SA_SIGINFO | SA_NODEFER |  \
> > +      SA_RESTART | SA_NOCLDWAIT | _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..e792f29b5846 100644
> > --- a/include/linux/signal_types.h
> > +++ b/include/linux/signal_types.h
> > @@ -68,4 +68,16 @@ struct ksignal {
> >       int sig;
> >  };
> >
> > +#ifndef SA_UAPI_FLAGS
> > +#ifdef SA_RESTORER
> > +#define SA_UAPI_FLAGS                                                          \
> > +     (SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
> > +      SA_NODEFER | SA_RESETHAND | SA_RESTORER)
> > +#else
> > +#define SA_UAPI_FLAGS                                                          \
> > +     (SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
> > +      SA_NODEFER | SA_RESETHAND)
> > +#endif
> > +#endif
> > +
> >  #endif /* _LINUX_SIGNAL_TYPES_H */
> > diff --git a/kernel/signal.c b/kernel/signal.c
> > index 42b67d2cea37..348b7981f1ff 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 &= SA_UAPI_FLAGS;
> > +     if (oact)
> > +             oact->sa.sa_flags &= SA_UAPI_FLAGS;
> > +
>
> Seems reasonable.

Thanks. I also decided to check how other operating systems handle
unknown flag bits in sigaction.sa_flags. It looks like OpenBSD and
illumos also accept unknown bits but (implicitly, as a result of using
a different internal representation) end up clearing them in oldact:

https://github.com/openbsd/src/blob/f634a6a4b5bf832e9c1de77f7894ae2625e74484/sys/kern/kern_sig.c#L278
https://github.com/illumos/illumos-gate/blob/76f19f5fdc974fe5be5c82a556e43a4df93f1de1/usr/src/uts/common/syscall/sigaction.c#L86

and FreeBSD and NetBSD fail the syscall if unknown bits are set:

https://github.com/freebsd/freebsd/blob/eded70c37057857c6e23fae51f86b8f8f43cd2d0/sys/kern/kern_sig.c#L699
https://github.com/NetBSD/src/blob/3365779becdcedfca206091a645a0e8e22b2946e/sys/kern/sys_sig.c#L473

So there is some precedent for doing what we're planning to do here,
which makes it yet more likely that we'll be okay doing this.

Peter

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

* Re: [PATCH v9 3/6] signal: clear non-uapi flag bits when passing/returning sa_flags
@ 2020-08-19 23:39       ` Peter Collingbourne
  0 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-19 23:39 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, Aug 19, 2020 at 3:39 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Mon, Aug 17, 2020 at 08:33:48PM -0700, Peter Collingbourne wrote:
>
> Nit: please say what the patch does.  Subject line should summarise
> what is done, but should not add new information that is not present in
> the description proper.
>
> (Same for all the other patches.)

Will do.

> > 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.
> >
> > Signed-off-by: Peter Collingbourne <pcc@google.com>
> > ---
> > View this change in Gerrit: https://linux-review.googlesource.com/q/I35aab6f5be932505d90f3b3450c083b4db1eca86
> >
> >  arch/arm/include/asm/signal.h    |  4 ++++
> >  arch/parisc/include/asm/signal.h |  4 ++++
> >  arch/x86/kernel/signal_compat.c  |  7 -------
> >  include/linux/signal_types.h     | 12 ++++++++++++
> >  kernel/signal.c                  | 10 ++++++++++
> >  5 files changed, 30 insertions(+), 7 deletions(-)
> >
> > diff --git a/arch/arm/include/asm/signal.h b/arch/arm/include/asm/signal.h
> > index 65530a042009..d1070a783993 100644
> > --- a/arch/arm/include/asm/signal.h
> > +++ b/arch/arm/include/asm/signal.h
> > @@ -17,6 +17,10 @@ typedef struct {
> >       unsigned long sig[_NSIG_WORDS];
> >  } sigset_t;
> >
> > +#define SA_UAPI_FLAGS                                                          \
> > +     (SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_THIRTYTWO |             \
> > +      SA_RESTORER | SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_RESETHAND)
> > +
>
> I wonder whether all these per-arch definitions will tend to bitrot when
> people add new common flags.
>
> Can we have a common definition for the common bits, and just add the
> extra arch-specific ones here?

I think so. We could have something like:

#define ARCH_UAPI_SA_FLAGS SA_THIRTYTWO

here. Then in signal_types.h we can do:

#ifndef ARCH_UAPI_SA_FLAGS
#define ARCH_UAPI_SA_FLAGS 0
#endif

#define UAPI_SA_FLAGS (... | ARCH_UAPI_SA_FLAGS)

I'll do that in v10.

> Also, I wonder whether we should avoid the "SA_" prefix here.  Maybe
> UAPI_SA_FLAGS?

Sounds good to me.

>
> >  #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..ad06e14f6e8a 100644
> > --- a/arch/parisc/include/asm/signal.h
> > +++ b/arch/parisc/include/asm/signal.h
> > @@ -21,6 +21,10 @@ typedef struct {
> >       unsigned long sig[_NSIG_WORDS];
> >  } sigset_t;
> >
> > +#define SA_UAPI_FLAGS                                                          \
> > +     (SA_ONSTACK | SA_RESETHAND | SA_NOCLDSTOP | SA_SIGINFO | SA_NODEFER |  \
> > +      SA_RESTART | SA_NOCLDWAIT | _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..e792f29b5846 100644
> > --- a/include/linux/signal_types.h
> > +++ b/include/linux/signal_types.h
> > @@ -68,4 +68,16 @@ struct ksignal {
> >       int sig;
> >  };
> >
> > +#ifndef SA_UAPI_FLAGS
> > +#ifdef SA_RESTORER
> > +#define SA_UAPI_FLAGS                                                          \
> > +     (SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
> > +      SA_NODEFER | SA_RESETHAND | SA_RESTORER)
> > +#else
> > +#define SA_UAPI_FLAGS                                                          \
> > +     (SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
> > +      SA_NODEFER | SA_RESETHAND)
> > +#endif
> > +#endif
> > +
> >  #endif /* _LINUX_SIGNAL_TYPES_H */
> > diff --git a/kernel/signal.c b/kernel/signal.c
> > index 42b67d2cea37..348b7981f1ff 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 &= SA_UAPI_FLAGS;
> > +     if (oact)
> > +             oact->sa.sa_flags &= SA_UAPI_FLAGS;
> > +
>
> Seems reasonable.

Thanks. I also decided to check how other operating systems handle
unknown flag bits in sigaction.sa_flags. It looks like OpenBSD and
illumos also accept unknown bits but (implicitly, as a result of using
a different internal representation) end up clearing them in oldact:

https://github.com/openbsd/src/blob/f634a6a4b5bf832e9c1de77f7894ae2625e74484/sys/kern/kern_sig.c#L278
https://github.com/illumos/illumos-gate/blob/76f19f5fdc974fe5be5c82a556e43a4df93f1de1/usr/src/uts/common/syscall/sigaction.c#L86

and FreeBSD and NetBSD fail the syscall if unknown bits are set:

https://github.com/freebsd/freebsd/blob/eded70c37057857c6e23fae51f86b8f8f43cd2d0/sys/kern/kern_sig.c#L699
https://github.com/NetBSD/src/blob/3365779becdcedfca206091a645a0e8e22b2946e/sys/kern/sys_sig.c#L473

So there is some precedent for doing what we're planning to do here,
which makes it yet more likely that we'll be okay doing 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] 66+ messages in thread

* Re: [PATCH v9 4/6] signal: define the SA_UNSUPPORTED bit in sa_flags
  2020-08-19 14:51     ` Dave Martin
@ 2020-08-20  0:23       ` Peter Collingbourne
  -1 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-20  0: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 Wed, Aug 19, 2020 at 7:51 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Mon, Aug 17, 2020 at 08:33:49PM -0700, Peter Collingbourne wrote:
> > 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 91000b6b97e0..c30a9c1a77b2 100644
> > --- a/include/uapi/asm-generic/signal-defs.h
> > +++ b/include/uapi/asm-generic/signal-defs.h
> > @@ -13,6 +13,12 @@
> >   * 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_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 @@
> >   * 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.
> >   */
> > +#define SA_UNSUPPORTED       0x00000400
>
> This concept confused me a bit initially, since in a sense this flag is
> supported, just with a rather peculiar meaning.

Hmm. Maybe it should be named "SA_UNKNOWN" to mean that the bit will
always be "unknown" to the kernel in the sense that it shall be
treated in the same way as any other "unknown" bit. Then we can define
the kernel's behavior in terms of what happens if a bit is "known". I
don't know if this is just shuffling terms around though. At any rate,
this seems like a problem to be solved with documentation.

> Since the main (only) purpose of this bit will be to check whether

I wouldn't necessarily say that it is the only purpose. If another new
sa_flags bit were to be introduced in the future, SA_UN(whatever)
could be used to detect kernel support for that bit in the same way as
SA_XFLAGS.

> SA_XFLAGS is actually supported, I wonder whether it makes sense to weld
> the two together, say:
>
> #define SA_REQUEST_XFLAGS       0x00000c00
> #define SA_XFLAGS_MASK          0x00000c00
> #define SA_HAVE_XFLAGS          0x00000800
>
> This is a departure from the current style of definitions though.
>
>         sa.sa_flags |= SA_REQUEST_XFLAGS;
>         sigaction(..., &sa, &sa);
>         if ((sa.sa_flags & SA_XFLAGS_MASK) == SA_HAVE_XFLAGS)
>                 /* xflags available */
>
>
> This would require some juggling of the way SA_UAPI_FLAGS works though.
> Maybe not worth it, so long as the semantics get clearly documented.

I'm not sure about this. I personally think that it would be clearer
to keep the flags orthogonal.

Peter

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

* Re: [PATCH v9 4/6] signal: define the SA_UNSUPPORTED bit in sa_flags
@ 2020-08-20  0:23       ` Peter Collingbourne
  0 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-20  0: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 Wed, Aug 19, 2020 at 7:51 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Mon, Aug 17, 2020 at 08:33:49PM -0700, Peter Collingbourne wrote:
> > 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 91000b6b97e0..c30a9c1a77b2 100644
> > --- a/include/uapi/asm-generic/signal-defs.h
> > +++ b/include/uapi/asm-generic/signal-defs.h
> > @@ -13,6 +13,12 @@
> >   * 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_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 @@
> >   * 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.
> >   */
> > +#define SA_UNSUPPORTED       0x00000400
>
> This concept confused me a bit initially, since in a sense this flag is
> supported, just with a rather peculiar meaning.

Hmm. Maybe it should be named "SA_UNKNOWN" to mean that the bit will
always be "unknown" to the kernel in the sense that it shall be
treated in the same way as any other "unknown" bit. Then we can define
the kernel's behavior in terms of what happens if a bit is "known". I
don't know if this is just shuffling terms around though. At any rate,
this seems like a problem to be solved with documentation.

> Since the main (only) purpose of this bit will be to check whether

I wouldn't necessarily say that it is the only purpose. If another new
sa_flags bit were to be introduced in the future, SA_UN(whatever)
could be used to detect kernel support for that bit in the same way as
SA_XFLAGS.

> SA_XFLAGS is actually supported, I wonder whether it makes sense to weld
> the two together, say:
>
> #define SA_REQUEST_XFLAGS       0x00000c00
> #define SA_XFLAGS_MASK          0x00000c00
> #define SA_HAVE_XFLAGS          0x00000800
>
> This is a departure from the current style of definitions though.
>
>         sa.sa_flags |= SA_REQUEST_XFLAGS;
>         sigaction(..., &sa, &sa);
>         if ((sa.sa_flags & SA_XFLAGS_MASK) == SA_HAVE_XFLAGS)
>                 /* xflags available */
>
>
> This would require some juggling of the way SA_UAPI_FLAGS works though.
> Maybe not worth it, so long as the semantics get clearly documented.

I'm not sure about this. I personally think that it would be clearer
to keep the flags orthogonal.

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] 66+ messages in thread

* Re: [PATCH v9 5/6] signal: define the field siginfo.si_xflags
  2020-08-19 15:40     ` Dave Martin
@ 2020-08-20  1:37       ` Peter Collingbourne
  -1 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-20  1:37 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, Aug 19, 2020 at 8:40 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Mon, Aug 17, 2020 at 08:33:50PM -0700, Peter Collingbourne wrote:
> > 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.
> >
> > 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.
>
> For clarity, is the new si_xflags field supposed to be valid for all
> signal types, or just certain signals and si_codes?

It is intended to be valid for all signal types that use the _sigfault
union member of siginfo. As listed in siginfo.h these are: SIGILL,
SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT.

> What happens for things like a rt_sigqueueinfo() from userspace?

Hmm. Let's enumerate each of these things, which I believe are all of
the call sites of the function copy_siginfo_from_user and related
functions (correct me if I'm wrong):

- ptrace(PTRACE_SETSIGINFO)
- pidfd_send_signal
- rt_sigqueueinfo
- rt_tgsigqueueinfo

We can handle the last three by observing that the kernel forbids
sending a signal with these syscalls if si_code >= 0, so we can say
that the value of si_xflags is only valid if si_code >= 0.

As for the first one, it's more tricky. Arguably something like a
debugger should be able to send arbitrary signals to a debuggee, and
there's no reason why it shouldn't be able to set si_xflags in
siginfo, but on the other hand who knows how existing debuggers end up
setting this field today. Maybe all that we can do is have the kernel
clear si_xflags if it detects that the signal uses _sigfault, and let
si_xflags aware debuggers opt out of this behavior, perhaps by
introducing a PTRACE_SETSIGINFO2 or something.

> >
> > Signed-off-by: Peter Collingbourne <pcc@google.com>
> > ---
> > View this change in Gerrit: https://linux-review.googlesource.com/q/Ide155ce29366c3eab2a944ae4c51205982e5b8b2
> >
> >  arch/arm/include/asm/signal.h              |  3 ++-
> >  arch/parisc/include/asm/signal.h           |  2 +-
> >  arch/powerpc/platforms/powernv/vas-fault.c |  1 +
> >  include/linux/compat.h                     |  2 ++
> >  include/linux/signal_types.h               |  4 ++--
> >  include/uapi/asm-generic/siginfo.h         |  3 +++
> >  include/uapi/asm-generic/signal-defs.h     |  4 ++++
> >  kernel/signal.c                            | 15 +++++++++++++++
> >  8 files changed, 30 insertions(+), 4 deletions(-)
> >
> > diff --git a/arch/arm/include/asm/signal.h b/arch/arm/include/asm/signal.h
> > index d1070a783993..6b2630dfe1df 100644
> > --- a/arch/arm/include/asm/signal.h
> > +++ b/arch/arm/include/asm/signal.h
> > @@ -19,7 +19,8 @@ typedef struct {
> >
> >  #define SA_UAPI_FLAGS                                                          \
> >       (SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_THIRTYTWO |             \
> > -      SA_RESTORER | SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_RESETHAND)
> > +      SA_RESTORER | SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_RESETHAND |   \
> > +      SA_XFLAGS)
> >
> >  #define __ARCH_HAS_SA_RESTORER
> >
> > diff --git a/arch/parisc/include/asm/signal.h b/arch/parisc/include/asm/signal.h
> > index ad06e14f6e8a..3582bce44520 100644
> > --- a/arch/parisc/include/asm/signal.h
> > +++ b/arch/parisc/include/asm/signal.h
> > @@ -23,7 +23,7 @@ typedef struct {
> >
> >  #define SA_UAPI_FLAGS                                                          \
> >       (SA_ONSTACK | SA_RESETHAND | SA_NOCLDSTOP | SA_SIGINFO | SA_NODEFER |  \
> > -      SA_RESTART | SA_NOCLDWAIT | _SA_SIGGFAULT)
> > +      SA_RESTART | SA_NOCLDWAIT | _SA_SIGGFAULT | SA_XFLAGS)
> >
> >  #include <asm/sigcontext.h>
> >
> > 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/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 e792f29b5846..cd3d08dde47a 100644
> > --- a/include/linux/signal_types.h
> > +++ b/include/linux/signal_types.h
> > @@ -72,11 +72,11 @@ struct ksignal {
> >  #ifdef SA_RESTORER
> >  #define SA_UAPI_FLAGS                                                          \
> >       (SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
> > -      SA_NODEFER | SA_RESETHAND | SA_RESTORER)
> > +      SA_NODEFER | SA_RESETHAND | SA_RESTORER | SA_XFLAGS)
> >  #else
> >  #define SA_UAPI_FLAGS                                                          \
> >       (SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
> > -      SA_NODEFER | SA_RESETHAND)
> > +      SA_NODEFER | SA_RESETHAND | SA_XFLAGS)
> >  #endif
> >  #endif
> >
> > diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
> > index cb3d6c267181..413d804623c0 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,7 @@ typedef struct siginfo {
> >  #define si_trapno    _sifields._sigfault._trapno
> >  #endif
> >  #define si_addr_lsb  _sifields._sigfault._addr_lsb
> > +#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 c30a9c1a77b2..aeee6bb0763b 100644
> > --- a/include/uapi/asm-generic/signal-defs.h
> > +++ b/include/uapi/asm-generic/signal-defs.h
> > @@ -19,6 +19,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 @@
> >   * should be avoided for new generic flags: 3, 4, 5, 6, 7, 8, 9, 16, 24, 25, 26.
> >   */
> >  #define SA_UNSUPPORTED       0x00000400
> > +#define SA_XFLAGS    0x00000800
> >
> >  #define SA_NOMASK    SA_NODEFER
> >  #define SA_ONESHOT   SA_RESETHAND
> > diff --git a/kernel/signal.c b/kernel/signal.c
> > index 664a6c31137e..72182eed1b8d 100644
> > --- a/kernel/signal.c
> > +++ b/kernel/signal.c
> > @@ -1669,6 +1669,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
> >       info.si_flags = flags;
> >       info.si_isr = isr;
> >  #endif
> > +     info.si_xflags = 0;
> >       return force_sig_info_to_task(&info, t);
> >  }
> >
> > @@ -1701,6 +1702,7 @@ int send_sig_fault(int sig, int code, void __user *addr
> >       info.si_flags = flags;
> >       info.si_isr = isr;
> >  #endif
> > +     info.si_xflags = 0;
> >       return send_sig_info(info.si_signo, &info, t);
> >  }
> >
> > @@ -1715,6 +1717,7 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
> >       info.si_code = code;
> >       info.si_addr = addr;
> >       info.si_addr_lsb = lsb;
> > +     info.si_xflags = 0;
> >       return force_sig_info(&info);
> >  }
> >
> > @@ -1729,6 +1732,7 @@ int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *
> >       info.si_code = code;
> >       info.si_addr = addr;
> >       info.si_addr_lsb = lsb;
> > +     info.si_xflags = 0;
> >       return send_sig_info(info.si_signo, &info, t);
> >  }
> >  EXPORT_SYMBOL(send_sig_mceerr);
> > @@ -1744,6 +1748,7 @@ int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
> >       info.si_addr  = addr;
> >       info.si_lower = lower;
> >       info.si_upper = upper;
> > +     info.si_xflags = 0;
> >       return force_sig_info(&info);
> >  }
> >
> > @@ -1758,6 +1763,7 @@ int force_sig_pkuerr(void __user *addr, u32 pkey)
> >       info.si_code  = SEGV_PKUERR;
> >       info.si_addr  = addr;
> >       info.si_pkey  = pkey;
> > +     info.si_xflags = 0;
> >       return force_sig_info(&info);
> >  }
> >  #endif
> > @@ -1774,6 +1780,7 @@ int force_sig_ptrace_errno_trap(int errno, void __user *addr)
> >       info.si_errno = errno;
> >       info.si_code  = TRAP_HWBKPT;
> >       info.si_addr  = addr;
> > +     info.si_xflags = 0;
> >       return force_sig_info(&info);
> >  }
> >
> > @@ -3290,6 +3297,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;
> >               break;
> >       case SIL_FAULT_MCEERR:
> >               to->si_addr = ptr_to_compat(from->si_addr);
> > @@ -3297,6 +3305,7 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
> >               to->si_trapno = from->si_trapno;
> >  #endif
> >               to->si_addr_lsb = from->si_addr_lsb;
> > +             to->si_xflags = from->si_xflags;
> >               break;
> >       case SIL_FAULT_BNDERR:
> >               to->si_addr = ptr_to_compat(from->si_addr);
> > @@ -3305,6 +3314,7 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
> >  #endif
> >               to->si_lower = ptr_to_compat(from->si_lower);
> >               to->si_upper = ptr_to_compat(from->si_upper);
> > +             to->si_xflags = from->si_xflags;
> >               break;
> >       case SIL_FAULT_PKUERR:
> >               to->si_addr = ptr_to_compat(from->si_addr);
> > @@ -3312,6 +3322,7 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
> >               to->si_trapno = from->si_trapno;
> >  #endif
> >               to->si_pkey = from->si_pkey;
> > +             to->si_xflags = from->si_xflags;
> >               break;
> >       case SIL_CHLD:
> >               to->si_pid = from->si_pid;
> > @@ -3370,6 +3381,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;
> >               break;
> >       case SIL_FAULT_MCEERR:
> >               to->si_addr = compat_ptr(from->si_addr);
> > @@ -3377,6 +3389,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> >               to->si_trapno = from->si_trapno;
> >  #endif
> >               to->si_addr_lsb = from->si_addr_lsb;
> > +             to->si_xflags = from->si_xflags;
> >               break;
> >       case SIL_FAULT_BNDERR:
> >               to->si_addr = compat_ptr(from->si_addr);
> > @@ -3385,6 +3398,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> >  #endif
> >               to->si_lower = compat_ptr(from->si_lower);
> >               to->si_upper = compat_ptr(from->si_upper);
> > +             to->si_xflags = from->si_xflags;
> >               break;
> >       case SIL_FAULT_PKUERR:
> >               to->si_addr = compat_ptr(from->si_addr);
> > @@ -3392,6 +3406,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> >               to->si_trapno = from->si_trapno;
> >  #endif
> >               to->si_pkey = from->si_pkey;
> > +             to->si_xflags = from->si_xflags;
>
> How did you figure out the list of places to make these changes?  I'm
> not sure how to confirm that it's exhaustive.

I looked for all places in the kernel where the si_addr field was
being assigned to (basically: git grep '\bsi_addr\s*=') and added my
code there.

> It's a shame if we can't simply apply the change in one place.
> Would the refactoring be too invasive to accomplish that?

I believe that Eric mentioned that kernel/signal.c is supposed to be
"the" file that knows about all of the fields of siginfo (I'm not sure
what's going on in arch/powerpc, I think that's a recent regression).
Maybe it's possible to eliminate the duplication between the various
SIL_FAULT* cases, but aside from that it looks like there wouldn't be
much duplication in the rest of the code.

Peter

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

* Re: [PATCH v9 5/6] signal: define the field siginfo.si_xflags
@ 2020-08-20  1:37       ` Peter Collingbourne
  0 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-20  1:37 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, Aug 19, 2020 at 8:40 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Mon, Aug 17, 2020 at 08:33:50PM -0700, Peter Collingbourne wrote:
> > 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.
> >
> > 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.
>
> For clarity, is the new si_xflags field supposed to be valid for all
> signal types, or just certain signals and si_codes?

It is intended to be valid for all signal types that use the _sigfault
union member of siginfo. As listed in siginfo.h these are: SIGILL,
SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT.

> What happens for things like a rt_sigqueueinfo() from userspace?

Hmm. Let's enumerate each of these things, which I believe are all of
the call sites of the function copy_siginfo_from_user and related
functions (correct me if I'm wrong):

- ptrace(PTRACE_SETSIGINFO)
- pidfd_send_signal
- rt_sigqueueinfo
- rt_tgsigqueueinfo

We can handle the last three by observing that the kernel forbids
sending a signal with these syscalls if si_code >= 0, so we can say
that the value of si_xflags is only valid if si_code >= 0.

As for the first one, it's more tricky. Arguably something like a
debugger should be able to send arbitrary signals to a debuggee, and
there's no reason why it shouldn't be able to set si_xflags in
siginfo, but on the other hand who knows how existing debuggers end up
setting this field today. Maybe all that we can do is have the kernel
clear si_xflags if it detects that the signal uses _sigfault, and let
si_xflags aware debuggers opt out of this behavior, perhaps by
introducing a PTRACE_SETSIGINFO2 or something.

> >
> > Signed-off-by: Peter Collingbourne <pcc@google.com>
> > ---
> > View this change in Gerrit: https://linux-review.googlesource.com/q/Ide155ce29366c3eab2a944ae4c51205982e5b8b2
> >
> >  arch/arm/include/asm/signal.h              |  3 ++-
> >  arch/parisc/include/asm/signal.h           |  2 +-
> >  arch/powerpc/platforms/powernv/vas-fault.c |  1 +
> >  include/linux/compat.h                     |  2 ++
> >  include/linux/signal_types.h               |  4 ++--
> >  include/uapi/asm-generic/siginfo.h         |  3 +++
> >  include/uapi/asm-generic/signal-defs.h     |  4 ++++
> >  kernel/signal.c                            | 15 +++++++++++++++
> >  8 files changed, 30 insertions(+), 4 deletions(-)
> >
> > diff --git a/arch/arm/include/asm/signal.h b/arch/arm/include/asm/signal.h
> > index d1070a783993..6b2630dfe1df 100644
> > --- a/arch/arm/include/asm/signal.h
> > +++ b/arch/arm/include/asm/signal.h
> > @@ -19,7 +19,8 @@ typedef struct {
> >
> >  #define SA_UAPI_FLAGS                                                          \
> >       (SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_THIRTYTWO |             \
> > -      SA_RESTORER | SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_RESETHAND)
> > +      SA_RESTORER | SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_RESETHAND |   \
> > +      SA_XFLAGS)
> >
> >  #define __ARCH_HAS_SA_RESTORER
> >
> > diff --git a/arch/parisc/include/asm/signal.h b/arch/parisc/include/asm/signal.h
> > index ad06e14f6e8a..3582bce44520 100644
> > --- a/arch/parisc/include/asm/signal.h
> > +++ b/arch/parisc/include/asm/signal.h
> > @@ -23,7 +23,7 @@ typedef struct {
> >
> >  #define SA_UAPI_FLAGS                                                          \
> >       (SA_ONSTACK | SA_RESETHAND | SA_NOCLDSTOP | SA_SIGINFO | SA_NODEFER |  \
> > -      SA_RESTART | SA_NOCLDWAIT | _SA_SIGGFAULT)
> > +      SA_RESTART | SA_NOCLDWAIT | _SA_SIGGFAULT | SA_XFLAGS)
> >
> >  #include <asm/sigcontext.h>
> >
> > 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/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 e792f29b5846..cd3d08dde47a 100644
> > --- a/include/linux/signal_types.h
> > +++ b/include/linux/signal_types.h
> > @@ -72,11 +72,11 @@ struct ksignal {
> >  #ifdef SA_RESTORER
> >  #define SA_UAPI_FLAGS                                                          \
> >       (SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
> > -      SA_NODEFER | SA_RESETHAND | SA_RESTORER)
> > +      SA_NODEFER | SA_RESETHAND | SA_RESTORER | SA_XFLAGS)
> >  #else
> >  #define SA_UAPI_FLAGS                                                          \
> >       (SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
> > -      SA_NODEFER | SA_RESETHAND)
> > +      SA_NODEFER | SA_RESETHAND | SA_XFLAGS)
> >  #endif
> >  #endif
> >
> > diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
> > index cb3d6c267181..413d804623c0 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,7 @@ typedef struct siginfo {
> >  #define si_trapno    _sifields._sigfault._trapno
> >  #endif
> >  #define si_addr_lsb  _sifields._sigfault._addr_lsb
> > +#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 c30a9c1a77b2..aeee6bb0763b 100644
> > --- a/include/uapi/asm-generic/signal-defs.h
> > +++ b/include/uapi/asm-generic/signal-defs.h
> > @@ -19,6 +19,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 @@
> >   * should be avoided for new generic flags: 3, 4, 5, 6, 7, 8, 9, 16, 24, 25, 26.
> >   */
> >  #define SA_UNSUPPORTED       0x00000400
> > +#define SA_XFLAGS    0x00000800
> >
> >  #define SA_NOMASK    SA_NODEFER
> >  #define SA_ONESHOT   SA_RESETHAND
> > diff --git a/kernel/signal.c b/kernel/signal.c
> > index 664a6c31137e..72182eed1b8d 100644
> > --- a/kernel/signal.c
> > +++ b/kernel/signal.c
> > @@ -1669,6 +1669,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
> >       info.si_flags = flags;
> >       info.si_isr = isr;
> >  #endif
> > +     info.si_xflags = 0;
> >       return force_sig_info_to_task(&info, t);
> >  }
> >
> > @@ -1701,6 +1702,7 @@ int send_sig_fault(int sig, int code, void __user *addr
> >       info.si_flags = flags;
> >       info.si_isr = isr;
> >  #endif
> > +     info.si_xflags = 0;
> >       return send_sig_info(info.si_signo, &info, t);
> >  }
> >
> > @@ -1715,6 +1717,7 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
> >       info.si_code = code;
> >       info.si_addr = addr;
> >       info.si_addr_lsb = lsb;
> > +     info.si_xflags = 0;
> >       return force_sig_info(&info);
> >  }
> >
> > @@ -1729,6 +1732,7 @@ int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *
> >       info.si_code = code;
> >       info.si_addr = addr;
> >       info.si_addr_lsb = lsb;
> > +     info.si_xflags = 0;
> >       return send_sig_info(info.si_signo, &info, t);
> >  }
> >  EXPORT_SYMBOL(send_sig_mceerr);
> > @@ -1744,6 +1748,7 @@ int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
> >       info.si_addr  = addr;
> >       info.si_lower = lower;
> >       info.si_upper = upper;
> > +     info.si_xflags = 0;
> >       return force_sig_info(&info);
> >  }
> >
> > @@ -1758,6 +1763,7 @@ int force_sig_pkuerr(void __user *addr, u32 pkey)
> >       info.si_code  = SEGV_PKUERR;
> >       info.si_addr  = addr;
> >       info.si_pkey  = pkey;
> > +     info.si_xflags = 0;
> >       return force_sig_info(&info);
> >  }
> >  #endif
> > @@ -1774,6 +1780,7 @@ int force_sig_ptrace_errno_trap(int errno, void __user *addr)
> >       info.si_errno = errno;
> >       info.si_code  = TRAP_HWBKPT;
> >       info.si_addr  = addr;
> > +     info.si_xflags = 0;
> >       return force_sig_info(&info);
> >  }
> >
> > @@ -3290,6 +3297,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;
> >               break;
> >       case SIL_FAULT_MCEERR:
> >               to->si_addr = ptr_to_compat(from->si_addr);
> > @@ -3297,6 +3305,7 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
> >               to->si_trapno = from->si_trapno;
> >  #endif
> >               to->si_addr_lsb = from->si_addr_lsb;
> > +             to->si_xflags = from->si_xflags;
> >               break;
> >       case SIL_FAULT_BNDERR:
> >               to->si_addr = ptr_to_compat(from->si_addr);
> > @@ -3305,6 +3314,7 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
> >  #endif
> >               to->si_lower = ptr_to_compat(from->si_lower);
> >               to->si_upper = ptr_to_compat(from->si_upper);
> > +             to->si_xflags = from->si_xflags;
> >               break;
> >       case SIL_FAULT_PKUERR:
> >               to->si_addr = ptr_to_compat(from->si_addr);
> > @@ -3312,6 +3322,7 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
> >               to->si_trapno = from->si_trapno;
> >  #endif
> >               to->si_pkey = from->si_pkey;
> > +             to->si_xflags = from->si_xflags;
> >               break;
> >       case SIL_CHLD:
> >               to->si_pid = from->si_pid;
> > @@ -3370,6 +3381,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;
> >               break;
> >       case SIL_FAULT_MCEERR:
> >               to->si_addr = compat_ptr(from->si_addr);
> > @@ -3377,6 +3389,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> >               to->si_trapno = from->si_trapno;
> >  #endif
> >               to->si_addr_lsb = from->si_addr_lsb;
> > +             to->si_xflags = from->si_xflags;
> >               break;
> >       case SIL_FAULT_BNDERR:
> >               to->si_addr = compat_ptr(from->si_addr);
> > @@ -3385,6 +3398,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> >  #endif
> >               to->si_lower = compat_ptr(from->si_lower);
> >               to->si_upper = compat_ptr(from->si_upper);
> > +             to->si_xflags = from->si_xflags;
> >               break;
> >       case SIL_FAULT_PKUERR:
> >               to->si_addr = compat_ptr(from->si_addr);
> > @@ -3392,6 +3406,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> >               to->si_trapno = from->si_trapno;
> >  #endif
> >               to->si_pkey = from->si_pkey;
> > +             to->si_xflags = from->si_xflags;
>
> How did you figure out the list of places to make these changes?  I'm
> not sure how to confirm that it's exhaustive.

I looked for all places in the kernel where the si_addr field was
being assigned to (basically: git grep '\bsi_addr\s*=') and added my
code there.

> It's a shame if we can't simply apply the change in one place.
> Would the refactoring be too invasive to accomplish that?

I believe that Eric mentioned that kernel/signal.c is supposed to be
"the" file that knows about all of the fields of siginfo (I'm not sure
what's going on in arch/powerpc, I think that's a recent regression).
Maybe it's possible to eliminate the duplication between the various
SIL_FAULT* cases, but aside from that it looks like there wouldn't be
much duplication in the rest of the code.

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] 66+ messages in thread

* Re: [PATCH v9 6/6] arm64: expose FAR_EL1 tag bits in siginfo
  2020-08-19 15:56     ` Dave Martin
@ 2020-08-20  1:49       ` Peter Collingbourne
  -1 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-20  1:49 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, Aug 19, 2020 at 8:56 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Mon, Aug 17, 2020 at 08:33:51PM -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
> >
> > 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/traps.h          |  7 +++-
> >  arch/arm64/kernel/debug-monitors.c      |  4 +-
> >  arch/arm64/kernel/entry-common.c        |  2 -
> >  arch/arm64/kernel/ptrace.c              |  2 +-
> >  arch/arm64/kernel/traps.c               | 15 ++++---
> >  arch/arm64/mm/fault.c                   | 54 ++++++++++++++-----------
> >  arch/mips/kernel/traps.c                |  2 +-
> >  arch/parisc/kernel/ptrace.c             |  2 +-
> >  arch/parisc/mm/fault.c                  |  2 +-
> >  arch/powerpc/mm/fault.c                 |  2 +-
> >  arch/x86/mm/fault.c                     |  3 +-
> >  include/linux/compat.h                  |  2 +
> >  include/linux/sched/signal.h            | 12 +++++-
> >  include/uapi/asm-generic/siginfo.h      | 10 +++++
> >  kernel/signal.c                         | 50 +++++++++++++++++++----
> >  mm/memory-failure.c                     |  2 +-
> >  18 files changed, 136 insertions(+), 58 deletions(-)
> >
> > diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst
> > index eab4323609b9..bd23039841a5 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 SI_XFLAG_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/traps.h b/arch/arm64/include/asm/traps.h
> > index cee5928e1b7d..8e4f6c5b97af 100644
> > --- a/arch/arm64/include/asm/traps.h
> > +++ b/arch/arm64/include/asm/traps.h
> > @@ -26,8 +26,11 @@ 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_fault(int signo, int code, void __user *addr,
> > +                        unsigned long far, unsigned char far_tb_mask,
> > +                        const char *str);
> > +void arm64_force_sig_mceerr(int code, void __user *addr, short lsb,
> > +                         unsigned long far, const char *str);
> >  void arm64_force_sig_ptrace_errno_trap(int errno, void __user *addr, const char *str);
> >
> >  /*
> > diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
> > index 7310a4f7f993..bc9e02fbb710 100644
> > --- a/arch/arm64/kernel/debug-monitors.c
> > +++ b/arch/arm64/kernel/debug-monitors.c
> > @@ -235,8 +235,8 @@ static void send_user_sigtrap(int si_code)
> >               local_irq_enable();
> >
> >       arm64_force_sig_fault(SIGTRAP, si_code,
> > -                          (void __user *)instruction_pointer(regs),
> > -                          "User debug trap");
> > +                           (void __user *)instruction_pointer(regs), 0, 0,
> > +                           "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..c73312064220 100644
> > --- a/arch/arm64/kernel/ptrace.c
> > +++ b/arch/arm64/kernel/ptrace.c
> > @@ -197,7 +197,7 @@ static void ptrace_hbptriggered(struct perf_event *bp,
> >       }
> >  #endif
> >       arm64_force_sig_fault(SIGTRAP, TRAP_HWBKPT,
> > -                           (void __user *)(bkpt->trigger),
> > +                           (void __user *)(bkpt->trigger), 0, 0,
> >                             desc);
> >  }
> >
> > diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
> > index 13ebd5ca2070..c945c5cc1312 100644
> > --- a/arch/arm64/kernel/traps.c
> > +++ b/arch/arm64/kernel/traps.c
> > @@ -235,20 +235,25 @@ static void arm64_show_signal(int signo, const char *str)
> >  }
> >
> >  void arm64_force_sig_fault(int signo, int code, void __user *addr,
> > +                        unsigned long far, unsigned char far_tb_mask,
> >                          const char *str)
> >  {
> > +     unsigned long ignored_bits_mask = ((unsigned long)far_tb_mask) << 56;
> > +
> >       arm64_show_signal(signo, str);
> >       if (signo == SIGKILL)
> >               force_sig(SIGKILL);
> >       else
> > -             force_sig_fault(signo, code, addr);
> > +             force_sig_fault_with_ignored_bits(signo, code, addr,
> > +                                               far & ignored_bits_mask,
> > +                                               ignored_bits_mask);
> >  }
> >
> >  void arm64_force_sig_mceerr(int code, void __user *addr, short lsb,
> > -                         const char *str)
> > +                         unsigned long far, const char *str)
> >  {
> >       arm64_show_signal(SIGBUS, str);
> > -     force_sig_mceerr(code, addr, lsb);
> > +     force_sig_mceerr(code, addr, lsb, far & (0xffUL << 56), 0xffUL << 56);
> >  }
> >
> >  void arm64_force_sig_ptrace_errno_trap(int errno, void __user *addr,
> > @@ -267,7 +272,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, addr, 0, 0, str);
> >       } else {
> >               die(str, regs, err);
> >       }
> > @@ -829,7 +834,7 @@ void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr)
> >       current->thread.fault_address = 0;
> >       current->thread.fault_code = esr;
> >
> > -     arm64_force_sig_fault(SIGILL, ILL_ILLOPC, pc,
> > +     arm64_force_sig_fault(SIGILL, ILL_ILLOPC, pc, 0, 0,
> >                             "Bad EL0 synchronous exception");
> >  }
> >
> > diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
> > index f07333e86c2f..82f05644417e 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.
> > @@ -394,7 +397,7 @@ static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *re
> >
> >               set_thread_esr(addr, esr);
> >               arm64_force_sig_fault(inf->sig, inf->code, (void __user *)addr,
> > -                                   inf->name);
> > +                                   far, 0xff, inf->name);
> >       } else {
> >               __do_kernel_fault(addr, esr, regs);
> >       }
> > @@ -446,7 +449,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 +457,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;
> > @@ -566,7 +570,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
> >                * this page fault.
> >                */
> >               arm64_force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)addr,
> > -                                   inf->name);
> > +                                   far, 0xff, inf->name);
> >       } else if (fault & (VM_FAULT_HWPOISON_LARGE | VM_FAULT_HWPOISON)) {
> >               unsigned int lsb;
> >
> > @@ -575,7 +579,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
> >                       lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault));
> >
> >               arm64_force_sig_mceerr(BUS_MCEERR_AR, (void __user *)addr, lsb,
> > -                                    inf->name);
> > +                                    far, inf->name);
> >       } else {
> >               /*
> >                * Something tried to access memory that isn't in our memory
> > @@ -583,8 +587,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);
> > +                                   (void __user *)addr, far, 0xff, inf->name);
> >       }
> >
> >       return 0;
> > @@ -594,30 +597,32 @@ 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;
> > @@ -635,7 +640,7 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
> >       if (esr & ESR_ELx_FnV)
> >               siaddr = NULL;
> >       else
> > -             siaddr  = (void __user *)addr;
> > +             siaddr  = (void __user *)untagged_addr(far);
> >       arm64_notify_die(inf->name, regs, inf->sig, inf->code, siaddr, esr);
> >
> >       return 0;
> > @@ -708,11 +713,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 +727,8 @@ 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,
> > +                      (void __user *)addr, esr);
> >  }
> >  NOKPROBE_SYMBOL(do_mem_abort);
> >
> > @@ -735,8 +741,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,
> > +                      (void __user *)addr, esr);
> >  }
> >  NOKPROBE_SYMBOL(do_sp_pc_abort);
> >
> > @@ -862,8 +868,8 @@ 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,
> > +                              (void __user *)pc, esr);
> >       }
> >
> >       debug_exception_exit(regs);
> > diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
> > index 38aa07ccdbcc..73a181c904b0 100644
> > --- a/arch/mips/kernel/traps.c
> > +++ b/arch/mips/kernel/traps.c
> > @@ -775,7 +775,7 @@ void force_fcr31_sig(unsigned long fcr31, void __user *fault_addr,
> >       else if (fcr31 & FPU_CSR_INE_X)
> >               si_code = FPE_FLTRES;
> >
> > -     force_sig_fault_to_task(SIGFPE, si_code, fault_addr, tsk);
> > +     force_sig_fault_to_task(SIGFPE, si_code, fault_addr, 0, 0, tsk);
> >  }
> >
> >  int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcr31)
> > diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
> > index 2127974982df..62c8bb0d7d31 100644
> > --- a/arch/parisc/kernel/ptrace.c
> > +++ b/arch/parisc/kernel/ptrace.c
> > @@ -89,7 +89,7 @@ void user_enable_single_step(struct task_struct *task)
> >                  parent know something happened. */
> >               force_sig_fault_to_task(SIGTRAP, TRAP_TRACE,
> >                                       (void __user *) (task_regs(task)->iaoq[0] & ~3),
> > -                                     task);
> > +                                     0, 0, task);
> >               /* notify_parent(task, SIGCHLD); */
> >               return;
> >       }
> > diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
> > index 4bfe2da9fbe3..2a6064ea2dfc 100644
> > --- a/arch/parisc/mm/fault.c
> > +++ b/arch/parisc/mm/fault.c
> > @@ -400,7 +400,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
> >                               lsb = PAGE_SHIFT;
> >
> >                       force_sig_mceerr(BUS_MCEERR_AR, (void __user *) address,
> > -                                      lsb);
> > +                                      lsb, 0, 0);
> >                       return;
> >               }
> >  #endif
> > diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
> > index 0add963a849b..4ffe2fb8e31a 100644
> > --- a/arch/powerpc/mm/fault.c
> > +++ b/arch/powerpc/mm/fault.c
> > @@ -152,7 +152,7 @@ static int do_sigbus(struct pt_regs *regs, unsigned long address,
> >               if (fault & VM_FAULT_HWPOISON)
> >                       lsb = PAGE_SHIFT;
> >
> > -             force_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb);
> > +             force_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb, 0, 0);
> >               return 0;
> >       }
> >
> > diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
> > index 35f1498e9832..a443eec157f6 100644
> > --- a/arch/x86/mm/fault.c
> > +++ b/arch/x86/mm/fault.c
> > @@ -898,7 +898,8 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address,
> >                       lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault));
> >               if (fault & VM_FAULT_HWPOISON)
> >                       lsb = PAGE_SHIFT;
> > -             force_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb);
> > +             force_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb, 0,
> > +                              0);
> >               return;
> >       }
> >  #endif
> > 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/sched/signal.h b/include/linux/sched/signal.h
> > index 1bad18a1d8ba..f62a014a5a4d 100644
> > --- a/include/linux/sched/signal.h
> > +++ b/include/linux/sched/signal.h
> > @@ -311,16 +311,24 @@ static inline void kernel_signal_stop(void)
> >  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)
> > -     , struct task_struct *t);
> > +     , unsigned long addr_ignored_bits, unsigned long addr_ignored_bits_mask,
> > +     struct task_struct *t);
> >  int force_sig_fault(int sig, int code, void __user *addr
> >       ___ARCH_SI_TRAPNO(int trapno)
> >       ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr));
> > +int force_sig_fault_with_ignored_bits(int sig, int code, void __user *addr
> > +     ___ARCH_SI_TRAPNO(int trapno)
> > +     ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
> > +     , unsigned long addr_ignored_bits,
> > +     unsigned long addr_ignored_bits_mask);
> >  int send_sig_fault(int sig, int code, void __user *addr
> >       ___ARCH_SI_TRAPNO(int trapno)
> >       ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
> >       , struct task_struct *t);
> >
> > -int force_sig_mceerr(int code, void __user *, short);
> > +int force_sig_mceerr(int code, void __user *addr, short addr_lsb,
> > +                  unsigned long addr_ignored_bits,
> > +                  unsigned long addr_ignored_bits_mask);
> >  int send_sig_mceerr(int code, void __user *, short, struct task_struct *);
> >
> >  int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper);
> > diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
> > index 413d804623c0..1fc6482b0ad4 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 */
> > @@ -155,6 +157,8 @@ typedef struct siginfo {
> >  #endif
> >  #define si_addr_lsb  _sifields._sigfault._addr_lsb
> >  #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
> > @@ -295,6 +299,12 @@ typedef struct siginfo {
> >  #define EMT_TAGOVF   1       /* tag overflow */
> >  #define NSIGEMT              1
> >
> > +/*
> > + * SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT si_xflags
> > + */
> > +#define SI_XFLAG_IGNORED_BITS        1
> > +/* si_addr_ignored_bits{,_mask} fields valid */
> > +
> >  /*
> >   * sigevent definitions
> >   *
> > diff --git a/kernel/signal.c b/kernel/signal.c
> > index 72182eed1b8d..1f1e42adc57d 100644
> > --- a/kernel/signal.c
> > +++ b/kernel/signal.c
> > @@ -1652,7 +1652,8 @@ void force_sigsegv(int sig)
> >  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)
> > -     , struct task_struct *t)
> > +     , unsigned long addr_ignored_bits, unsigned long addr_ignored_bits_mask,
> > +     struct task_struct *t)
> >  {
> >       struct kernel_siginfo info;
> >
> > @@ -1669,17 +1670,32 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
> >       info.si_flags = flags;
> >       info.si_isr = isr;
> >  #endif
> > -     info.si_xflags = 0;
> > +     info.si_xflags = SI_XFLAG_IGNORED_BITS;
> > +     info.si_addr_ignored_bits = addr_ignored_bits;
> > +     info.si_addr_ignored_bits_mask = addr_ignored_bits_mask;
> >       return force_sig_info_to_task(&info, t);
> >  }
> >
> > -int force_sig_fault(int sig, int code, void __user *addr
> > +int force_sig_fault_with_ignored_bits(int sig, int code, void __user *addr
> >       ___ARCH_SI_TRAPNO(int trapno)
> > -     ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr))
> > +     ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr),
> > +     unsigned long addr_ignored_bits, unsigned long addr_ignored_bits_mask)
> >  {
> >       return force_sig_fault_to_task(sig, code, addr
> >                                      ___ARCH_SI_TRAPNO(trapno)
> > -                                    ___ARCH_SI_IA64(imm, flags, isr), current);
> > +                                    ___ARCH_SI_IA64(imm, flags, isr),
> > +                                    addr_ignored_bits,
> > +                                    addr_ignored_bits_mask, current);
> > +}
> > +
> > +int force_sig_fault(int sig, int code, void __user *addr
> > +     ___ARCH_SI_TRAPNO(int trapno)
> > +     ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr))
> > +{
> > +     return force_sig_fault_with_ignored_bits(sig, code, addr
> > +                                              ___ARCH_SI_TRAPNO(trapno)
> > +                                              ___ARCH_SI_IA64(imm, flags,
> > +                                                              isr), 0, 0);
> >  }
> >
> >  int send_sig_fault(int sig, int code, void __user *addr
> > @@ -1706,7 +1722,9 @@ int send_sig_fault(int sig, int code, void __user *addr
> >       return send_sig_info(info.si_signo, &info, t);
> >  }
> >
> > -int force_sig_mceerr(int code, void __user *addr, short lsb)
> > +int force_sig_mceerr(int code, void __user *addr, short lsb,
> > +                  unsigned long addr_ignored_bits,
> > +                  unsigned long addr_ignored_bits_mask)
>
> Rather than having to pass these extra arguments all over the place, can
> we just pass the far for addr, and have an arch-specific hook for
> splitting the ignored from non-ignored bits.  For now at least, I expect
> that ignored bits mask to be constant for a given platform and kernel.

That sounds like a good idea. I think that for MTE we will want to
make it conditional on the si_code (so SEGV_MTESERR would get 0xf <<
56 while everything else would get 0xff << 56) so I can hook that up
at the same time.

> >  {
> >       struct kernel_siginfo info;
> >
> > @@ -1717,7 +1735,9 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
> >       info.si_code = code;
> >       info.si_addr = addr;
> >       info.si_addr_lsb = lsb;
> > -     info.si_xflags = 0;
> > +     info.si_xflags = SI_XFLAG_IGNORED_BITS;
>
> Maybe drop the first _, so that this becomes
>
>         SIXFLAG_IGNORED_BITS
>
> ?  This may help to avoid anyone thinking this might be an si_code
> value.  Maybe ..._IGNORED_ADDR_BITS would also help make it clearer what
> this bit is referring to.

Yes, it should have been spelled the same way as the field name (i.e.
SIXFLAG_ADDR_IGNORED_BITS), that was my mistake. I don't have a strong
opinion on whether to keep the underscore in the middle or not.

> > +     info.si_addr_ignored_bits = addr_ignored_bits;
> > +     info.si_addr_ignored_bits_mask = addr_ignored_bits_mask;
> >       return force_sig_info(&info);
> >  }
> >
> > @@ -3298,6 +3318,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;
> >               break;
> >       case SIL_FAULT_MCEERR:
> >               to->si_addr = ptr_to_compat(from->si_addr);
> > @@ -3306,6 +3328,8 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
> >  #endif
> >               to->si_addr_lsb = from->si_addr_lsb;
> >               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;
> >               break;
> >       case SIL_FAULT_BNDERR:
> >               to->si_addr = ptr_to_compat(from->si_addr);
> > @@ -3315,6 +3339,8 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
> >               to->si_lower = ptr_to_compat(from->si_lower);
> >               to->si_upper = ptr_to_compat(from->si_upper);
> >               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;
> >               break;
> >       case SIL_FAULT_PKUERR:
> >               to->si_addr = ptr_to_compat(from->si_addr);
> > @@ -3323,6 +3349,8 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
> >  #endif
> >               to->si_pkey = from->si_pkey;
> >               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;
> >               break;>         case SIL_CHLD:
> >               to->si_pid = from->si_pid;
> > @@ -3382,6 +3410,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;
> >               break;
> >       case SIL_FAULT_MCEERR:
> >               to->si_addr = compat_ptr(from->si_addr);
> > @@ -3390,6 +3420,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> >  #endif
> >               to->si_addr_lsb = from->si_addr_lsb;
> >               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;
> >               break;
> >       case SIL_FAULT_BNDERR:
> >               to->si_addr = compat_ptr(from->si_addr);
> > @@ -3399,6 +3431,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> >               to->si_lower = compat_ptr(from->si_lower);
> >               to->si_upper = compat_ptr(from->si_upper);
> >               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;
> >               break;
> >       case SIL_FAULT_PKUERR:
> >               to->si_addr = compat_ptr(from->si_addr);
> > @@ -3407,6 +3441,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> >  #endif
> >               to->si_pkey = from->si_pkey;
> >               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;
>
> Again, can you justify why this is exhaustive?  If there any way to
> factor this so as to reduce the number of places we need to hack this
> in?

Addressed on the other patch. Once I've factored the various
SIL_FAULT* cases there should be only a handful of places requiring
changes.

Peter

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

* Re: [PATCH v9 6/6] arm64: expose FAR_EL1 tag bits in siginfo
@ 2020-08-20  1:49       ` Peter Collingbourne
  0 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-20  1:49 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, Aug 19, 2020 at 8:56 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Mon, Aug 17, 2020 at 08:33:51PM -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
> >
> > 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/traps.h          |  7 +++-
> >  arch/arm64/kernel/debug-monitors.c      |  4 +-
> >  arch/arm64/kernel/entry-common.c        |  2 -
> >  arch/arm64/kernel/ptrace.c              |  2 +-
> >  arch/arm64/kernel/traps.c               | 15 ++++---
> >  arch/arm64/mm/fault.c                   | 54 ++++++++++++++-----------
> >  arch/mips/kernel/traps.c                |  2 +-
> >  arch/parisc/kernel/ptrace.c             |  2 +-
> >  arch/parisc/mm/fault.c                  |  2 +-
> >  arch/powerpc/mm/fault.c                 |  2 +-
> >  arch/x86/mm/fault.c                     |  3 +-
> >  include/linux/compat.h                  |  2 +
> >  include/linux/sched/signal.h            | 12 +++++-
> >  include/uapi/asm-generic/siginfo.h      | 10 +++++
> >  kernel/signal.c                         | 50 +++++++++++++++++++----
> >  mm/memory-failure.c                     |  2 +-
> >  18 files changed, 136 insertions(+), 58 deletions(-)
> >
> > diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst
> > index eab4323609b9..bd23039841a5 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 SI_XFLAG_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/traps.h b/arch/arm64/include/asm/traps.h
> > index cee5928e1b7d..8e4f6c5b97af 100644
> > --- a/arch/arm64/include/asm/traps.h
> > +++ b/arch/arm64/include/asm/traps.h
> > @@ -26,8 +26,11 @@ 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_fault(int signo, int code, void __user *addr,
> > +                        unsigned long far, unsigned char far_tb_mask,
> > +                        const char *str);
> > +void arm64_force_sig_mceerr(int code, void __user *addr, short lsb,
> > +                         unsigned long far, const char *str);
> >  void arm64_force_sig_ptrace_errno_trap(int errno, void __user *addr, const char *str);
> >
> >  /*
> > diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
> > index 7310a4f7f993..bc9e02fbb710 100644
> > --- a/arch/arm64/kernel/debug-monitors.c
> > +++ b/arch/arm64/kernel/debug-monitors.c
> > @@ -235,8 +235,8 @@ static void send_user_sigtrap(int si_code)
> >               local_irq_enable();
> >
> >       arm64_force_sig_fault(SIGTRAP, si_code,
> > -                          (void __user *)instruction_pointer(regs),
> > -                          "User debug trap");
> > +                           (void __user *)instruction_pointer(regs), 0, 0,
> > +                           "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..c73312064220 100644
> > --- a/arch/arm64/kernel/ptrace.c
> > +++ b/arch/arm64/kernel/ptrace.c
> > @@ -197,7 +197,7 @@ static void ptrace_hbptriggered(struct perf_event *bp,
> >       }
> >  #endif
> >       arm64_force_sig_fault(SIGTRAP, TRAP_HWBKPT,
> > -                           (void __user *)(bkpt->trigger),
> > +                           (void __user *)(bkpt->trigger), 0, 0,
> >                             desc);
> >  }
> >
> > diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
> > index 13ebd5ca2070..c945c5cc1312 100644
> > --- a/arch/arm64/kernel/traps.c
> > +++ b/arch/arm64/kernel/traps.c
> > @@ -235,20 +235,25 @@ static void arm64_show_signal(int signo, const char *str)
> >  }
> >
> >  void arm64_force_sig_fault(int signo, int code, void __user *addr,
> > +                        unsigned long far, unsigned char far_tb_mask,
> >                          const char *str)
> >  {
> > +     unsigned long ignored_bits_mask = ((unsigned long)far_tb_mask) << 56;
> > +
> >       arm64_show_signal(signo, str);
> >       if (signo == SIGKILL)
> >               force_sig(SIGKILL);
> >       else
> > -             force_sig_fault(signo, code, addr);
> > +             force_sig_fault_with_ignored_bits(signo, code, addr,
> > +                                               far & ignored_bits_mask,
> > +                                               ignored_bits_mask);
> >  }
> >
> >  void arm64_force_sig_mceerr(int code, void __user *addr, short lsb,
> > -                         const char *str)
> > +                         unsigned long far, const char *str)
> >  {
> >       arm64_show_signal(SIGBUS, str);
> > -     force_sig_mceerr(code, addr, lsb);
> > +     force_sig_mceerr(code, addr, lsb, far & (0xffUL << 56), 0xffUL << 56);
> >  }
> >
> >  void arm64_force_sig_ptrace_errno_trap(int errno, void __user *addr,
> > @@ -267,7 +272,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, addr, 0, 0, str);
> >       } else {
> >               die(str, regs, err);
> >       }
> > @@ -829,7 +834,7 @@ void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr)
> >       current->thread.fault_address = 0;
> >       current->thread.fault_code = esr;
> >
> > -     arm64_force_sig_fault(SIGILL, ILL_ILLOPC, pc,
> > +     arm64_force_sig_fault(SIGILL, ILL_ILLOPC, pc, 0, 0,
> >                             "Bad EL0 synchronous exception");
> >  }
> >
> > diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
> > index f07333e86c2f..82f05644417e 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.
> > @@ -394,7 +397,7 @@ static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *re
> >
> >               set_thread_esr(addr, esr);
> >               arm64_force_sig_fault(inf->sig, inf->code, (void __user *)addr,
> > -                                   inf->name);
> > +                                   far, 0xff, inf->name);
> >       } else {
> >               __do_kernel_fault(addr, esr, regs);
> >       }
> > @@ -446,7 +449,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 +457,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;
> > @@ -566,7 +570,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
> >                * this page fault.
> >                */
> >               arm64_force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)addr,
> > -                                   inf->name);
> > +                                   far, 0xff, inf->name);
> >       } else if (fault & (VM_FAULT_HWPOISON_LARGE | VM_FAULT_HWPOISON)) {
> >               unsigned int lsb;
> >
> > @@ -575,7 +579,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
> >                       lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault));
> >
> >               arm64_force_sig_mceerr(BUS_MCEERR_AR, (void __user *)addr, lsb,
> > -                                    inf->name);
> > +                                    far, inf->name);
> >       } else {
> >               /*
> >                * Something tried to access memory that isn't in our memory
> > @@ -583,8 +587,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);
> > +                                   (void __user *)addr, far, 0xff, inf->name);
> >       }
> >
> >       return 0;
> > @@ -594,30 +597,32 @@ 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;
> > @@ -635,7 +640,7 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
> >       if (esr & ESR_ELx_FnV)
> >               siaddr = NULL;
> >       else
> > -             siaddr  = (void __user *)addr;
> > +             siaddr  = (void __user *)untagged_addr(far);
> >       arm64_notify_die(inf->name, regs, inf->sig, inf->code, siaddr, esr);
> >
> >       return 0;
> > @@ -708,11 +713,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 +727,8 @@ 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,
> > +                      (void __user *)addr, esr);
> >  }
> >  NOKPROBE_SYMBOL(do_mem_abort);
> >
> > @@ -735,8 +741,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,
> > +                      (void __user *)addr, esr);
> >  }
> >  NOKPROBE_SYMBOL(do_sp_pc_abort);
> >
> > @@ -862,8 +868,8 @@ 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,
> > +                              (void __user *)pc, esr);
> >       }
> >
> >       debug_exception_exit(regs);
> > diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
> > index 38aa07ccdbcc..73a181c904b0 100644
> > --- a/arch/mips/kernel/traps.c
> > +++ b/arch/mips/kernel/traps.c
> > @@ -775,7 +775,7 @@ void force_fcr31_sig(unsigned long fcr31, void __user *fault_addr,
> >       else if (fcr31 & FPU_CSR_INE_X)
> >               si_code = FPE_FLTRES;
> >
> > -     force_sig_fault_to_task(SIGFPE, si_code, fault_addr, tsk);
> > +     force_sig_fault_to_task(SIGFPE, si_code, fault_addr, 0, 0, tsk);
> >  }
> >
> >  int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcr31)
> > diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
> > index 2127974982df..62c8bb0d7d31 100644
> > --- a/arch/parisc/kernel/ptrace.c
> > +++ b/arch/parisc/kernel/ptrace.c
> > @@ -89,7 +89,7 @@ void user_enable_single_step(struct task_struct *task)
> >                  parent know something happened. */
> >               force_sig_fault_to_task(SIGTRAP, TRAP_TRACE,
> >                                       (void __user *) (task_regs(task)->iaoq[0] & ~3),
> > -                                     task);
> > +                                     0, 0, task);
> >               /* notify_parent(task, SIGCHLD); */
> >               return;
> >       }
> > diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
> > index 4bfe2da9fbe3..2a6064ea2dfc 100644
> > --- a/arch/parisc/mm/fault.c
> > +++ b/arch/parisc/mm/fault.c
> > @@ -400,7 +400,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
> >                               lsb = PAGE_SHIFT;
> >
> >                       force_sig_mceerr(BUS_MCEERR_AR, (void __user *) address,
> > -                                      lsb);
> > +                                      lsb, 0, 0);
> >                       return;
> >               }
> >  #endif
> > diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
> > index 0add963a849b..4ffe2fb8e31a 100644
> > --- a/arch/powerpc/mm/fault.c
> > +++ b/arch/powerpc/mm/fault.c
> > @@ -152,7 +152,7 @@ static int do_sigbus(struct pt_regs *regs, unsigned long address,
> >               if (fault & VM_FAULT_HWPOISON)
> >                       lsb = PAGE_SHIFT;
> >
> > -             force_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb);
> > +             force_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb, 0, 0);
> >               return 0;
> >       }
> >
> > diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
> > index 35f1498e9832..a443eec157f6 100644
> > --- a/arch/x86/mm/fault.c
> > +++ b/arch/x86/mm/fault.c
> > @@ -898,7 +898,8 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address,
> >                       lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault));
> >               if (fault & VM_FAULT_HWPOISON)
> >                       lsb = PAGE_SHIFT;
> > -             force_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb);
> > +             force_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb, 0,
> > +                              0);
> >               return;
> >       }
> >  #endif
> > 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/sched/signal.h b/include/linux/sched/signal.h
> > index 1bad18a1d8ba..f62a014a5a4d 100644
> > --- a/include/linux/sched/signal.h
> > +++ b/include/linux/sched/signal.h
> > @@ -311,16 +311,24 @@ static inline void kernel_signal_stop(void)
> >  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)
> > -     , struct task_struct *t);
> > +     , unsigned long addr_ignored_bits, unsigned long addr_ignored_bits_mask,
> > +     struct task_struct *t);
> >  int force_sig_fault(int sig, int code, void __user *addr
> >       ___ARCH_SI_TRAPNO(int trapno)
> >       ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr));
> > +int force_sig_fault_with_ignored_bits(int sig, int code, void __user *addr
> > +     ___ARCH_SI_TRAPNO(int trapno)
> > +     ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
> > +     , unsigned long addr_ignored_bits,
> > +     unsigned long addr_ignored_bits_mask);
> >  int send_sig_fault(int sig, int code, void __user *addr
> >       ___ARCH_SI_TRAPNO(int trapno)
> >       ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
> >       , struct task_struct *t);
> >
> > -int force_sig_mceerr(int code, void __user *, short);
> > +int force_sig_mceerr(int code, void __user *addr, short addr_lsb,
> > +                  unsigned long addr_ignored_bits,
> > +                  unsigned long addr_ignored_bits_mask);
> >  int send_sig_mceerr(int code, void __user *, short, struct task_struct *);
> >
> >  int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper);
> > diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
> > index 413d804623c0..1fc6482b0ad4 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 */
> > @@ -155,6 +157,8 @@ typedef struct siginfo {
> >  #endif
> >  #define si_addr_lsb  _sifields._sigfault._addr_lsb
> >  #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
> > @@ -295,6 +299,12 @@ typedef struct siginfo {
> >  #define EMT_TAGOVF   1       /* tag overflow */
> >  #define NSIGEMT              1
> >
> > +/*
> > + * SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT si_xflags
> > + */
> > +#define SI_XFLAG_IGNORED_BITS        1
> > +/* si_addr_ignored_bits{,_mask} fields valid */
> > +
> >  /*
> >   * sigevent definitions
> >   *
> > diff --git a/kernel/signal.c b/kernel/signal.c
> > index 72182eed1b8d..1f1e42adc57d 100644
> > --- a/kernel/signal.c
> > +++ b/kernel/signal.c
> > @@ -1652,7 +1652,8 @@ void force_sigsegv(int sig)
> >  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)
> > -     , struct task_struct *t)
> > +     , unsigned long addr_ignored_bits, unsigned long addr_ignored_bits_mask,
> > +     struct task_struct *t)
> >  {
> >       struct kernel_siginfo info;
> >
> > @@ -1669,17 +1670,32 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
> >       info.si_flags = flags;
> >       info.si_isr = isr;
> >  #endif
> > -     info.si_xflags = 0;
> > +     info.si_xflags = SI_XFLAG_IGNORED_BITS;
> > +     info.si_addr_ignored_bits = addr_ignored_bits;
> > +     info.si_addr_ignored_bits_mask = addr_ignored_bits_mask;
> >       return force_sig_info_to_task(&info, t);
> >  }
> >
> > -int force_sig_fault(int sig, int code, void __user *addr
> > +int force_sig_fault_with_ignored_bits(int sig, int code, void __user *addr
> >       ___ARCH_SI_TRAPNO(int trapno)
> > -     ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr))
> > +     ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr),
> > +     unsigned long addr_ignored_bits, unsigned long addr_ignored_bits_mask)
> >  {
> >       return force_sig_fault_to_task(sig, code, addr
> >                                      ___ARCH_SI_TRAPNO(trapno)
> > -                                    ___ARCH_SI_IA64(imm, flags, isr), current);
> > +                                    ___ARCH_SI_IA64(imm, flags, isr),
> > +                                    addr_ignored_bits,
> > +                                    addr_ignored_bits_mask, current);
> > +}
> > +
> > +int force_sig_fault(int sig, int code, void __user *addr
> > +     ___ARCH_SI_TRAPNO(int trapno)
> > +     ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr))
> > +{
> > +     return force_sig_fault_with_ignored_bits(sig, code, addr
> > +                                              ___ARCH_SI_TRAPNO(trapno)
> > +                                              ___ARCH_SI_IA64(imm, flags,
> > +                                                              isr), 0, 0);
> >  }
> >
> >  int send_sig_fault(int sig, int code, void __user *addr
> > @@ -1706,7 +1722,9 @@ int send_sig_fault(int sig, int code, void __user *addr
> >       return send_sig_info(info.si_signo, &info, t);
> >  }
> >
> > -int force_sig_mceerr(int code, void __user *addr, short lsb)
> > +int force_sig_mceerr(int code, void __user *addr, short lsb,
> > +                  unsigned long addr_ignored_bits,
> > +                  unsigned long addr_ignored_bits_mask)
>
> Rather than having to pass these extra arguments all over the place, can
> we just pass the far for addr, and have an arch-specific hook for
> splitting the ignored from non-ignored bits.  For now at least, I expect
> that ignored bits mask to be constant for a given platform and kernel.

That sounds like a good idea. I think that for MTE we will want to
make it conditional on the si_code (so SEGV_MTESERR would get 0xf <<
56 while everything else would get 0xff << 56) so I can hook that up
at the same time.

> >  {
> >       struct kernel_siginfo info;
> >
> > @@ -1717,7 +1735,9 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
> >       info.si_code = code;
> >       info.si_addr = addr;
> >       info.si_addr_lsb = lsb;
> > -     info.si_xflags = 0;
> > +     info.si_xflags = SI_XFLAG_IGNORED_BITS;
>
> Maybe drop the first _, so that this becomes
>
>         SIXFLAG_IGNORED_BITS
>
> ?  This may help to avoid anyone thinking this might be an si_code
> value.  Maybe ..._IGNORED_ADDR_BITS would also help make it clearer what
> this bit is referring to.

Yes, it should have been spelled the same way as the field name (i.e.
SIXFLAG_ADDR_IGNORED_BITS), that was my mistake. I don't have a strong
opinion on whether to keep the underscore in the middle or not.

> > +     info.si_addr_ignored_bits = addr_ignored_bits;
> > +     info.si_addr_ignored_bits_mask = addr_ignored_bits_mask;
> >       return force_sig_info(&info);
> >  }
> >
> > @@ -3298,6 +3318,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;
> >               break;
> >       case SIL_FAULT_MCEERR:
> >               to->si_addr = ptr_to_compat(from->si_addr);
> > @@ -3306,6 +3328,8 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
> >  #endif
> >               to->si_addr_lsb = from->si_addr_lsb;
> >               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;
> >               break;
> >       case SIL_FAULT_BNDERR:
> >               to->si_addr = ptr_to_compat(from->si_addr);
> > @@ -3315,6 +3339,8 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
> >               to->si_lower = ptr_to_compat(from->si_lower);
> >               to->si_upper = ptr_to_compat(from->si_upper);
> >               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;
> >               break;
> >       case SIL_FAULT_PKUERR:
> >               to->si_addr = ptr_to_compat(from->si_addr);
> > @@ -3323,6 +3349,8 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
> >  #endif
> >               to->si_pkey = from->si_pkey;
> >               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;
> >               break;>         case SIL_CHLD:
> >               to->si_pid = from->si_pid;
> > @@ -3382,6 +3410,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;
> >               break;
> >       case SIL_FAULT_MCEERR:
> >               to->si_addr = compat_ptr(from->si_addr);
> > @@ -3390,6 +3420,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> >  #endif
> >               to->si_addr_lsb = from->si_addr_lsb;
> >               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;
> >               break;
> >       case SIL_FAULT_BNDERR:
> >               to->si_addr = compat_ptr(from->si_addr);
> > @@ -3399,6 +3431,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> >               to->si_lower = compat_ptr(from->si_lower);
> >               to->si_upper = compat_ptr(from->si_upper);
> >               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;
> >               break;
> >       case SIL_FAULT_PKUERR:
> >               to->si_addr = compat_ptr(from->si_addr);
> > @@ -3407,6 +3441,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> >  #endif
> >               to->si_pkey = from->si_pkey;
> >               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;
>
> Again, can you justify why this is exhaustive?  If there any way to
> factor this so as to reduce the number of places we need to hack this
> in?

Addressed on the other patch. Once I've factored the various
SIL_FAULT* cases there should be only a handful of places requiring
changes.

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] 66+ messages in thread

* Re: [PATCH v9 3/6] signal: clear non-uapi flag bits when passing/returning sa_flags
  2020-08-19 23:39       ` Peter Collingbourne
@ 2020-08-24 13:40         ` Dave Martin
  -1 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-24 13:40 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, Aug 19, 2020 at 04:39:53PM -0700, Peter Collingbourne wrote:
> On Wed, Aug 19, 2020 at 3:39 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Mon, Aug 17, 2020 at 08:33:48PM -0700, Peter Collingbourne wrote:
> >
> > Nit: please say what the patch does.  Subject line should summarise
> > what is done, but should not add new information that is not present in
> > the description proper.
> >
> > (Same for all the other patches.)
> 
> Will do.

Thanks

[...]

> > > diff --git a/arch/arm/include/asm/signal.h b/arch/arm/include/asm/signal.h
> > > index 65530a042009..d1070a783993 100644
> > > --- a/arch/arm/include/asm/signal.h
> > > +++ b/arch/arm/include/asm/signal.h
> > > @@ -17,6 +17,10 @@ typedef struct {
> > >       unsigned long sig[_NSIG_WORDS];
> > >  } sigset_t;
> > >
> > > +#define SA_UAPI_FLAGS                                                          \
> > > +     (SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_THIRTYTWO |             \
> > > +      SA_RESTORER | SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_RESETHAND)
> > > +
> >
> > I wonder whether all these per-arch definitions will tend to bitrot when
> > people add new common flags.
> >
> > Can we have a common definition for the common bits, and just add the
> > extra arch-specific ones here?
> 
> I think so. We could have something like:
> 
> #define ARCH_UAPI_SA_FLAGS SA_THIRTYTWO
> 
> here. Then in signal_types.h we can do:
> 
> #ifndef ARCH_UAPI_SA_FLAGS
> #define ARCH_UAPI_SA_FLAGS 0
> #endif
> 
> #define UAPI_SA_FLAGS (... | ARCH_UAPI_SA_FLAGS)
> 
> I'll do that in v10.

Yes, something like that would be fine, I should think.

> > Also, I wonder whether we should avoid the "SA_" prefix here.  Maybe
> > UAPI_SA_FLAGS?
> 
> Sounds good to me.

OK, great.

[...]

> > > diff --git a/kernel/signal.c b/kernel/signal.c
> > > index 42b67d2cea37..348b7981f1ff 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 &= SA_UAPI_FLAGS;
> > > +     if (oact)
> > > +             oact->sa.sa_flags &= SA_UAPI_FLAGS;
> > > +
> >
> > Seems reasonable.
> 
> Thanks. I also decided to check how other operating systems handle
> unknown flag bits in sigaction.sa_flags. It looks like OpenBSD and
> illumos also accept unknown bits but (implicitly, as a result of using
> a different internal representation) end up clearing them in oldact:
> 
> https://github.com/openbsd/src/blob/f634a6a4b5bf832e9c1de77f7894ae2625e74484/sys/kern/kern_sig.c#L278
> https://github.com/illumos/illumos-gate/blob/76f19f5fdc974fe5be5c82a556e43a4df93f1de1/usr/src/uts/common/syscall/sigaction.c#L86
> 
> and FreeBSD and NetBSD fail the syscall if unknown bits are set:
> 
> https://github.com/freebsd/freebsd/blob/eded70c37057857c6e23fae51f86b8f8f43cd2d0/sys/kern/kern_sig.c#L699
> https://github.com/NetBSD/src/blob/3365779becdcedfca206091a645a0e8e22b2946e/sys/kern/sys_sig.c#L473
> 
> So there is some precedent for doing what we're planning to do here,
> which makes it yet more likely that we'll be okay doing this.

Ack, it's good to have that extra evidence to support this approach.

This also means that other OSes could adopt the new Linux flag(s) with
comatible semantics, if they wanted to.  Or have I misunderstood
something there?

Cheers
---Dave

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

* Re: [PATCH v9 3/6] signal: clear non-uapi flag bits when passing/returning sa_flags
@ 2020-08-24 13:40         ` Dave Martin
  0 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-24 13:40 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, Aug 19, 2020 at 04:39:53PM -0700, Peter Collingbourne wrote:
> On Wed, Aug 19, 2020 at 3:39 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Mon, Aug 17, 2020 at 08:33:48PM -0700, Peter Collingbourne wrote:
> >
> > Nit: please say what the patch does.  Subject line should summarise
> > what is done, but should not add new information that is not present in
> > the description proper.
> >
> > (Same for all the other patches.)
> 
> Will do.

Thanks

[...]

> > > diff --git a/arch/arm/include/asm/signal.h b/arch/arm/include/asm/signal.h
> > > index 65530a042009..d1070a783993 100644
> > > --- a/arch/arm/include/asm/signal.h
> > > +++ b/arch/arm/include/asm/signal.h
> > > @@ -17,6 +17,10 @@ typedef struct {
> > >       unsigned long sig[_NSIG_WORDS];
> > >  } sigset_t;
> > >
> > > +#define SA_UAPI_FLAGS                                                          \
> > > +     (SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_THIRTYTWO |             \
> > > +      SA_RESTORER | SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_RESETHAND)
> > > +
> >
> > I wonder whether all these per-arch definitions will tend to bitrot when
> > people add new common flags.
> >
> > Can we have a common definition for the common bits, and just add the
> > extra arch-specific ones here?
> 
> I think so. We could have something like:
> 
> #define ARCH_UAPI_SA_FLAGS SA_THIRTYTWO
> 
> here. Then in signal_types.h we can do:
> 
> #ifndef ARCH_UAPI_SA_FLAGS
> #define ARCH_UAPI_SA_FLAGS 0
> #endif
> 
> #define UAPI_SA_FLAGS (... | ARCH_UAPI_SA_FLAGS)
> 
> I'll do that in v10.

Yes, something like that would be fine, I should think.

> > Also, I wonder whether we should avoid the "SA_" prefix here.  Maybe
> > UAPI_SA_FLAGS?
> 
> Sounds good to me.

OK, great.

[...]

> > > diff --git a/kernel/signal.c b/kernel/signal.c
> > > index 42b67d2cea37..348b7981f1ff 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 &= SA_UAPI_FLAGS;
> > > +     if (oact)
> > > +             oact->sa.sa_flags &= SA_UAPI_FLAGS;
> > > +
> >
> > Seems reasonable.
> 
> Thanks. I also decided to check how other operating systems handle
> unknown flag bits in sigaction.sa_flags. It looks like OpenBSD and
> illumos also accept unknown bits but (implicitly, as a result of using
> a different internal representation) end up clearing them in oldact:
> 
> https://github.com/openbsd/src/blob/f634a6a4b5bf832e9c1de77f7894ae2625e74484/sys/kern/kern_sig.c#L278
> https://github.com/illumos/illumos-gate/blob/76f19f5fdc974fe5be5c82a556e43a4df93f1de1/usr/src/uts/common/syscall/sigaction.c#L86
> 
> and FreeBSD and NetBSD fail the syscall if unknown bits are set:
> 
> https://github.com/freebsd/freebsd/blob/eded70c37057857c6e23fae51f86b8f8f43cd2d0/sys/kern/kern_sig.c#L699
> https://github.com/NetBSD/src/blob/3365779becdcedfca206091a645a0e8e22b2946e/sys/kern/sys_sig.c#L473
> 
> So there is some precedent for doing what we're planning to do here,
> which makes it yet more likely that we'll be okay doing this.

Ack, it's good to have that extra evidence to support this approach.

This also means that other OSes could adopt the new Linux flag(s) with
comatible semantics, if they wanted to.  Or have I misunderstood
something there?

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] 66+ messages in thread

* Re: [PATCH v9 4/6] signal: define the SA_UNSUPPORTED bit in sa_flags
  2020-08-20  0:23       ` Peter Collingbourne
@ 2020-08-24 13:41         ` Dave Martin
  -1 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-24 13:41 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, Aug 19, 2020 at 05:23:25PM -0700, Peter Collingbourne wrote:
> On Wed, Aug 19, 2020 at 7:51 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Mon, Aug 17, 2020 at 08:33:49PM -0700, Peter Collingbourne wrote:
> > > 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 91000b6b97e0..c30a9c1a77b2 100644
> > > --- a/include/uapi/asm-generic/signal-defs.h
> > > +++ b/include/uapi/asm-generic/signal-defs.h
> > > @@ -13,6 +13,12 @@
> > >   * 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_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 @@
> > >   * 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.
> > >   */
> > > +#define SA_UNSUPPORTED       0x00000400
> >
> > This concept confused me a bit initially, since in a sense this flag is
> > supported, just with a rather peculiar meaning.
> 
> Hmm. Maybe it should be named "SA_UNKNOWN" to mean that the bit will
> always be "unknown" to the kernel in the sense that it shall be
> treated in the same way as any other "unknown" bit. Then we can define
> the kernel's behavior in terms of what happens if a bit is "known". I
> don't know if this is just shuffling terms around though. At any rate,
> this seems like a problem to be solved with documentation.
> 
> > Since the main (only) purpose of this bit will be to check whether
> 
> I wouldn't necessarily say that it is the only purpose. If another new
> sa_flags bit were to be introduced in the future, SA_UN(whatever)
> could be used to detect kernel support for that bit in the same way as
> SA_XFLAGS.
> 
> > SA_XFLAGS is actually supported, I wonder whether it makes sense to weld
> > the two together, say:
> >
> > #define SA_REQUEST_XFLAGS       0x00000c00
> > #define SA_XFLAGS_MASK          0x00000c00
> > #define SA_HAVE_XFLAGS          0x00000800
> >
> > This is a departure from the current style of definitions though.
> >
> >         sa.sa_flags |= SA_REQUEST_XFLAGS;
> >         sigaction(..., &sa, &sa);
> >         if ((sa.sa_flags & SA_XFLAGS_MASK) == SA_HAVE_XFLAGS)
> >                 /* xflags available */
> >
> >
> > This would require some juggling of the way SA_UAPI_FLAGS works though.
> > Maybe not worth it, so long as the semantics get clearly documented.
> 
> I'm not sure about this. I personally think that it would be clearer
> to keep the flags orthogonal.

Fair enough.  I didn't think my approach was a whole lot better tbh.

Cheers
---Dave

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

* Re: [PATCH v9 4/6] signal: define the SA_UNSUPPORTED bit in sa_flags
@ 2020-08-24 13:41         ` Dave Martin
  0 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-24 13:41 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, Aug 19, 2020 at 05:23:25PM -0700, Peter Collingbourne wrote:
> On Wed, Aug 19, 2020 at 7:51 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Mon, Aug 17, 2020 at 08:33:49PM -0700, Peter Collingbourne wrote:
> > > 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 91000b6b97e0..c30a9c1a77b2 100644
> > > --- a/include/uapi/asm-generic/signal-defs.h
> > > +++ b/include/uapi/asm-generic/signal-defs.h
> > > @@ -13,6 +13,12 @@
> > >   * 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_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 @@
> > >   * 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.
> > >   */
> > > +#define SA_UNSUPPORTED       0x00000400
> >
> > This concept confused me a bit initially, since in a sense this flag is
> > supported, just with a rather peculiar meaning.
> 
> Hmm. Maybe it should be named "SA_UNKNOWN" to mean that the bit will
> always be "unknown" to the kernel in the sense that it shall be
> treated in the same way as any other "unknown" bit. Then we can define
> the kernel's behavior in terms of what happens if a bit is "known". I
> don't know if this is just shuffling terms around though. At any rate,
> this seems like a problem to be solved with documentation.
> 
> > Since the main (only) purpose of this bit will be to check whether
> 
> I wouldn't necessarily say that it is the only purpose. If another new
> sa_flags bit were to be introduced in the future, SA_UN(whatever)
> could be used to detect kernel support for that bit in the same way as
> SA_XFLAGS.
> 
> > SA_XFLAGS is actually supported, I wonder whether it makes sense to weld
> > the two together, say:
> >
> > #define SA_REQUEST_XFLAGS       0x00000c00
> > #define SA_XFLAGS_MASK          0x00000c00
> > #define SA_HAVE_XFLAGS          0x00000800
> >
> > This is a departure from the current style of definitions though.
> >
> >         sa.sa_flags |= SA_REQUEST_XFLAGS;
> >         sigaction(..., &sa, &sa);
> >         if ((sa.sa_flags & SA_XFLAGS_MASK) == SA_HAVE_XFLAGS)
> >                 /* xflags available */
> >
> >
> > This would require some juggling of the way SA_UAPI_FLAGS works though.
> > Maybe not worth it, so long as the semantics get clearly documented.
> 
> I'm not sure about this. I personally think that it would be clearer
> to keep the flags orthogonal.

Fair enough.  I didn't think my approach was a whole lot better tbh.

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] 66+ messages in thread

* Re: [PATCH v9 5/6] signal: define the field siginfo.si_xflags
  2020-08-20  1:37       ` Peter Collingbourne
@ 2020-08-24 14:03         ` Dave Martin
  -1 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-24 14:03 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, Aug 19, 2020 at 06:37:25PM -0700, Peter Collingbourne wrote:
> On Wed, Aug 19, 2020 at 8:40 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Mon, Aug 17, 2020 at 08:33:50PM -0700, Peter Collingbourne wrote:
> > > 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.
> > >
> > > 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.
> >
> > For clarity, is the new si_xflags field supposed to be valid for all
> > signal types, or just certain signals and si_codes?
> 
> It is intended to be valid for all signal types that use the _sigfault
> union member of siginfo. As listed in siginfo.h these are: SIGILL,
> SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT.

SIGSYS is similar to SIGILL, is that included also?

> > What happens for things like a rt_sigqueueinfo() from userspace?
> 
> Hmm. Let's enumerate each of these things, which I believe are all of
> the call sites of the function copy_siginfo_from_user and related
> functions (correct me if I'm wrong):
> 
> - ptrace(PTRACE_SETSIGINFO)
> - pidfd_send_signal
> - rt_sigqueueinfo
> - rt_tgsigqueueinfo
> 
> We can handle the last three by observing that the kernel forbids
> sending a signal with these syscalls if si_code >= 0, so we can say
> that the value of si_xflags is only valid if si_code >= 0.

Hmmm, that's what the code says (actually >= 0 or SI_TKILL), but it's
illogical.  Those are user signals, so there's no obvious reason why
userspace shouldn't be allowed to generate their siginfo.  It would
probably be better for the kernel to police si_pid etc. in the SI_USER
and SI_TKILL cases rather than flatly refusing, but I guess that's a
discussion for another day.

I guess the combination of SI_FROMKERNEL() and the signal number being a
known fault signal if probably sufficient for now.


It might be helpful to have a helper to identify fault signals, but we
don't have this today, and it's unlikely that a new kind of fault signal
will crop up any time soon.

Handlers that handle specific signal types won't care, but debuggers and
generic backtracer code would have to be hand-hacked to add new kinds of
fault signal today -- not a huge priority though, and orthogonal to this
series.

> As for the first one, it's more tricky. Arguably something like a
> debugger should be able to send arbitrary signals to a debuggee, and
> there's no reason why it shouldn't be able to set si_xflags in
> siginfo, but on the other hand who knows how existing debuggers end up
> setting this field today. Maybe all that we can do is have the kernel
> clear si_xflags if it detects that the signal uses _sigfault, and let
> si_xflags aware debuggers opt out of this behavior, perhaps by
> introducing a PTRACE_SETSIGINFO2 or something.

Most likely a debugger usually amends an existing siginfo from a trapped
signal than generating a new one from scratch.

Given the other things that ptrace can do to the target process I don't
think we need to police here, but your suggestion about a
PTRACE_SETSIGINFO2 or similar, and zeroing this field by default with
PTRACE_SETSIGINFO, does make sense.

[...]

> > > diff --git a/kernel/signal.c b/kernel/signal.c
> > > index 664a6c31137e..72182eed1b8d 100644
> > > --- a/kernel/signal.c
> > > +++ b/kernel/signal.c

[...]

> > > @@ -3377,6 +3389,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> > >               to->si_trapno = from->si_trapno;
> > >  #endif
> > >               to->si_addr_lsb = from->si_addr_lsb;
> > > +             to->si_xflags = from->si_xflags;
> > >               break;
> > >       case SIL_FAULT_BNDERR:
> > >               to->si_addr = compat_ptr(from->si_addr);
> > > @@ -3385,6 +3398,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> > >  #endif
> > >               to->si_lower = compat_ptr(from->si_lower);
> > >               to->si_upper = compat_ptr(from->si_upper);
> > > +             to->si_xflags = from->si_xflags;
> > >               break;
> > >       case SIL_FAULT_PKUERR:
> > >               to->si_addr = compat_ptr(from->si_addr);
> > > @@ -3392,6 +3406,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> > >               to->si_trapno = from->si_trapno;
> > >  #endif
> > >               to->si_pkey = from->si_pkey;
> > > +             to->si_xflags = from->si_xflags;
> >
> > How did you figure out the list of places to make these changes?  I'm
> > not sure how to confirm that it's exhaustive.
> 
> I looked for all places in the kernel where the si_addr field was
> being assigned to (basically: git grep '\bsi_addr\s*=') and added my
> code there.
> 
> > It's a shame if we can't simply apply the change in one place.
> > Would the refactoring be too invasive to accomplish that?
> 
> I believe that Eric mentioned that kernel/signal.c is supposed to be
> "the" file that knows about all of the fields of siginfo (I'm not sure
> what's going on in arch/powerpc, I think that's a recent regression).
> Maybe it's possible to eliminate the duplication between the various
> SIL_FAULT* cases, but aside from that it looks like there wouldn't be
> much duplication in the rest of the code.

If it's all contained in signal.c I guess it's not quite so bad,
especially if powerpc can be brought back into the fold.

Cheers
---Dave

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

* Re: [PATCH v9 5/6] signal: define the field siginfo.si_xflags
@ 2020-08-24 14:03         ` Dave Martin
  0 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-24 14:03 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, Aug 19, 2020 at 06:37:25PM -0700, Peter Collingbourne wrote:
> On Wed, Aug 19, 2020 at 8:40 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Mon, Aug 17, 2020 at 08:33:50PM -0700, Peter Collingbourne wrote:
> > > 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.
> > >
> > > 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.
> >
> > For clarity, is the new si_xflags field supposed to be valid for all
> > signal types, or just certain signals and si_codes?
> 
> It is intended to be valid for all signal types that use the _sigfault
> union member of siginfo. As listed in siginfo.h these are: SIGILL,
> SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT.

SIGSYS is similar to SIGILL, is that included also?

> > What happens for things like a rt_sigqueueinfo() from userspace?
> 
> Hmm. Let's enumerate each of these things, which I believe are all of
> the call sites of the function copy_siginfo_from_user and related
> functions (correct me if I'm wrong):
> 
> - ptrace(PTRACE_SETSIGINFO)
> - pidfd_send_signal
> - rt_sigqueueinfo
> - rt_tgsigqueueinfo
> 
> We can handle the last three by observing that the kernel forbids
> sending a signal with these syscalls if si_code >= 0, so we can say
> that the value of si_xflags is only valid if si_code >= 0.

Hmmm, that's what the code says (actually >= 0 or SI_TKILL), but it's
illogical.  Those are user signals, so there's no obvious reason why
userspace shouldn't be allowed to generate their siginfo.  It would
probably be better for the kernel to police si_pid etc. in the SI_USER
and SI_TKILL cases rather than flatly refusing, but I guess that's a
discussion for another day.

I guess the combination of SI_FROMKERNEL() and the signal number being a
known fault signal if probably sufficient for now.


It might be helpful to have a helper to identify fault signals, but we
don't have this today, and it's unlikely that a new kind of fault signal
will crop up any time soon.

Handlers that handle specific signal types won't care, but debuggers and
generic backtracer code would have to be hand-hacked to add new kinds of
fault signal today -- not a huge priority though, and orthogonal to this
series.

> As for the first one, it's more tricky. Arguably something like a
> debugger should be able to send arbitrary signals to a debuggee, and
> there's no reason why it shouldn't be able to set si_xflags in
> siginfo, but on the other hand who knows how existing debuggers end up
> setting this field today. Maybe all that we can do is have the kernel
> clear si_xflags if it detects that the signal uses _sigfault, and let
> si_xflags aware debuggers opt out of this behavior, perhaps by
> introducing a PTRACE_SETSIGINFO2 or something.

Most likely a debugger usually amends an existing siginfo from a trapped
signal than generating a new one from scratch.

Given the other things that ptrace can do to the target process I don't
think we need to police here, but your suggestion about a
PTRACE_SETSIGINFO2 or similar, and zeroing this field by default with
PTRACE_SETSIGINFO, does make sense.

[...]

> > > diff --git a/kernel/signal.c b/kernel/signal.c
> > > index 664a6c31137e..72182eed1b8d 100644
> > > --- a/kernel/signal.c
> > > +++ b/kernel/signal.c

[...]

> > > @@ -3377,6 +3389,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> > >               to->si_trapno = from->si_trapno;
> > >  #endif
> > >               to->si_addr_lsb = from->si_addr_lsb;
> > > +             to->si_xflags = from->si_xflags;
> > >               break;
> > >       case SIL_FAULT_BNDERR:
> > >               to->si_addr = compat_ptr(from->si_addr);
> > > @@ -3385,6 +3398,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> > >  #endif
> > >               to->si_lower = compat_ptr(from->si_lower);
> > >               to->si_upper = compat_ptr(from->si_upper);
> > > +             to->si_xflags = from->si_xflags;
> > >               break;
> > >       case SIL_FAULT_PKUERR:
> > >               to->si_addr = compat_ptr(from->si_addr);
> > > @@ -3392,6 +3406,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> > >               to->si_trapno = from->si_trapno;
> > >  #endif
> > >               to->si_pkey = from->si_pkey;
> > > +             to->si_xflags = from->si_xflags;
> >
> > How did you figure out the list of places to make these changes?  I'm
> > not sure how to confirm that it's exhaustive.
> 
> I looked for all places in the kernel where the si_addr field was
> being assigned to (basically: git grep '\bsi_addr\s*=') and added my
> code there.
> 
> > It's a shame if we can't simply apply the change in one place.
> > Would the refactoring be too invasive to accomplish that?
> 
> I believe that Eric mentioned that kernel/signal.c is supposed to be
> "the" file that knows about all of the fields of siginfo (I'm not sure
> what's going on in arch/powerpc, I think that's a recent regression).
> Maybe it's possible to eliminate the duplication between the various
> SIL_FAULT* cases, but aside from that it looks like there wouldn't be
> much duplication in the rest of the code.

If it's all contained in signal.c I guess it's not quite so bad,
especially if powerpc can be brought back into the fold.

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] 66+ messages in thread

* Re: [PATCH v9 6/6] arm64: expose FAR_EL1 tag bits in siginfo
  2020-08-20  1:49       ` Peter Collingbourne
@ 2020-08-24 14:23         ` Dave Martin
  -1 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-24 14:23 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, Aug 19, 2020 at 06:49:01PM -0700, Peter Collingbourne wrote:
> On Wed, Aug 19, 2020 at 8:56 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Mon, Aug 17, 2020 at 08:33:51PM -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>
> > > ---

[...]

> > > diff --git a/kernel/signal.c b/kernel/signal.c
> > > index 72182eed1b8d..1f1e42adc57d 100644
> > > --- a/kernel/signal.c
> > > +++ b/kernel/signal.c

[...]

> > > @@ -1706,7 +1722,9 @@ int send_sig_fault(int sig, int code, void __user *addr
> > >       return send_sig_info(info.si_signo, &info, t);
> > >  }
> > >
> > > -int force_sig_mceerr(int code, void __user *addr, short lsb)
> > > +int force_sig_mceerr(int code, void __user *addr, short lsb,
> > > +                  unsigned long addr_ignored_bits,
> > > +                  unsigned long addr_ignored_bits_mask)
> >
> > Rather than having to pass these extra arguments all over the place, can
> > we just pass the far for addr, and have an arch-specific hook for
> > splitting the ignored from non-ignored bits.  For now at least, I expect
> > that ignored bits mask to be constant for a given platform and kernel.
> 
> That sounds like a good idea. I think that for MTE we will want to
> make it conditional on the si_code (so SEGV_MTESERR would get 0xf <<
> 56 while everything else would get 0xff << 56) so I can hook that up
> at the same time.

OK, I think that's reasonable.

Mind you, we seem to have 3 kinds of bits here, so I'm starting to
wonder whether this is really sufficient:

	1) address bits used in the faulted access
	2) attribute/permission bits used in the faulted access
	3) unavailable bits.

si_addr contains (1).

si_addr_ignored_bits contains (2).

The tag bits from non-MTE faults seem to fall under case (3).  Code that
looks for these bits in si_addr_ignored_bits won't find them.


So perhaps it would make sense to amend the design a bit.  We'd have

	si_addr = address bits only
	si_attr = attribute bits only
	si_attr_mask = mask of valid bits in si_addr

Thinking about it, I've just shortened/changed some named and changed
the meaning of the mask, so it's very similar to what you already have.

The mask of valid bits in si_addr is decided by architectural
convention (i.e., ~0xffUL << 56), but we could also expose

	si_addr_mask = mask of valid bits in si_addr

This is a bit redundant though.  I think people would already assume
that all bits required for classifying the faulting location accurately
must already be provided there.

> 
> > >  {
> > >       struct kernel_siginfo info;
> > >
> > > @@ -1717,7 +1735,9 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
> > >       info.si_code = code;
> > >       info.si_addr = addr;
> > >       info.si_addr_lsb = lsb;
> > > -     info.si_xflags = 0;
> > > +     info.si_xflags = SI_XFLAG_IGNORED_BITS;
> >
> > Maybe drop the first _, so that this becomes
> >
> >         SIXFLAG_IGNORED_BITS
> >
> > ?  This may help to avoid anyone thinking this might be an si_code
> > value.  Maybe ..._IGNORED_ADDR_BITS would also help make it clearer what
> > this bit is referring to.
> 
> Yes, it should have been spelled the same way as the field name (i.e.
> SIXFLAG_ADDR_IGNORED_BITS), that was my mistake. I don't have a strong
> opinion on whether to keep the underscore in the middle or not.

Fair enough (modulo possible changes above).

[...]

> > >       case SIL_FAULT_BNDERR:
> > >               to->si_addr = compat_ptr(from->si_addr);
> > > @@ -3399,6 +3431,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> > >               to->si_lower = compat_ptr(from->si_lower);
> > >               to->si_upper = compat_ptr(from->si_upper);
> > >               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;
> > >               break;
> > >       case SIL_FAULT_PKUERR:
> > >               to->si_addr = compat_ptr(from->si_addr);
> > > @@ -3407,6 +3441,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> > >  #endif
> > >               to->si_pkey = from->si_pkey;
> > >               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;
> >
> > Again, can you justify why this is exhaustive?  If there any way to
> > factor this so as to reduce the number of places we need to hack this
> > in?
> 
> Addressed on the other patch. Once I've factored the various
> SIL_FAULT* cases there should be only a handful of places requiring
> changes.

And that looked like a reasonable justification.

Cheers
---Dave

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

* Re: [PATCH v9 6/6] arm64: expose FAR_EL1 tag bits in siginfo
@ 2020-08-24 14:23         ` Dave Martin
  0 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-24 14:23 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, Aug 19, 2020 at 06:49:01PM -0700, Peter Collingbourne wrote:
> On Wed, Aug 19, 2020 at 8:56 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Mon, Aug 17, 2020 at 08:33:51PM -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>
> > > ---

[...]

> > > diff --git a/kernel/signal.c b/kernel/signal.c
> > > index 72182eed1b8d..1f1e42adc57d 100644
> > > --- a/kernel/signal.c
> > > +++ b/kernel/signal.c

[...]

> > > @@ -1706,7 +1722,9 @@ int send_sig_fault(int sig, int code, void __user *addr
> > >       return send_sig_info(info.si_signo, &info, t);
> > >  }
> > >
> > > -int force_sig_mceerr(int code, void __user *addr, short lsb)
> > > +int force_sig_mceerr(int code, void __user *addr, short lsb,
> > > +                  unsigned long addr_ignored_bits,
> > > +                  unsigned long addr_ignored_bits_mask)
> >
> > Rather than having to pass these extra arguments all over the place, can
> > we just pass the far for addr, and have an arch-specific hook for
> > splitting the ignored from non-ignored bits.  For now at least, I expect
> > that ignored bits mask to be constant for a given platform and kernel.
> 
> That sounds like a good idea. I think that for MTE we will want to
> make it conditional on the si_code (so SEGV_MTESERR would get 0xf <<
> 56 while everything else would get 0xff << 56) so I can hook that up
> at the same time.

OK, I think that's reasonable.

Mind you, we seem to have 3 kinds of bits here, so I'm starting to
wonder whether this is really sufficient:

	1) address bits used in the faulted access
	2) attribute/permission bits used in the faulted access
	3) unavailable bits.

si_addr contains (1).

si_addr_ignored_bits contains (2).

The tag bits from non-MTE faults seem to fall under case (3).  Code that
looks for these bits in si_addr_ignored_bits won't find them.


So perhaps it would make sense to amend the design a bit.  We'd have

	si_addr = address bits only
	si_attr = attribute bits only
	si_attr_mask = mask of valid bits in si_addr

Thinking about it, I've just shortened/changed some named and changed
the meaning of the mask, so it's very similar to what you already have.

The mask of valid bits in si_addr is decided by architectural
convention (i.e., ~0xffUL << 56), but we could also expose

	si_addr_mask = mask of valid bits in si_addr

This is a bit redundant though.  I think people would already assume
that all bits required for classifying the faulting location accurately
must already be provided there.

> 
> > >  {
> > >       struct kernel_siginfo info;
> > >
> > > @@ -1717,7 +1735,9 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
> > >       info.si_code = code;
> > >       info.si_addr = addr;
> > >       info.si_addr_lsb = lsb;
> > > -     info.si_xflags = 0;
> > > +     info.si_xflags = SI_XFLAG_IGNORED_BITS;
> >
> > Maybe drop the first _, so that this becomes
> >
> >         SIXFLAG_IGNORED_BITS
> >
> > ?  This may help to avoid anyone thinking this might be an si_code
> > value.  Maybe ..._IGNORED_ADDR_BITS would also help make it clearer what
> > this bit is referring to.
> 
> Yes, it should have been spelled the same way as the field name (i.e.
> SIXFLAG_ADDR_IGNORED_BITS), that was my mistake. I don't have a strong
> opinion on whether to keep the underscore in the middle or not.

Fair enough (modulo possible changes above).

[...]

> > >       case SIL_FAULT_BNDERR:
> > >               to->si_addr = compat_ptr(from->si_addr);
> > > @@ -3399,6 +3431,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> > >               to->si_lower = compat_ptr(from->si_lower);
> > >               to->si_upper = compat_ptr(from->si_upper);
> > >               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;
> > >               break;
> > >       case SIL_FAULT_PKUERR:
> > >               to->si_addr = compat_ptr(from->si_addr);
> > > @@ -3407,6 +3441,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> > >  #endif
> > >               to->si_pkey = from->si_pkey;
> > >               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;
> >
> > Again, can you justify why this is exhaustive?  If there any way to
> > factor this so as to reduce the number of places we need to hack this
> > in?
> 
> Addressed on the other patch. Once I've factored the various
> SIL_FAULT* cases there should be only a handful of places requiring
> changes.

And that looked like a reasonable justification.

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] 66+ messages in thread

* Re: [PATCH v9 3/6] signal: clear non-uapi flag bits when passing/returning sa_flags
  2020-08-24 13:40         ` Dave Martin
@ 2020-08-25  0:51           ` Peter Collingbourne
  -1 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-25  0:51 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 Mon, Aug 24, 2020 at 6:40 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Wed, Aug 19, 2020 at 04:39:53PM -0700, Peter Collingbourne wrote:
> > On Wed, Aug 19, 2020 at 3:39 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > >
> > > On Mon, Aug 17, 2020 at 08:33:48PM -0700, Peter Collingbourne wrote:
> > >
> > > Nit: please say what the patch does.  Subject line should summarise
> > > what is done, but should not add new information that is not present in
> > > the description proper.
> > >
> > > (Same for all the other patches.)
> >
> > Will do.
>
> Thanks
>
> [...]
>
> > > > diff --git a/arch/arm/include/asm/signal.h b/arch/arm/include/asm/signal.h
> > > > index 65530a042009..d1070a783993 100644
> > > > --- a/arch/arm/include/asm/signal.h
> > > > +++ b/arch/arm/include/asm/signal.h
> > > > @@ -17,6 +17,10 @@ typedef struct {
> > > >       unsigned long sig[_NSIG_WORDS];
> > > >  } sigset_t;
> > > >
> > > > +#define SA_UAPI_FLAGS                                                          \
> > > > +     (SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_THIRTYTWO |             \
> > > > +      SA_RESTORER | SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_RESETHAND)
> > > > +
> > >
> > > I wonder whether all these per-arch definitions will tend to bitrot when
> > > people add new common flags.
> > >
> > > Can we have a common definition for the common bits, and just add the
> > > extra arch-specific ones here?
> >
> > I think so. We could have something like:
> >
> > #define ARCH_UAPI_SA_FLAGS SA_THIRTYTWO
> >
> > here. Then in signal_types.h we can do:
> >
> > #ifndef ARCH_UAPI_SA_FLAGS
> > #define ARCH_UAPI_SA_FLAGS 0
> > #endif
> >
> > #define UAPI_SA_FLAGS (... | ARCH_UAPI_SA_FLAGS)
> >
> > I'll do that in v10.
>
> Yes, something like that would be fine, I should think.
>
> > > Also, I wonder whether we should avoid the "SA_" prefix here.  Maybe
> > > UAPI_SA_FLAGS?
> >
> > Sounds good to me.
>
> OK, great.
>
> [...]
>
> > > > diff --git a/kernel/signal.c b/kernel/signal.c
> > > > index 42b67d2cea37..348b7981f1ff 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 &= SA_UAPI_FLAGS;
> > > > +     if (oact)
> > > > +             oact->sa.sa_flags &= SA_UAPI_FLAGS;
> > > > +
> > >
> > > Seems reasonable.
> >
> > Thanks. I also decided to check how other operating systems handle
> > unknown flag bits in sigaction.sa_flags. It looks like OpenBSD and
> > illumos also accept unknown bits but (implicitly, as a result of using
> > a different internal representation) end up clearing them in oldact:
> >
> > https://github.com/openbsd/src/blob/f634a6a4b5bf832e9c1de77f7894ae2625e74484/sys/kern/kern_sig.c#L278
> > https://github.com/illumos/illumos-gate/blob/76f19f5fdc974fe5be5c82a556e43a4df93f1de1/usr/src/uts/common/syscall/sigaction.c#L86

XNU does the same:

https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/kern/kern_sig.c#L480

> >
> > and FreeBSD and NetBSD fail the syscall if unknown bits are set:
> >
> > https://github.com/freebsd/freebsd/blob/eded70c37057857c6e23fae51f86b8f8f43cd2d0/sys/kern/kern_sig.c#L699
> > https://github.com/NetBSD/src/blob/3365779becdcedfca206091a645a0e8e22b2946e/sys/kern/sys_sig.c#L473
> >
> > So there is some precedent for doing what we're planning to do here,
> > which makes it yet more likely that we'll be okay doing this.
>
> Ack, it's good to have that extra evidence to support this approach.
>
> This also means that other OSes could adopt the new Linux flag(s) with
> comatible semantics, if they wanted to.  Or have I misunderstood
> something there?

The other OSs could adopt SA_XFLAGS, but they would probably have no
need for SA_UNSUPPORTED because they already have a protocol for
detecting missing flag support in the kernel (Linux is really the odd
one out here in not supporting such a protocol from the start).
Userspace programs running on OpenBSD, illumos and XNU could use the
Linux protocol without the SA_UNSUPPORTED part, while programs running
on FreeBSD and NetBSD could do something like:

static bool has_xflags = true;
[...]
struct sigaction act;
act.sa_flags = SA_SIGINFO | SA_XFLAGS;
if (sigaction(SIGSEGV, &act, 0) != 0) {
  has_xflags = false;
  act.sa_flags = SA_SIGINFO;
  if (sigaction(SIGSEGV, &act, 0) != 0)
    perror("sigaction");
}

It would probably be possible to write a unified function that would
support all three protocols.

Peter

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

* Re: [PATCH v9 3/6] signal: clear non-uapi flag bits when passing/returning sa_flags
@ 2020-08-25  0:51           ` Peter Collingbourne
  0 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-25  0:51 UTC (permalink / raw)
  To: Dave Martin
  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, Aug 24, 2020 at 6:40 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Wed, Aug 19, 2020 at 04:39:53PM -0700, Peter Collingbourne wrote:
> > On Wed, Aug 19, 2020 at 3:39 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > >
> > > On Mon, Aug 17, 2020 at 08:33:48PM -0700, Peter Collingbourne wrote:
> > >
> > > Nit: please say what the patch does.  Subject line should summarise
> > > what is done, but should not add new information that is not present in
> > > the description proper.
> > >
> > > (Same for all the other patches.)
> >
> > Will do.
>
> Thanks
>
> [...]
>
> > > > diff --git a/arch/arm/include/asm/signal.h b/arch/arm/include/asm/signal.h
> > > > index 65530a042009..d1070a783993 100644
> > > > --- a/arch/arm/include/asm/signal.h
> > > > +++ b/arch/arm/include/asm/signal.h
> > > > @@ -17,6 +17,10 @@ typedef struct {
> > > >       unsigned long sig[_NSIG_WORDS];
> > > >  } sigset_t;
> > > >
> > > > +#define SA_UAPI_FLAGS                                                          \
> > > > +     (SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_THIRTYTWO |             \
> > > > +      SA_RESTORER | SA_ONSTACK | SA_RESTART | SA_NODEFER | SA_RESETHAND)
> > > > +
> > >
> > > I wonder whether all these per-arch definitions will tend to bitrot when
> > > people add new common flags.
> > >
> > > Can we have a common definition for the common bits, and just add the
> > > extra arch-specific ones here?
> >
> > I think so. We could have something like:
> >
> > #define ARCH_UAPI_SA_FLAGS SA_THIRTYTWO
> >
> > here. Then in signal_types.h we can do:
> >
> > #ifndef ARCH_UAPI_SA_FLAGS
> > #define ARCH_UAPI_SA_FLAGS 0
> > #endif
> >
> > #define UAPI_SA_FLAGS (... | ARCH_UAPI_SA_FLAGS)
> >
> > I'll do that in v10.
>
> Yes, something like that would be fine, I should think.
>
> > > Also, I wonder whether we should avoid the "SA_" prefix here.  Maybe
> > > UAPI_SA_FLAGS?
> >
> > Sounds good to me.
>
> OK, great.
>
> [...]
>
> > > > diff --git a/kernel/signal.c b/kernel/signal.c
> > > > index 42b67d2cea37..348b7981f1ff 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 &= SA_UAPI_FLAGS;
> > > > +     if (oact)
> > > > +             oact->sa.sa_flags &= SA_UAPI_FLAGS;
> > > > +
> > >
> > > Seems reasonable.
> >
> > Thanks. I also decided to check how other operating systems handle
> > unknown flag bits in sigaction.sa_flags. It looks like OpenBSD and
> > illumos also accept unknown bits but (implicitly, as a result of using
> > a different internal representation) end up clearing them in oldact:
> >
> > https://github.com/openbsd/src/blob/f634a6a4b5bf832e9c1de77f7894ae2625e74484/sys/kern/kern_sig.c#L278
> > https://github.com/illumos/illumos-gate/blob/76f19f5fdc974fe5be5c82a556e43a4df93f1de1/usr/src/uts/common/syscall/sigaction.c#L86

XNU does the same:

https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/kern/kern_sig.c#L480

> >
> > and FreeBSD and NetBSD fail the syscall if unknown bits are set:
> >
> > https://github.com/freebsd/freebsd/blob/eded70c37057857c6e23fae51f86b8f8f43cd2d0/sys/kern/kern_sig.c#L699
> > https://github.com/NetBSD/src/blob/3365779becdcedfca206091a645a0e8e22b2946e/sys/kern/sys_sig.c#L473
> >
> > So there is some precedent for doing what we're planning to do here,
> > which makes it yet more likely that we'll be okay doing this.
>
> Ack, it's good to have that extra evidence to support this approach.
>
> This also means that other OSes could adopt the new Linux flag(s) with
> comatible semantics, if they wanted to.  Or have I misunderstood
> something there?

The other OSs could adopt SA_XFLAGS, but they would probably have no
need for SA_UNSUPPORTED because they already have a protocol for
detecting missing flag support in the kernel (Linux is really the odd
one out here in not supporting such a protocol from the start).
Userspace programs running on OpenBSD, illumos and XNU could use the
Linux protocol without the SA_UNSUPPORTED part, while programs running
on FreeBSD and NetBSD could do something like:

static bool has_xflags = true;
[...]
struct sigaction act;
act.sa_flags = SA_SIGINFO | SA_XFLAGS;
if (sigaction(SIGSEGV, &act, 0) != 0) {
  has_xflags = false;
  act.sa_flags = SA_SIGINFO;
  if (sigaction(SIGSEGV, &act, 0) != 0)
    perror("sigaction");
}

It would probably be possible to write a unified function that would
support all three protocols.

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] 66+ messages in thread

* Re: [PATCH v9 5/6] signal: define the field siginfo.si_xflags
  2020-08-24 14:03         ` Dave Martin
@ 2020-08-25  1:27           ` Peter Collingbourne
  -1 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-25  1:27 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 Mon, Aug 24, 2020 at 7:03 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Wed, Aug 19, 2020 at 06:37:25PM -0700, Peter Collingbourne wrote:
> > On Wed, Aug 19, 2020 at 8:40 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > >
> > > On Mon, Aug 17, 2020 at 08:33:50PM -0700, Peter Collingbourne wrote:
> > > > 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.
> > > >
> > > > 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.
> > >
> > > For clarity, is the new si_xflags field supposed to be valid for all
> > > signal types, or just certain signals and si_codes?
> >
> > It is intended to be valid for all signal types that use the _sigfault
> > union member of siginfo. As listed in siginfo.h these are: SIGILL,
> > SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT.
>
> SIGSYS is similar to SIGILL, is that included also?

I think that SIGSYS is covered by a separate _sigsys union member.

> > > What happens for things like a rt_sigqueueinfo() from userspace?
> >
> > Hmm. Let's enumerate each of these things, which I believe are all of
> > the call sites of the function copy_siginfo_from_user and related
> > functions (correct me if I'm wrong):
> >
> > - ptrace(PTRACE_SETSIGINFO)
> > - pidfd_send_signal
> > - rt_sigqueueinfo
> > - rt_tgsigqueueinfo
> >
> > We can handle the last three by observing that the kernel forbids
> > sending a signal with these syscalls if si_code >= 0, so we can say
> > that the value of si_xflags is only valid if si_code >= 0.
>
> Hmmm, that's what the code says (actually >= 0 or SI_TKILL), but it's
> illogical.  Those are user signals, so there's no obvious reason why
> userspace shouldn't be allowed to generate their siginfo.  It would
> probably be better for the kernel to police si_pid etc. in the SI_USER
> and SI_TKILL cases rather than flatly refusing, but I guess that's a
> discussion for another day.
>
> I guess the combination of SI_FROMKERNEL() and the signal number being a
> known fault signal if probably sufficient for now.

In v10 I ended up adding a comment saying that si_xflags is only valid
if 0 <= si_code < SI_KERNEL (the SI_KERNEL part was due to my
discovery of kernel code that was calling force_sig(SIGSEGV) where
force_sig uses the _kill union member). Your comment about SI_USER
made me realize that is not exactly true (since kill and
pidfd_send_signal can send a fault signal with si_code == SI_USER). I
was not aware of the SI_FROMKERNEL() macro. In v11 I will update the
comment to say that SI_FROMKERNEL(si) && si->si_code != SI_KERNEL must
be true in order for si_xflags to be valid.

> It might be helpful to have a helper to identify fault signals, but we
> don't have this today, and it's unlikely that a new kind of fault signal
> will crop up any time soon.
>
> Handlers that handle specific signal types won't care, but debuggers and
> generic backtracer code would have to be hand-hacked to add new kinds of
> fault signal today -- not a huge priority though, and orthogonal to this
> series.
>
> > As for the first one, it's more tricky. Arguably something like a
> > debugger should be able to send arbitrary signals to a debuggee, and
> > there's no reason why it shouldn't be able to set si_xflags in
> > siginfo, but on the other hand who knows how existing debuggers end up
> > setting this field today. Maybe all that we can do is have the kernel
> > clear si_xflags if it detects that the signal uses _sigfault, and let
> > si_xflags aware debuggers opt out of this behavior, perhaps by
> > introducing a PTRACE_SETSIGINFO2 or something.
>
> Most likely a debugger usually amends an existing siginfo from a trapped
> signal than generating a new one from scratch.

Right, but it could have copied the fields by hand from a
kernel-supplied siginfo before amending it.

> Given the other things that ptrace can do to the target process I don't
> think we need to police here, but your suggestion about a
> PTRACE_SETSIGINFO2 or similar, and zeroing this field by default with
> PTRACE_SETSIGINFO, does make sense.

Ack. I've implemented that in v10.

Peter

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

* Re: [PATCH v9 5/6] signal: define the field siginfo.si_xflags
@ 2020-08-25  1:27           ` Peter Collingbourne
  0 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-25  1:27 UTC (permalink / raw)
  To: Dave Martin
  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, Aug 24, 2020 at 7:03 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Wed, Aug 19, 2020 at 06:37:25PM -0700, Peter Collingbourne wrote:
> > On Wed, Aug 19, 2020 at 8:40 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > >
> > > On Mon, Aug 17, 2020 at 08:33:50PM -0700, Peter Collingbourne wrote:
> > > > 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.
> > > >
> > > > 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.
> > >
> > > For clarity, is the new si_xflags field supposed to be valid for all
> > > signal types, or just certain signals and si_codes?
> >
> > It is intended to be valid for all signal types that use the _sigfault
> > union member of siginfo. As listed in siginfo.h these are: SIGILL,
> > SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT.
>
> SIGSYS is similar to SIGILL, is that included also?

I think that SIGSYS is covered by a separate _sigsys union member.

> > > What happens for things like a rt_sigqueueinfo() from userspace?
> >
> > Hmm. Let's enumerate each of these things, which I believe are all of
> > the call sites of the function copy_siginfo_from_user and related
> > functions (correct me if I'm wrong):
> >
> > - ptrace(PTRACE_SETSIGINFO)
> > - pidfd_send_signal
> > - rt_sigqueueinfo
> > - rt_tgsigqueueinfo
> >
> > We can handle the last three by observing that the kernel forbids
> > sending a signal with these syscalls if si_code >= 0, so we can say
> > that the value of si_xflags is only valid if si_code >= 0.
>
> Hmmm, that's what the code says (actually >= 0 or SI_TKILL), but it's
> illogical.  Those are user signals, so there's no obvious reason why
> userspace shouldn't be allowed to generate their siginfo.  It would
> probably be better for the kernel to police si_pid etc. in the SI_USER
> and SI_TKILL cases rather than flatly refusing, but I guess that's a
> discussion for another day.
>
> I guess the combination of SI_FROMKERNEL() and the signal number being a
> known fault signal if probably sufficient for now.

In v10 I ended up adding a comment saying that si_xflags is only valid
if 0 <= si_code < SI_KERNEL (the SI_KERNEL part was due to my
discovery of kernel code that was calling force_sig(SIGSEGV) where
force_sig uses the _kill union member). Your comment about SI_USER
made me realize that is not exactly true (since kill and
pidfd_send_signal can send a fault signal with si_code == SI_USER). I
was not aware of the SI_FROMKERNEL() macro. In v11 I will update the
comment to say that SI_FROMKERNEL(si) && si->si_code != SI_KERNEL must
be true in order for si_xflags to be valid.

> It might be helpful to have a helper to identify fault signals, but we
> don't have this today, and it's unlikely that a new kind of fault signal
> will crop up any time soon.
>
> Handlers that handle specific signal types won't care, but debuggers and
> generic backtracer code would have to be hand-hacked to add new kinds of
> fault signal today -- not a huge priority though, and orthogonal to this
> series.
>
> > As for the first one, it's more tricky. Arguably something like a
> > debugger should be able to send arbitrary signals to a debuggee, and
> > there's no reason why it shouldn't be able to set si_xflags in
> > siginfo, but on the other hand who knows how existing debuggers end up
> > setting this field today. Maybe all that we can do is have the kernel
> > clear si_xflags if it detects that the signal uses _sigfault, and let
> > si_xflags aware debuggers opt out of this behavior, perhaps by
> > introducing a PTRACE_SETSIGINFO2 or something.
>
> Most likely a debugger usually amends an existing siginfo from a trapped
> signal than generating a new one from scratch.

Right, but it could have copied the fields by hand from a
kernel-supplied siginfo before amending it.

> Given the other things that ptrace can do to the target process I don't
> think we need to police here, but your suggestion about a
> PTRACE_SETSIGINFO2 or similar, and zeroing this field by default with
> PTRACE_SETSIGINFO, does make sense.

Ack. I've implemented that in v10.

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] 66+ messages in thread

* Re: [PATCH v9 6/6] arm64: expose FAR_EL1 tag bits in siginfo
  2020-08-24 14:23         ` Dave Martin
@ 2020-08-25  2:18           ` Peter Collingbourne
  -1 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-25  2:18 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 Mon, Aug 24, 2020 at 7:23 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Wed, Aug 19, 2020 at 06:49:01PM -0700, Peter Collingbourne wrote:
> > On Wed, Aug 19, 2020 at 8:56 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > >
> > > On Mon, Aug 17, 2020 at 08:33:51PM -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>
> > > > ---
>
> [...]
>
> > > > diff --git a/kernel/signal.c b/kernel/signal.c
> > > > index 72182eed1b8d..1f1e42adc57d 100644
> > > > --- a/kernel/signal.c
> > > > +++ b/kernel/signal.c
>
> [...]
>
> > > > @@ -1706,7 +1722,9 @@ int send_sig_fault(int sig, int code, void __user *addr
> > > >       return send_sig_info(info.si_signo, &info, t);
> > > >  }
> > > >
> > > > -int force_sig_mceerr(int code, void __user *addr, short lsb)
> > > > +int force_sig_mceerr(int code, void __user *addr, short lsb,
> > > > +                  unsigned long addr_ignored_bits,
> > > > +                  unsigned long addr_ignored_bits_mask)
> > >
> > > Rather than having to pass these extra arguments all over the place, can
> > > we just pass the far for addr, and have an arch-specific hook for
> > > splitting the ignored from non-ignored bits.  For now at least, I expect
> > > that ignored bits mask to be constant for a given platform and kernel.
> >
> > That sounds like a good idea. I think that for MTE we will want to
> > make it conditional on the si_code (so SEGV_MTESERR would get 0xf <<
> > 56 while everything else would get 0xff << 56) so I can hook that up
> > at the same time.
>
> OK, I think that's reasonable.
>
> Mind you, we seem to have 3 kinds of bits here, so I'm starting to
> wonder whether this is really sufficient:
>
>         1) address bits used in the faulted access
>         2) attribute/permission bits used in the faulted access
>         3) unavailable bits.
>
> si_addr contains (1).
>
> si_addr_ignored_bits contains (2).
>
> The tag bits from non-MTE faults seem to fall under case (3).  Code that
> looks for these bits in si_addr_ignored_bits won't find them.

I'm reasonably sure that the tag bits are available for non-MTE
faults. From https://developer.arm.com/docs/ddi0595/h/aarch64-system-registers/far_el1
:
"For a Data Abort or Watchpoint exception, if address tagging is
enabled for the address accessed by the data access that caused the
exception, then this field includes the tag."

This language applies to non-tag-check-fault data aborts but is
superseded by the following paragraph for tag check faults:
"For a synchronous Tag Check Fault abort, bits[63:60] are UNKNOWN."

> So perhaps it would make sense to amend the design a bit.  We'd have
>
>         si_addr = address bits only
>         si_attr = attribute bits only
>         si_attr_mask = mask of valid bits in si_addr
>
> Thinking about it, I've just shortened/changed some named and changed
> the meaning of the mask, so it's very similar to what you already have.

Did you mean "si_attr_mask = mask of valid bits in si_attr"? I assume
so because below you talk about si_addr_mask also being the mask of
valid bits in si_addr, but I don't think this is a change in meaning
for the mask field as I specified it. Maybe, given your claim above
that the tag bits are unavailable for non-tag check faults, you
misunderstood why I am setting si_addr_ignored_bits_mask to 0xf << 56
for tag check faults and 0xff << 56 for non-tag check faults?

That being said, maybe we can make the names shorter with something
like your suggestion.

> The mask of valid bits in si_addr is decided by architectural
> convention (i.e., ~0xffUL << 56), but we could also expose
>
>         si_addr_mask = mask of valid bits in si_addr
>
> This is a bit redundant though.  I think people would already assume
> that all bits required for classifying the faulting location accurately
> must already be provided there.

I think it's fine for this to be an architectural convention. If we
really wanted to expose something like this to userspace then I think
we should expose TASK_SIZE (this is something that I've wanted in the
past). But that's really a separate discussion.

Peter

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

* Re: [PATCH v9 6/6] arm64: expose FAR_EL1 tag bits in siginfo
@ 2020-08-25  2:18           ` Peter Collingbourne
  0 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-25  2:18 UTC (permalink / raw)
  To: Dave Martin
  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, Aug 24, 2020 at 7:23 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Wed, Aug 19, 2020 at 06:49:01PM -0700, Peter Collingbourne wrote:
> > On Wed, Aug 19, 2020 at 8:56 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > >
> > > On Mon, Aug 17, 2020 at 08:33:51PM -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>
> > > > ---
>
> [...]
>
> > > > diff --git a/kernel/signal.c b/kernel/signal.c
> > > > index 72182eed1b8d..1f1e42adc57d 100644
> > > > --- a/kernel/signal.c
> > > > +++ b/kernel/signal.c
>
> [...]
>
> > > > @@ -1706,7 +1722,9 @@ int send_sig_fault(int sig, int code, void __user *addr
> > > >       return send_sig_info(info.si_signo, &info, t);
> > > >  }
> > > >
> > > > -int force_sig_mceerr(int code, void __user *addr, short lsb)
> > > > +int force_sig_mceerr(int code, void __user *addr, short lsb,
> > > > +                  unsigned long addr_ignored_bits,
> > > > +                  unsigned long addr_ignored_bits_mask)
> > >
> > > Rather than having to pass these extra arguments all over the place, can
> > > we just pass the far for addr, and have an arch-specific hook for
> > > splitting the ignored from non-ignored bits.  For now at least, I expect
> > > that ignored bits mask to be constant for a given platform and kernel.
> >
> > That sounds like a good idea. I think that for MTE we will want to
> > make it conditional on the si_code (so SEGV_MTESERR would get 0xf <<
> > 56 while everything else would get 0xff << 56) so I can hook that up
> > at the same time.
>
> OK, I think that's reasonable.
>
> Mind you, we seem to have 3 kinds of bits here, so I'm starting to
> wonder whether this is really sufficient:
>
>         1) address bits used in the faulted access
>         2) attribute/permission bits used in the faulted access
>         3) unavailable bits.
>
> si_addr contains (1).
>
> si_addr_ignored_bits contains (2).
>
> The tag bits from non-MTE faults seem to fall under case (3).  Code that
> looks for these bits in si_addr_ignored_bits won't find them.

I'm reasonably sure that the tag bits are available for non-MTE
faults. From https://developer.arm.com/docs/ddi0595/h/aarch64-system-registers/far_el1
:
"For a Data Abort or Watchpoint exception, if address tagging is
enabled for the address accessed by the data access that caused the
exception, then this field includes the tag."

This language applies to non-tag-check-fault data aborts but is
superseded by the following paragraph for tag check faults:
"For a synchronous Tag Check Fault abort, bits[63:60] are UNKNOWN."

> So perhaps it would make sense to amend the design a bit.  We'd have
>
>         si_addr = address bits only
>         si_attr = attribute bits only
>         si_attr_mask = mask of valid bits in si_addr
>
> Thinking about it, I've just shortened/changed some named and changed
> the meaning of the mask, so it's very similar to what you already have.

Did you mean "si_attr_mask = mask of valid bits in si_attr"? I assume
so because below you talk about si_addr_mask also being the mask of
valid bits in si_addr, but I don't think this is a change in meaning
for the mask field as I specified it. Maybe, given your claim above
that the tag bits are unavailable for non-tag check faults, you
misunderstood why I am setting si_addr_ignored_bits_mask to 0xf << 56
for tag check faults and 0xff << 56 for non-tag check faults?

That being said, maybe we can make the names shorter with something
like your suggestion.

> The mask of valid bits in si_addr is decided by architectural
> convention (i.e., ~0xffUL << 56), but we could also expose
>
>         si_addr_mask = mask of valid bits in si_addr
>
> This is a bit redundant though.  I think people would already assume
> that all bits required for classifying the faulting location accurately
> must already be provided there.

I think it's fine for this to be an architectural convention. If we
really wanted to expose something like this to userspace then I think
we should expose TASK_SIZE (this is something that I've wanted in the
past). But that's really a separate discussion.

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] 66+ messages in thread

* Re: [PATCH v9 3/6] signal: clear non-uapi flag bits when passing/returning sa_flags
  2020-08-25  0:51           ` Peter Collingbourne
@ 2020-08-25 14:25             ` Dave Martin
  -1 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-25 14:25 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, Aug 24, 2020 at 05:51:34PM -0700, Peter Collingbourne wrote:
> On Mon, Aug 24, 2020 at 6:40 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Wed, Aug 19, 2020 at 04:39:53PM -0700, Peter Collingbourne wrote:
> > > On Wed, Aug 19, 2020 at 3:39 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > > >
> > > > On Mon, Aug 17, 2020 at 08:33:48PM -0700, Peter Collingbourne wrote:

[...]

> > > > > diff --git a/kernel/signal.c b/kernel/signal.c
> > > > > index 42b67d2cea37..348b7981f1ff 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 &= SA_UAPI_FLAGS;
> > > > > +     if (oact)
> > > > > +             oact->sa.sa_flags &= SA_UAPI_FLAGS;
> > > > > +
> > > >
> > > > Seems reasonable.
> > >
> > > Thanks. I also decided to check how other operating systems handle
> > > unknown flag bits in sigaction.sa_flags. It looks like OpenBSD and
> > > illumos also accept unknown bits but (implicitly, as a result of using
> > > a different internal representation) end up clearing them in oldact:
> > >
> > > https://github.com/openbsd/src/blob/f634a6a4b5bf832e9c1de77f7894ae2625e74484/sys/kern/kern_sig.c#L278
> > > https://github.com/illumos/illumos-gate/blob/76f19f5fdc974fe5be5c82a556e43a4df93f1de1/usr/src/uts/common/syscall/sigaction.c#L86
> 
> XNU does the same:
> 
> https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/kern/kern_sig.c#L480
> 
> > >
> > > and FreeBSD and NetBSD fail the syscall if unknown bits are set:
> > >
> > > https://github.com/freebsd/freebsd/blob/eded70c37057857c6e23fae51f86b8f8f43cd2d0/sys/kern/kern_sig.c#L699
> > > https://github.com/NetBSD/src/blob/3365779becdcedfca206091a645a0e8e22b2946e/sys/kern/sys_sig.c#L473
> > >
> > > So there is some precedent for doing what we're planning to do here,
> > > which makes it yet more likely that we'll be okay doing this.
> >
> > Ack, it's good to have that extra evidence to support this approach.
> >
> > This also means that other OSes could adopt the new Linux flag(s) with
> > comatible semantics, if they wanted to.  Or have I misunderstood
> > something there?
> 
> The other OSs could adopt SA_XFLAGS, but they would probably have no
> need for SA_UNSUPPORTED because they already have a protocol for
> detecting missing flag support in the kernel (Linux is really the odd
> one out here in not supporting such a protocol from the start).
> Userspace programs running on OpenBSD, illumos and XNU could use the
> Linux protocol without the SA_UNSUPPORTED part, while programs running
> on FreeBSD and NetBSD could do something like:
> 
> static bool has_xflags = true;
> [...]
> struct sigaction act;
> act.sa_flags = SA_SIGINFO | SA_XFLAGS;
> if (sigaction(SIGSEGV, &act, 0) != 0) {
>   has_xflags = false;
>   act.sa_flags = SA_SIGINFO;
>   if (sigaction(SIGSEGV, &act, 0) != 0)
>     perror("sigaction");
> }
> 
> It would probably be possible to write a unified function that would
> support all three protocols.

Ack, I think that's about as well as we can reasonably do in the
circumstances.

Cheers
---Dave

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

* Re: [PATCH v9 3/6] signal: clear non-uapi flag bits when passing/returning sa_flags
@ 2020-08-25 14:25             ` Dave Martin
  0 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-25 14:25 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, Aug 24, 2020 at 05:51:34PM -0700, Peter Collingbourne wrote:
> On Mon, Aug 24, 2020 at 6:40 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Wed, Aug 19, 2020 at 04:39:53PM -0700, Peter Collingbourne wrote:
> > > On Wed, Aug 19, 2020 at 3:39 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > > >
> > > > On Mon, Aug 17, 2020 at 08:33:48PM -0700, Peter Collingbourne wrote:

[...]

> > > > > diff --git a/kernel/signal.c b/kernel/signal.c
> > > > > index 42b67d2cea37..348b7981f1ff 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 &= SA_UAPI_FLAGS;
> > > > > +     if (oact)
> > > > > +             oact->sa.sa_flags &= SA_UAPI_FLAGS;
> > > > > +
> > > >
> > > > Seems reasonable.
> > >
> > > Thanks. I also decided to check how other operating systems handle
> > > unknown flag bits in sigaction.sa_flags. It looks like OpenBSD and
> > > illumos also accept unknown bits but (implicitly, as a result of using
> > > a different internal representation) end up clearing them in oldact:
> > >
> > > https://github.com/openbsd/src/blob/f634a6a4b5bf832e9c1de77f7894ae2625e74484/sys/kern/kern_sig.c#L278
> > > https://github.com/illumos/illumos-gate/blob/76f19f5fdc974fe5be5c82a556e43a4df93f1de1/usr/src/uts/common/syscall/sigaction.c#L86
> 
> XNU does the same:
> 
> https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/kern/kern_sig.c#L480
> 
> > >
> > > and FreeBSD and NetBSD fail the syscall if unknown bits are set:
> > >
> > > https://github.com/freebsd/freebsd/blob/eded70c37057857c6e23fae51f86b8f8f43cd2d0/sys/kern/kern_sig.c#L699
> > > https://github.com/NetBSD/src/blob/3365779becdcedfca206091a645a0e8e22b2946e/sys/kern/sys_sig.c#L473
> > >
> > > So there is some precedent for doing what we're planning to do here,
> > > which makes it yet more likely that we'll be okay doing this.
> >
> > Ack, it's good to have that extra evidence to support this approach.
> >
> > This also means that other OSes could adopt the new Linux flag(s) with
> > comatible semantics, if they wanted to.  Or have I misunderstood
> > something there?
> 
> The other OSs could adopt SA_XFLAGS, but they would probably have no
> need for SA_UNSUPPORTED because they already have a protocol for
> detecting missing flag support in the kernel (Linux is really the odd
> one out here in not supporting such a protocol from the start).
> Userspace programs running on OpenBSD, illumos and XNU could use the
> Linux protocol without the SA_UNSUPPORTED part, while programs running
> on FreeBSD and NetBSD could do something like:
> 
> static bool has_xflags = true;
> [...]
> struct sigaction act;
> act.sa_flags = SA_SIGINFO | SA_XFLAGS;
> if (sigaction(SIGSEGV, &act, 0) != 0) {
>   has_xflags = false;
>   act.sa_flags = SA_SIGINFO;
>   if (sigaction(SIGSEGV, &act, 0) != 0)
>     perror("sigaction");
> }
> 
> It would probably be possible to write a unified function that would
> support all three protocols.

Ack, I think that's about as well as we can reasonably do in the
circumstances.

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] 66+ messages in thread

* Re: [PATCH v9 5/6] signal: define the field siginfo.si_xflags
  2020-08-25  1:27           ` Peter Collingbourne
@ 2020-08-25 14:47             ` Dave Martin
  -1 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-25 14:47 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, Aug 24, 2020 at 06:27:51PM -0700, Peter Collingbourne wrote:
> On Mon, Aug 24, 2020 at 7:03 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Wed, Aug 19, 2020 at 06:37:25PM -0700, Peter Collingbourne wrote:
> > > On Wed, Aug 19, 2020 at 8:40 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > > >
> > > > On Mon, Aug 17, 2020 at 08:33:50PM -0700, Peter Collingbourne wrote:
> > > > > 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.
> > > > >
> > > > > 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.
> > > >
> > > > For clarity, is the new si_xflags field supposed to be valid for all
> > > > signal types, or just certain signals and si_codes?
> > >
> > > It is intended to be valid for all signal types that use the _sigfault
> > > union member of siginfo. As listed in siginfo.h these are: SIGILL,
> > > SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT.
> >
> > SIGSYS is similar to SIGILL, is that included also?
> 
> I think that SIGSYS is covered by a separate _sigsys union member.
> 
> > > > What happens for things like a rt_sigqueueinfo() from userspace?
> > >
> > > Hmm. Let's enumerate each of these things, which I believe are all of
> > > the call sites of the function copy_siginfo_from_user and related
> > > functions (correct me if I'm wrong):
> > >
> > > - ptrace(PTRACE_SETSIGINFO)
> > > - pidfd_send_signal
> > > - rt_sigqueueinfo
> > > - rt_tgsigqueueinfo
> > >
> > > We can handle the last three by observing that the kernel forbids
> > > sending a signal with these syscalls if si_code >= 0, so we can say
> > > that the value of si_xflags is only valid if si_code >= 0.
> >
> > Hmmm, that's what the code says (actually >= 0 or SI_TKILL), but it's
> > illogical.  Those are user signals, so there's no obvious reason why
> > userspace shouldn't be allowed to generate their siginfo.  It would
> > probably be better for the kernel to police si_pid etc. in the SI_USER
> > and SI_TKILL cases rather than flatly refusing, but I guess that's a
> > discussion for another day.
> >
> > I guess the combination of SI_FROMKERNEL() and the signal number being a
> > known fault signal if probably sufficient for now.
> 
> In v10 I ended up adding a comment saying that si_xflags is only valid
> if 0 <= si_code < SI_KERNEL (the SI_KERNEL part was due to my
> discovery of kernel code that was calling force_sig(SIGSEGV) where
> force_sig uses the _kill union member). Your comment about SI_USER

Although it's been there a long time, is this a bug?

sigaction(2) says that SI_KERNEL can be reported for any signal, but
doesn't say how/why.  It also says that si_addr is [unconditionally]
valid for [kernel-generated] SIGSEGV.  ([] are my insertions).

While it may be reasonable to expect userspace code to filter out user
signals before assuming that siginfo fields are value, requiring user
code to check for specific si_codes is a bit nastier.

I rather suspect that little or no code out there is explicity checking
for SI_KERNEL before assuming that si_addr etc. are valid today.

> made me realize that is not exactly true (since kill and
> pidfd_send_signal can send a fault signal with si_code == SI_USER). I
> was not aware of the SI_FROMKERNEL() macro. In v11 I will update the
> comment to say that SI_FROMKERNEL(si) && si->si_code != SI_KERNEL must
> be true in order for si_xflags to be valid.

Given the above, maybe it would be better to say nothing explicit about
SI_KERNEL, but make sure that the additional siginfo fields are sanely
zeroed anyway.  For kernel-generated signals we can guarantee this, so I
think that requiring userspace to check explicitly for SI_KERNEL is too
unrealistic (i.e., 90% of the time, people will forget ... and 99% of
the time they will get away with it).


I'm not sure that SI_FROMKERNEL() is standard btw, but I observed that
it is present in the Linux UAPI header.

The "si_code < 0 means userspace" convention seems well established, but
I haven't found anywhere that this is clearly specified.

> 
> > It might be helpful to have a helper to identify fault signals, but we
> > don't have this today, and it's unlikely that a new kind of fault signal
> > will crop up any time soon.
> >
> > Handlers that handle specific signal types won't care, but debuggers and
> > generic backtracer code would have to be hand-hacked to add new kinds of
> > fault signal today -- not a huge priority though, and orthogonal to this
> > series.
> >
> > > As for the first one, it's more tricky. Arguably something like a
> > > debugger should be able to send arbitrary signals to a debuggee, and
> > > there's no reason why it shouldn't be able to set si_xflags in
> > > siginfo, but on the other hand who knows how existing debuggers end up
> > > setting this field today. Maybe all that we can do is have the kernel
> > > clear si_xflags if it detects that the signal uses _sigfault, and let
> > > si_xflags aware debuggers opt out of this behavior, perhaps by
> > > introducing a PTRACE_SETSIGINFO2 or something.
> >
> > Most likely a debugger usually amends an existing siginfo from a trapped
> > signal than generating a new one from scratch.
> 
> Right, but it could have copied the fields by hand from a
> kernel-supplied siginfo before amending it.

It could have, but we can't cover every eventuality.  With a
PTRACE_SETSIGINFO2, we at least get a promise from userspace that it
processed the fields correctly.  (If userspace is wrong, or lying,
that's its own funeral.  The ptracer is as good as root from the point
of view of the traced process anyway.)

> > Given the other things that ptrace can do to the target process I don't
> > think we need to police here, but your suggestion about a
> > PTRACE_SETSIGINFO2 or similar, and zeroing this field by default with
> > PTRACE_SETSIGINFO, does make sense.
> 
> Ack. I've implemented that in v10.

Cheers
---Dave

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

* Re: [PATCH v9 5/6] signal: define the field siginfo.si_xflags
@ 2020-08-25 14:47             ` Dave Martin
  0 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-25 14:47 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, Aug 24, 2020 at 06:27:51PM -0700, Peter Collingbourne wrote:
> On Mon, Aug 24, 2020 at 7:03 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Wed, Aug 19, 2020 at 06:37:25PM -0700, Peter Collingbourne wrote:
> > > On Wed, Aug 19, 2020 at 8:40 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > > >
> > > > On Mon, Aug 17, 2020 at 08:33:50PM -0700, Peter Collingbourne wrote:
> > > > > 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.
> > > > >
> > > > > 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.
> > > >
> > > > For clarity, is the new si_xflags field supposed to be valid for all
> > > > signal types, or just certain signals and si_codes?
> > >
> > > It is intended to be valid for all signal types that use the _sigfault
> > > union member of siginfo. As listed in siginfo.h these are: SIGILL,
> > > SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT.
> >
> > SIGSYS is similar to SIGILL, is that included also?
> 
> I think that SIGSYS is covered by a separate _sigsys union member.
> 
> > > > What happens for things like a rt_sigqueueinfo() from userspace?
> > >
> > > Hmm. Let's enumerate each of these things, which I believe are all of
> > > the call sites of the function copy_siginfo_from_user and related
> > > functions (correct me if I'm wrong):
> > >
> > > - ptrace(PTRACE_SETSIGINFO)
> > > - pidfd_send_signal
> > > - rt_sigqueueinfo
> > > - rt_tgsigqueueinfo
> > >
> > > We can handle the last three by observing that the kernel forbids
> > > sending a signal with these syscalls if si_code >= 0, so we can say
> > > that the value of si_xflags is only valid if si_code >= 0.
> >
> > Hmmm, that's what the code says (actually >= 0 or SI_TKILL), but it's
> > illogical.  Those are user signals, so there's no obvious reason why
> > userspace shouldn't be allowed to generate their siginfo.  It would
> > probably be better for the kernel to police si_pid etc. in the SI_USER
> > and SI_TKILL cases rather than flatly refusing, but I guess that's a
> > discussion for another day.
> >
> > I guess the combination of SI_FROMKERNEL() and the signal number being a
> > known fault signal if probably sufficient for now.
> 
> In v10 I ended up adding a comment saying that si_xflags is only valid
> if 0 <= si_code < SI_KERNEL (the SI_KERNEL part was due to my
> discovery of kernel code that was calling force_sig(SIGSEGV) where
> force_sig uses the _kill union member). Your comment about SI_USER

Although it's been there a long time, is this a bug?

sigaction(2) says that SI_KERNEL can be reported for any signal, but
doesn't say how/why.  It also says that si_addr is [unconditionally]
valid for [kernel-generated] SIGSEGV.  ([] are my insertions).

While it may be reasonable to expect userspace code to filter out user
signals before assuming that siginfo fields are value, requiring user
code to check for specific si_codes is a bit nastier.

I rather suspect that little or no code out there is explicity checking
for SI_KERNEL before assuming that si_addr etc. are valid today.

> made me realize that is not exactly true (since kill and
> pidfd_send_signal can send a fault signal with si_code == SI_USER). I
> was not aware of the SI_FROMKERNEL() macro. In v11 I will update the
> comment to say that SI_FROMKERNEL(si) && si->si_code != SI_KERNEL must
> be true in order for si_xflags to be valid.

Given the above, maybe it would be better to say nothing explicit about
SI_KERNEL, but make sure that the additional siginfo fields are sanely
zeroed anyway.  For kernel-generated signals we can guarantee this, so I
think that requiring userspace to check explicitly for SI_KERNEL is too
unrealistic (i.e., 90% of the time, people will forget ... and 99% of
the time they will get away with it).


I'm not sure that SI_FROMKERNEL() is standard btw, but I observed that
it is present in the Linux UAPI header.

The "si_code < 0 means userspace" convention seems well established, but
I haven't found anywhere that this is clearly specified.

> 
> > It might be helpful to have a helper to identify fault signals, but we
> > don't have this today, and it's unlikely that a new kind of fault signal
> > will crop up any time soon.
> >
> > Handlers that handle specific signal types won't care, but debuggers and
> > generic backtracer code would have to be hand-hacked to add new kinds of
> > fault signal today -- not a huge priority though, and orthogonal to this
> > series.
> >
> > > As for the first one, it's more tricky. Arguably something like a
> > > debugger should be able to send arbitrary signals to a debuggee, and
> > > there's no reason why it shouldn't be able to set si_xflags in
> > > siginfo, but on the other hand who knows how existing debuggers end up
> > > setting this field today. Maybe all that we can do is have the kernel
> > > clear si_xflags if it detects that the signal uses _sigfault, and let
> > > si_xflags aware debuggers opt out of this behavior, perhaps by
> > > introducing a PTRACE_SETSIGINFO2 or something.
> >
> > Most likely a debugger usually amends an existing siginfo from a trapped
> > signal than generating a new one from scratch.
> 
> Right, but it could have copied the fields by hand from a
> kernel-supplied siginfo before amending it.

It could have, but we can't cover every eventuality.  With a
PTRACE_SETSIGINFO2, we at least get a promise from userspace that it
processed the fields correctly.  (If userspace is wrong, or lying,
that's its own funeral.  The ptracer is as good as root from the point
of view of the traced process anyway.)

> > Given the other things that ptrace can do to the target process I don't
> > think we need to police here, but your suggestion about a
> > PTRACE_SETSIGINFO2 or similar, and zeroing this field by default with
> > PTRACE_SETSIGINFO, does make sense.
> 
> Ack. I've implemented that in v10.

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] 66+ messages in thread

* Re: [PATCH v9 6/6] arm64: expose FAR_EL1 tag bits in siginfo
  2020-08-25  2:18           ` Peter Collingbourne
@ 2020-08-25 15:02             ` Dave Martin
  -1 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-25 15:02 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, Aug 24, 2020 at 07:18:19PM -0700, Peter Collingbourne wrote:
> On Mon, Aug 24, 2020 at 7:23 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Wed, Aug 19, 2020 at 06:49:01PM -0700, Peter Collingbourne wrote:
> > > On Wed, Aug 19, 2020 at 8:56 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > > >
> > > > On Mon, Aug 17, 2020 at 08:33:51PM -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>
> > > > > ---
> >
> > [...]
> >
> > > > > diff --git a/kernel/signal.c b/kernel/signal.c
> > > > > index 72182eed1b8d..1f1e42adc57d 100644
> > > > > --- a/kernel/signal.c
> > > > > +++ b/kernel/signal.c
> >
> > [...]
> >
> > > > > @@ -1706,7 +1722,9 @@ int send_sig_fault(int sig, int code, void __user *addr
> > > > >       return send_sig_info(info.si_signo, &info, t);
> > > > >  }
> > > > >
> > > > > -int force_sig_mceerr(int code, void __user *addr, short lsb)
> > > > > +int force_sig_mceerr(int code, void __user *addr, short lsb,
> > > > > +                  unsigned long addr_ignored_bits,
> > > > > +                  unsigned long addr_ignored_bits_mask)
> > > >
> > > > Rather than having to pass these extra arguments all over the place, can
> > > > we just pass the far for addr, and have an arch-specific hook for
> > > > splitting the ignored from non-ignored bits.  For now at least, I expect
> > > > that ignored bits mask to be constant for a given platform and kernel.
> > >
> > > That sounds like a good idea. I think that for MTE we will want to
> > > make it conditional on the si_code (so SEGV_MTESERR would get 0xf <<
> > > 56 while everything else would get 0xff << 56) so I can hook that up
> > > at the same time.
> >
> > OK, I think that's reasonable.
> >
> > Mind you, we seem to have 3 kinds of bits here, so I'm starting to
> > wonder whether this is really sufficient:
> >
> >         1) address bits used in the faulted access
> >         2) attribute/permission bits used in the faulted access
> >         3) unavailable bits.
> >
> > si_addr contains (1).
> >
> > si_addr_ignored_bits contains (2).
> >
> > The tag bits from non-MTE faults seem to fall under case (3).  Code that
> > looks for these bits in si_addr_ignored_bits won't find them.
> 
> I'm reasonably sure that the tag bits are available for non-MTE
> faults. From https://developer.arm.com/docs/ddi0595/h/aarch64-system-registers/far_el1
> :
> "For a Data Abort or Watchpoint exception, if address tagging is
> enabled for the address accessed by the data access that caused the
> exception, then this field includes the tag."

Right, but I wonder whether it would still be good idea to have a way to
tell userspace which bits are valid.

Collecting and synchronising all the correct information for reporting a
fault is notoriously easy to mess up in the implementation, and
misreporting of the tag bits might be regarded as a tolerable fail.

We also don't get tag bits for prefetch aborts (which may be reported
via SIGSEGV).  Arguably the architecture doesn't allow a nonzero tag
(BR etc. likely just throw those bits on the floor).  But it might be
nice to be explicit about this.

Other architectures may also have other reasons why the additional bits
are sometimes available, sometimes not.

> This language applies to non-tag-check-fault data aborts but is
> superseded by the following paragraph for tag check faults:
> "For a synchronous Tag Check Fault abort, bits[63:60] are UNKNOWN."

Right, so in this case we should squash those bits and not report them
in the mask.  Currently are you implying that these are address bits,
because you exclude them from si_addr_ignored_mask?

> > So perhaps it would make sense to amend the design a bit.  We'd have
> >
> >         si_addr = address bits only
> >         si_attr = attribute bits only
> >         si_attr_mask = mask of valid bits in si_addr
> >
> > Thinking about it, I've just shortened/changed some named and changed
> > the meaning of the mask, so it's very similar to what you already have.
> 
> Did you mean "si_attr_mask = mask of valid bits in si_attr"? I assume

Yeah, my bad.

> so because below you talk about si_addr_mask also being the mask of
> valid bits in si_addr, but I don't think this is a change in meaning
> for the mask field as I specified it. Maybe, given your claim above
> that the tag bits are unavailable for non-tag check faults, you
> misunderstood why I am setting si_addr_ignored_bits_mask to 0xf << 56
> for tag check faults and 0xff << 56 for non-tag check faults?

Possibly.  I'll read your respin.

> That being said, maybe we can make the names shorter with something
> like your suggestion.
> 
> > The mask of valid bits in si_addr is decided by architectural
> > convention (i.e., ~0xffUL << 56), but we could also expose
> >
> >         si_addr_mask = mask of valid bits in si_addr
> >
> > This is a bit redundant though.  I think people would already assume
> > that all bits required for classifying the faulting location accurately
> > must already be provided there.
> 
> I think it's fine for this to be an architectural convention. If we
> really wanted to expose something like this to userspace then I think
> we should expose TASK_SIZE (this is something that I've wanted in the
> past). But that's really a separate discussion.

Agreed.

Cheers
---Dave

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

* Re: [PATCH v9 6/6] arm64: expose FAR_EL1 tag bits in siginfo
@ 2020-08-25 15:02             ` Dave Martin
  0 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-25 15:02 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, Aug 24, 2020 at 07:18:19PM -0700, Peter Collingbourne wrote:
> On Mon, Aug 24, 2020 at 7:23 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Wed, Aug 19, 2020 at 06:49:01PM -0700, Peter Collingbourne wrote:
> > > On Wed, Aug 19, 2020 at 8:56 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > > >
> > > > On Mon, Aug 17, 2020 at 08:33:51PM -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>
> > > > > ---
> >
> > [...]
> >
> > > > > diff --git a/kernel/signal.c b/kernel/signal.c
> > > > > index 72182eed1b8d..1f1e42adc57d 100644
> > > > > --- a/kernel/signal.c
> > > > > +++ b/kernel/signal.c
> >
> > [...]
> >
> > > > > @@ -1706,7 +1722,9 @@ int send_sig_fault(int sig, int code, void __user *addr
> > > > >       return send_sig_info(info.si_signo, &info, t);
> > > > >  }
> > > > >
> > > > > -int force_sig_mceerr(int code, void __user *addr, short lsb)
> > > > > +int force_sig_mceerr(int code, void __user *addr, short lsb,
> > > > > +                  unsigned long addr_ignored_bits,
> > > > > +                  unsigned long addr_ignored_bits_mask)
> > > >
> > > > Rather than having to pass these extra arguments all over the place, can
> > > > we just pass the far for addr, and have an arch-specific hook for
> > > > splitting the ignored from non-ignored bits.  For now at least, I expect
> > > > that ignored bits mask to be constant for a given platform and kernel.
> > >
> > > That sounds like a good idea. I think that for MTE we will want to
> > > make it conditional on the si_code (so SEGV_MTESERR would get 0xf <<
> > > 56 while everything else would get 0xff << 56) so I can hook that up
> > > at the same time.
> >
> > OK, I think that's reasonable.
> >
> > Mind you, we seem to have 3 kinds of bits here, so I'm starting to
> > wonder whether this is really sufficient:
> >
> >         1) address bits used in the faulted access
> >         2) attribute/permission bits used in the faulted access
> >         3) unavailable bits.
> >
> > si_addr contains (1).
> >
> > si_addr_ignored_bits contains (2).
> >
> > The tag bits from non-MTE faults seem to fall under case (3).  Code that
> > looks for these bits in si_addr_ignored_bits won't find them.
> 
> I'm reasonably sure that the tag bits are available for non-MTE
> faults. From https://developer.arm.com/docs/ddi0595/h/aarch64-system-registers/far_el1
> :
> "For a Data Abort or Watchpoint exception, if address tagging is
> enabled for the address accessed by the data access that caused the
> exception, then this field includes the tag."

Right, but I wonder whether it would still be good idea to have a way to
tell userspace which bits are valid.

Collecting and synchronising all the correct information for reporting a
fault is notoriously easy to mess up in the implementation, and
misreporting of the tag bits might be regarded as a tolerable fail.

We also don't get tag bits for prefetch aborts (which may be reported
via SIGSEGV).  Arguably the architecture doesn't allow a nonzero tag
(BR etc. likely just throw those bits on the floor).  But it might be
nice to be explicit about this.

Other architectures may also have other reasons why the additional bits
are sometimes available, sometimes not.

> This language applies to non-tag-check-fault data aborts but is
> superseded by the following paragraph for tag check faults:
> "For a synchronous Tag Check Fault abort, bits[63:60] are UNKNOWN."

Right, so in this case we should squash those bits and not report them
in the mask.  Currently are you implying that these are address bits,
because you exclude them from si_addr_ignored_mask?

> > So perhaps it would make sense to amend the design a bit.  We'd have
> >
> >         si_addr = address bits only
> >         si_attr = attribute bits only
> >         si_attr_mask = mask of valid bits in si_addr
> >
> > Thinking about it, I've just shortened/changed some named and changed
> > the meaning of the mask, so it's very similar to what you already have.
> 
> Did you mean "si_attr_mask = mask of valid bits in si_attr"? I assume

Yeah, my bad.

> so because below you talk about si_addr_mask also being the mask of
> valid bits in si_addr, but I don't think this is a change in meaning
> for the mask field as I specified it. Maybe, given your claim above
> that the tag bits are unavailable for non-tag check faults, you
> misunderstood why I am setting si_addr_ignored_bits_mask to 0xf << 56
> for tag check faults and 0xff << 56 for non-tag check faults?

Possibly.  I'll read your respin.

> That being said, maybe we can make the names shorter with something
> like your suggestion.
> 
> > The mask of valid bits in si_addr is decided by architectural
> > convention (i.e., ~0xffUL << 56), but we could also expose
> >
> >         si_addr_mask = mask of valid bits in si_addr
> >
> > This is a bit redundant though.  I think people would already assume
> > that all bits required for classifying the faulting location accurately
> > must already be provided there.
> 
> I think it's fine for this to be an architectural convention. If we
> really wanted to expose something like this to userspace then I think
> we should expose TASK_SIZE (this is something that I've wanted in the
> past). But that's really a separate discussion.

Agreed.

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] 66+ messages in thread

* Re: [PATCH v9 5/6] signal: define the field siginfo.si_xflags
  2020-08-25 14:47             ` Dave Martin
@ 2020-08-25 20:08               ` Peter Collingbourne
  -1 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-25 20:08 UTC (permalink / raw)
  To: Dave Martin
  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 Tue, Aug 25, 2020 at 7:47 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Mon, Aug 24, 2020 at 06:27:51PM -0700, Peter Collingbourne wrote:
> > On Mon, Aug 24, 2020 at 7:03 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > >
> > > On Wed, Aug 19, 2020 at 06:37:25PM -0700, Peter Collingbourne wrote:
> > > > On Wed, Aug 19, 2020 at 8:40 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > > > >
> > > > > On Mon, Aug 17, 2020 at 08:33:50PM -0700, Peter Collingbourne wrote:
> > > > > > 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.
> > > > > >
> > > > > > 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.
> > > > >
> > > > > For clarity, is the new si_xflags field supposed to be valid for all
> > > > > signal types, or just certain signals and si_codes?
> > > >
> > > > It is intended to be valid for all signal types that use the _sigfault
> > > > union member of siginfo. As listed in siginfo.h these are: SIGILL,
> > > > SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT.
> > >
> > > SIGSYS is similar to SIGILL, is that included also?
> >
> > I think that SIGSYS is covered by a separate _sigsys union member.
> >
> > > > > What happens for things like a rt_sigqueueinfo() from userspace?
> > > >
> > > > Hmm. Let's enumerate each of these things, which I believe are all of
> > > > the call sites of the function copy_siginfo_from_user and related
> > > > functions (correct me if I'm wrong):
> > > >
> > > > - ptrace(PTRACE_SETSIGINFO)
> > > > - pidfd_send_signal
> > > > - rt_sigqueueinfo
> > > > - rt_tgsigqueueinfo
> > > >
> > > > We can handle the last three by observing that the kernel forbids
> > > > sending a signal with these syscalls if si_code >= 0, so we can say
> > > > that the value of si_xflags is only valid if si_code >= 0.
> > >
> > > Hmmm, that's what the code says (actually >= 0 or SI_TKILL), but it's
> > > illogical.  Those are user signals, so there's no obvious reason why
> > > userspace shouldn't be allowed to generate their siginfo.  It would
> > > probably be better for the kernel to police si_pid etc. in the SI_USER
> > > and SI_TKILL cases rather than flatly refusing, but I guess that's a
> > > discussion for another day.
> > >
> > > I guess the combination of SI_FROMKERNEL() and the signal number being a
> > > known fault signal if probably sufficient for now.
> >
> > In v10 I ended up adding a comment saying that si_xflags is only valid
> > if 0 <= si_code < SI_KERNEL (the SI_KERNEL part was due to my
> > discovery of kernel code that was calling force_sig(SIGSEGV) where
> > force_sig uses the _kill union member). Your comment about SI_USER
>
> Although it's been there a long time, is this a bug?
>
> sigaction(2) says that SI_KERNEL can be reported for any signal, but
> doesn't say how/why.  It also says that si_addr is [unconditionally]
> valid for [kernel-generated] SIGSEGV.  ([] are my insertions).
>
> While it may be reasonable to expect userspace code to filter out user
> signals before assuming that siginfo fields are value, requiring user
> code to check for specific si_codes is a bit nastier.
>
> I rather suspect that little or no code out there is explicity checking
> for SI_KERNEL before assuming that si_addr etc. are valid today.

Right, but maybe that can be attributed to poor documentation (in the
man page), so maybe the right thing to do here is to make the
documentation more explicit. The kernel code itself is fairly clear
that SI_KERNEL does not use the _sigfault layout:
https://github.com/torvalds/linux/blob/6a9dc5fd6170d0a41c8a14eb19e63d94bea5705a/kernel/signal.c#L3173

And note that force_sig does not make the si_addr field valid either,
it sets it to 0 (on most architectures, as a result of si_addr
overlapping si_pid/si_uid which get set to 0 by that function), which
is not necessarily the correct value. For example, on 64-bit x86,
executing this code:

  volatile auto ptr = (char *)0xfedcba9876543210;
  *ptr = 42;

(i.e. accessing outside of the TASK_SIZE limit) will result in a call
to force_sig(SIGSEGV) setting si_addr=0. But this is clearly not an
accurate fault address. I don't know how x86 reports the fault address
to the kernel in this case but maybe it simply isn't available for
addresses larger than TASK_SIZE, so the right thing for the kernel to
do would be to indicate that the address is unavailable (for example,
by setting si_code=SI_KERNEL, as it is already doing). Then through
documentation updates, userspace can know that si_code=SI_KERNEL means
that the address is unavailable.

> > made me realize that is not exactly true (since kill and
> > pidfd_send_signal can send a fault signal with si_code == SI_USER). I
> > was not aware of the SI_FROMKERNEL() macro. In v11 I will update the
> > comment to say that SI_FROMKERNEL(si) && si->si_code != SI_KERNEL must
> > be true in order for si_xflags to be valid.
>
> Given the above, maybe it would be better to say nothing explicit about
> SI_KERNEL, but make sure that the additional siginfo fields are sanely
> zeroed anyway.

I think that for si_addr this happens as a result of setting
si_pid/si_uid, and for the other fields this happens as a result of
zeroing the padding between fields. I know that we'd prefer not to
rely on zeroing padding, but perhaps the zero padding can more be seen
as a last resort for keeping things working in case userspace fails to
check for SI_KERNEL.

> For kernel-generated signals we can guarantee this, so I
> think that requiring userspace to check explicitly for SI_KERNEL is too
> unrealistic (i.e., 90% of the time, people will forget ... and 99% of
> the time they will get away with it).

It's unfortunate that the conditions for accessing these fields are so
complex, but again this seems like part of the hand that we've been
dealt with this API. Fortunately the requirement to check for
SI_KERNEL should only really apply in practice to code accessing our
new fields. We can make it retroactively apply to existing fields, but
since that wouldn't be a change to the kernel code, just the
documentation, existing code will continue to operate in the same way
as it did before.

> I'm not sure that SI_FROMKERNEL() is standard btw, but I observed that
> it is present in the Linux UAPI header.
>
> The "si_code < 0 means userspace" convention seems well established, but
> I haven't found anywhere that this is clearly specified.
>
> >
> > > It might be helpful to have a helper to identify fault signals, but we
> > > don't have this today, and it's unlikely that a new kind of fault signal
> > > will crop up any time soon.
> > >
> > > Handlers that handle specific signal types won't care, but debuggers and
> > > generic backtracer code would have to be hand-hacked to add new kinds of
> > > fault signal today -- not a huge priority though, and orthogonal to this
> > > series.
> > >
> > > > As for the first one, it's more tricky. Arguably something like a
> > > > debugger should be able to send arbitrary signals to a debuggee, and
> > > > there's no reason why it shouldn't be able to set si_xflags in
> > > > siginfo, but on the other hand who knows how existing debuggers end up
> > > > setting this field today. Maybe all that we can do is have the kernel
> > > > clear si_xflags if it detects that the signal uses _sigfault, and let
> > > > si_xflags aware debuggers opt out of this behavior, perhaps by
> > > > introducing a PTRACE_SETSIGINFO2 or something.
> > >
> > > Most likely a debugger usually amends an existing siginfo from a trapped
> > > signal than generating a new one from scratch.
> >
> > Right, but it could have copied the fields by hand from a
> > kernel-supplied siginfo before amending it.
>
> It could have, but we can't cover every eventuality.  With a
> PTRACE_SETSIGINFO2, we at least get a promise from userspace that it
> processed the fields correctly.  (If userspace is wrong, or lying,
> that's its own funeral.  The ptracer is as good as root from the point
> of view of the traced process anyway.)

Agreed.


Peter

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

* Re: [PATCH v9 5/6] signal: define the field siginfo.si_xflags
@ 2020-08-25 20:08               ` Peter Collingbourne
  0 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-25 20:08 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, Aug 25, 2020 at 7:47 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Mon, Aug 24, 2020 at 06:27:51PM -0700, Peter Collingbourne wrote:
> > On Mon, Aug 24, 2020 at 7:03 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > >
> > > On Wed, Aug 19, 2020 at 06:37:25PM -0700, Peter Collingbourne wrote:
> > > > On Wed, Aug 19, 2020 at 8:40 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > > > >
> > > > > On Mon, Aug 17, 2020 at 08:33:50PM -0700, Peter Collingbourne wrote:
> > > > > > 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.
> > > > > >
> > > > > > 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.
> > > > >
> > > > > For clarity, is the new si_xflags field supposed to be valid for all
> > > > > signal types, or just certain signals and si_codes?
> > > >
> > > > It is intended to be valid for all signal types that use the _sigfault
> > > > union member of siginfo. As listed in siginfo.h these are: SIGILL,
> > > > SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT.
> > >
> > > SIGSYS is similar to SIGILL, is that included also?
> >
> > I think that SIGSYS is covered by a separate _sigsys union member.
> >
> > > > > What happens for things like a rt_sigqueueinfo() from userspace?
> > > >
> > > > Hmm. Let's enumerate each of these things, which I believe are all of
> > > > the call sites of the function copy_siginfo_from_user and related
> > > > functions (correct me if I'm wrong):
> > > >
> > > > - ptrace(PTRACE_SETSIGINFO)
> > > > - pidfd_send_signal
> > > > - rt_sigqueueinfo
> > > > - rt_tgsigqueueinfo
> > > >
> > > > We can handle the last three by observing that the kernel forbids
> > > > sending a signal with these syscalls if si_code >= 0, so we can say
> > > > that the value of si_xflags is only valid if si_code >= 0.
> > >
> > > Hmmm, that's what the code says (actually >= 0 or SI_TKILL), but it's
> > > illogical.  Those are user signals, so there's no obvious reason why
> > > userspace shouldn't be allowed to generate their siginfo.  It would
> > > probably be better for the kernel to police si_pid etc. in the SI_USER
> > > and SI_TKILL cases rather than flatly refusing, but I guess that's a
> > > discussion for another day.
> > >
> > > I guess the combination of SI_FROMKERNEL() and the signal number being a
> > > known fault signal if probably sufficient for now.
> >
> > In v10 I ended up adding a comment saying that si_xflags is only valid
> > if 0 <= si_code < SI_KERNEL (the SI_KERNEL part was due to my
> > discovery of kernel code that was calling force_sig(SIGSEGV) where
> > force_sig uses the _kill union member). Your comment about SI_USER
>
> Although it's been there a long time, is this a bug?
>
> sigaction(2) says that SI_KERNEL can be reported for any signal, but
> doesn't say how/why.  It also says that si_addr is [unconditionally]
> valid for [kernel-generated] SIGSEGV.  ([] are my insertions).
>
> While it may be reasonable to expect userspace code to filter out user
> signals before assuming that siginfo fields are value, requiring user
> code to check for specific si_codes is a bit nastier.
>
> I rather suspect that little or no code out there is explicity checking
> for SI_KERNEL before assuming that si_addr etc. are valid today.

Right, but maybe that can be attributed to poor documentation (in the
man page), so maybe the right thing to do here is to make the
documentation more explicit. The kernel code itself is fairly clear
that SI_KERNEL does not use the _sigfault layout:
https://github.com/torvalds/linux/blob/6a9dc5fd6170d0a41c8a14eb19e63d94bea5705a/kernel/signal.c#L3173

And note that force_sig does not make the si_addr field valid either,
it sets it to 0 (on most architectures, as a result of si_addr
overlapping si_pid/si_uid which get set to 0 by that function), which
is not necessarily the correct value. For example, on 64-bit x86,
executing this code:

  volatile auto ptr = (char *)0xfedcba9876543210;
  *ptr = 42;

(i.e. accessing outside of the TASK_SIZE limit) will result in a call
to force_sig(SIGSEGV) setting si_addr=0. But this is clearly not an
accurate fault address. I don't know how x86 reports the fault address
to the kernel in this case but maybe it simply isn't available for
addresses larger than TASK_SIZE, so the right thing for the kernel to
do would be to indicate that the address is unavailable (for example,
by setting si_code=SI_KERNEL, as it is already doing). Then through
documentation updates, userspace can know that si_code=SI_KERNEL means
that the address is unavailable.

> > made me realize that is not exactly true (since kill and
> > pidfd_send_signal can send a fault signal with si_code == SI_USER). I
> > was not aware of the SI_FROMKERNEL() macro. In v11 I will update the
> > comment to say that SI_FROMKERNEL(si) && si->si_code != SI_KERNEL must
> > be true in order for si_xflags to be valid.
>
> Given the above, maybe it would be better to say nothing explicit about
> SI_KERNEL, but make sure that the additional siginfo fields are sanely
> zeroed anyway.

I think that for si_addr this happens as a result of setting
si_pid/si_uid, and for the other fields this happens as a result of
zeroing the padding between fields. I know that we'd prefer not to
rely on zeroing padding, but perhaps the zero padding can more be seen
as a last resort for keeping things working in case userspace fails to
check for SI_KERNEL.

> For kernel-generated signals we can guarantee this, so I
> think that requiring userspace to check explicitly for SI_KERNEL is too
> unrealistic (i.e., 90% of the time, people will forget ... and 99% of
> the time they will get away with it).

It's unfortunate that the conditions for accessing these fields are so
complex, but again this seems like part of the hand that we've been
dealt with this API. Fortunately the requirement to check for
SI_KERNEL should only really apply in practice to code accessing our
new fields. We can make it retroactively apply to existing fields, but
since that wouldn't be a change to the kernel code, just the
documentation, existing code will continue to operate in the same way
as it did before.

> I'm not sure that SI_FROMKERNEL() is standard btw, but I observed that
> it is present in the Linux UAPI header.
>
> The "si_code < 0 means userspace" convention seems well established, but
> I haven't found anywhere that this is clearly specified.
>
> >
> > > It might be helpful to have a helper to identify fault signals, but we
> > > don't have this today, and it's unlikely that a new kind of fault signal
> > > will crop up any time soon.
> > >
> > > Handlers that handle specific signal types won't care, but debuggers and
> > > generic backtracer code would have to be hand-hacked to add new kinds of
> > > fault signal today -- not a huge priority though, and orthogonal to this
> > > series.
> > >
> > > > As for the first one, it's more tricky. Arguably something like a
> > > > debugger should be able to send arbitrary signals to a debuggee, and
> > > > there's no reason why it shouldn't be able to set si_xflags in
> > > > siginfo, but on the other hand who knows how existing debuggers end up
> > > > setting this field today. Maybe all that we can do is have the kernel
> > > > clear si_xflags if it detects that the signal uses _sigfault, and let
> > > > si_xflags aware debuggers opt out of this behavior, perhaps by
> > > > introducing a PTRACE_SETSIGINFO2 or something.
> > >
> > > Most likely a debugger usually amends an existing siginfo from a trapped
> > > signal than generating a new one from scratch.
> >
> > Right, but it could have copied the fields by hand from a
> > kernel-supplied siginfo before amending it.
>
> It could have, but we can't cover every eventuality.  With a
> PTRACE_SETSIGINFO2, we at least get a promise from userspace that it
> processed the fields correctly.  (If userspace is wrong, or lying,
> that's its own funeral.  The ptracer is as good as root from the point
> of view of the traced process anyway.)

Agreed.


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] 66+ messages in thread

* Re: [PATCH v9 6/6] arm64: expose FAR_EL1 tag bits in siginfo
  2020-08-25 15:02             ` Dave Martin
@ 2020-08-25 22:06               ` Peter Collingbourne
  -1 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-25 22:06 UTC (permalink / raw)
  To: Dave Martin
  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 Tue, Aug 25, 2020 at 8:02 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Mon, Aug 24, 2020 at 07:18:19PM -0700, Peter Collingbourne wrote:
> > On Mon, Aug 24, 2020 at 7:23 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > >
> > > On Wed, Aug 19, 2020 at 06:49:01PM -0700, Peter Collingbourne wrote:
> > > > On Wed, Aug 19, 2020 at 8:56 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > > > >
> > > > > On Mon, Aug 17, 2020 at 08:33:51PM -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>
> > > > > > ---
> > >
> > > [...]
> > >
> > > > > > diff --git a/kernel/signal.c b/kernel/signal.c
> > > > > > index 72182eed1b8d..1f1e42adc57d 100644
> > > > > > --- a/kernel/signal.c
> > > > > > +++ b/kernel/signal.c
> > >
> > > [...]
> > >
> > > > > > @@ -1706,7 +1722,9 @@ int send_sig_fault(int sig, int code, void __user *addr
> > > > > >       return send_sig_info(info.si_signo, &info, t);
> > > > > >  }
> > > > > >
> > > > > > -int force_sig_mceerr(int code, void __user *addr, short lsb)
> > > > > > +int force_sig_mceerr(int code, void __user *addr, short lsb,
> > > > > > +                  unsigned long addr_ignored_bits,
> > > > > > +                  unsigned long addr_ignored_bits_mask)
> > > > >
> > > > > Rather than having to pass these extra arguments all over the place, can
> > > > > we just pass the far for addr, and have an arch-specific hook for
> > > > > splitting the ignored from non-ignored bits.  For now at least, I expect
> > > > > that ignored bits mask to be constant for a given platform and kernel.
> > > >
> > > > That sounds like a good idea. I think that for MTE we will want to
> > > > make it conditional on the si_code (so SEGV_MTESERR would get 0xf <<
> > > > 56 while everything else would get 0xff << 56) so I can hook that up
> > > > at the same time.
> > >
> > > OK, I think that's reasonable.
> > >
> > > Mind you, we seem to have 3 kinds of bits here, so I'm starting to
> > > wonder whether this is really sufficient:
> > >
> > >         1) address bits used in the faulted access
> > >         2) attribute/permission bits used in the faulted access
> > >         3) unavailable bits.
> > >
> > > si_addr contains (1).
> > >
> > > si_addr_ignored_bits contains (2).
> > >
> > > The tag bits from non-MTE faults seem to fall under case (3).  Code that
> > > looks for these bits in si_addr_ignored_bits won't find them.
> >
> > I'm reasonably sure that the tag bits are available for non-MTE
> > faults. From https://developer.arm.com/docs/ddi0595/h/aarch64-system-registers/far_el1
> > :
> > "For a Data Abort or Watchpoint exception, if address tagging is
> > enabled for the address accessed by the data access that caused the
> > exception, then this field includes the tag."
>
> Right, but I wonder whether it would still be good idea to have a way to
> tell userspace which bits are valid.

I'm a bit confused by this. si_addr_ignored_bits_mask is exactly the
mechanism for telling userspace which bits are valid. Or maybe you're
arguing that we should consider *not* having the mask of valid bits in
siginfo?

> Collecting and synchronising all the correct information for reporting a
> fault is notoriously easy to mess up in the implementation, and
> misreporting of the tag bits might be regarded as a tolerable fail.

It really depends. Imagine that a future change to the architecture
exposes bits 60-63 in FAR_EL1 in tag fault errors (we have a number of
ideas for how to use these bits to distinguish between different
use-after-frees in error reports). It would be nice for userspace to
be able to distinguish between the situation where bits 60-63 are 0
and the situation where the bits are unknown, in order to avoid
producing an incorrect/misleading report.

> We also don't get tag bits for prefetch aborts (which may be reported
> via SIGSEGV).  Arguably the architecture doesn't allow a nonzero tag
> (BR etc. likely just throw those bits on the floor).  But it might be
> nice to be explicit about this.

If we view the PC as being a 64-bit value where the architecture does
not allow setting bits 56-63, I think it would be correct to claim
that addresses derived from the PC have bits 56-63 clear.

> Other architectures may also have other reasons why the additional bits
> are sometimes available, sometimes not.

If this is the case for an architecture, it can always report the bits
to be unavailable until it can figure out in which cases the bits are
available.

> > This language applies to non-tag-check-fault data aborts but is
> > superseded by the following paragraph for tag check faults:
> > "For a synchronous Tag Check Fault abort, bits[63:60] are UNKNOWN."
>
> Right, so in this case we should squash those bits and not report them
> in the mask.  Currently are you implying that these are address bits,
> because you exclude them from si_addr_ignored_mask?

My intent was that these are implied to be unavailable bits, as they
are not set in the architecturally-defined si_addr mask ~(0xff << 56)
nor in si_addr_ignored_mask.

Peter

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

* Re: [PATCH v9 6/6] arm64: expose FAR_EL1 tag bits in siginfo
@ 2020-08-25 22:06               ` Peter Collingbourne
  0 siblings, 0 replies; 66+ messages in thread
From: Peter Collingbourne @ 2020-08-25 22:06 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, Aug 25, 2020 at 8:02 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Mon, Aug 24, 2020 at 07:18:19PM -0700, Peter Collingbourne wrote:
> > On Mon, Aug 24, 2020 at 7:23 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > >
> > > On Wed, Aug 19, 2020 at 06:49:01PM -0700, Peter Collingbourne wrote:
> > > > On Wed, Aug 19, 2020 at 8:56 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > > > >
> > > > > On Mon, Aug 17, 2020 at 08:33:51PM -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>
> > > > > > ---
> > >
> > > [...]
> > >
> > > > > > diff --git a/kernel/signal.c b/kernel/signal.c
> > > > > > index 72182eed1b8d..1f1e42adc57d 100644
> > > > > > --- a/kernel/signal.c
> > > > > > +++ b/kernel/signal.c
> > >
> > > [...]
> > >
> > > > > > @@ -1706,7 +1722,9 @@ int send_sig_fault(int sig, int code, void __user *addr
> > > > > >       return send_sig_info(info.si_signo, &info, t);
> > > > > >  }
> > > > > >
> > > > > > -int force_sig_mceerr(int code, void __user *addr, short lsb)
> > > > > > +int force_sig_mceerr(int code, void __user *addr, short lsb,
> > > > > > +                  unsigned long addr_ignored_bits,
> > > > > > +                  unsigned long addr_ignored_bits_mask)
> > > > >
> > > > > Rather than having to pass these extra arguments all over the place, can
> > > > > we just pass the far for addr, and have an arch-specific hook for
> > > > > splitting the ignored from non-ignored bits.  For now at least, I expect
> > > > > that ignored bits mask to be constant for a given platform and kernel.
> > > >
> > > > That sounds like a good idea. I think that for MTE we will want to
> > > > make it conditional on the si_code (so SEGV_MTESERR would get 0xf <<
> > > > 56 while everything else would get 0xff << 56) so I can hook that up
> > > > at the same time.
> > >
> > > OK, I think that's reasonable.
> > >
> > > Mind you, we seem to have 3 kinds of bits here, so I'm starting to
> > > wonder whether this is really sufficient:
> > >
> > >         1) address bits used in the faulted access
> > >         2) attribute/permission bits used in the faulted access
> > >         3) unavailable bits.
> > >
> > > si_addr contains (1).
> > >
> > > si_addr_ignored_bits contains (2).
> > >
> > > The tag bits from non-MTE faults seem to fall under case (3).  Code that
> > > looks for these bits in si_addr_ignored_bits won't find them.
> >
> > I'm reasonably sure that the tag bits are available for non-MTE
> > faults. From https://developer.arm.com/docs/ddi0595/h/aarch64-system-registers/far_el1
> > :
> > "For a Data Abort or Watchpoint exception, if address tagging is
> > enabled for the address accessed by the data access that caused the
> > exception, then this field includes the tag."
>
> Right, but I wonder whether it would still be good idea to have a way to
> tell userspace which bits are valid.

I'm a bit confused by this. si_addr_ignored_bits_mask is exactly the
mechanism for telling userspace which bits are valid. Or maybe you're
arguing that we should consider *not* having the mask of valid bits in
siginfo?

> Collecting and synchronising all the correct information for reporting a
> fault is notoriously easy to mess up in the implementation, and
> misreporting of the tag bits might be regarded as a tolerable fail.

It really depends. Imagine that a future change to the architecture
exposes bits 60-63 in FAR_EL1 in tag fault errors (we have a number of
ideas for how to use these bits to distinguish between different
use-after-frees in error reports). It would be nice for userspace to
be able to distinguish between the situation where bits 60-63 are 0
and the situation where the bits are unknown, in order to avoid
producing an incorrect/misleading report.

> We also don't get tag bits for prefetch aborts (which may be reported
> via SIGSEGV).  Arguably the architecture doesn't allow a nonzero tag
> (BR etc. likely just throw those bits on the floor).  But it might be
> nice to be explicit about this.

If we view the PC as being a 64-bit value where the architecture does
not allow setting bits 56-63, I think it would be correct to claim
that addresses derived from the PC have bits 56-63 clear.

> Other architectures may also have other reasons why the additional bits
> are sometimes available, sometimes not.

If this is the case for an architecture, it can always report the bits
to be unavailable until it can figure out in which cases the bits are
available.

> > This language applies to non-tag-check-fault data aborts but is
> > superseded by the following paragraph for tag check faults:
> > "For a synchronous Tag Check Fault abort, bits[63:60] are UNKNOWN."
>
> Right, so in this case we should squash those bits and not report them
> in the mask.  Currently are you implying that these are address bits,
> because you exclude them from si_addr_ignored_mask?

My intent was that these are implied to be unavailable bits, as they
are not set in the architecturally-defined si_addr mask ~(0xff << 56)
nor in si_addr_ignored_mask.

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] 66+ messages in thread

* Re: [PATCH v9 6/6] arm64: expose FAR_EL1 tag bits in siginfo
  2020-08-25 22:06               ` Peter Collingbourne
@ 2020-08-26 15:32                 ` Dave Martin
  -1 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-26 15:32 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 Tue, Aug 25, 2020 at 03:06:39PM -0700, Peter Collingbourne wrote:
> On Tue, Aug 25, 2020 at 8:02 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Mon, Aug 24, 2020 at 07:18:19PM -0700, Peter Collingbourne wrote:
> > > On Mon, Aug 24, 2020 at 7:23 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > > >
> > > > On Wed, Aug 19, 2020 at 06:49:01PM -0700, Peter Collingbourne wrote:
> > > > > On Wed, Aug 19, 2020 at 8:56 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > > > > >
> > > > > > On Mon, Aug 17, 2020 at 08:33:51PM -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>
> > > > > > > ---
> > > >
> > > > [...]
> > > >
> > > > > > > diff --git a/kernel/signal.c b/kernel/signal.c
> > > > > > > index 72182eed1b8d..1f1e42adc57d 100644
> > > > > > > --- a/kernel/signal.c
> > > > > > > +++ b/kernel/signal.c
> > > >
> > > > [...]
> > > >
> > > > > > > @@ -1706,7 +1722,9 @@ int send_sig_fault(int sig, int code, void __user *addr
> > > > > > >       return send_sig_info(info.si_signo, &info, t);
> > > > > > >  }
> > > > > > >
> > > > > > > -int force_sig_mceerr(int code, void __user *addr, short lsb)
> > > > > > > +int force_sig_mceerr(int code, void __user *addr, short lsb,
> > > > > > > +                  unsigned long addr_ignored_bits,
> > > > > > > +                  unsigned long addr_ignored_bits_mask)
> > > > > >
> > > > > > Rather than having to pass these extra arguments all over the place, can
> > > > > > we just pass the far for addr, and have an arch-specific hook for
> > > > > > splitting the ignored from non-ignored bits.  For now at least, I expect
> > > > > > that ignored bits mask to be constant for a given platform and kernel.
> > > > >
> > > > > That sounds like a good idea. I think that for MTE we will want to
> > > > > make it conditional on the si_code (so SEGV_MTESERR would get 0xf <<
> > > > > 56 while everything else would get 0xff << 56) so I can hook that up
> > > > > at the same time.
> > > >
> > > > OK, I think that's reasonable.
> > > >
> > > > Mind you, we seem to have 3 kinds of bits here, so I'm starting to
> > > > wonder whether this is really sufficient:
> > > >
> > > >         1) address bits used in the faulted access
> > > >         2) attribute/permission bits used in the faulted access
> > > >         3) unavailable bits.
> > > >
> > > > si_addr contains (1).
> > > >
> > > > si_addr_ignored_bits contains (2).
> > > >
> > > > The tag bits from non-MTE faults seem to fall under case (3).  Code that
> > > > looks for these bits in si_addr_ignored_bits won't find them.
> > >
> > > I'm reasonably sure that the tag bits are available for non-MTE
> > > faults. From https://developer.arm.com/docs/ddi0595/h/aarch64-system-registers/far_el1
> > > :
> > > "For a Data Abort or Watchpoint exception, if address tagging is
> > > enabled for the address accessed by the data access that caused the
> > > exception, then this field includes the tag."
> >
> > Right, but I wonder whether it would still be good idea to have a way to
> > tell userspace which bits are valid.
> 
> I'm a bit confused by this. si_addr_ignored_bits_mask is exactly the
> mechanism for telling userspace which bits are valid. Or maybe you're
> arguing that we should consider *not* having the mask of valid bits in
> siginfo?
> 
> > Collecting and synchronising all the correct information for reporting a
> > fault is notoriously easy to mess up in the implementation, and
> > misreporting of the tag bits might be regarded as a tolerable fail.
> 
> It really depends. Imagine that a future change to the architecture
> exposes bits 60-63 in FAR_EL1 in tag fault errors (we have a number of
> ideas for how to use these bits to distinguish between different
> use-after-frees in error reports). It would be nice for userspace to
> be able to distinguish between the situation where bits 60-63 are 0
> and the situation where the bits are unknown, in order to avoid
> producing an incorrect/misleading report.
> 
> > We also don't get tag bits for prefetch aborts (which may be reported
> > via SIGSEGV).  Arguably the architecture doesn't allow a nonzero tag
> > (BR etc. likely just throw those bits on the floor).  But it might be
> > nice to be explicit about this.
> 
> If we view the PC as being a 64-bit value where the architecture does
> not allow setting bits 56-63, I think it would be correct to claim
> that addresses derived from the PC have bits 56-63 clear.
> 
> > Other architectures may also have other reasons why the additional bits
> > are sometimes available, sometimes not.
> 
> If this is the case for an architecture, it can always report the bits
> to be unavailable until it can figure out in which cases the bits are
> available.
> 
> > > This language applies to non-tag-check-fault data aborts but is
> > > superseded by the following paragraph for tag check faults:
> > > "For a synchronous Tag Check Fault abort, bits[63:60] are UNKNOWN."
> >
> > Right, so in this case we should squash those bits and not report them
> > in the mask.  Currently are you implying that these are address bits,
> > because you exclude them from si_addr_ignored_mask?
> 
> My intent was that these are implied to be unavailable bits, as they
> are not set in the architecturally-defined si_addr mask ~(0xff << 56)
> nor in si_addr_ignored_mask.

OK, I think part of my confusion here is coming from the "ignored_bits"
naming.

These really aren't ignored, but rather they are meaningful -- that's
why you're implementing this extension.  True, they're ignored for
addressing purposes (i.e., these bits can never distinguish a memory
location from a second, distinct, memory location).  So for backwards
compatibility we mask them out from si_addr.

In the interests of moving on to reviewing the actual code and avoiding
the discussion from getting too fragmented, can I suggest that you
don't reply in detail to this: I'll reflect, and then reiterate my
comments on the v10/v11 thread if I still have concerns.  I may not get
to it this week -- apologies for that -- but if I can start looking at
the updated series today I will.

Cheers
---Dave

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

* Re: [PATCH v9 6/6] arm64: expose FAR_EL1 tag bits in siginfo
@ 2020-08-26 15:32                 ` Dave Martin
  0 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-26 15:32 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 Tue, Aug 25, 2020 at 03:06:39PM -0700, Peter Collingbourne wrote:
> On Tue, Aug 25, 2020 at 8:02 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Mon, Aug 24, 2020 at 07:18:19PM -0700, Peter Collingbourne wrote:
> > > On Mon, Aug 24, 2020 at 7:23 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > > >
> > > > On Wed, Aug 19, 2020 at 06:49:01PM -0700, Peter Collingbourne wrote:
> > > > > On Wed, Aug 19, 2020 at 8:56 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > > > > >
> > > > > > On Mon, Aug 17, 2020 at 08:33:51PM -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>
> > > > > > > ---
> > > >
> > > > [...]
> > > >
> > > > > > > diff --git a/kernel/signal.c b/kernel/signal.c
> > > > > > > index 72182eed1b8d..1f1e42adc57d 100644
> > > > > > > --- a/kernel/signal.c
> > > > > > > +++ b/kernel/signal.c
> > > >
> > > > [...]
> > > >
> > > > > > > @@ -1706,7 +1722,9 @@ int send_sig_fault(int sig, int code, void __user *addr
> > > > > > >       return send_sig_info(info.si_signo, &info, t);
> > > > > > >  }
> > > > > > >
> > > > > > > -int force_sig_mceerr(int code, void __user *addr, short lsb)
> > > > > > > +int force_sig_mceerr(int code, void __user *addr, short lsb,
> > > > > > > +                  unsigned long addr_ignored_bits,
> > > > > > > +                  unsigned long addr_ignored_bits_mask)
> > > > > >
> > > > > > Rather than having to pass these extra arguments all over the place, can
> > > > > > we just pass the far for addr, and have an arch-specific hook for
> > > > > > splitting the ignored from non-ignored bits.  For now at least, I expect
> > > > > > that ignored bits mask to be constant for a given platform and kernel.
> > > > >
> > > > > That sounds like a good idea. I think that for MTE we will want to
> > > > > make it conditional on the si_code (so SEGV_MTESERR would get 0xf <<
> > > > > 56 while everything else would get 0xff << 56) so I can hook that up
> > > > > at the same time.
> > > >
> > > > OK, I think that's reasonable.
> > > >
> > > > Mind you, we seem to have 3 kinds of bits here, so I'm starting to
> > > > wonder whether this is really sufficient:
> > > >
> > > >         1) address bits used in the faulted access
> > > >         2) attribute/permission bits used in the faulted access
> > > >         3) unavailable bits.
> > > >
> > > > si_addr contains (1).
> > > >
> > > > si_addr_ignored_bits contains (2).
> > > >
> > > > The tag bits from non-MTE faults seem to fall under case (3).  Code that
> > > > looks for these bits in si_addr_ignored_bits won't find them.
> > >
> > > I'm reasonably sure that the tag bits are available for non-MTE
> > > faults. From https://developer.arm.com/docs/ddi0595/h/aarch64-system-registers/far_el1
> > > :
> > > "For a Data Abort or Watchpoint exception, if address tagging is
> > > enabled for the address accessed by the data access that caused the
> > > exception, then this field includes the tag."
> >
> > Right, but I wonder whether it would still be good idea to have a way to
> > tell userspace which bits are valid.
> 
> I'm a bit confused by this. si_addr_ignored_bits_mask is exactly the
> mechanism for telling userspace which bits are valid. Or maybe you're
> arguing that we should consider *not* having the mask of valid bits in
> siginfo?
> 
> > Collecting and synchronising all the correct information for reporting a
> > fault is notoriously easy to mess up in the implementation, and
> > misreporting of the tag bits might be regarded as a tolerable fail.
> 
> It really depends. Imagine that a future change to the architecture
> exposes bits 60-63 in FAR_EL1 in tag fault errors (we have a number of
> ideas for how to use these bits to distinguish between different
> use-after-frees in error reports). It would be nice for userspace to
> be able to distinguish between the situation where bits 60-63 are 0
> and the situation where the bits are unknown, in order to avoid
> producing an incorrect/misleading report.
> 
> > We also don't get tag bits for prefetch aborts (which may be reported
> > via SIGSEGV).  Arguably the architecture doesn't allow a nonzero tag
> > (BR etc. likely just throw those bits on the floor).  But it might be
> > nice to be explicit about this.
> 
> If we view the PC as being a 64-bit value where the architecture does
> not allow setting bits 56-63, I think it would be correct to claim
> that addresses derived from the PC have bits 56-63 clear.
> 
> > Other architectures may also have other reasons why the additional bits
> > are sometimes available, sometimes not.
> 
> If this is the case for an architecture, it can always report the bits
> to be unavailable until it can figure out in which cases the bits are
> available.
> 
> > > This language applies to non-tag-check-fault data aborts but is
> > > superseded by the following paragraph for tag check faults:
> > > "For a synchronous Tag Check Fault abort, bits[63:60] are UNKNOWN."
> >
> > Right, so in this case we should squash those bits and not report them
> > in the mask.  Currently are you implying that these are address bits,
> > because you exclude them from si_addr_ignored_mask?
> 
> My intent was that these are implied to be unavailable bits, as they
> are not set in the architecturally-defined si_addr mask ~(0xff << 56)
> nor in si_addr_ignored_mask.

OK, I think part of my confusion here is coming from the "ignored_bits"
naming.

These really aren't ignored, but rather they are meaningful -- that's
why you're implementing this extension.  True, they're ignored for
addressing purposes (i.e., these bits can never distinguish a memory
location from a second, distinct, memory location).  So for backwards
compatibility we mask them out from si_addr.

In the interests of moving on to reviewing the actual code and avoiding
the discussion from getting too fragmented, can I suggest that you
don't reply in detail to this: I'll reflect, and then reiterate my
comments on the v10/v11 thread if I still have concerns.  I may not get
to it this week -- apologies for that -- but if I can start looking at
the updated series today I will.

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] 66+ messages in thread

* Re: [PATCH v9 5/6] signal: define the field siginfo.si_xflags
  2020-08-25 20:08               ` Peter Collingbourne
@ 2020-08-26 16:15                 ` Dave Martin
  -1 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-26 16:15 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 Tue, Aug 25, 2020 at 01:08:35PM -0700, Peter Collingbourne wrote:
> On Tue, Aug 25, 2020 at 7:47 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Mon, Aug 24, 2020 at 06:27:51PM -0700, Peter Collingbourne wrote:
> > > On Mon, Aug 24, 2020 at 7:03 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > > >
> > > > On Wed, Aug 19, 2020 at 06:37:25PM -0700, Peter Collingbourne wrote:
> > > > > On Wed, Aug 19, 2020 at 8:40 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > > > > >
> > > > > > On Mon, Aug 17, 2020 at 08:33:50PM -0700, Peter Collingbourne wrote:
> > > > > > > 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.
> > > > > > >
> > > > > > > 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.
> > > > > >
> > > > > > For clarity, is the new si_xflags field supposed to be valid for all
> > > > > > signal types, or just certain signals and si_codes?
> > > > >
> > > > > It is intended to be valid for all signal types that use the _sigfault
> > > > > union member of siginfo. As listed in siginfo.h these are: SIGILL,
> > > > > SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT.
> > > >
> > > > SIGSYS is similar to SIGILL, is that included also?
> > >
> > > I think that SIGSYS is covered by a separate _sigsys union member.
> > >
> > > > > > What happens for things like a rt_sigqueueinfo() from userspace?
> > > > >
> > > > > Hmm. Let's enumerate each of these things, which I believe are all of
> > > > > the call sites of the function copy_siginfo_from_user and related
> > > > > functions (correct me if I'm wrong):
> > > > >
> > > > > - ptrace(PTRACE_SETSIGINFO)
> > > > > - pidfd_send_signal
> > > > > - rt_sigqueueinfo
> > > > > - rt_tgsigqueueinfo
> > > > >
> > > > > We can handle the last three by observing that the kernel forbids
> > > > > sending a signal with these syscalls if si_code >= 0, so we can say
> > > > > that the value of si_xflags is only valid if si_code >= 0.
> > > >
> > > > Hmmm, that's what the code says (actually >= 0 or SI_TKILL), but it's
> > > > illogical.  Those are user signals, so there's no obvious reason why
> > > > userspace shouldn't be allowed to generate their siginfo.  It would
> > > > probably be better for the kernel to police si_pid etc. in the SI_USER
> > > > and SI_TKILL cases rather than flatly refusing, but I guess that's a
> > > > discussion for another day.
> > > >
> > > > I guess the combination of SI_FROMKERNEL() and the signal number being a
> > > > known fault signal if probably sufficient for now.
> > >
> > > In v10 I ended up adding a comment saying that si_xflags is only valid
> > > if 0 <= si_code < SI_KERNEL (the SI_KERNEL part was due to my
> > > discovery of kernel code that was calling force_sig(SIGSEGV) where
> > > force_sig uses the _kill union member). Your comment about SI_USER
> >
> > Although it's been there a long time, is this a bug?
> >
> > sigaction(2) says that SI_KERNEL can be reported for any signal, but
> > doesn't say how/why.  It also says that si_addr is [unconditionally]
> > valid for [kernel-generated] SIGSEGV.  ([] are my insertions).
> >
> > While it may be reasonable to expect userspace code to filter out user
> > signals before assuming that siginfo fields are value, requiring user
> > code to check for specific si_codes is a bit nastier.
> >
> > I rather suspect that little or no code out there is explicity checking
> > for SI_KERNEL before assuming that si_addr etc. are valid today.
> 
> Right, but maybe that can be attributed to poor documentation (in the
> man page), so maybe the right thing to do here is to make the
> documentation more explicit. The kernel code itself is fairly clear
> that SI_KERNEL does not use the _sigfault layout:
> https://github.com/torvalds/linux/blob/6a9dc5fd6170d0a41c8a14eb19e63d94bea5705a/kernel/signal.c#L3173
> 
> And note that force_sig does not make the si_addr field valid either,
> it sets it to 0 (on most architectures, as a result of si_addr
> overlapping si_pid/si_uid which get set to 0 by that function), which
> is not necessarily the correct value. For example, on 64-bit x86,
> executing this code:
> 
>   volatile auto ptr = (char *)0xfedcba9876543210;
>   *ptr = 42;
> 
> (i.e. accessing outside of the TASK_SIZE limit) will result in a call
> to force_sig(SIGSEGV) setting si_addr=0. But this is clearly not an
> accurate fault address. I don't know how x86 reports the fault address
> to the kernel in this case but maybe it simply isn't available for
> addresses larger than TASK_SIZE, so the right thing for the kernel to
> do would be to indicate that the address is unavailable (for example,
> by setting si_code=SI_KERNEL, as it is already doing). Then through
> documentation updates, userspace can know that si_code=SI_KERNEL means
> that the address is unavailable.
> 
> > > made me realize that is not exactly true (since kill and
> > > pidfd_send_signal can send a fault signal with si_code == SI_USER). I
> > > was not aware of the SI_FROMKERNEL() macro. In v11 I will update the
> > > comment to say that SI_FROMKERNEL(si) && si->si_code != SI_KERNEL must
> > > be true in order for si_xflags to be valid.
> >
> > Given the above, maybe it would be better to say nothing explicit about
> > SI_KERNEL, but make sure that the additional siginfo fields are sanely
> > zeroed anyway.
> 
> I think that for si_addr this happens as a result of setting
> si_pid/si_uid, and for the other fields this happens as a result of
> zeroing the padding between fields. I know that we'd prefer not to
> rely on zeroing padding, but perhaps the zero padding can more be seen
> as a last resort for keeping things working in case userspace fails to
> check for SI_KERNEL.

Yes, I think this is reasonable -- slightly icky, but it should work in
practice.

As you say, things are already a bit of a mess in this area, so the best
we can reasonably aim for just now is to avoid making it the situation
worse.


So, can we make the condition something like:

For a given signal delivery, si_xflags exists if and only if:

	a) the sigaction() trickery worked, _and_
	b) si_addr exists.


We could provide a helper macro for this test, but the condition for (b)
will be fragile and tend to bitrot unless the problem is addressed more
broadly.  Seems out of scope for this series, though.


[--- This is a digression, but:

Yielding SI_KERNEL for SIGSEGV seems to be against POSIX, unless
SI_KERNEL provides si_addr -- see [1]:

	[...] the following signal-specific information shall be
	available: [...] SIGSEGV, SIGBUS: void *si_addr: Address of
	faulting memory references.

(stated unconditionally).  Though, also:

	For some implementations, the value of si_addr may be
	inaccurate.

IMHO, raising SIGSEGV from the kernel with an si_code that doesn't
provide an si_addr (contents notwithstanding) is simply wrong, and in
some of the affected cases (such as access to kernel memory) it's wrong
to use non-POSIX codes at all.  This is obviously just access to a duff
address, so we should probably use SEGV_MAPERR for this.  POSIX permits
that si_addr is not always "accurate", so we could happily yield
si_addr == 0 for such cases, if we don't have the address or would
rather not expose it (though if the address came from userspace, it
probably doesn't hurt to expose it).

AFAICT, SI_KERNEL most naturally applies to situations that closely
resemble kill(2) but don't originate from userspace, such as when the
OOM killer kills a task.  It doesn't seem right to be reporting any such
thing via SIGSEGV.

Anyway, this is a separate discussion from this series...

 --

[1] SUSv7, signal.h:
https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html

---]

> 
> > For kernel-generated signals we can guarantee this, so I
> > think that requiring userspace to check explicitly for SI_KERNEL is too
> > unrealistic (i.e., 90% of the time, people will forget ... and 99% of
> > the time they will get away with it).
> 
> It's unfortunate that the conditions for accessing these fields are so
> complex, but again this seems like part of the hand that we've been
> dealt with this API. Fortunately the requirement to check for
> SI_KERNEL should only really apply in practice to code accessing our
> new fields. We can make it retroactively apply to existing fields, but
> since that wouldn't be a change to the kernel code, just the
> documentation, existing code will continue to operate in the same way
> as it did before.

Agreed.  Again, we should try not to make things worse, but that's all.

si_code stinks generally, because it's so inextensible.  There's no way
to add new values without leaving software utterly baffled (or more
likely mistaken, since software often ignores si_code or doesn't check
it exhaustively, before relying on si_* fields).

[...]

Cheers
---Dave

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

* Re: [PATCH v9 5/6] signal: define the field siginfo.si_xflags
@ 2020-08-26 16:15                 ` Dave Martin
  0 siblings, 0 replies; 66+ messages in thread
From: Dave Martin @ 2020-08-26 16:15 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 Tue, Aug 25, 2020 at 01:08:35PM -0700, Peter Collingbourne wrote:
> On Tue, Aug 25, 2020 at 7:47 AM Dave Martin <Dave.Martin@arm.com> wrote:
> >
> > On Mon, Aug 24, 2020 at 06:27:51PM -0700, Peter Collingbourne wrote:
> > > On Mon, Aug 24, 2020 at 7:03 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > > >
> > > > On Wed, Aug 19, 2020 at 06:37:25PM -0700, Peter Collingbourne wrote:
> > > > > On Wed, Aug 19, 2020 at 8:40 AM Dave Martin <Dave.Martin@arm.com> wrote:
> > > > > >
> > > > > > On Mon, Aug 17, 2020 at 08:33:50PM -0700, Peter Collingbourne wrote:
> > > > > > > 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.
> > > > > > >
> > > > > > > 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.
> > > > > >
> > > > > > For clarity, is the new si_xflags field supposed to be valid for all
> > > > > > signal types, or just certain signals and si_codes?
> > > > >
> > > > > It is intended to be valid for all signal types that use the _sigfault
> > > > > union member of siginfo. As listed in siginfo.h these are: SIGILL,
> > > > > SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT.
> > > >
> > > > SIGSYS is similar to SIGILL, is that included also?
> > >
> > > I think that SIGSYS is covered by a separate _sigsys union member.
> > >
> > > > > > What happens for things like a rt_sigqueueinfo() from userspace?
> > > > >
> > > > > Hmm. Let's enumerate each of these things, which I believe are all of
> > > > > the call sites of the function copy_siginfo_from_user and related
> > > > > functions (correct me if I'm wrong):
> > > > >
> > > > > - ptrace(PTRACE_SETSIGINFO)
> > > > > - pidfd_send_signal
> > > > > - rt_sigqueueinfo
> > > > > - rt_tgsigqueueinfo
> > > > >
> > > > > We can handle the last three by observing that the kernel forbids
> > > > > sending a signal with these syscalls if si_code >= 0, so we can say
> > > > > that the value of si_xflags is only valid if si_code >= 0.
> > > >
> > > > Hmmm, that's what the code says (actually >= 0 or SI_TKILL), but it's
> > > > illogical.  Those are user signals, so there's no obvious reason why
> > > > userspace shouldn't be allowed to generate their siginfo.  It would
> > > > probably be better for the kernel to police si_pid etc. in the SI_USER
> > > > and SI_TKILL cases rather than flatly refusing, but I guess that's a
> > > > discussion for another day.
> > > >
> > > > I guess the combination of SI_FROMKERNEL() and the signal number being a
> > > > known fault signal if probably sufficient for now.
> > >
> > > In v10 I ended up adding a comment saying that si_xflags is only valid
> > > if 0 <= si_code < SI_KERNEL (the SI_KERNEL part was due to my
> > > discovery of kernel code that was calling force_sig(SIGSEGV) where
> > > force_sig uses the _kill union member). Your comment about SI_USER
> >
> > Although it's been there a long time, is this a bug?
> >
> > sigaction(2) says that SI_KERNEL can be reported for any signal, but
> > doesn't say how/why.  It also says that si_addr is [unconditionally]
> > valid for [kernel-generated] SIGSEGV.  ([] are my insertions).
> >
> > While it may be reasonable to expect userspace code to filter out user
> > signals before assuming that siginfo fields are value, requiring user
> > code to check for specific si_codes is a bit nastier.
> >
> > I rather suspect that little or no code out there is explicity checking
> > for SI_KERNEL before assuming that si_addr etc. are valid today.
> 
> Right, but maybe that can be attributed to poor documentation (in the
> man page), so maybe the right thing to do here is to make the
> documentation more explicit. The kernel code itself is fairly clear
> that SI_KERNEL does not use the _sigfault layout:
> https://github.com/torvalds/linux/blob/6a9dc5fd6170d0a41c8a14eb19e63d94bea5705a/kernel/signal.c#L3173
> 
> And note that force_sig does not make the si_addr field valid either,
> it sets it to 0 (on most architectures, as a result of si_addr
> overlapping si_pid/si_uid which get set to 0 by that function), which
> is not necessarily the correct value. For example, on 64-bit x86,
> executing this code:
> 
>   volatile auto ptr = (char *)0xfedcba9876543210;
>   *ptr = 42;
> 
> (i.e. accessing outside of the TASK_SIZE limit) will result in a call
> to force_sig(SIGSEGV) setting si_addr=0. But this is clearly not an
> accurate fault address. I don't know how x86 reports the fault address
> to the kernel in this case but maybe it simply isn't available for
> addresses larger than TASK_SIZE, so the right thing for the kernel to
> do would be to indicate that the address is unavailable (for example,
> by setting si_code=SI_KERNEL, as it is already doing). Then through
> documentation updates, userspace can know that si_code=SI_KERNEL means
> that the address is unavailable.
> 
> > > made me realize that is not exactly true (since kill and
> > > pidfd_send_signal can send a fault signal with si_code == SI_USER). I
> > > was not aware of the SI_FROMKERNEL() macro. In v11 I will update the
> > > comment to say that SI_FROMKERNEL(si) && si->si_code != SI_KERNEL must
> > > be true in order for si_xflags to be valid.
> >
> > Given the above, maybe it would be better to say nothing explicit about
> > SI_KERNEL, but make sure that the additional siginfo fields are sanely
> > zeroed anyway.
> 
> I think that for si_addr this happens as a result of setting
> si_pid/si_uid, and for the other fields this happens as a result of
> zeroing the padding between fields. I know that we'd prefer not to
> rely on zeroing padding, but perhaps the zero padding can more be seen
> as a last resort for keeping things working in case userspace fails to
> check for SI_KERNEL.

Yes, I think this is reasonable -- slightly icky, but it should work in
practice.

As you say, things are already a bit of a mess in this area, so the best
we can reasonably aim for just now is to avoid making it the situation
worse.


So, can we make the condition something like:

For a given signal delivery, si_xflags exists if and only if:

	a) the sigaction() trickery worked, _and_
	b) si_addr exists.


We could provide a helper macro for this test, but the condition for (b)
will be fragile and tend to bitrot unless the problem is addressed more
broadly.  Seems out of scope for this series, though.


[--- This is a digression, but:

Yielding SI_KERNEL for SIGSEGV seems to be against POSIX, unless
SI_KERNEL provides si_addr -- see [1]:

	[...] the following signal-specific information shall be
	available: [...] SIGSEGV, SIGBUS: void *si_addr: Address of
	faulting memory references.

(stated unconditionally).  Though, also:

	For some implementations, the value of si_addr may be
	inaccurate.

IMHO, raising SIGSEGV from the kernel with an si_code that doesn't
provide an si_addr (contents notwithstanding) is simply wrong, and in
some of the affected cases (such as access to kernel memory) it's wrong
to use non-POSIX codes at all.  This is obviously just access to a duff
address, so we should probably use SEGV_MAPERR for this.  POSIX permits
that si_addr is not always "accurate", so we could happily yield
si_addr == 0 for such cases, if we don't have the address or would
rather not expose it (though if the address came from userspace, it
probably doesn't hurt to expose it).

AFAICT, SI_KERNEL most naturally applies to situations that closely
resemble kill(2) but don't originate from userspace, such as when the
OOM killer kills a task.  It doesn't seem right to be reporting any such
thing via SIGSEGV.

Anyway, this is a separate discussion from this series...

 --

[1] SUSv7, signal.h:
https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html

---]

> 
> > For kernel-generated signals we can guarantee this, so I
> > think that requiring userspace to check explicitly for SI_KERNEL is too
> > unrealistic (i.e., 90% of the time, people will forget ... and 99% of
> > the time they will get away with it).
> 
> It's unfortunate that the conditions for accessing these fields are so
> complex, but again this seems like part of the hand that we've been
> dealt with this API. Fortunately the requirement to check for
> SI_KERNEL should only really apply in practice to code accessing our
> new fields. We can make it retroactively apply to existing fields, but
> since that wouldn't be a change to the kernel code, just the
> documentation, existing code will continue to operate in the same way
> as it did before.

Agreed.  Again, we should try not to make things worse, but that's all.

si_code stinks generally, because it's so inextensible.  There's no way
to add new values without leaving software utterly baffled (or more
likely mistaken, since software often ignores si_code or doesn't check
it exhaustively, before relying on si_* fields).

[...]

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] 66+ messages in thread

end of thread, other threads:[~2020-08-26 16:17 UTC | newest]

Thread overview: 66+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-18  3:33 [PATCH v9 0/6] arm64: expose FAR_EL1 tag bits in siginfo Peter Collingbourne
2020-08-18  3:33 ` Peter Collingbourne
2020-08-18  3:33 ` [PATCH v9 1/6] parisc: start using signal-defs.h Peter Collingbourne
2020-08-18  3:33   ` Peter Collingbourne
2020-08-18  3:33 ` [PATCH v9 2/6] arch: move SA_* definitions to generic headers Peter Collingbourne
2020-08-18  3:33   ` Peter Collingbourne
2020-08-19  7:13   ` Geert Uytterhoeven
2020-08-19  7:13     ` Geert Uytterhoeven
2020-08-19 22:44     ` Peter Collingbourne
2020-08-19 22:44       ` Peter Collingbourne
2020-08-19 10:30   ` Dave Martin
2020-08-19 10:30     ` Dave Martin
2020-08-19 21:35     ` Peter Collingbourne
2020-08-19 21:35       ` Peter Collingbourne
2020-08-18  3:33 ` [PATCH v9 3/6] signal: clear non-uapi flag bits when passing/returning sa_flags Peter Collingbourne
2020-08-18  3:33   ` Peter Collingbourne
2020-08-19 10:39   ` Dave Martin
2020-08-19 10:39     ` Dave Martin
2020-08-19 23:39     ` Peter Collingbourne
2020-08-19 23:39       ` Peter Collingbourne
2020-08-24 13:40       ` Dave Martin
2020-08-24 13:40         ` Dave Martin
2020-08-25  0:51         ` Peter Collingbourne
2020-08-25  0:51           ` Peter Collingbourne
2020-08-25 14:25           ` Dave Martin
2020-08-25 14:25             ` Dave Martin
2020-08-18  3:33 ` [PATCH v9 4/6] signal: define the SA_UNSUPPORTED bit in sa_flags Peter Collingbourne
2020-08-18  3:33   ` Peter Collingbourne
2020-08-19 14:51   ` Dave Martin
2020-08-19 14:51     ` Dave Martin
2020-08-20  0:23     ` Peter Collingbourne
2020-08-20  0:23       ` Peter Collingbourne
2020-08-24 13:41       ` Dave Martin
2020-08-24 13:41         ` Dave Martin
2020-08-18  3:33 ` [PATCH v9 5/6] signal: define the field siginfo.si_xflags Peter Collingbourne
2020-08-18  3:33   ` Peter Collingbourne
2020-08-19 15:40   ` Dave Martin
2020-08-19 15:40     ` Dave Martin
2020-08-20  1:37     ` Peter Collingbourne
2020-08-20  1:37       ` Peter Collingbourne
2020-08-24 14:03       ` Dave Martin
2020-08-24 14:03         ` Dave Martin
2020-08-25  1:27         ` Peter Collingbourne
2020-08-25  1:27           ` Peter Collingbourne
2020-08-25 14:47           ` Dave Martin
2020-08-25 14:47             ` Dave Martin
2020-08-25 20:08             ` Peter Collingbourne
2020-08-25 20:08               ` Peter Collingbourne
2020-08-26 16:15               ` Dave Martin
2020-08-26 16:15                 ` Dave Martin
2020-08-18  3:33 ` [PATCH v9 6/6] arm64: expose FAR_EL1 tag bits in siginfo Peter Collingbourne
2020-08-18  3:33   ` Peter Collingbourne
2020-08-19 15:56   ` Dave Martin
2020-08-19 15:56     ` Dave Martin
2020-08-20  1:49     ` Peter Collingbourne
2020-08-20  1:49       ` Peter Collingbourne
2020-08-24 14:23       ` Dave Martin
2020-08-24 14:23         ` Dave Martin
2020-08-25  2:18         ` Peter Collingbourne
2020-08-25  2:18           ` Peter Collingbourne
2020-08-25 15:02           ` Dave Martin
2020-08-25 15:02             ` Dave Martin
2020-08-25 22:06             ` Peter Collingbourne
2020-08-25 22:06               ` Peter Collingbourne
2020-08-26 15:32               ` Dave Martin
2020-08-26 15:32                 ` 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.