linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v16 0/6] arm64: expose FAR_EL1 tag bits in siginfo
@ 2020-11-13  2:53 Peter Collingbourne
  2020-11-13  2:53 ` [PATCH v16 1/6] parisc: Drop parisc special case for __sighandler_t Peter Collingbourne
                   ` (5 more replies)
  0 siblings, 6 replies; 19+ messages in thread
From: Peter Collingbourne @ 2020-11-13  2:53 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: Andrey Konovalov, Helge Deller, Kevin Brodsky, linux-api,
	David Spickett, Peter Collingbourne, Linux ARM

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, introduce a flag in
sigaction.sa_flags, SA_EXPOSE_TAGBITS, and only expose the tag bits
there if the signal handler has this flag set.

In order to allow userspace to determine whether SA_EXPOSE_TAGBITS
is supported, we first introduce a mechanism for userspace to detect
kernel support for SA_* flags.

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

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

Helge Deller (1):
  parisc: Drop parisc special case for __sighandler_t

Peter Collingbourne (5):
  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
  arm64: expose FAR_EL1 tag bits in siginfo

 Documentation/arm64/tagged-pointers.rst | 25 ++++++---
 arch/alpha/include/uapi/asm/signal.h    | 14 -----
 arch/arm/include/asm/signal.h           |  2 +
 arch/arm/include/uapi/asm/signal.h      | 27 ++--------
 arch/arm64/include/asm/exception.h      |  2 +-
 arch/arm64/include/asm/signal.h         | 25 +++++++++
 arch/arm64/include/asm/system_misc.h    |  2 +-
 arch/arm64/include/asm/traps.h          |  6 +--
 arch/arm64/kernel/debug-monitors.c      |  5 +-
 arch/arm64/kernel/entry-common.c        |  2 -
 arch/arm64/kernel/ptrace.c              |  7 +--
 arch/arm64/kernel/sys_compat.c          |  5 +-
 arch/arm64/kernel/traps.c               | 29 ++++++-----
 arch/arm64/mm/fault.c                   | 68 ++++++++++++++-----------
 arch/h8300/include/uapi/asm/signal.h    | 24 ---------
 arch/ia64/include/uapi/asm/signal.h     | 24 ---------
 arch/m68k/include/uapi/asm/signal.h     | 24 ---------
 arch/mips/include/uapi/asm/signal.h     | 12 -----
 arch/parisc/include/asm/signal.h        |  2 +
 arch/parisc/include/uapi/asm/signal.h   | 34 +------------
 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/x86/kernel/signal_compat.c         |  7 ---
 arch/xtensa/include/uapi/asm/signal.h   | 24 ---------
 include/linux/signal.h                  | 14 +++++
 include/linux/signal_types.h            | 12 +++++
 include/uapi/asm-generic/signal-defs.h  | 57 +++++++++++++++++++++
 include/uapi/asm-generic/signal.h       | 29 -----------
 kernel/signal.c                         | 39 +++++++++++---
 31 files changed, 231 insertions(+), 366 deletions(-)
 create mode 100644 arch/arm64/include/asm/signal.h

-- 
2.29.2.299.gdc1121823c-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] 19+ messages in thread

* [PATCH v16 1/6] parisc: Drop parisc special case for __sighandler_t
  2020-11-13  2:53 [PATCH v16 0/6] arm64: expose FAR_EL1 tag bits in siginfo Peter Collingbourne
@ 2020-11-13  2:53 ` Peter Collingbourne
  2020-11-13  2:53 ` [PATCH v16 2/6] parisc: start using signal-defs.h Peter Collingbourne
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 19+ messages in thread
From: Peter Collingbourne @ 2020-11-13  2:53 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: Andrey Konovalov, Helge Deller, Kevin Brodsky, linux-api,
	David Spickett, Peter Collingbourne, Linux ARM

From: Helge Deller <deller@gmx.de>

I believe we can and *should* drop this parisc-specific typedef for
__sighandler_t when compiling a 64-bit kernel. The reasons:

1. We don't have a 64-bit userspace yet, so nothing (on userspace side)
can break.

2. Inside the Linux kernel, this is only used in kernel/signal.c, in
function kernel_sigaction() where the signal handler is compared against
SIG_IGN.  SIG_IGN is defined as (__sighandler_t)1), so only the pointers
are compared.

3. Even when a 64-bit userspace gets added at some point, I think
__sighandler_t should be defined what it is: a function pointer struct.

I compiled kernel/signal.c with and without the patch, and the produced code
is identical in both cases.

Signed-off-by: Helge Deller <deller@gmx.de>
Signed-off-by: Peter Collingbourne <pcc@google.com>
Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>
Reviewed-by: Peter Collingbourne <pcc@google.com>
Link: https://linux-review.googlesource.com/id/I21c43f21b264f339e3aa395626af838646f62d97
---
 arch/parisc/include/uapi/asm/signal.h | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/arch/parisc/include/uapi/asm/signal.h b/arch/parisc/include/uapi/asm/signal.h
index e605197b462c..d9c51769851a 100644
--- a/arch/parisc/include/uapi/asm/signal.h
+++ b/arch/parisc/include/uapi/asm/signal.h
@@ -85,16 +85,8 @@
 struct siginfo;
 
 /* Type of a signal handler.  */
-#if defined(__LP64__)
-/* function pointers on 64-bit parisc are pointers to little structs and the
- * compiler doesn't support code which changes or tests the address of
- * the function in the little struct.  This is really ugly -PB
- */
-typedef char __user *__sighandler_t;
-#else
 typedef void __signalfn_t(int);
 typedef __signalfn_t __user *__sighandler_t;
-#endif
 
 typedef struct sigaltstack {
 	void __user *ss_sp;
-- 
2.29.2.299.gdc1121823c-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] 19+ messages in thread

* [PATCH v16 2/6] parisc: start using signal-defs.h
  2020-11-13  2:53 [PATCH v16 0/6] arm64: expose FAR_EL1 tag bits in siginfo Peter Collingbourne
  2020-11-13  2:53 ` [PATCH v16 1/6] parisc: Drop parisc special case for __sighandler_t Peter Collingbourne
@ 2020-11-13  2:53 ` Peter Collingbourne
  2020-11-13  2:53 ` [PATCH v16 3/6] arch: move SA_* definitions to generic headers Peter Collingbourne
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 19+ messages in thread
From: Peter Collingbourne @ 2020-11-13  2:53 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: Andrey Konovalov, Helge Deller, Kevin Brodsky, linux-api,
	David Spickett, Peter Collingbourne, Linux ARM

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>
Acked-by: Helge Deller <deller@gmx.de>
Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>
Link: https://linux-review.googlesource.com/id/If03a5135fb514fe96548fb74610e6c3586a04064
---
 arch/parisc/include/uapi/asm/signal.h | 13 +------------
 1 file changed, 1 insertion(+), 12 deletions(-)

diff --git a/arch/parisc/include/uapi/asm/signal.h b/arch/parisc/include/uapi/asm/signal.h
index d9c51769851a..9e6f87bc8a73 100644
--- a/arch/parisc/include/uapi/asm/signal.h
+++ b/arch/parisc/include/uapi/asm/signal.h
@@ -68,14 +68,7 @@
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
 
-
-#define SIG_BLOCK          0	/* for blocking signals */
-#define SIG_UNBLOCK        1	/* for unblocking signals */
-#define SIG_SETMASK        2	/* for setting the signal mask */
-
-#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
-#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
-#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+#include <asm-generic/signal-defs.h>
 
 # ifndef __ASSEMBLY__
 
@@ -84,10 +77,6 @@
 /* Avoid too many header ordering problems.  */
 struct siginfo;
 
-/* Type of a signal handler.  */
-typedef void __signalfn_t(int);
-typedef __signalfn_t __user *__sighandler_t;
-
 typedef struct sigaltstack {
 	void __user *ss_sp;
 	int ss_flags;
-- 
2.29.2.299.gdc1121823c-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] 19+ messages in thread

* [PATCH v16 3/6] arch: move SA_* definitions to generic headers
  2020-11-13  2:53 [PATCH v16 0/6] arm64: expose FAR_EL1 tag bits in siginfo Peter Collingbourne
  2020-11-13  2:53 ` [PATCH v16 1/6] parisc: Drop parisc special case for __sighandler_t Peter Collingbourne
  2020-11-13  2:53 ` [PATCH v16 2/6] parisc: start using signal-defs.h Peter Collingbourne
@ 2020-11-13  2:53 ` Peter Collingbourne
  2020-11-13  2:53 ` [PATCH v16 4/6] signal: clear non-uapi flag bits when passing/returning sa_flags Peter Collingbourne
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 19+ messages in thread
From: Peter Collingbourne @ 2020-11-13  2:53 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: Andrey Konovalov, Helge Deller, Kevin Brodsky,
	Geert Uytterhoeven, linux-api, David Spickett,
	Peter Collingbourne, Linux ARM

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.

A consequence of this change is that on powerpc and x86, the constants'
values aside from SA_RESETHAND change signedness from unsigned
to signed. This is not expected to impact realistic use of these
constants. In particular the typical use of the constants where they
are or'ed together and assigned to sa_flags (or another int variable)
would not be affected.

Signed-off-by: Peter Collingbourne <pcc@google.com>
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>
Reviewed-by: Dave Martin <Dave.Martin@arm.com>
Link: https://linux-review.googlesource.com/id/Ia3849f18b8009bf41faca374e701cdca36974528
---
v14:
- revert unintentional removal of SA_RESTORER on arm as pointed
  out by Eric

v11:
- tweak the commit message to point out the change from unsigned
  to signed

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

 arch/alpha/include/uapi/asm/signal.h   | 14 --------
 arch/arm/include/uapi/asm/signal.h     | 27 ++-------------
 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(+), 263 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..c9a3ea1d8d41 100644
--- a/arch/arm/include/uapi/asm/signal.h
+++ b/arch/arm/include/uapi/asm/signal.h
@@ -60,33 +60,12 @@ 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 9e6f87bc8a73..e5a2657477ac 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
 
-/*
- * 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 e9304c95ceea..493953fe319b 100644
--- a/include/uapi/asm-generic/signal-defs.h
+++ b/include/uapi/asm-generic/signal-defs.h
@@ -4,6 +4,53 @@
 
 #include <linux/compiler.h>
 
+/*
+ * SA_FLAGS values:
+ *
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_SIGINFO delivers the signal with SIGINFO structs.
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ *
+ * The following bits are used in architecture-specific SA_* definitions and
+ * should be avoided for new generic flags: 3, 4, 5, 6, 7, 8, 9, 16, 24, 25, 26.
+ */
+#ifndef SA_NOCLDSTOP
+#define SA_NOCLDSTOP	0x00000001
+#endif
+#ifndef SA_NOCLDWAIT
+#define SA_NOCLDWAIT	0x00000002
+#endif
+#ifndef SA_SIGINFO
+#define SA_SIGINFO	0x00000004
+#endif
+#ifndef SA_ONSTACK
+#define SA_ONSTACK	0x08000000
+#endif
+#ifndef SA_RESTART
+#define SA_RESTART	0x10000000
+#endif
+#ifndef SA_NODEFER
+#define SA_NODEFER	0x40000000
+#endif
+#ifndef SA_RESETHAND
+#define SA_RESETHAND	0x80000000
+#endif
+
+#define SA_NOMASK	SA_NODEFER
+#define SA_ONESHOT	SA_RESETHAND
+
+/*
+ * New architectures should not define the obsolete
+ *	SA_RESTORER	0x04000000
+ */
+
 #ifndef SIG_BLOCK
 #define SIG_BLOCK          0	/* for blocking signals */
 #endif
diff --git a/include/uapi/asm-generic/signal.h b/include/uapi/asm-generic/signal.h
index 5c716a952cbe..f634822906e4 100644
--- a/include/uapi/asm-generic/signal.h
+++ b/include/uapi/asm-generic/signal.h
@@ -52,35 +52,6 @@
 #define SIGRTMAX	_NSIG
 #endif
 
-/*
- * SA_FLAGS values:
- *
- * SA_ONSTACK indicates that a registered stack_t will be used.
- * SA_RESTART flag to get restarting signals (which were the default long ago)
- * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
- * SA_RESETHAND clears the handler when the signal is delivered.
- * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
- * SA_NODEFER prevents the current signal from being masked in the handler.
- *
- * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
- * Unix names RESETHAND and NODEFER respectively.
- */
-#define SA_NOCLDSTOP	0x00000001
-#define SA_NOCLDWAIT	0x00000002
-#define SA_SIGINFO	0x00000004
-#define SA_ONSTACK	0x08000000
-#define SA_RESTART	0x10000000
-#define SA_NODEFER	0x40000000
-#define SA_RESETHAND	0x80000000
-
-#define SA_NOMASK	SA_NODEFER
-#define SA_ONESHOT	SA_RESETHAND
-
-/*
- * New architectures should not define the obsolete
- *	SA_RESTORER	0x04000000
- */
-
 #if !defined MINSIGSTKSZ || !defined SIGSTKSZ
 #define MINSIGSTKSZ	2048
 #define SIGSTKSZ	8192
-- 
2.29.2.299.gdc1121823c-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] 19+ messages in thread

* [PATCH v16 4/6] signal: clear non-uapi flag bits when passing/returning sa_flags
  2020-11-13  2:53 [PATCH v16 0/6] arm64: expose FAR_EL1 tag bits in siginfo Peter Collingbourne
                   ` (2 preceding siblings ...)
  2020-11-13  2:53 ` [PATCH v16 3/6] arch: move SA_* definitions to generic headers Peter Collingbourne
@ 2020-11-13  2:53 ` Peter Collingbourne
  2020-11-13  2:53 ` [PATCH v16 5/6] signal: define the SA_UNSUPPORTED bit in sa_flags Peter Collingbourne
  2020-11-13  2:53 ` [PATCH v16 6/6] arm64: expose FAR_EL1 tag bits in siginfo Peter Collingbourne
  5 siblings, 0 replies; 19+ messages in thread
From: Peter Collingbourne @ 2020-11-13  2:53 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: Andrey Konovalov, Helge Deller, Kevin Brodsky, linux-api,
	David Spickett, Peter Collingbourne, Linux ARM

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

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

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

Link: [1] https://github.com/openbsd/src/blob/f634a6a4b5bf832e9c1de77f7894ae2625e74484/sys/kern/kern_sig.c#L278
Link: [2] https://github.com/illumos/illumos-gate/blob/76f19f5fdc974fe5be5c82a556e43a4df93f1de1/usr/src/uts/common/syscall/sigaction.c#L86
Link: [3] https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/kern/kern_sig.c#L480
Link: [4] https://github.com/freebsd/freebsd/blob/eded70c37057857c6e23fae51f86b8f8f43cd2d0/sys/kern/kern_sig.c#L699
Link: [5] https://github.com/NetBSD/src/blob/3365779becdcedfca206091a645a0e8e22b2946e/sys/kern/sys_sig.c#L473
Signed-off-by: Peter Collingbourne <pcc@google.com>
Reviewed-by: Dave Martin <Dave.Martin@arm.com>
Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>
Link: https://linux-review.googlesource.com/id/I35aab6f5be932505d90f3b3450c083b4db1eca86
---
v10:
- rename SA_UAPI_FLAGS -> UAPI_SA_FLAGS
- refactor how we define it to avoid mentioning flags more
  than once

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

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

* [PATCH v16 5/6] signal: define the SA_UNSUPPORTED bit in sa_flags
  2020-11-13  2:53 [PATCH v16 0/6] arm64: expose FAR_EL1 tag bits in siginfo Peter Collingbourne
                   ` (3 preceding siblings ...)
  2020-11-13  2:53 ` [PATCH v16 4/6] signal: clear non-uapi flag bits when passing/returning sa_flags Peter Collingbourne
@ 2020-11-13  2:53 ` Peter Collingbourne
  2020-11-14 13:53   ` Eric W. Biederman
  2020-11-13  2:53 ` [PATCH v16 6/6] arm64: expose FAR_EL1 tag bits in siginfo Peter Collingbourne
  5 siblings, 1 reply; 19+ messages in thread
From: Peter Collingbourne @ 2020-11-13  2:53 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: Andrey Konovalov, Helge Deller, Kevin Brodsky, linux-api,
	David Spickett, Peter Collingbourne, Linux ARM

Define a sa_flags bit, SA_UNSUPPORTED, which 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 does something like:

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

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

Signed-off-by: Peter Collingbourne <pcc@google.com>
Reviewed-by: Dave Martin <Dave.Martin@arm.com>
Link: https://linux-review.googlesource.com/id/Ic2501ad150a3a79c1cf27fb8c99be342e9dffbcb
---
v11:
- clarify the commit message

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

* [PATCH v16 6/6] arm64: expose FAR_EL1 tag bits in siginfo
  2020-11-13  2:53 [PATCH v16 0/6] arm64: expose FAR_EL1 tag bits in siginfo Peter Collingbourne
                   ` (4 preceding siblings ...)
  2020-11-13  2:53 ` [PATCH v16 5/6] signal: define the SA_UNSUPPORTED bit in sa_flags Peter Collingbourne
@ 2020-11-13  2:53 ` Peter Collingbourne
  2020-11-15 14:08   ` Eric W. Biederman
  2020-11-16 19:01   ` Catalin Marinas
  5 siblings, 2 replies; 19+ messages in thread
From: Peter Collingbourne @ 2020-11-13  2:53 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: Andrey Konovalov, Helge Deller, Kevin Brodsky, linux-api,
	David Spickett, Peter Collingbourne, Linux ARM

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, introduce a flag in
sigaction.sa_flags, SA_EXPOSE_TAGBITS, and only expose the tag bits
there if the signal handler has this flag set.

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

Signed-off-by: Peter Collingbourne <pcc@google.com>
Link: https://linux-review.googlesource.com/id/Ia8876bad8c798e0a32df7c2ce1256c4771c81446
---
v16:
- add missing file

v15:
- switched to the SA_EXPOSE_TAGBITS approach
  proposed by Eric
- rebased to 5.10-rc3

v14:
- fix an inaccuracy in the commit message
- add some comments to arch_addr_tag_bits_mask

v13:
- renamed si_xflags to si_faultflags
- rebased to 5.10-rc2

v12:
- add new fields to signal_compat.c test cases
- rebased to 5.10-rc1
- mask out bits 63:60 for tag check faults

v11:
- add a comment explaining what the arch hook should do
- rename ignored bits to tag bits

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

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

v8:
- rebase onto 5.8rc2

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

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

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

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

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

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

 Documentation/arm64/tagged-pointers.rst | 25 ++++++---
 arch/arm64/include/asm/exception.h      |  2 +-
 arch/arm64/include/asm/signal.h         | 25 +++++++++
 arch/arm64/include/asm/system_misc.h    |  2 +-
 arch/arm64/include/asm/traps.h          |  6 +--
 arch/arm64/kernel/debug-monitors.c      |  5 +-
 arch/arm64/kernel/entry-common.c        |  2 -
 arch/arm64/kernel/ptrace.c              |  7 +--
 arch/arm64/kernel/sys_compat.c          |  5 +-
 arch/arm64/kernel/traps.c               | 29 ++++++-----
 arch/arm64/mm/fault.c                   | 68 ++++++++++++++-----------
 include/linux/signal.h                  | 14 +++++
 include/linux/signal_types.h            |  2 +-
 include/uapi/asm-generic/signal-defs.h  |  3 ++
 kernel/signal.c                         | 23 ++++++---
 15 files changed, 141 insertions(+), 77 deletions(-)
 create mode 100644 arch/arm64/include/asm/signal.h

diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst
index eab4323609b9..19d284b70384 100644
--- a/Documentation/arm64/tagged-pointers.rst
+++ b/Documentation/arm64/tagged-pointers.rst
@@ -53,12 +53,25 @@ 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.
+When delivering signals, non-zero tags are not preserved in
+siginfo.si_addr unless the flag SA_EXPOSE_TAGBITS was set in
+sigaction.sa_flags when the signal handler was installed. 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 unless the flag was set.
+
+Due to architecture limitations, bits 63:60 of the fault address
+are not preserved in response to synchronous tag check faults
+(SEGV_MTESERR) even if SA_EXPOSE_TAGBITS was set. Applications should
+treat the values of these bits as undefined in order to accommodate
+future architecture revisions which may preserve the bits.
+
+For signals raised in response to watchpoint debug exceptions, the
+tag information will be preserved regardless of the SA_EXPOSE_TAGBITS
+flag setting.
+
+Non-zero tags are never preserved in sigcontext.fault_address
+regardless of the SA_EXPOSE_TAGBITS flag setting.
 
 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 99b9383cd036..2a8aa1884d8a 100644
--- a/arch/arm64/include/asm/exception.h
+++ b/arch/arm64/include/asm/exception.h
@@ -32,7 +32,7 @@ static inline u32 disr_to_esr(u64 disr)
 }
 
 asmlinkage void enter_from_user_mode(void);
-void do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs);
+void do_mem_abort(unsigned long far, unsigned int esr, struct pt_regs *regs);
 void do_undefinstr(struct pt_regs *regs);
 void do_bti(struct pt_regs *regs);
 asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr);
diff --git a/arch/arm64/include/asm/signal.h b/arch/arm64/include/asm/signal.h
new file mode 100644
index 000000000000..ef449f5f4ba8
--- /dev/null
+++ b/arch/arm64/include/asm/signal.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ARM64_ASM_SIGNAL_H
+#define __ARM64_ASM_SIGNAL_H
+
+#include <asm/memory.h>
+#include <uapi/asm/signal.h>
+#include <uapi/asm/siginfo.h>
+
+static inline void __user *arch_untagged_si_addr(void __user *addr,
+						 unsigned long sig,
+						 unsigned long si_code)
+{
+	/*
+	 * For historical reasons, all bits of the fault address are exposed as
+	 * address bits for watchpoint exceptions. New architectures should
+	 * handle the tag bits consistently.
+	 */
+	if (sig == SIGTRAP && si_code == TRAP_BRKPT)
+		return addr;
+
+	return untagged_addr(addr);
+}
+#define arch_untagged_si_addr arch_untagged_si_addr
+
+#endif
diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h
index 1ab63cfbbaf1..673be2d1263c 100644
--- a/arch/arm64/include/asm/system_misc.h
+++ b/arch/arm64/include/asm/system_misc.h
@@ -22,7 +22,7 @@ void die(const char *msg, struct pt_regs *regs, int err);
 
 struct siginfo;
 void arm64_notify_die(const char *str, struct pt_regs *regs,
-		      int signo, int sicode, void __user *addr,
+		      int signo, int sicode, unsigned long far,
 		      int err);
 
 void hook_debug_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h
index d96dc2c7c09d..54f32a0675df 100644
--- a/arch/arm64/include/asm/traps.h
+++ b/arch/arm64/include/asm/traps.h
@@ -26,9 +26,9 @@ void register_undef_hook(struct undef_hook *hook);
 void unregister_undef_hook(struct undef_hook *hook);
 void force_signal_inject(int signal, int code, unsigned long address, unsigned int err);
 void arm64_notify_segfault(unsigned long addr);
-void arm64_force_sig_fault(int signo, int code, void __user *addr, const char *str);
-void arm64_force_sig_mceerr(int code, void __user *addr, short lsb, const char *str);
-void arm64_force_sig_ptrace_errno_trap(int errno, void __user *addr, const char *str);
+void arm64_force_sig_fault(int signo, int code, unsigned long far, const char *str);
+void arm64_force_sig_mceerr(int code, unsigned long far, short lsb, const char *str);
+void arm64_force_sig_ptrace_errno_trap(int errno, unsigned long far, const char *str);
 
 /*
  * Move regs->pc to next instruction and do necessary setup before it
diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
index fa76151de6ff..4f3661eeb7ec 100644
--- a/arch/arm64/kernel/debug-monitors.c
+++ b/arch/arm64/kernel/debug-monitors.c
@@ -234,9 +234,8 @@ static void send_user_sigtrap(int si_code)
 	if (interrupts_enabled(regs))
 		local_irq_enable();
 
-	arm64_force_sig_fault(SIGTRAP, si_code,
-			     (void __user *)instruction_pointer(regs),
-			     "User debug trap");
+	arm64_force_sig_fault(SIGTRAP, si_code, instruction_pointer(regs),
+			      "User debug trap");
 }
 
 static int single_step_handler(unsigned long unused, unsigned int esr,
diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index 43d4c329775f..dbbddfbf4a72 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);
@@ -114,7 +113,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 f49b349e16a3..8ac487c84e37 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -192,14 +192,11 @@ static void ptrace_hbptriggered(struct perf_event *bp,
 				break;
 			}
 		}
-		arm64_force_sig_ptrace_errno_trap(si_errno,
-						  (void __user *)bkpt->trigger,
+		arm64_force_sig_ptrace_errno_trap(si_errno, bkpt->trigger,
 						  desc);
 	}
 #endif
-	arm64_force_sig_fault(SIGTRAP, TRAP_HWBKPT,
-			      (void __user *)(bkpt->trigger),
-			      desc);
+	arm64_force_sig_fault(SIGTRAP, TRAP_HWBKPT, bkpt->trigger, desc);
 }
 
 /*
diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c
index 3c18c2454089..265fe3eb1069 100644
--- a/arch/arm64/kernel/sys_compat.c
+++ b/arch/arm64/kernel/sys_compat.c
@@ -68,7 +68,7 @@ do_compat_cache_op(unsigned long start, unsigned long end, int flags)
  */
 long compat_arm_syscall(struct pt_regs *regs, int scno)
 {
-	void __user *addr;
+	unsigned long addr;
 
 	switch (scno) {
 	/*
@@ -111,8 +111,7 @@ long compat_arm_syscall(struct pt_regs *regs, int scno)
 		break;
 	}
 
-	addr  = (void __user *)instruction_pointer(regs) -
-		(compat_thumb_mode(regs) ? 2 : 4);
+	addr = instruction_pointer(regs) - (compat_thumb_mode(regs) ? 2 : 4);
 
 	arm64_notify_die("Oops - bad compat syscall(2)", regs,
 			 SIGILL, ILL_ILLTRP, addr, scno);
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 8af4e0e85736..f4ddbe9ed3f1 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -170,32 +170,32 @@ static void arm64_show_signal(int signo, const char *str)
 	__show_regs(regs);
 }
 
-void arm64_force_sig_fault(int signo, int code, void __user *addr,
+void arm64_force_sig_fault(int signo, int code, unsigned long far,
 			   const char *str)
 {
 	arm64_show_signal(signo, str);
 	if (signo == SIGKILL)
 		force_sig(SIGKILL);
 	else
-		force_sig_fault(signo, code, addr);
+		force_sig_fault(signo, code, (void __user *)far);
 }
 
-void arm64_force_sig_mceerr(int code, void __user *addr, short lsb,
+void arm64_force_sig_mceerr(int code, unsigned long far, short lsb,
 			    const char *str)
 {
 	arm64_show_signal(SIGBUS, str);
-	force_sig_mceerr(code, addr, lsb);
+	force_sig_mceerr(code, (void __user *)far, lsb);
 }
 
-void arm64_force_sig_ptrace_errno_trap(int errno, void __user *addr,
+void arm64_force_sig_ptrace_errno_trap(int errno, unsigned long far,
 				       const char *str)
 {
 	arm64_show_signal(SIGTRAP, str);
-	force_sig_ptrace_errno_trap(errno, addr);
+	force_sig_ptrace_errno_trap(errno, (void __user *)far);
 }
 
 void arm64_notify_die(const char *str, struct pt_regs *regs,
-		      int signo, int sicode, void __user *addr,
+		      int signo, int sicode, unsigned long far,
 		      int err)
 {
 	if (user_mode(regs)) {
@@ -203,7 +203,7 @@ void arm64_notify_die(const char *str, struct pt_regs *regs,
 		current->thread.fault_address = 0;
 		current->thread.fault_code = err;
 
-		arm64_force_sig_fault(signo, sicode, addr, str);
+		arm64_force_sig_fault(signo, sicode, far, str);
 	} else {
 		die(str, regs, err);
 	}
@@ -374,7 +374,7 @@ void force_signal_inject(int signal, int code, unsigned long address, unsigned i
 		signal = SIGKILL;
 	}
 
-	arm64_notify_die(desc, regs, signal, code, (void __user *)address, err);
+	arm64_notify_die(desc, regs, signal, code, address, err);
 }
 
 /*
@@ -385,7 +385,7 @@ void arm64_notify_segfault(unsigned long addr)
 	int code;
 
 	mmap_read_lock(current->mm);
-	if (find_vma(current->mm, addr) == NULL)
+	if (find_vma(current->mm, untagged_addr(addr)) == NULL)
 		code = SEGV_MAPERR;
 	else
 		code = SEGV_ACCERR;
@@ -448,12 +448,13 @@ NOKPROBE_SYMBOL(do_ptrauth_fault);
 
 static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs)
 {
-	unsigned long address;
+	unsigned long tagged_address, address;
 	int rt = ESR_ELx_SYS64_ISS_RT(esr);
 	int crm = (esr & ESR_ELx_SYS64_ISS_CRM_MASK) >> ESR_ELx_SYS64_ISS_CRM_SHIFT;
 	int ret = 0;
 
-	address = untagged_addr(pt_regs_read_reg(regs, rt));
+	tagged_address = pt_regs_read_reg(regs, rt);
+	address = untagged_addr(tagged_address);
 
 	switch (crm) {
 	case ESR_ELx_SYS64_ISS_CRM_DC_CVAU:	/* DC CVAU, gets promoted */
@@ -480,7 +481,7 @@ static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs)
 	}
 
 	if (ret)
-		arm64_notify_segfault(address);
+		arm64_notify_segfault(tagged_address);
 	else
 		arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE);
 }
@@ -772,7 +773,7 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr)
  */
 void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr)
 {
-	void __user *pc = (void __user *)instruction_pointer(regs);
+	unsigned long pc = instruction_pointer(regs);
 
 	current->thread.fault_address = 0;
 	current->thread.fault_code = esr;
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 1ee94002801f..c5375cb7763d 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;
@@ -385,8 +385,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.
@@ -395,8 +398,7 @@ static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *re
 		const struct fault_info *inf = esr_to_fault_info(esr);
 
 		set_thread_esr(addr, esr);
-		arm64_force_sig_fault(inf->sig, inf->code, (void __user *)addr,
-				      inf->name);
+		arm64_force_sig_fault(inf->sig, inf->code, far, inf->name);
 	} else {
 		__do_kernel_fault(addr, esr, regs);
 	}
@@ -448,7 +450,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;
@@ -456,6 +458,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;
@@ -567,8 +570,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
 		 * We had some memory, but were unable to successfully fix up
 		 * this page fault.
 		 */
-		arm64_force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)addr,
-				      inf->name);
+		arm64_force_sig_fault(SIGBUS, BUS_ADRERR, far, inf->name);
 	} else if (fault & (VM_FAULT_HWPOISON_LARGE | VM_FAULT_HWPOISON)) {
 		unsigned int lsb;
 
@@ -576,8 +578,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
 		if (fault & VM_FAULT_HWPOISON_LARGE)
 			lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault));
 
-		arm64_force_sig_mceerr(BUS_MCEERR_AR, (void __user *)addr, lsb,
-				       inf->name);
+		arm64_force_sig_mceerr(BUS_MCEERR_AR, far, lsb, inf->name);
 	} else {
 		/*
 		 * Something tried to access memory that isn't in our memory
@@ -585,8 +586,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
 		 */
 		arm64_force_sig_fault(SIGSEGV,
 				      fault == VM_FAULT_BADACCESS ? SEGV_ACCERR : SEGV_MAPERR,
-				      (void __user *)addr,
-				      inf->name);
+				      far, inf->name);
 	}
 
 	return 0;
@@ -596,33 +596,35 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
 	return 0;
 }
 
-static int __kprobes do_translation_fault(unsigned long addr,
+static int __kprobes do_translation_fault(unsigned long far,
 					  unsigned int esr,
 					  struct pt_regs *regs)
 {
+	unsigned long addr = untagged_addr(far);
+
 	if (is_ttbr0_addr(addr))
-		return do_page_fault(addr, esr, regs);
+		return do_page_fault(far, esr, regs);
 
-	do_bad_area(addr, esr, regs);
+	do_bad_area(far, esr, regs);
 	return 0;
 }
 
-static int do_alignment_fault(unsigned long addr, unsigned int esr,
+static int do_alignment_fault(unsigned long far, unsigned int esr,
 			      struct pt_regs *regs)
 {
-	do_bad_area(addr, esr, regs);
+	do_bad_area(far, esr, regs);
 	return 0;
 }
 
-static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs)
+static int do_bad(unsigned long far, unsigned int esr, struct pt_regs *regs)
 {
 	return 1; /* "fault" */
 }
 
-static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
+static int do_sea(unsigned long far, unsigned int esr, struct pt_regs *regs)
 {
 	const struct fault_info *inf;
-	void __user *siaddr;
+	unsigned long siaddr;
 
 	inf = esr_to_fault_info(esr);
 
@@ -635,18 +637,23 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
 	}
 
 	if (esr & ESR_ELx_FnV)
-		siaddr = NULL;
+		siaddr = 0;
 	else
-		siaddr  = (void __user *)addr;
+		siaddr  = untagged_addr(far);
 	arm64_notify_die(inf->name, regs, inf->sig, inf->code, siaddr, esr);
 
 	return 0;
 }
 
-static int do_tag_check_fault(unsigned long addr, unsigned int esr,
+static int do_tag_check_fault(unsigned long far, unsigned int esr,
 			      struct pt_regs *regs)
 {
-	do_bad_area(addr, esr, regs);
+	/*
+	 * The architecture specifies that bits 63:60 of FAR_EL1 are UNKNOWN for tag
+	 * check faults. Mask them out now so that userspace doesn't see them.
+	 */
+	far &= (1UL << 60) - 1;
+	do_bad_area(far, esr, regs);
 	return 0;
 }
 
@@ -717,11 +724,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)) {
@@ -730,8 +738,7 @@ void do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs)
 		show_pte(addr);
 	}
 
-	arm64_notify_die(inf->name, regs,
-			 inf->sig, inf->code, (void __user *)addr, esr);
+	arm64_notify_die(inf->name, regs, inf->sig, inf->code, addr, esr);
 }
 NOKPROBE_SYMBOL(do_mem_abort);
 
@@ -744,8 +751,8 @@ NOKPROBE_SYMBOL(do_el0_irq_bp_hardening);
 
 void do_sp_pc_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs)
 {
-	arm64_notify_die("SP/PC alignment exception", regs,
-			 SIGBUS, BUS_ADRALN, (void __user *)addr, esr);
+	arm64_notify_die("SP/PC alignment exception", regs, SIGBUS, BUS_ADRALN,
+			 addr, esr);
 }
 NOKPROBE_SYMBOL(do_sp_pc_abort);
 
@@ -871,8 +878,7 @@ void do_debug_exception(unsigned long addr_if_watchpoint, unsigned int esr,
 		arm64_apply_bp_hardening();
 
 	if (inf->fn(addr_if_watchpoint, esr, regs)) {
-		arm64_notify_die(inf->name, regs,
-				 inf->sig, inf->code, (void __user *)pc, esr);
+		arm64_notify_die(inf->name, regs, inf->sig, inf->code, pc, esr);
 	}
 
 	debug_exception_exit(regs);
diff --git a/include/linux/signal.h b/include/linux/signal.h
index b256f9c65661..205526c4003a 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -469,4 +469,18 @@ struct seq_file;
 extern void render_sigset_t(struct seq_file *, const char *, sigset_t *);
 #endif
 
+#ifndef arch_untagged_si_addr
+/*
+ * Given a fault address and a signal and si_code which correspond to the
+ * _sigfault union member, returns the address that must appear in si_addr if
+ * the signal handler does not have SA_EXPOSE_TAGBITS enabled in sa_flags.
+ */
+static inline void __user *arch_untagged_si_addr(void __user *addr,
+						 unsigned long sig,
+						 unsigned long si_code)
+{
+	return addr;
+}
+#endif
+
 #endif /* _LINUX_SIGNAL_H */
diff --git a/include/linux/signal_types.h b/include/linux/signal_types.h
index a7887ad84d36..68e06c75c5b2 100644
--- a/include/linux/signal_types.h
+++ b/include/linux/signal_types.h
@@ -78,6 +78,6 @@ struct ksignal {
 
 #define UAPI_SA_FLAGS                                                          \
 	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
-	 SA_NODEFER | SA_RESETHAND | __ARCH_UAPI_SA_FLAGS)
+	 SA_NODEFER | SA_RESETHAND | SA_EXPOSE_TAGBITS | __ARCH_UAPI_SA_FLAGS)
 
 #endif /* _LINUX_SIGNAL_TYPES_H */
diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
index 0126ebda4d31..5276bdd4a9e2 100644
--- a/include/uapi/asm-generic/signal-defs.h
+++ b/include/uapi/asm-generic/signal-defs.h
@@ -20,6 +20,8 @@
  * 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_EXPOSE_TAGBITS exposes an architecture-defined set of tag bits in
+ * siginfo.si_addr.
  *
  * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
  * Unix names RESETHAND and NODEFER respectively.
@@ -49,6 +51,7 @@
 #define SA_RESETHAND	0x80000000
 #endif
 #define SA_UNSUPPORTED	0x00000400
+#define SA_EXPOSE_TAGBITS	0x00000800
 
 #define SA_NOMASK	SA_NODEFER
 #define SA_ONESHOT	SA_RESETHAND
diff --git a/kernel/signal.c b/kernel/signal.c
index 8f34819e80de..16be62e6d341 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1650,6 +1650,15 @@ void force_sigsegv(int sig)
 	force_sig(SIGSEGV);
 }
 
+static void __user *get_si_addr(void __user *addr, unsigned long sig,
+				unsigned long si_code)
+{
+	if (current->sighand->action[sig - 1].sa.sa_flags & SA_EXPOSE_TAGBITS)
+		return addr;
+
+	return arch_untagged_si_addr(addr, sig, si_code);
+}
+
 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)
@@ -1661,7 +1670,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
 	info.si_signo = sig;
 	info.si_errno = 0;
 	info.si_code  = code;
-	info.si_addr  = addr;
+	info.si_addr  = get_si_addr(addr, sig, code);
 #ifdef __ARCH_SI_TRAPNO
 	info.si_trapno = trapno;
 #endif
@@ -1693,7 +1702,7 @@ int send_sig_fault(int sig, int code, void __user *addr
 	info.si_signo = sig;
 	info.si_errno = 0;
 	info.si_code  = code;
-	info.si_addr  = addr;
+	info.si_addr  = get_si_addr(addr, sig, code);
 #ifdef __ARCH_SI_TRAPNO
 	info.si_trapno = trapno;
 #endif
@@ -1714,7 +1723,7 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
 	info.si_signo = SIGBUS;
 	info.si_errno = 0;
 	info.si_code = code;
-	info.si_addr = addr;
+	info.si_addr = get_si_addr(addr, SIGBUS, code);
 	info.si_addr_lsb = lsb;
 	return force_sig_info(&info);
 }
@@ -1728,7 +1737,7 @@ int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *
 	info.si_signo = SIGBUS;
 	info.si_errno = 0;
 	info.si_code = code;
-	info.si_addr = addr;
+	info.si_addr = get_si_addr(addr, SIGBUS, code);
 	info.si_addr_lsb = lsb;
 	return send_sig_info(info.si_signo, &info, t);
 }
@@ -1742,7 +1751,7 @@ int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
 	info.si_signo = SIGSEGV;
 	info.si_errno = 0;
 	info.si_code  = SEGV_BNDERR;
-	info.si_addr  = addr;
+	info.si_addr  = get_si_addr(addr, SIGSEGV, SEGV_BNDERR);
 	info.si_lower = lower;
 	info.si_upper = upper;
 	return force_sig_info(&info);
@@ -1757,7 +1766,7 @@ int force_sig_pkuerr(void __user *addr, u32 pkey)
 	info.si_signo = SIGSEGV;
 	info.si_errno = 0;
 	info.si_code  = SEGV_PKUERR;
-	info.si_addr  = addr;
+	info.si_addr  = get_si_addr(addr, SIGSEGV, SEGV_PKUERR);
 	info.si_pkey  = pkey;
 	return force_sig_info(&info);
 }
@@ -1774,7 +1783,7 @@ int force_sig_ptrace_errno_trap(int errno, void __user *addr)
 	info.si_signo = SIGTRAP;
 	info.si_errno = errno;
 	info.si_code  = TRAP_HWBKPT;
-	info.si_addr  = addr;
+	info.si_addr  = get_si_addr(addr, SIGTRAP, TRAP_HWBKPT);
 	return force_sig_info(&info);
 }
 
-- 
2.29.2.299.gdc1121823c-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] 19+ messages in thread

* Re: [PATCH v16 5/6] signal: define the SA_UNSUPPORTED bit in sa_flags
  2020-11-13  2:53 ` [PATCH v16 5/6] signal: define the SA_UNSUPPORTED bit in sa_flags Peter Collingbourne
@ 2020-11-14 13:53   ` Eric W. Biederman
  2020-11-14 22:12     ` Peter Collingbourne
  0 siblings, 1 reply; 19+ messages in thread
From: Eric W. Biederman @ 2020-11-14 13:53 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Catalin Marinas, Helge Deller, Kevin Brodsky, Oleg Nesterov,
	linux-api, James E.J. Bottomley, Kostya Serebryany, Linux ARM,
	Andrey Konovalov, David Spickett, Vincenzo Frascino, Will Deacon,
	Dave Martin, Evgenii Stepanov

Peter Collingbourne <pcc@google.com> writes:

> Define a sa_flags bit, SA_UNSUPPORTED, which 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 does something like:
>
>   act.sa_flags |= SA_UNSUPPORTED;
>   sigaction(SIGSEGV, &act, 0);
>   sigaction(SIGSEGV, 0, &oldact);
>
> and finds that SA_UNSUPPORTED remains set in oldact.sa_flags, it means
> that the kernel cannot be trusted to have cleared unknown flag bits
> from sa_flags, so no assumptions about flag bit support can be made.
>
> Signed-off-by: Peter Collingbourne <pcc@google.com>
> Reviewed-by: Dave Martin <Dave.Martin@arm.com>
> Link: https://linux-review.googlesource.com/id/Ic2501ad150a3a79c1cf27fb8c99be342e9dffbcb
> ---
> v11:
> - clarify the commit message
>
>  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 493953fe319b..0126ebda4d31 100644
> --- a/include/uapi/asm-generic/signal-defs.h
> +++ b/include/uapi/asm-generic/signal-defs.h
> @@ -14,6 +14,12 @@
>   * SA_RESTART flag to get restarting signals (which were the default long ago)
>   * SA_NODEFER prevents the current signal from being masked in the handler.
>   * SA_RESETHAND clears the handler when the signal is delivered.
> + * SA_UNSUPPORTED is a flag bit that will never be supported. Kernels from
> + * before the introduction of SA_UNSUPPORTED did not clear unknown bits from
> + * sa_flags when read using the oldact argument to sigaction and rt_sigaction,
> + * so this bit allows flag bit support to be detected from userspace while
> + * allowing an old kernel to be distinguished from a kernel that supports every
> + * flag bit.
>   *
>   * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
>   * Unix names RESETHAND and NODEFER respectively.
> @@ -42,6 +48,7 @@
>  #ifndef SA_RESETHAND
>  #define SA_RESETHAND	0x80000000
>  #endif
> +#define SA_UNSUPPORTED	0x00000400

Why this value and why not in numerical order with the other flags?

At the very least not being in order with the other bits makes it
a little easier to overlook it and define something at that position.

Eric


>  #define SA_NOMASK	SA_NODEFER
>  #define SA_ONESHOT	SA_RESETHAND
> diff --git a/kernel/signal.c b/kernel/signal.c
> index 8f5bd12ee41b..8f34819e80de 100644
> --- a/kernel/signal.c
> +++ b/kernel/signal.c
> @@ -3985,6 +3985,12 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
>  	if (oact)
>  		*oact = *k;
>  
> +	/*
> +	 * Make sure that we never accidentally claim to support SA_UNSUPPORTED,
> +	 * e.g. by having an architecture use the bit in their uapi.
> +	 */
> +	BUILD_BUG_ON(UAPI_SA_FLAGS & SA_UNSUPPORTED);
> +
>  	/*
>  	 * Clear unknown flag bits in order to allow userspace to detect missing
>  	 * support for flag bits and to allow the kernel to use non-uapi bits

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

* Re: [PATCH v16 5/6] signal: define the SA_UNSUPPORTED bit in sa_flags
  2020-11-14 13:53   ` Eric W. Biederman
@ 2020-11-14 22:12     ` Peter Collingbourne
  2020-11-16 23:48       ` Eric W. Biederman
  0 siblings, 1 reply; 19+ messages in thread
From: Peter Collingbourne @ 2020-11-14 22:12 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Catalin Marinas, Helge Deller, Kevin Brodsky, Oleg Nesterov,
	Linux API, James E.J. Bottomley, Kostya Serebryany, Linux ARM,
	Andrey Konovalov, David Spickett, Vincenzo Frascino, Will Deacon,
	Dave Martin, Evgenii Stepanov

On Sat, Nov 14, 2020 at 5:53 AM Eric W. Biederman <ebiederm@xmission.com> wrote:
>
> Peter Collingbourne <pcc@google.com> writes:
>
> > Define a sa_flags bit, SA_UNSUPPORTED, which 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 does something like:
> >
> >   act.sa_flags |= SA_UNSUPPORTED;
> >   sigaction(SIGSEGV, &act, 0);
> >   sigaction(SIGSEGV, 0, &oldact);
> >
> > and finds that SA_UNSUPPORTED remains set in oldact.sa_flags, it means
> > that the kernel cannot be trusted to have cleared unknown flag bits
> > from sa_flags, so no assumptions about flag bit support can be made.
> >
> > Signed-off-by: Peter Collingbourne <pcc@google.com>
> > Reviewed-by: Dave Martin <Dave.Martin@arm.com>
> > Link: https://linux-review.googlesource.com/id/Ic2501ad150a3a79c1cf27fb8c99be342e9dffbcb
> > ---
> > v11:
> > - clarify the commit message
> >
> >  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 493953fe319b..0126ebda4d31 100644
> > --- a/include/uapi/asm-generic/signal-defs.h
> > +++ b/include/uapi/asm-generic/signal-defs.h
> > @@ -14,6 +14,12 @@
> >   * SA_RESTART flag to get restarting signals (which were the default long ago)
> >   * SA_NODEFER prevents the current signal from being masked in the handler.
> >   * SA_RESETHAND clears the handler when the signal is delivered.
> > + * SA_UNSUPPORTED is a flag bit that will never be supported. Kernels from
> > + * before the introduction of SA_UNSUPPORTED did not clear unknown bits from
> > + * sa_flags when read using the oldact argument to sigaction and rt_sigaction,
> > + * so this bit allows flag bit support to be detected from userspace while
> > + * allowing an old kernel to be distinguished from a kernel that supports every
> > + * flag bit.
> >   *
> >   * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
> >   * Unix names RESETHAND and NODEFER respectively.
> > @@ -42,6 +48,7 @@
> >  #ifndef SA_RESETHAND
> >  #define SA_RESETHAND 0x80000000
> >  #endif
> > +#define SA_UNSUPPORTED       0x00000400
>
> Why this value and why not in numerical order with the other flags?
>
> At the very least not being in order with the other bits makes it
> a little easier to overlook it and define something at that position.

The value is because this is the first bit that isn't already taken by
an architecture-specific flag bit. It seems okay to move it into
numerical order.

The taken flag bits are listed in the comment that I added in patch 3.
Do you think there would be a more prominent way to document them?
Maybe we can replace that comment with inline, in-order comments along
the lines of:

#ifndef SA_NOCLDSTOP
#define SA_NOCLDSTOP   0x00000001
#endif
#ifndef SA_NOCLDWAIT
#define SA_NOCLDWAIT   0x00000002
#endif
#ifndef SA_SIGINFO
#define SA_SIGINFO     0x00000004
#endif
/* 0x00000008 has arch-specific definition */
/* 0x00000010 has arch-specific definition */

etc.

And then this patch would add the new bit in the right place.

Peter

>
> Eric
>
>
> >  #define SA_NOMASK    SA_NODEFER
> >  #define SA_ONESHOT   SA_RESETHAND
> > diff --git a/kernel/signal.c b/kernel/signal.c
> > index 8f5bd12ee41b..8f34819e80de 100644
> > --- a/kernel/signal.c
> > +++ b/kernel/signal.c
> > @@ -3985,6 +3985,12 @@ int do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact)
> >       if (oact)
> >               *oact = *k;
> >
> > +     /*
> > +      * Make sure that we never accidentally claim to support SA_UNSUPPORTED,
> > +      * e.g. by having an architecture use the bit in their uapi.
> > +      */
> > +     BUILD_BUG_ON(UAPI_SA_FLAGS & SA_UNSUPPORTED);
> > +
> >       /*
> >        * Clear unknown flag bits in order to allow userspace to detect missing
> >        * support for flag bits and to allow the kernel to use non-uapi bits

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

* Re: [PATCH v16 6/6] arm64: expose FAR_EL1 tag bits in siginfo
  2020-11-13  2:53 ` [PATCH v16 6/6] arm64: expose FAR_EL1 tag bits in siginfo Peter Collingbourne
@ 2020-11-15 14:08   ` Eric W. Biederman
  2020-11-16 13:36     ` Dave Martin
  2020-11-16 19:01   ` Catalin Marinas
  1 sibling, 1 reply; 19+ messages in thread
From: Eric W. Biederman @ 2020-11-15 14:08 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Catalin Marinas, Helge Deller, Kevin Brodsky, Oleg Nesterov,
	linux-api, James E.J. Bottomley, Kostya Serebryany, Linux ARM,
	Andrey Konovalov, David Spickett, Vincenzo Frascino, Will Deacon,
	Dave Martin, Evgenii Stepanov

Peter Collingbourne <pcc@google.com> writes:

> 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, introduce a flag in
> sigaction.sa_flags, SA_EXPOSE_TAGBITS, and only expose the tag bits
> there if the signal handler has this flag set.

For future architectures that implement something similar does it make
sense that to hide tag bits by default?

I am wondering if SA_EXPOSE_TABGITS might make sense as an architecture
specific sa bit.

Otherwise this patch looks good to me.

Eric


> [1] http://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html
>
> Signed-off-by: Peter Collingbourne <pcc@google.com>
> Link: https://linux-review.googlesource.com/id/Ia8876bad8c798e0a32df7c2ce1256c4771c81446
> ---
> v16:
> - add missing file
>
> v15:
> - switched to the SA_EXPOSE_TAGBITS approach
>   proposed by Eric
> - rebased to 5.10-rc3
>
> v14:
> - fix an inaccuracy in the commit message
> - add some comments to arch_addr_tag_bits_mask
>
> v13:
> - renamed si_xflags to si_faultflags
> - rebased to 5.10-rc2
>
> v12:
> - add new fields to signal_compat.c test cases
> - rebased to 5.10-rc1
> - mask out bits 63:60 for tag check faults
>
> v11:
> - add a comment explaining what the arch hook should do
> - rename ignored bits to tag bits
>
> v10:
> - rename the flag to SIFAULTFLAG_ADDR_IGNORED_BITS
> - use an arch hook to specify which bits are ignored, instead
>   of passing them explicitly
> - while refactoring for the arch hook, noticed that my previous
>   patches missed a case involving cache maintenance instructions,
>   so expose the tag bits for that signal as well
>
> v9:
> - make the ignored bits fields generic
> - add some new dependent patches that prepare us to store the
>   field in such a way that userspace can detect their presence
>
> v8:
> - rebase onto 5.8rc2
>
> v7:
> - switch to a new siginfo field instead of using sigcontext
> - merge the patch back into one since the other patches are now
>   unnecessary
>
> v6:
> - move fault address and fault code into the kernel_siginfo data structure
> - split the patch in three since it was getting large and now has
>   generic and arch-specific parts
>
> v5:
> - add padding to fault_addr_top_byte_context in order to ensure the correct
>   size and preserve sp alignment
>
> v4:
> - expose only the tag bits in the context instead of the entire FAR_EL1
> - remove mention of the new context from the sigcontext.__reserved[] note
>
> v3:
> - add documentation to tagged-pointers.rst
> - update comments in sigcontext.h
>
> v2:
> - revert changes to hw_breakpoint.c
> - rename set_thread_esr to set_thread_far_esr
>
>  Documentation/arm64/tagged-pointers.rst | 25 ++++++---
>  arch/arm64/include/asm/exception.h      |  2 +-
>  arch/arm64/include/asm/signal.h         | 25 +++++++++
>  arch/arm64/include/asm/system_misc.h    |  2 +-
>  arch/arm64/include/asm/traps.h          |  6 +--
>  arch/arm64/kernel/debug-monitors.c      |  5 +-
>  arch/arm64/kernel/entry-common.c        |  2 -
>  arch/arm64/kernel/ptrace.c              |  7 +--
>  arch/arm64/kernel/sys_compat.c          |  5 +-
>  arch/arm64/kernel/traps.c               | 29 ++++++-----
>  arch/arm64/mm/fault.c                   | 68 ++++++++++++++-----------
>  include/linux/signal.h                  | 14 +++++
>  include/linux/signal_types.h            |  2 +-
>  include/uapi/asm-generic/signal-defs.h  |  3 ++
>  kernel/signal.c                         | 23 ++++++---
>  15 files changed, 141 insertions(+), 77 deletions(-)
>  create mode 100644 arch/arm64/include/asm/signal.h
>
> diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst
> index eab4323609b9..19d284b70384 100644
> --- a/Documentation/arm64/tagged-pointers.rst
> +++ b/Documentation/arm64/tagged-pointers.rst
> @@ -53,12 +53,25 @@ 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.
> +When delivering signals, non-zero tags are not preserved in
> +siginfo.si_addr unless the flag SA_EXPOSE_TAGBITS was set in
> +sigaction.sa_flags when the signal handler was installed. 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 unless the flag was set.
> +
> +Due to architecture limitations, bits 63:60 of the fault address
> +are not preserved in response to synchronous tag check faults
> +(SEGV_MTESERR) even if SA_EXPOSE_TAGBITS was set. Applications should
> +treat the values of these bits as undefined in order to accommodate
> +future architecture revisions which may preserve the bits.
> +
> +For signals raised in response to watchpoint debug exceptions, the
> +tag information will be preserved regardless of the SA_EXPOSE_TAGBITS
> +flag setting.
> +
> +Non-zero tags are never preserved in sigcontext.fault_address
> +regardless of the SA_EXPOSE_TAGBITS flag setting.
>  
>  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 99b9383cd036..2a8aa1884d8a 100644
> --- a/arch/arm64/include/asm/exception.h
> +++ b/arch/arm64/include/asm/exception.h
> @@ -32,7 +32,7 @@ static inline u32 disr_to_esr(u64 disr)
>  }
>  
>  asmlinkage void enter_from_user_mode(void);
> -void do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs);
> +void do_mem_abort(unsigned long far, unsigned int esr, struct pt_regs *regs);
>  void do_undefinstr(struct pt_regs *regs);
>  void do_bti(struct pt_regs *regs);
>  asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr);
> diff --git a/arch/arm64/include/asm/signal.h b/arch/arm64/include/asm/signal.h
> new file mode 100644
> index 000000000000..ef449f5f4ba8
> --- /dev/null
> +++ b/arch/arm64/include/asm/signal.h
> @@ -0,0 +1,25 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef __ARM64_ASM_SIGNAL_H
> +#define __ARM64_ASM_SIGNAL_H
> +
> +#include <asm/memory.h>
> +#include <uapi/asm/signal.h>
> +#include <uapi/asm/siginfo.h>
> +
> +static inline void __user *arch_untagged_si_addr(void __user *addr,
> +						 unsigned long sig,
> +						 unsigned long si_code)
> +{
> +	/*
> +	 * For historical reasons, all bits of the fault address are exposed as
> +	 * address bits for watchpoint exceptions. New architectures should
> +	 * handle the tag bits consistently.
> +	 */
> +	if (sig == SIGTRAP && si_code == TRAP_BRKPT)
> +		return addr;
> +
> +	return untagged_addr(addr);
> +}
> +#define arch_untagged_si_addr arch_untagged_si_addr
> +
> +#endif
> diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h
> index 1ab63cfbbaf1..673be2d1263c 100644
> --- a/arch/arm64/include/asm/system_misc.h
> +++ b/arch/arm64/include/asm/system_misc.h
> @@ -22,7 +22,7 @@ void die(const char *msg, struct pt_regs *regs, int err);
>  
>  struct siginfo;
>  void arm64_notify_die(const char *str, struct pt_regs *regs,
> -		      int signo, int sicode, void __user *addr,
> +		      int signo, int sicode, unsigned long far,
>  		      int err);
>  
>  void hook_debug_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
> diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h
> index d96dc2c7c09d..54f32a0675df 100644
> --- a/arch/arm64/include/asm/traps.h
> +++ b/arch/arm64/include/asm/traps.h
> @@ -26,9 +26,9 @@ void register_undef_hook(struct undef_hook *hook);
>  void unregister_undef_hook(struct undef_hook *hook);
>  void force_signal_inject(int signal, int code, unsigned long address, unsigned int err);
>  void arm64_notify_segfault(unsigned long addr);
> -void arm64_force_sig_fault(int signo, int code, void __user *addr, const char *str);
> -void arm64_force_sig_mceerr(int code, void __user *addr, short lsb, const char *str);
> -void arm64_force_sig_ptrace_errno_trap(int errno, void __user *addr, const char *str);
> +void arm64_force_sig_fault(int signo, int code, unsigned long far, const char *str);
> +void arm64_force_sig_mceerr(int code, unsigned long far, short lsb, const char *str);
> +void arm64_force_sig_ptrace_errno_trap(int errno, unsigned long far, const char *str);
>  
>  /*
>   * Move regs->pc to next instruction and do necessary setup before it
> diff --git a/arch/arm64/kernel/debug-monitors.c b/arch/arm64/kernel/debug-monitors.c
> index fa76151de6ff..4f3661eeb7ec 100644
> --- a/arch/arm64/kernel/debug-monitors.c
> +++ b/arch/arm64/kernel/debug-monitors.c
> @@ -234,9 +234,8 @@ static void send_user_sigtrap(int si_code)
>  	if (interrupts_enabled(regs))
>  		local_irq_enable();
>  
> -	arm64_force_sig_fault(SIGTRAP, si_code,
> -			     (void __user *)instruction_pointer(regs),
> -			     "User debug trap");
> +	arm64_force_sig_fault(SIGTRAP, si_code, instruction_pointer(regs),
> +			      "User debug trap");
>  }
>  
>  static int single_step_handler(unsigned long unused, unsigned int esr,
> diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
> index 43d4c329775f..dbbddfbf4a72 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);
> @@ -114,7 +113,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 f49b349e16a3..8ac487c84e37 100644
> --- a/arch/arm64/kernel/ptrace.c
> +++ b/arch/arm64/kernel/ptrace.c
> @@ -192,14 +192,11 @@ static void ptrace_hbptriggered(struct perf_event *bp,
>  				break;
>  			}
>  		}
> -		arm64_force_sig_ptrace_errno_trap(si_errno,
> -						  (void __user *)bkpt->trigger,
> +		arm64_force_sig_ptrace_errno_trap(si_errno, bkpt->trigger,
>  						  desc);
>  	}
>  #endif
> -	arm64_force_sig_fault(SIGTRAP, TRAP_HWBKPT,
> -			      (void __user *)(bkpt->trigger),
> -			      desc);
> +	arm64_force_sig_fault(SIGTRAP, TRAP_HWBKPT, bkpt->trigger, desc);
>  }
>  
>  /*
> diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c
> index 3c18c2454089..265fe3eb1069 100644
> --- a/arch/arm64/kernel/sys_compat.c
> +++ b/arch/arm64/kernel/sys_compat.c
> @@ -68,7 +68,7 @@ do_compat_cache_op(unsigned long start, unsigned long end, int flags)
>   */
>  long compat_arm_syscall(struct pt_regs *regs, int scno)
>  {
> -	void __user *addr;
> +	unsigned long addr;
>  
>  	switch (scno) {
>  	/*
> @@ -111,8 +111,7 @@ long compat_arm_syscall(struct pt_regs *regs, int scno)
>  		break;
>  	}
>  
> -	addr  = (void __user *)instruction_pointer(regs) -
> -		(compat_thumb_mode(regs) ? 2 : 4);
> +	addr = instruction_pointer(regs) - (compat_thumb_mode(regs) ? 2 : 4);
>  
>  	arm64_notify_die("Oops - bad compat syscall(2)", regs,
>  			 SIGILL, ILL_ILLTRP, addr, scno);
> diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
> index 8af4e0e85736..f4ddbe9ed3f1 100644
> --- a/arch/arm64/kernel/traps.c
> +++ b/arch/arm64/kernel/traps.c
> @@ -170,32 +170,32 @@ static void arm64_show_signal(int signo, const char *str)
>  	__show_regs(regs);
>  }
>  
> -void arm64_force_sig_fault(int signo, int code, void __user *addr,
> +void arm64_force_sig_fault(int signo, int code, unsigned long far,
>  			   const char *str)
>  {
>  	arm64_show_signal(signo, str);
>  	if (signo == SIGKILL)
>  		force_sig(SIGKILL);
>  	else
> -		force_sig_fault(signo, code, addr);
> +		force_sig_fault(signo, code, (void __user *)far);
>  }
>  
> -void arm64_force_sig_mceerr(int code, void __user *addr, short lsb,
> +void arm64_force_sig_mceerr(int code, unsigned long far, short lsb,
>  			    const char *str)
>  {
>  	arm64_show_signal(SIGBUS, str);
> -	force_sig_mceerr(code, addr, lsb);
> +	force_sig_mceerr(code, (void __user *)far, lsb);
>  }
>  
> -void arm64_force_sig_ptrace_errno_trap(int errno, void __user *addr,
> +void arm64_force_sig_ptrace_errno_trap(int errno, unsigned long far,
>  				       const char *str)
>  {
>  	arm64_show_signal(SIGTRAP, str);
> -	force_sig_ptrace_errno_trap(errno, addr);
> +	force_sig_ptrace_errno_trap(errno, (void __user *)far);
>  }
>  
>  void arm64_notify_die(const char *str, struct pt_regs *regs,
> -		      int signo, int sicode, void __user *addr,
> +		      int signo, int sicode, unsigned long far,
>  		      int err)
>  {
>  	if (user_mode(regs)) {
> @@ -203,7 +203,7 @@ void arm64_notify_die(const char *str, struct pt_regs *regs,
>  		current->thread.fault_address = 0;
>  		current->thread.fault_code = err;
>  
> -		arm64_force_sig_fault(signo, sicode, addr, str);
> +		arm64_force_sig_fault(signo, sicode, far, str);
>  	} else {
>  		die(str, regs, err);
>  	}
> @@ -374,7 +374,7 @@ void force_signal_inject(int signal, int code, unsigned long address, unsigned i
>  		signal = SIGKILL;
>  	}
>  
> -	arm64_notify_die(desc, regs, signal, code, (void __user *)address, err);
> +	arm64_notify_die(desc, regs, signal, code, address, err);
>  }
>  
>  /*
> @@ -385,7 +385,7 @@ void arm64_notify_segfault(unsigned long addr)
>  	int code;
>  
>  	mmap_read_lock(current->mm);
> -	if (find_vma(current->mm, addr) == NULL)
> +	if (find_vma(current->mm, untagged_addr(addr)) == NULL)
>  		code = SEGV_MAPERR;
>  	else
>  		code = SEGV_ACCERR;
> @@ -448,12 +448,13 @@ NOKPROBE_SYMBOL(do_ptrauth_fault);
>  
>  static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs)
>  {
> -	unsigned long address;
> +	unsigned long tagged_address, address;
>  	int rt = ESR_ELx_SYS64_ISS_RT(esr);
>  	int crm = (esr & ESR_ELx_SYS64_ISS_CRM_MASK) >> ESR_ELx_SYS64_ISS_CRM_SHIFT;
>  	int ret = 0;
>  
> -	address = untagged_addr(pt_regs_read_reg(regs, rt));
> +	tagged_address = pt_regs_read_reg(regs, rt);
> +	address = untagged_addr(tagged_address);
>  
>  	switch (crm) {
>  	case ESR_ELx_SYS64_ISS_CRM_DC_CVAU:	/* DC CVAU, gets promoted */
> @@ -480,7 +481,7 @@ static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs)
>  	}
>  
>  	if (ret)
> -		arm64_notify_segfault(address);
> +		arm64_notify_segfault(tagged_address);
>  	else
>  		arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE);
>  }
> @@ -772,7 +773,7 @@ asmlinkage void bad_mode(struct pt_regs *regs, int reason, unsigned int esr)
>   */
>  void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr)
>  {
> -	void __user *pc = (void __user *)instruction_pointer(regs);
> +	unsigned long pc = instruction_pointer(regs);
>  
>  	current->thread.fault_address = 0;
>  	current->thread.fault_code = esr;
> diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
> index 1ee94002801f..c5375cb7763d 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;
> @@ -385,8 +385,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.
> @@ -395,8 +398,7 @@ static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *re
>  		const struct fault_info *inf = esr_to_fault_info(esr);
>  
>  		set_thread_esr(addr, esr);
> -		arm64_force_sig_fault(inf->sig, inf->code, (void __user *)addr,
> -				      inf->name);
> +		arm64_force_sig_fault(inf->sig, inf->code, far, inf->name);
>  	} else {
>  		__do_kernel_fault(addr, esr, regs);
>  	}
> @@ -448,7 +450,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;
> @@ -456,6 +458,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;
> @@ -567,8 +570,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
>  		 * We had some memory, but were unable to successfully fix up
>  		 * this page fault.
>  		 */
> -		arm64_force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)addr,
> -				      inf->name);
> +		arm64_force_sig_fault(SIGBUS, BUS_ADRERR, far, inf->name);
>  	} else if (fault & (VM_FAULT_HWPOISON_LARGE | VM_FAULT_HWPOISON)) {
>  		unsigned int lsb;
>  
> @@ -576,8 +578,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
>  		if (fault & VM_FAULT_HWPOISON_LARGE)
>  			lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault));
>  
> -		arm64_force_sig_mceerr(BUS_MCEERR_AR, (void __user *)addr, lsb,
> -				       inf->name);
> +		arm64_force_sig_mceerr(BUS_MCEERR_AR, far, lsb, inf->name);
>  	} else {
>  		/*
>  		 * Something tried to access memory that isn't in our memory
> @@ -585,8 +586,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
>  		 */
>  		arm64_force_sig_fault(SIGSEGV,
>  				      fault == VM_FAULT_BADACCESS ? SEGV_ACCERR : SEGV_MAPERR,
> -				      (void __user *)addr,
> -				      inf->name);
> +				      far, inf->name);
>  	}
>  
>  	return 0;
> @@ -596,33 +596,35 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
>  	return 0;
>  }
>  
> -static int __kprobes do_translation_fault(unsigned long addr,
> +static int __kprobes do_translation_fault(unsigned long far,
>  					  unsigned int esr,
>  					  struct pt_regs *regs)
>  {
> +	unsigned long addr = untagged_addr(far);
> +
>  	if (is_ttbr0_addr(addr))
> -		return do_page_fault(addr, esr, regs);
> +		return do_page_fault(far, esr, regs);
>  
> -	do_bad_area(addr, esr, regs);
> +	do_bad_area(far, esr, regs);
>  	return 0;
>  }
>  
> -static int do_alignment_fault(unsigned long addr, unsigned int esr,
> +static int do_alignment_fault(unsigned long far, unsigned int esr,
>  			      struct pt_regs *regs)
>  {
> -	do_bad_area(addr, esr, regs);
> +	do_bad_area(far, esr, regs);
>  	return 0;
>  }
>  
> -static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs)
> +static int do_bad(unsigned long far, unsigned int esr, struct pt_regs *regs)
>  {
>  	return 1; /* "fault" */
>  }
>  
> -static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
> +static int do_sea(unsigned long far, unsigned int esr, struct pt_regs *regs)
>  {
>  	const struct fault_info *inf;
> -	void __user *siaddr;
> +	unsigned long siaddr;
>  
>  	inf = esr_to_fault_info(esr);
>  
> @@ -635,18 +637,23 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
>  	}
>  
>  	if (esr & ESR_ELx_FnV)
> -		siaddr = NULL;
> +		siaddr = 0;
>  	else
> -		siaddr  = (void __user *)addr;
> +		siaddr  = untagged_addr(far);
>  	arm64_notify_die(inf->name, regs, inf->sig, inf->code, siaddr, esr);
>  
>  	return 0;
>  }
>  
> -static int do_tag_check_fault(unsigned long addr, unsigned int esr,
> +static int do_tag_check_fault(unsigned long far, unsigned int esr,
>  			      struct pt_regs *regs)
>  {
> -	do_bad_area(addr, esr, regs);
> +	/*
> +	 * The architecture specifies that bits 63:60 of FAR_EL1 are UNKNOWN for tag
> +	 * check faults. Mask them out now so that userspace doesn't see them.
> +	 */
> +	far &= (1UL << 60) - 1;
> +	do_bad_area(far, esr, regs);
>  	return 0;
>  }
>  
> @@ -717,11 +724,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)) {
> @@ -730,8 +738,7 @@ void do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs)
>  		show_pte(addr);
>  	}
>  
> -	arm64_notify_die(inf->name, regs,
> -			 inf->sig, inf->code, (void __user *)addr, esr);
> +	arm64_notify_die(inf->name, regs, inf->sig, inf->code, addr, esr);
>  }
>  NOKPROBE_SYMBOL(do_mem_abort);
>  
> @@ -744,8 +751,8 @@ NOKPROBE_SYMBOL(do_el0_irq_bp_hardening);
>  
>  void do_sp_pc_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs)
>  {
> -	arm64_notify_die("SP/PC alignment exception", regs,
> -			 SIGBUS, BUS_ADRALN, (void __user *)addr, esr);
> +	arm64_notify_die("SP/PC alignment exception", regs, SIGBUS, BUS_ADRALN,
> +			 addr, esr);
>  }
>  NOKPROBE_SYMBOL(do_sp_pc_abort);
>  
> @@ -871,8 +878,7 @@ void do_debug_exception(unsigned long addr_if_watchpoint, unsigned int esr,
>  		arm64_apply_bp_hardening();
>  
>  	if (inf->fn(addr_if_watchpoint, esr, regs)) {
> -		arm64_notify_die(inf->name, regs,
> -				 inf->sig, inf->code, (void __user *)pc, esr);
> +		arm64_notify_die(inf->name, regs, inf->sig, inf->code, pc, esr);
>  	}
>  
>  	debug_exception_exit(regs);
> diff --git a/include/linux/signal.h b/include/linux/signal.h
> index b256f9c65661..205526c4003a 100644
> --- a/include/linux/signal.h
> +++ b/include/linux/signal.h
> @@ -469,4 +469,18 @@ struct seq_file;
>  extern void render_sigset_t(struct seq_file *, const char *, sigset_t *);
>  #endif
>  
> +#ifndef arch_untagged_si_addr
> +/*
> + * Given a fault address and a signal and si_code which correspond to the
> + * _sigfault union member, returns the address that must appear in si_addr if
> + * the signal handler does not have SA_EXPOSE_TAGBITS enabled in sa_flags.
> + */
> +static inline void __user *arch_untagged_si_addr(void __user *addr,
> +						 unsigned long sig,
> +						 unsigned long si_code)
> +{
> +	return addr;
> +}
> +#endif
> +
>  #endif /* _LINUX_SIGNAL_H */
> diff --git a/include/linux/signal_types.h b/include/linux/signal_types.h
> index a7887ad84d36..68e06c75c5b2 100644
> --- a/include/linux/signal_types.h
> +++ b/include/linux/signal_types.h
> @@ -78,6 +78,6 @@ struct ksignal {
>  
>  #define UAPI_SA_FLAGS                                                          \
>  	(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART |  \
> -	 SA_NODEFER | SA_RESETHAND | __ARCH_UAPI_SA_FLAGS)
> +	 SA_NODEFER | SA_RESETHAND | SA_EXPOSE_TAGBITS | __ARCH_UAPI_SA_FLAGS)
>  
>  #endif /* _LINUX_SIGNAL_TYPES_H */
> diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
> index 0126ebda4d31..5276bdd4a9e2 100644
> --- a/include/uapi/asm-generic/signal-defs.h
> +++ b/include/uapi/asm-generic/signal-defs.h
> @@ -20,6 +20,8 @@
>   * 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_EXPOSE_TAGBITS exposes an architecture-defined set of tag bits in
> + * siginfo.si_addr.
>   *
>   * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
>   * Unix names RESETHAND and NODEFER respectively.
> @@ -49,6 +51,7 @@
>  #define SA_RESETHAND	0x80000000
>  #endif
>  #define SA_UNSUPPORTED	0x00000400
> +#define SA_EXPOSE_TAGBITS	0x00000800
>  
>  #define SA_NOMASK	SA_NODEFER
>  #define SA_ONESHOT	SA_RESETHAND
> diff --git a/kernel/signal.c b/kernel/signal.c
> index 8f34819e80de..16be62e6d341 100644
> --- a/kernel/signal.c
> +++ b/kernel/signal.c
> @@ -1650,6 +1650,15 @@ void force_sigsegv(int sig)
>  	force_sig(SIGSEGV);
>  }
>  
> +static void __user *get_si_addr(void __user *addr, unsigned long sig,
> +				unsigned long si_code)
> +{
> +	if (current->sighand->action[sig - 1].sa.sa_flags & SA_EXPOSE_TAGBITS)
> +		return addr;
> +
> +	return arch_untagged_si_addr(addr, sig, si_code);
> +}
> +
>  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)
> @@ -1661,7 +1670,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
>  	info.si_signo = sig;
>  	info.si_errno = 0;
>  	info.si_code  = code;
> -	info.si_addr  = addr;
> +	info.si_addr  = get_si_addr(addr, sig, code);
>  #ifdef __ARCH_SI_TRAPNO
>  	info.si_trapno = trapno;
>  #endif
> @@ -1693,7 +1702,7 @@ int send_sig_fault(int sig, int code, void __user *addr
>  	info.si_signo = sig;
>  	info.si_errno = 0;
>  	info.si_code  = code;
> -	info.si_addr  = addr;
> +	info.si_addr  = get_si_addr(addr, sig, code);
>  #ifdef __ARCH_SI_TRAPNO
>  	info.si_trapno = trapno;
>  #endif
> @@ -1714,7 +1723,7 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
>  	info.si_signo = SIGBUS;
>  	info.si_errno = 0;
>  	info.si_code = code;
> -	info.si_addr = addr;
> +	info.si_addr = get_si_addr(addr, SIGBUS, code);
>  	info.si_addr_lsb = lsb;
>  	return force_sig_info(&info);
>  }
> @@ -1728,7 +1737,7 @@ int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *
>  	info.si_signo = SIGBUS;
>  	info.si_errno = 0;
>  	info.si_code = code;
> -	info.si_addr = addr;
> +	info.si_addr = get_si_addr(addr, SIGBUS, code);
>  	info.si_addr_lsb = lsb;
>  	return send_sig_info(info.si_signo, &info, t);
>  }
> @@ -1742,7 +1751,7 @@ int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
>  	info.si_signo = SIGSEGV;
>  	info.si_errno = 0;
>  	info.si_code  = SEGV_BNDERR;
> -	info.si_addr  = addr;
> +	info.si_addr  = get_si_addr(addr, SIGSEGV, SEGV_BNDERR);
>  	info.si_lower = lower;
>  	info.si_upper = upper;
>  	return force_sig_info(&info);
> @@ -1757,7 +1766,7 @@ int force_sig_pkuerr(void __user *addr, u32 pkey)
>  	info.si_signo = SIGSEGV;
>  	info.si_errno = 0;
>  	info.si_code  = SEGV_PKUERR;
> -	info.si_addr  = addr;
> +	info.si_addr  = get_si_addr(addr, SIGSEGV, SEGV_PKUERR);
>  	info.si_pkey  = pkey;
>  	return force_sig_info(&info);
>  }
> @@ -1774,7 +1783,7 @@ int force_sig_ptrace_errno_trap(int errno, void __user *addr)
>  	info.si_signo = SIGTRAP;
>  	info.si_errno = errno;
>  	info.si_code  = TRAP_HWBKPT;
> -	info.si_addr  = addr;
> +	info.si_addr  = get_si_addr(addr, SIGTRAP, TRAP_HWBKPT);
>  	return force_sig_info(&info);
>  }

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

* Re: [PATCH v16 6/6] arm64: expose FAR_EL1 tag bits in siginfo
  2020-11-15 14:08   ` Eric W. Biederman
@ 2020-11-16 13:36     ` Dave Martin
  2020-11-16 18:32       ` Peter Collingbourne
  0 siblings, 1 reply; 19+ messages in thread
From: Dave Martin @ 2020-11-16 13:36 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Peter Collingbourne, Catalin Marinas, Helge Deller,
	Kevin Brodsky, Oleg Nesterov, linux-api, James E.J. Bottomley,
	Kostya Serebryany, Linux ARM, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Will Deacon, Evgenii Stepanov

On Sun, Nov 15, 2020 at 08:08:36AM -0600, Eric W. Biederman wrote:
> Peter Collingbourne <pcc@google.com> writes:
> 
> > 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, introduce a flag in
> > sigaction.sa_flags, SA_EXPOSE_TAGBITS, and only expose the tag bits
> > there if the signal handler has this flag set.
> 
> For future architectures that implement something similar does it make
> sense that to hide tag bits by default?

I think on arm64 this comes from the fact that the tag bits information
is not available in all scenarios.  To keep things clean, the decision
was taken early on to just zero them all the time in si_addr to avoid
software getting confused.  Possibly other arches do something similar,
but that would need digging into.

There seems to be debate on whether these bits are part of the address
or not.  For si_addr I think they probably _should_ be regarded as part
of the address in general, and arches that can always report all these
bits in si_addr should probably do so IMHO.

> I am wondering if SA_EXPOSE_TABGITS might make sense as an architecture
> specific sa bit.

Perhaps.  Peter, do you see other arches masking out bits in si_addr?

[...]

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

* Re: [PATCH v16 6/6] arm64: expose FAR_EL1 tag bits in siginfo
  2020-11-16 13:36     ` Dave Martin
@ 2020-11-16 18:32       ` Peter Collingbourne
  0 siblings, 0 replies; 19+ messages in thread
From: Peter Collingbourne @ 2020-11-16 18:32 UTC (permalink / raw)
  To: Dave Martin
  Cc: Linux ARM, Catalin Marinas, Helge Deller, Kevin Brodsky,
	Oleg Nesterov, Linux API, James E.J. Bottomley,
	Kostya Serebryany, Eric W. Biederman, Andrey Konovalov,
	David Spickett, Vincenzo Frascino, Will Deacon, Evgenii Stepanov

On Mon, Nov 16, 2020 at 5:36 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Sun, Nov 15, 2020 at 08:08:36AM -0600, Eric W. Biederman wrote:
> > Peter Collingbourne <pcc@google.com> writes:
> >
> > > 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, introduce a flag in
> > > sigaction.sa_flags, SA_EXPOSE_TAGBITS, and only expose the tag bits
> > > there if the signal handler has this flag set.
> >
> > For future architectures that implement something similar does it make
> > sense that to hide tag bits by default?
>
> I think on arm64 this comes from the fact that the tag bits information
> is not available in all scenarios.  To keep things clean, the decision
> was taken early on to just zero them all the time in si_addr to avoid
> software getting confused.  Possibly other arches do something similar,
> but that would need digging into.
>
> There seems to be debate on whether these bits are part of the address
> or not.  For si_addr I think they probably _should_ be regarded as part
> of the address in general, and arches that can always report all these
> bits in si_addr should probably do so IMHO.
>
> > I am wondering if SA_EXPOSE_TABGITS might make sense as an architecture
> > specific sa bit.
>
> Perhaps.  Peter, do you see other arches masking out bits in si_addr?

I think it's possible, since it seems likely to me that the bits would
only be able to be exposed unconditionally if the architecture with
the tag bits is new. For existing architectures that are being
extended with tag bits (e.g. RISC-V), I can see folks running into the
same problem of software getting confused by the tag bits, so they
would want to put them behind a flag, ideally the same one.

Another point in favor of making it generic is that in many cases
where you want these bits your signal handler will for the most part
not be arch-specific. In Android's case for example we have a
tombstone signal handler which is mostly generic with the
arch-specific parts hidden behind an abstraction, and the libsigchain
signal handler that needs to hide the bits if the flag is not set, but
is otherwise generic. Making it generic avoids an #ifdef around the
points where we need to refer to the flag. Please see my AOSP
userspace changes [1] for reference. As you can see there is no #ifdef
__aarch64__ required at all except for tests (there is already a
helper function for untagging addresses that has the required #ifdef),
but there are several points at which we need to refer to the flag.
With an arch-specific flag the #ifdef would become more pervasive.

Peter

[1] https://android-review.googlesource.com/id/I57f24c07c01ceb3e5b81cfc15edf559ef7dfc740

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

* Re: [PATCH v16 6/6] arm64: expose FAR_EL1 tag bits in siginfo
  2020-11-13  2:53 ` [PATCH v16 6/6] arm64: expose FAR_EL1 tag bits in siginfo Peter Collingbourne
  2020-11-15 14:08   ` Eric W. Biederman
@ 2020-11-16 19:01   ` Catalin Marinas
  2020-11-16 21:55     ` Eric W. Biederman
  1 sibling, 1 reply; 19+ messages in thread
From: Catalin Marinas @ 2020-11-16 19:01 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Linux ARM, Andrey Konovalov, Helge Deller, Kevin Brodsky,
	Oleg Nesterov, James E.J. Bottomley, Kostya Serebryany,
	Eric W. Biederman, linux-api, David Spickett, Vincenzo Frascino,
	Will Deacon, Dave Martin, Evgenii Stepanov

On Thu, Nov 12, 2020 at 06:53:36PM -0800, Peter Collingbourne wrote:
> diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst
> index eab4323609b9..19d284b70384 100644
> --- a/Documentation/arm64/tagged-pointers.rst
> +++ b/Documentation/arm64/tagged-pointers.rst
> @@ -53,12 +53,25 @@ 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.
> +When delivering signals, non-zero tags are not preserved in
> +siginfo.si_addr unless the flag SA_EXPOSE_TAGBITS was set in
> +sigaction.sa_flags when the signal handler was installed. 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 unless the flag was set.
> +
> +Due to architecture limitations, bits 63:60 of the fault address
> +are not preserved in response to synchronous tag check faults
> +(SEGV_MTESERR) even if SA_EXPOSE_TAGBITS was set. Applications should
> +treat the values of these bits as undefined in order to accommodate
> +future architecture revisions which may preserve the bits.

If future architecture versions will preserve these bits, most likely
we'll add a new HWCAP bit so that the user knows what's going on. But
the user shouldn't rely on them being 0, just in case.

> +For signals raised in response to watchpoint debug exceptions, the
> +tag information will be preserved regardless of the SA_EXPOSE_TAGBITS
> +flag setting.
> +
> +Non-zero tags are never preserved in sigcontext.fault_address
> +regardless of the SA_EXPOSE_TAGBITS flag setting.

We could've done it the other way around (fault_address tagged, si_addr
untagged) but that would be specific to arm64, so I think we should
solve it for other architectures that implement (or plan to) tagging.
The fault_address in the arm64 sigcontext was an oversight, we should
have removed it but when we realised it was already ABI.

Anyway, I'm fine with the arm64 changes here:

Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>

With Eric's ack, I'm happy to take the series through the arm64 tree,
otherwise Eric's tree is fine as well.

Thanks.

-- 
Catalin

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

* Re: [PATCH v16 6/6] arm64: expose FAR_EL1 tag bits in siginfo
  2020-11-16 19:01   ` Catalin Marinas
@ 2020-11-16 21:55     ` Eric W. Biederman
  2020-11-16 22:08       ` Catalin Marinas
  2020-11-16 23:28       ` Peter Collingbourne
  0 siblings, 2 replies; 19+ messages in thread
From: Eric W. Biederman @ 2020-11-16 21:55 UTC (permalink / raw)
  To: Catalin Marinas
  Cc: Peter Collingbourne, Helge Deller, Kevin Brodsky, Oleg Nesterov,
	linux-api, James E.J. Bottomley, Kostya Serebryany, Linux ARM,
	Andrey Konovalov, David Spickett, Vincenzo Frascino, Will Deacon,
	Dave Martin, Evgenii Stepanov

Catalin Marinas <catalin.marinas@arm.com> writes:

> On Thu, Nov 12, 2020 at 06:53:36PM -0800, Peter Collingbourne wrote:
>> diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst
>> index eab4323609b9..19d284b70384 100644
>> --- a/Documentation/arm64/tagged-pointers.rst
>> +++ b/Documentation/arm64/tagged-pointers.rst
>> @@ -53,12 +53,25 @@ 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.
>> +When delivering signals, non-zero tags are not preserved in
>> +siginfo.si_addr unless the flag SA_EXPOSE_TAGBITS was set in
>> +sigaction.sa_flags when the signal handler was installed. 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 unless the flag was set.
>> +
>> +Due to architecture limitations, bits 63:60 of the fault address
>> +are not preserved in response to synchronous tag check faults
>> +(SEGV_MTESERR) even if SA_EXPOSE_TAGBITS was set. Applications should
>> +treat the values of these bits as undefined in order to accommodate
>> +future architecture revisions which may preserve the bits.
>
> If future architecture versions will preserve these bits, most likely
> we'll add a new HWCAP bit so that the user knows what's going on. But
> the user shouldn't rely on them being 0, just in case.
>
>> +For signals raised in response to watchpoint debug exceptions, the
>> +tag information will be preserved regardless of the SA_EXPOSE_TAGBITS
>> +flag setting.
>> +
>> +Non-zero tags are never preserved in sigcontext.fault_address
>> +regardless of the SA_EXPOSE_TAGBITS flag setting.
>
> We could've done it the other way around (fault_address tagged, si_addr
> untagged) but that would be specific to arm64, so I think we should
> solve it for other architectures that implement (or plan to) tagging.
> The fault_address in the arm64 sigcontext was an oversight, we should
> have removed it but when we realised it was already ABI.
>
> Anyway, I'm fine with the arm64 changes here:
>
> Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
>
> With Eric's ack, I'm happy to take the series through the arm64 tree,
> otherwise Eric's tree is fine as well.

In general I am fine with the last two patches.

I want to understand where the value for SA_UNSUPPORTED comes from, and
while I have good answers I am still digesting the question of if
SA_EXPOSE_TAGBITS should be implemented in the arch specific header or
in a generic header.  I quite agree it should have a generic
definition/implementation.  I just don't know if it makes sense to make
the value available to userspace if the architecture does not have
tagbits.  Mostly my concern is about bit consumption as we only have
30ish sigaction bits.

I will follow with my acks when I have resolved those issues.

Thank you,
Eric


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

* Re: [PATCH v16 6/6] arm64: expose FAR_EL1 tag bits in siginfo
  2020-11-16 21:55     ` Eric W. Biederman
@ 2020-11-16 22:08       ` Catalin Marinas
  2020-11-16 23:28       ` Peter Collingbourne
  1 sibling, 0 replies; 19+ messages in thread
From: Catalin Marinas @ 2020-11-16 22:08 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Peter Collingbourne, Helge Deller, Kevin Brodsky, Oleg Nesterov,
	linux-api, James E.J. Bottomley, Kostya Serebryany, Linux ARM,
	Andrey Konovalov, David Spickett, Vincenzo Frascino, Will Deacon,
	Dave Martin, Evgenii Stepanov

On Mon, Nov 16, 2020 at 03:55:05PM -0600, Eric W. Biederman wrote:
> Catalin Marinas <catalin.marinas@arm.com> writes:
> > On Thu, Nov 12, 2020 at 06:53:36PM -0800, Peter Collingbourne wrote:
> >> diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst
> >> index eab4323609b9..19d284b70384 100644
> >> --- a/Documentation/arm64/tagged-pointers.rst
> >> +++ b/Documentation/arm64/tagged-pointers.rst
> >> @@ -53,12 +53,25 @@ 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.
> >> +When delivering signals, non-zero tags are not preserved in
> >> +siginfo.si_addr unless the flag SA_EXPOSE_TAGBITS was set in
> >> +sigaction.sa_flags when the signal handler was installed. 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 unless the flag was set.
> >> +
> >> +Due to architecture limitations, bits 63:60 of the fault address
> >> +are not preserved in response to synchronous tag check faults
> >> +(SEGV_MTESERR) even if SA_EXPOSE_TAGBITS was set. Applications should
> >> +treat the values of these bits as undefined in order to accommodate
> >> +future architecture revisions which may preserve the bits.
> >
> > If future architecture versions will preserve these bits, most likely
> > we'll add a new HWCAP bit so that the user knows what's going on. But
> > the user shouldn't rely on them being 0, just in case.
> >
> >> +For signals raised in response to watchpoint debug exceptions, the
> >> +tag information will be preserved regardless of the SA_EXPOSE_TAGBITS
> >> +flag setting.
> >> +
> >> +Non-zero tags are never preserved in sigcontext.fault_address
> >> +regardless of the SA_EXPOSE_TAGBITS flag setting.
> >
> > We could've done it the other way around (fault_address tagged, si_addr
> > untagged) but that would be specific to arm64, so I think we should
> > solve it for other architectures that implement (or plan to) tagging.
> > The fault_address in the arm64 sigcontext was an oversight, we should
> > have removed it but when we realised it was already ABI.
> >
> > Anyway, I'm fine with the arm64 changes here:
> >
> > Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
> >
> > With Eric's ack, I'm happy to take the series through the arm64 tree,
> > otherwise Eric's tree is fine as well.
> 
> In general I am fine with the last two patches.
> 
> I want to understand where the value for SA_UNSUPPORTED comes from, and
> while I have good answers I am still digesting the question of if
> SA_EXPOSE_TAGBITS should be implemented in the arch specific header or
> in a generic header.  I quite agree it should have a generic
> definition/implementation.  I just don't know if it makes sense to make
> the value available to userspace if the architecture does not have
> tagbits.  Mostly my concern is about bit consumption as we only have
> 30ish sigaction bits.

An alternative would be to make this opt-in per process (or thread)
based on a prctl() call. We already have one for PR_TAGGED_ADDR_ENABLE
to allow tagged addresses from user at the syscall ABI level. Another
bit in there would allow si_addr to be tagged. The disadvantage is that
this is quite coarse control affecting other signal handlers.

> I will follow with my acks when I have resolved those issues.

Thanks.

-- 
Catalin

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

* Re: [PATCH v16 6/6] arm64: expose FAR_EL1 tag bits in siginfo
  2020-11-16 21:55     ` Eric W. Biederman
  2020-11-16 22:08       ` Catalin Marinas
@ 2020-11-16 23:28       ` Peter Collingbourne
  2020-11-16 23:59         ` Eric W. Biederman
  1 sibling, 1 reply; 19+ messages in thread
From: Peter Collingbourne @ 2020-11-16 23:28 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Catalin Marinas, Helge Deller, Kevin Brodsky, Oleg Nesterov,
	Linux API, James E.J. Bottomley, Kostya Serebryany, Linux ARM,
	Andrey Konovalov, David Spickett, Vincenzo Frascino, Will Deacon,
	Dave Martin, Evgenii Stepanov

On Mon, Nov 16, 2020 at 1:55 PM Eric W. Biederman <ebiederm@xmission.com> wrote:
>
> Catalin Marinas <catalin.marinas@arm.com> writes:
>
> > On Thu, Nov 12, 2020 at 06:53:36PM -0800, Peter Collingbourne wrote:
> >> diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst
> >> index eab4323609b9..19d284b70384 100644
> >> --- a/Documentation/arm64/tagged-pointers.rst
> >> +++ b/Documentation/arm64/tagged-pointers.rst
> >> @@ -53,12 +53,25 @@ 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.
> >> +When delivering signals, non-zero tags are not preserved in
> >> +siginfo.si_addr unless the flag SA_EXPOSE_TAGBITS was set in
> >> +sigaction.sa_flags when the signal handler was installed. 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 unless the flag was set.
> >> +
> >> +Due to architecture limitations, bits 63:60 of the fault address
> >> +are not preserved in response to synchronous tag check faults
> >> +(SEGV_MTESERR) even if SA_EXPOSE_TAGBITS was set. Applications should
> >> +treat the values of these bits as undefined in order to accommodate
> >> +future architecture revisions which may preserve the bits.
> >
> > If future architecture versions will preserve these bits, most likely
> > we'll add a new HWCAP bit so that the user knows what's going on. But
> > the user shouldn't rely on them being 0, just in case.
> >
> >> +For signals raised in response to watchpoint debug exceptions, the
> >> +tag information will be preserved regardless of the SA_EXPOSE_TAGBITS
> >> +flag setting.
> >> +
> >> +Non-zero tags are never preserved in sigcontext.fault_address
> >> +regardless of the SA_EXPOSE_TAGBITS flag setting.
> >
> > We could've done it the other way around (fault_address tagged, si_addr
> > untagged) but that would be specific to arm64, so I think we should
> > solve it for other architectures that implement (or plan to) tagging.
> > The fault_address in the arm64 sigcontext was an oversight, we should
> > have removed it but when we realised it was already ABI.
> >
> > Anyway, I'm fine with the arm64 changes here:
> >
> > Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
> >
> > With Eric's ack, I'm happy to take the series through the arm64 tree,
> > otherwise Eric's tree is fine as well.
>
> In general I am fine with the last two patches.
>
> I want to understand where the value for SA_UNSUPPORTED comes from, and

I hope I explained it well enough in [1]. If documenting the
arch-specific bits that way looks good to you let me know and I will
update patch 3.

> while I have good answers I am still digesting the question of if
> SA_EXPOSE_TAGBITS should be implemented in the arch specific header or
> in a generic header.  I quite agree it should have a generic
> definition/implementation.  I just don't know if it makes sense to make
> the value available to userspace if the architecture does not have
> tagbits.  Mostly my concern is about bit consumption as we only have
> 30ish sigaction bits.

As mentioned in [2] I would favor making the bits generic as that
would simplify the client code. And I would personally not be too
concerned about consuming bits here. Our historical rate of adding new
bits is very low (as far as I know these are the first new bits to be
added in about 20 years!) And once we are at the point where we are
close to running out of bits it would be a good time to consider a new
sigaction API anyway that addresses some of the historical warts of
the existing one, and at that point we should be able to come up with
a way to add more bits.

Peter

[1] https://lore.kernel.org/linux-arm-kernel/CAMn1gO52j4fSEn5S2GdrtyCq+iiaMK16DkKiyj=Go91Jy+xR-w@mail.gmail.com/
[2] https://lore.kernel.org/linux-arm-kernel/CAMn1gO6n7NrM8A+vkMt=ixvbSzUJbrr2s6Ko3WENPoT-84J15w@mail.gmail.com/

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

* Re: [PATCH v16 5/6] signal: define the SA_UNSUPPORTED bit in sa_flags
  2020-11-14 22:12     ` Peter Collingbourne
@ 2020-11-16 23:48       ` Eric W. Biederman
  0 siblings, 0 replies; 19+ messages in thread
From: Eric W. Biederman @ 2020-11-16 23:48 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Catalin Marinas, Helge Deller, Kevin Brodsky, Oleg Nesterov,
	Linux API, James E.J. Bottomley, Kostya Serebryany, Linux ARM,
	Andrey Konovalov, David Spickett, Vincenzo Frascino, Will Deacon,
	Dave Martin, Evgenii Stepanov

Peter Collingbourne <pcc@google.com> writes:

> On Sat, Nov 14, 2020 at 5:53 AM Eric W. Biederman <ebiederm@xmission.com> wrote:
>>
>> Peter Collingbourne <pcc@google.com> writes:
>>
>> > Define a sa_flags bit, SA_UNSUPPORTED, which 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 does something like:
>> >
>> >   act.sa_flags |= SA_UNSUPPORTED;
>> >   sigaction(SIGSEGV, &act, 0);
>> >   sigaction(SIGSEGV, 0, &oldact);
>> >
>> > and finds that SA_UNSUPPORTED remains set in oldact.sa_flags, it means
>> > that the kernel cannot be trusted to have cleared unknown flag bits
>> > from sa_flags, so no assumptions about flag bit support can be made.
>> >
>> > Signed-off-by: Peter Collingbourne <pcc@google.com>
>> > Reviewed-by: Dave Martin <Dave.Martin@arm.com>
>> > Link: https://linux-review.googlesource.com/id/Ic2501ad150a3a79c1cf27fb8c99be342e9dffbcb
>> > ---
>> > v11:
>> > - clarify the commit message
>> >
>> >  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 493953fe319b..0126ebda4d31 100644
>> > --- a/include/uapi/asm-generic/signal-defs.h
>> > +++ b/include/uapi/asm-generic/signal-defs.h
>> > @@ -14,6 +14,12 @@
>> >   * SA_RESTART flag to get restarting signals (which were the default long ago)
>> >   * SA_NODEFER prevents the current signal from being masked in the handler.
>> >   * SA_RESETHAND clears the handler when the signal is delivered.
>> > + * SA_UNSUPPORTED is a flag bit that will never be supported. Kernels from
>> > + * before the introduction of SA_UNSUPPORTED did not clear unknown bits from
>> > + * sa_flags when read using the oldact argument to sigaction and rt_sigaction,
>> > + * so this bit allows flag bit support to be detected from userspace while
>> > + * allowing an old kernel to be distinguished from a kernel that supports every
>> > + * flag bit.
>> >   *
>> >   * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
>> >   * Unix names RESETHAND and NODEFER respectively.
>> > @@ -42,6 +48,7 @@
>> >  #ifndef SA_RESETHAND
>> >  #define SA_RESETHAND 0x80000000
>> >  #endif
>> > +#define SA_UNSUPPORTED       0x00000400
>>
>> Why this value and why not in numerical order with the other flags?
>>
>> At the very least not being in order with the other bits makes it
>> a little easier to overlook it and define something at that position.
>
> The value is because this is the first bit that isn't already taken by
> an architecture-specific flag bit. It seems okay to move it into
> numerical order.
>
> The taken flag bits are listed in the comment that I added in patch 3.
> Do you think there would be a more prominent way to document them?
> Maybe we can replace that comment with inline, in-order comments along
> the lines of:
>
> #ifndef SA_NOCLDSTOP
> #define SA_NOCLDSTOP   0x00000001
> #endif
> #ifndef SA_NOCLDWAIT
> #define SA_NOCLDWAIT   0x00000002
> #endif
> #ifndef SA_SIGINFO
> #define SA_SIGINFO     0x00000004
> #endif
> /* 0x00000008 has arch-specific definition */
> /* 0x00000010 has arch-specific definition */
>
> etc.
>
> And then this patch would add the new bit in the right place.

Yes.  That seems like it would be easier to think about.

If you could also add the architectures that use those bits that would
be helpful.  Then if someone wants to look and see what is going on they
need to look, and as a bunus in the if in event those architectures are
deleted we would know that the bit no longer need to be reserved.

Eric

p.s. Apologies for some reason I did not see this reply earlier.

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

* Re: [PATCH v16 6/6] arm64: expose FAR_EL1 tag bits in siginfo
  2020-11-16 23:28       ` Peter Collingbourne
@ 2020-11-16 23:59         ` Eric W. Biederman
  2020-11-17  3:24           ` Peter Collingbourne
  0 siblings, 1 reply; 19+ messages in thread
From: Eric W. Biederman @ 2020-11-16 23:59 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Catalin Marinas, Helge Deller, Kevin Brodsky, Oleg Nesterov,
	Linux API, James E.J. Bottomley, Kostya Serebryany, Linux ARM,
	Andrey Konovalov, David Spickett, Vincenzo Frascino, Will Deacon,
	Dave Martin, Evgenii Stepanov

Peter Collingbourne <pcc@google.com> writes:

> On Mon, Nov 16, 2020 at 1:55 PM Eric W. Biederman <ebiederm@xmission.com> wrote:
>>
>> Catalin Marinas <catalin.marinas@arm.com> writes:
>>
>> > On Thu, Nov 12, 2020 at 06:53:36PM -0800, Peter Collingbourne wrote:
>> >> diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst
>> >> index eab4323609b9..19d284b70384 100644
>> >> --- a/Documentation/arm64/tagged-pointers.rst
>> >> +++ b/Documentation/arm64/tagged-pointers.rst
>> >> @@ -53,12 +53,25 @@ 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.
>> >> +When delivering signals, non-zero tags are not preserved in
>> >> +siginfo.si_addr unless the flag SA_EXPOSE_TAGBITS was set in
>> >> +sigaction.sa_flags when the signal handler was installed. 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 unless the flag was set.
>> >> +
>> >> +Due to architecture limitations, bits 63:60 of the fault address
>> >> +are not preserved in response to synchronous tag check faults
>> >> +(SEGV_MTESERR) even if SA_EXPOSE_TAGBITS was set. Applications should
>> >> +treat the values of these bits as undefined in order to accommodate
>> >> +future architecture revisions which may preserve the bits.
>> >
>> > If future architecture versions will preserve these bits, most likely
>> > we'll add a new HWCAP bit so that the user knows what's going on. But
>> > the user shouldn't rely on them being 0, just in case.
>> >
>> >> +For signals raised in response to watchpoint debug exceptions, the
>> >> +tag information will be preserved regardless of the SA_EXPOSE_TAGBITS
>> >> +flag setting.
>> >> +
>> >> +Non-zero tags are never preserved in sigcontext.fault_address
>> >> +regardless of the SA_EXPOSE_TAGBITS flag setting.
>> >
>> > We could've done it the other way around (fault_address tagged, si_addr
>> > untagged) but that would be specific to arm64, so I think we should
>> > solve it for other architectures that implement (or plan to) tagging.
>> > The fault_address in the arm64 sigcontext was an oversight, we should
>> > have removed it but when we realised it was already ABI.
>> >
>> > Anyway, I'm fine with the arm64 changes here:
>> >
>> > Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
>> >
>> > With Eric's ack, I'm happy to take the series through the arm64 tree,
>> > otherwise Eric's tree is fine as well.
>>
>> In general I am fine with the last two patches.
>>
>> I want to understand where the value for SA_UNSUPPORTED comes from, and
>
> I hope I explained it well enough in [1]. If documenting the
> arch-specific bits that way looks good to you let me know and I will
> update patch 3.

Bah.  I missed your reply.

Please send me an incremental patch against:

 https://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace.git signal-for-v5.11

As I have already applied your first 4 patches and have them in
linux-next.

>> while I have good answers I am still digesting the question of if
>> SA_EXPOSE_TAGBITS should be implemented in the arch specific header or
>> in a generic header.  I quite agree it should have a generic
>> definition/implementation.  I just don't know if it makes sense to make
>> the value available to userspace if the architecture does not have
>> tagbits.  Mostly my concern is about bit consumption as we only have
>> 30ish sigaction bits.
>
> As mentioned in [2] I would favor making the bits generic as that
> would simplify the client code. And I would personally not be too
> concerned about consuming bits here. Our historical rate of adding new
> bits is very low (as far as I know these are the first new bits to be
> added in about 20 years!) And once we are at the point where we are
> close to running out of bits it would be a good time to consider a new
> sigaction API anyway that addresses some of the historical warts of
> the existing one, and at that point we should be able to come up with
> a way to add more bits.

It is a good point that this areay hasn't seen much action in ages.  So
there is not too much need to be concerned.

In general portable code will need to do "#ifdef SA_EXPOSE_TAGBITS"
somewhere.  But certainly it should be at least as generic as
SA_RESTORER.  With the same meaning everywhere it is defined.
And certainly it makes sense for the implementation to live
in the generic signal code for to ensure all architectures implement
it with the same semantics.

I am going to sleep on this one and then see if I see any real concerns.

This is bike-shedding I know, and you have done a very nice job gettin
this far.  So I don't expect I will come up with any compelling reasons
to change after sleeping on it, but I am going to sleep on it.


> [1] https://lore.kernel.org/linux-arm-kernel/CAMn1gO52j4fSEn5S2GdrtyCq+iiaMK16DkKiyj=Go91Jy+xR-w@mail.gmail.com/
> [2] https://lore.kernel.org/linux-arm-kernel/CAMn1gO6n7NrM8A+vkMt=ixvbSzUJbrr2s6Ko3WENPoT-84J15w@mail.gmail.com/

Eric

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

* Re: [PATCH v16 6/6] arm64: expose FAR_EL1 tag bits in siginfo
  2020-11-16 23:59         ` Eric W. Biederman
@ 2020-11-17  3:24           ` Peter Collingbourne
  0 siblings, 0 replies; 19+ messages in thread
From: Peter Collingbourne @ 2020-11-17  3:24 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Catalin Marinas, Helge Deller, Kevin Brodsky, Oleg Nesterov,
	Linux API, James E.J. Bottomley, Kostya Serebryany, Linux ARM,
	Andrey Konovalov, David Spickett, Vincenzo Frascino, Will Deacon,
	Dave Martin, Evgenii Stepanov

On Mon, Nov 16, 2020 at 4:00 PM Eric W. Biederman <ebiederm@xmission.com> wrote:
>
> Peter Collingbourne <pcc@google.com> writes:
>
> > On Mon, Nov 16, 2020 at 1:55 PM Eric W. Biederman <ebiederm@xmission.com> wrote:
> >>
> >> Catalin Marinas <catalin.marinas@arm.com> writes:
> >>
> >> > On Thu, Nov 12, 2020 at 06:53:36PM -0800, Peter Collingbourne wrote:
> >> >> diff --git a/Documentation/arm64/tagged-pointers.rst b/Documentation/arm64/tagged-pointers.rst
> >> >> index eab4323609b9..19d284b70384 100644
> >> >> --- a/Documentation/arm64/tagged-pointers.rst
> >> >> +++ b/Documentation/arm64/tagged-pointers.rst
> >> >> @@ -53,12 +53,25 @@ 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.
> >> >> +When delivering signals, non-zero tags are not preserved in
> >> >> +siginfo.si_addr unless the flag SA_EXPOSE_TAGBITS was set in
> >> >> +sigaction.sa_flags when the signal handler was installed. 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 unless the flag was set.
> >> >> +
> >> >> +Due to architecture limitations, bits 63:60 of the fault address
> >> >> +are not preserved in response to synchronous tag check faults
> >> >> +(SEGV_MTESERR) even if SA_EXPOSE_TAGBITS was set. Applications should
> >> >> +treat the values of these bits as undefined in order to accommodate
> >> >> +future architecture revisions which may preserve the bits.
> >> >
> >> > If future architecture versions will preserve these bits, most likely
> >> > we'll add a new HWCAP bit so that the user knows what's going on. But
> >> > the user shouldn't rely on them being 0, just in case.
> >> >
> >> >> +For signals raised in response to watchpoint debug exceptions, the
> >> >> +tag information will be preserved regardless of the SA_EXPOSE_TAGBITS
> >> >> +flag setting.
> >> >> +
> >> >> +Non-zero tags are never preserved in sigcontext.fault_address
> >> >> +regardless of the SA_EXPOSE_TAGBITS flag setting.
> >> >
> >> > We could've done it the other way around (fault_address tagged, si_addr
> >> > untagged) but that would be specific to arm64, so I think we should
> >> > solve it for other architectures that implement (or plan to) tagging.
> >> > The fault_address in the arm64 sigcontext was an oversight, we should
> >> > have removed it but when we realised it was already ABI.
> >> >
> >> > Anyway, I'm fine with the arm64 changes here:
> >> >
> >> > Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
> >> >
> >> > With Eric's ack, I'm happy to take the series through the arm64 tree,
> >> > otherwise Eric's tree is fine as well.
> >>
> >> In general I am fine with the last two patches.
> >>
> >> I want to understand where the value for SA_UNSUPPORTED comes from, and
> >
> > I hope I explained it well enough in [1]. If documenting the
> > arch-specific bits that way looks good to you let me know and I will
> > update patch 3.
>
> Bah.  I missed your reply.
>
> Please send me an incremental patch against:
>
>  https://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace.git signal-for-v5.11
>
> As I have already applied your first 4 patches and have them in
> linux-next.

Okay, I've sent a v17 to be applied on top of your branch.

> >> while I have good answers I am still digesting the question of if
> >> SA_EXPOSE_TAGBITS should be implemented in the arch specific header or
> >> in a generic header.  I quite agree it should have a generic
> >> definition/implementation.  I just don't know if it makes sense to make
> >> the value available to userspace if the architecture does not have
> >> tagbits.  Mostly my concern is about bit consumption as we only have
> >> 30ish sigaction bits.
> >
> > As mentioned in [2] I would favor making the bits generic as that
> > would simplify the client code. And I would personally not be too
> > concerned about consuming bits here. Our historical rate of adding new
> > bits is very low (as far as I know these are the first new bits to be
> > added in about 20 years!) And once we are at the point where we are
> > close to running out of bits it would be a good time to consider a new
> > sigaction API anyway that addresses some of the historical warts of
> > the existing one, and at that point we should be able to come up with
> > a way to add more bits.
>
> It is a good point that this areay hasn't seen much action in ages.  So
> there is not too much need to be concerned.
>
> In general portable code will need to do "#ifdef SA_EXPOSE_TAGBITS"
> somewhere.  But certainly it should be at least as generic as

Sure. It's worth noting though that if you know that you are targeting
Linux and have the latest kernel headers (which is the case for
Android platform code for example) you would be able to use new
#defines unconditionally.

> SA_RESTORER.  With the same meaning everywhere it is defined.
> And certainly it makes sense for the implementation to live
> in the generic signal code for to ensure all architectures implement
> it with the same semantics.
>
> I am going to sleep on this one and then see if I see any real concerns.
>
> This is bike-shedding I know, and you have done a very nice job gettin
> this far.  So I don't expect I will come up with any compelling reasons
> to change after sleeping on it, but I am going to sleep on it.

Okay, let me know if you find any concerns.

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

end of thread, other threads:[~2020-11-17  3:24 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-13  2:53 [PATCH v16 0/6] arm64: expose FAR_EL1 tag bits in siginfo Peter Collingbourne
2020-11-13  2:53 ` [PATCH v16 1/6] parisc: Drop parisc special case for __sighandler_t Peter Collingbourne
2020-11-13  2:53 ` [PATCH v16 2/6] parisc: start using signal-defs.h Peter Collingbourne
2020-11-13  2:53 ` [PATCH v16 3/6] arch: move SA_* definitions to generic headers Peter Collingbourne
2020-11-13  2:53 ` [PATCH v16 4/6] signal: clear non-uapi flag bits when passing/returning sa_flags Peter Collingbourne
2020-11-13  2:53 ` [PATCH v16 5/6] signal: define the SA_UNSUPPORTED bit in sa_flags Peter Collingbourne
2020-11-14 13:53   ` Eric W. Biederman
2020-11-14 22:12     ` Peter Collingbourne
2020-11-16 23:48       ` Eric W. Biederman
2020-11-13  2:53 ` [PATCH v16 6/6] arm64: expose FAR_EL1 tag bits in siginfo Peter Collingbourne
2020-11-15 14:08   ` Eric W. Biederman
2020-11-16 13:36     ` Dave Martin
2020-11-16 18:32       ` Peter Collingbourne
2020-11-16 19:01   ` Catalin Marinas
2020-11-16 21:55     ` Eric W. Biederman
2020-11-16 22:08       ` Catalin Marinas
2020-11-16 23:28       ` Peter Collingbourne
2020-11-16 23:59         ` Eric W. Biederman
2020-11-17  3:24           ` Peter Collingbourne

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).