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

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

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

However, one does not simply add fields to siginfo, at least not without
a mechanism for userspace to detect that they are present and valid.
Therefore, the first seven patches in this series introduce a mechanism
for userspace to detect the presence of our new siginfo fields,
and the last patch uses it to advertise the presence of said fields.

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

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

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

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

 Documentation/arm64/tagged-pointers.rst    |  21 +++-
 arch/alpha/include/uapi/asm/signal.h       |  14 ---
 arch/arm/include/asm/signal.h              |   2 +
 arch/arm/include/uapi/asm/signal.h         |  27 +----
 arch/arm64/include/asm/exception.h         |   2 +-
 arch/arm64/include/asm/signal.h            |  31 +++++
 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/powerpc/platforms/powernv/vas-fault.c |   1 +
 arch/s390/include/uapi/asm/signal.h        |  24 ----
 arch/sparc/include/uapi/asm/signal.h       |   4 +-
 arch/x86/include/uapi/asm/signal.h         |  24 ----
 arch/x86/kernel/signal_compat.c            |  19 +--
 arch/xtensa/include/uapi/asm/signal.h      |  24 ----
 include/linux/compat.h                     |   4 +
 include/linux/signal.h                     |  29 +++++
 include/linux/signal_types.h               |  12 ++
 include/uapi/asm-generic/siginfo.h         |  17 +++
 include/uapi/asm-generic/signal-defs.h     |  58 +++++++++
 include/uapi/asm-generic/signal.h          |  29 -----
 include/uapi/linux/ptrace.h                |  12 ++
 kernel/ptrace.c                            |  33 ++++-
 kernel/signal.c                            | 134 +++++++++++----------
 36 files changed, 361 insertions(+), 428 deletions(-)
 create mode 100644 arch/arm64/include/asm/signal.h

-- 
2.29.1.341.ge80a0c044ae-goog


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

* [PATCH v14 0/8] arm64: expose FAR_EL1 tag bits in siginfo
@ 2020-11-04 21:18 ` Peter Collingbourne
  0 siblings, 0 replies; 64+ messages in thread
From: Peter Collingbourne @ 2020-11-04 21:18 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,
	Richard Henderson

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

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

However, one does not simply add fields to siginfo, at least not without
a mechanism for userspace to detect that they are present and valid.
Therefore, the first seven patches in this series introduce a mechanism
for userspace to detect the presence of our new siginfo fields,
and the last patch uses it to advertise the presence of said fields.

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

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

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

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

 Documentation/arm64/tagged-pointers.rst    |  21 +++-
 arch/alpha/include/uapi/asm/signal.h       |  14 ---
 arch/arm/include/asm/signal.h              |   2 +
 arch/arm/include/uapi/asm/signal.h         |  27 +----
 arch/arm64/include/asm/exception.h         |   2 +-
 arch/arm64/include/asm/signal.h            |  31 +++++
 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/powerpc/platforms/powernv/vas-fault.c |   1 +
 arch/s390/include/uapi/asm/signal.h        |  24 ----
 arch/sparc/include/uapi/asm/signal.h       |   4 +-
 arch/x86/include/uapi/asm/signal.h         |  24 ----
 arch/x86/kernel/signal_compat.c            |  19 +--
 arch/xtensa/include/uapi/asm/signal.h      |  24 ----
 include/linux/compat.h                     |   4 +
 include/linux/signal.h                     |  29 +++++
 include/linux/signal_types.h               |  12 ++
 include/uapi/asm-generic/siginfo.h         |  17 +++
 include/uapi/asm-generic/signal-defs.h     |  58 +++++++++
 include/uapi/asm-generic/signal.h          |  29 -----
 include/uapi/linux/ptrace.h                |  12 ++
 kernel/ptrace.c                            |  33 ++++-
 kernel/signal.c                            | 134 +++++++++++----------
 36 files changed, 361 insertions(+), 428 deletions(-)
 create mode 100644 arch/arm64/include/asm/signal.h

-- 
2.29.1.341.ge80a0c044ae-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] 64+ messages in thread

* [PATCH v14 1/8] parisc: Drop parisc special case for __sighandler_t
  2020-11-04 21:18 ` Peter Collingbourne
@ 2020-11-04 21:18   ` Peter Collingbourne
  -1 siblings, 0 replies; 64+ messages in thread
From: Peter Collingbourne @ 2020-11-04 21:18 UTC (permalink / raw)
  To: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	Eric W. Biederman, James E.J. Bottomley
  Cc: Peter Collingbourne, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-api, Helge Deller, David Spickett

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.1.341.ge80a0c044ae-goog


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

* [PATCH v14 1/8] parisc: Drop parisc special case for __sighandler_t
@ 2020-11-04 21:18   ` Peter Collingbourne
  0 siblings, 0 replies; 64+ messages in thread
From: Peter Collingbourne @ 2020-11-04 21:18 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,
	Richard Henderson

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.1.341.ge80a0c044ae-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] 64+ messages in thread

* [PATCH v14 2/8] parisc: start using signal-defs.h
  2020-11-04 21:18 ` Peter Collingbourne
@ 2020-11-04 21:18   ` Peter Collingbourne
  -1 siblings, 0 replies; 64+ messages in thread
From: Peter Collingbourne @ 2020-11-04 21:18 UTC (permalink / raw)
  To: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	Eric W. Biederman, James E.J. Bottomley
  Cc: Peter Collingbourne, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-api, Helge Deller, David Spickett

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

Signed-off-by: Peter Collingbourne <pcc@google.com>
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.1.341.ge80a0c044ae-goog


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

* [PATCH v14 2/8] parisc: start using signal-defs.h
@ 2020-11-04 21:18   ` Peter Collingbourne
  0 siblings, 0 replies; 64+ messages in thread
From: Peter Collingbourne @ 2020-11-04 21:18 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,
	Richard Henderson

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

Signed-off-by: Peter Collingbourne <pcc@google.com>
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.1.341.ge80a0c044ae-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] 64+ messages in thread

* [PATCH v14 3/8] arch: move SA_* definitions to generic headers
  2020-11-04 21:18 ` Peter Collingbourne
@ 2020-11-04 21:18   ` Peter Collingbourne
  -1 siblings, 0 replies; 64+ messages in thread
From: Peter Collingbourne @ 2020-11-04 21:18 UTC (permalink / raw)
  To: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	Eric W. Biederman, James E.J. Bottomley
  Cc: Peter Collingbourne, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-api, Helge Deller, David Spickett,
	Geert Uytterhoeven

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.1.341.ge80a0c044ae-goog


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

* [PATCH v14 3/8] arch: move SA_* definitions to generic headers
@ 2020-11-04 21:18   ` Peter Collingbourne
  0 siblings, 0 replies; 64+ messages in thread
From: Peter Collingbourne @ 2020-11-04 21:18 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, Richard Henderson

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

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.1.341.ge80a0c044ae-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] 64+ messages in thread

* [PATCH v14 4/8] signal: deduplicate code dealing with common _sigfault fields
  2020-11-04 21:18 ` Peter Collingbourne
@ 2020-11-04 21:18   ` Peter Collingbourne
  -1 siblings, 0 replies; 64+ messages in thread
From: Peter Collingbourne @ 2020-11-04 21:18 UTC (permalink / raw)
  To: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	Eric W. Biederman, James E.J. Bottomley
  Cc: Peter Collingbourne, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-api, Helge Deller, David Spickett

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

Signed-off-by: Peter Collingbourne <pcc@google.com>
Link: https://linux-review.googlesource.com/id/I4f56174e1b7b2bf4a3c8139e6879cbfd52750a24
---
 include/linux/signal.h |  13 ++++++
 kernel/signal.c        | 101 ++++++++++++++++-------------------------
 2 files changed, 53 insertions(+), 61 deletions(-)

diff --git a/include/linux/signal.h b/include/linux/signal.h
index b256f9c65661..e9fb05041e7a 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -50,6 +50,19 @@ enum siginfo_layout {
 
 enum siginfo_layout siginfo_layout(unsigned sig, int si_code);
 
+static inline bool siginfo_layout_is_fault(enum siginfo_layout layout)
+{
+	switch (layout) {
+	case SIL_FAULT:
+	case SIL_FAULT_MCEERR:
+	case SIL_FAULT_BNDERR:
+	case SIL_FAULT_PKUERR:
+		return true;
+	default:
+		return false;
+	}
+}
+
 /*
  * Define some primitives to manipulate sigset_t.
  */
diff --git a/kernel/signal.c b/kernel/signal.c
index ef8f2a28d37c..74e7315c24db 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1650,6 +1650,15 @@ void force_sigsegv(int sig)
 	force_sig(SIGSEGV);
 }
 
+static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
+				       int code, void __user *addr)
+{
+	info->si_signo = sig;
+	info->si_errno = 0;
+	info->si_code = code;
+	info->si_addr = addr;
+}
+
 int force_sig_fault_to_task(int sig, int code, void __user *addr
 	___ARCH_SI_TRAPNO(int trapno)
 	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
@@ -1658,10 +1667,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
 	struct kernel_siginfo info;
 
 	clear_siginfo(&info);
-	info.si_signo = sig;
-	info.si_errno = 0;
-	info.si_code  = code;
-	info.si_addr  = addr;
+	set_sigfault_common_fields(&info, sig, code, addr);
 #ifdef __ARCH_SI_TRAPNO
 	info.si_trapno = trapno;
 #endif
@@ -1690,10 +1696,7 @@ int send_sig_fault(int sig, int code, void __user *addr
 	struct kernel_siginfo info;
 
 	clear_siginfo(&info);
-	info.si_signo = sig;
-	info.si_errno = 0;
-	info.si_code  = code;
-	info.si_addr  = addr;
+	set_sigfault_common_fields(&info, sig, code, addr);
 #ifdef __ARCH_SI_TRAPNO
 	info.si_trapno = trapno;
 #endif
@@ -1711,10 +1714,7 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
 
 	WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
 	clear_siginfo(&info);
-	info.si_signo = SIGBUS;
-	info.si_errno = 0;
-	info.si_code = code;
-	info.si_addr = addr;
+	set_sigfault_common_fields(&info, SIGBUS, code, addr);
 	info.si_addr_lsb = lsb;
 	return force_sig_info(&info);
 }
@@ -1725,10 +1725,7 @@ int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *
 
 	WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
 	clear_siginfo(&info);
-	info.si_signo = SIGBUS;
-	info.si_errno = 0;
-	info.si_code = code;
-	info.si_addr = addr;
+	set_sigfault_common_fields(&info, SIGBUS, code, addr);
 	info.si_addr_lsb = lsb;
 	return send_sig_info(info.si_signo, &info, t);
 }
@@ -1739,10 +1736,7 @@ int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
 	struct kernel_siginfo info;
 
 	clear_siginfo(&info);
-	info.si_signo = SIGSEGV;
-	info.si_errno = 0;
-	info.si_code  = SEGV_BNDERR;
-	info.si_addr  = addr;
+	set_sigfault_common_fields(&info, SIGSEGV, SEGV_BNDERR, addr);
 	info.si_lower = lower;
 	info.si_upper = upper;
 	return force_sig_info(&info);
@@ -1754,10 +1748,7 @@ int force_sig_pkuerr(void __user *addr, u32 pkey)
 	struct kernel_siginfo info;
 
 	clear_siginfo(&info);
-	info.si_signo = SIGSEGV;
-	info.si_errno = 0;
-	info.si_code  = SEGV_PKUERR;
-	info.si_addr  = addr;
+	set_sigfault_common_fields(&info, SIGSEGV, SEGV_PKUERR, addr);
 	info.si_pkey  = pkey;
 	return force_sig_info(&info);
 }
@@ -1771,10 +1762,8 @@ int force_sig_ptrace_errno_trap(int errno, void __user *addr)
 	struct kernel_siginfo info;
 
 	clear_siginfo(&info);
-	info.si_signo = SIGTRAP;
+	set_sigfault_common_fields(&info, SIGTRAP, TRAP_HWBKPT, addr);
 	info.si_errno = errno;
-	info.si_code  = TRAP_HWBKPT;
-	info.si_addr  = addr;
 	return force_sig_info(&info);
 }
 
@@ -3267,12 +3256,23 @@ int copy_siginfo_from_user(kernel_siginfo_t *to, const siginfo_t __user *from)
 void copy_siginfo_to_external32(struct compat_siginfo *to,
 		const struct kernel_siginfo *from)
 {
+	enum siginfo_layout layout =
+		siginfo_layout(from->si_signo, from->si_code);
+
 	memset(to, 0, sizeof(*to));
 
 	to->si_signo = from->si_signo;
 	to->si_errno = from->si_errno;
 	to->si_code  = from->si_code;
-	switch(siginfo_layout(from->si_signo, from->si_code)) {
+
+	if (siginfo_layout_is_fault(layout)) {
+		to->si_addr = ptr_to_compat(from->si_addr);
+#ifdef __ARCH_SI_TRAPNO
+		to->si_trapno = from->si_trapno;
+#endif
+	}
+
+	switch (layout) {
 	case SIL_KILL:
 		to->si_pid = from->si_pid;
 		to->si_uid = from->si_uid;
@@ -3287,31 +3287,15 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
 		to->si_fd   = from->si_fd;
 		break;
 	case SIL_FAULT:
-		to->si_addr = ptr_to_compat(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		break;
 	case SIL_FAULT_MCEERR:
-		to->si_addr = ptr_to_compat(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		to->si_addr_lsb = from->si_addr_lsb;
 		break;
 	case SIL_FAULT_BNDERR:
-		to->si_addr = ptr_to_compat(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		to->si_lower = ptr_to_compat(from->si_lower);
 		to->si_upper = ptr_to_compat(from->si_upper);
 		break;
 	case SIL_FAULT_PKUERR:
-		to->si_addr = ptr_to_compat(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		to->si_pkey = from->si_pkey;
 		break;
 	case SIL_CHLD:
@@ -3348,11 +3332,22 @@ int __copy_siginfo_to_user32(struct compat_siginfo __user *to,
 static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 					 const struct compat_siginfo *from)
 {
+	enum siginfo_layout layout =
+		siginfo_layout(from->si_signo, from->si_code);
+
 	clear_siginfo(to);
 	to->si_signo = from->si_signo;
 	to->si_errno = from->si_errno;
 	to->si_code  = from->si_code;
-	switch(siginfo_layout(from->si_signo, from->si_code)) {
+
+	if (siginfo_layout_is_fault(layout)) {
+		to->si_addr = compat_ptr(from->si_addr);
+#ifdef __ARCH_SI_TRAPNO
+		to->si_trapno = from->si_trapno;
+#endif
+	}
+
+	switch (layout) {
 	case SIL_KILL:
 		to->si_pid = from->si_pid;
 		to->si_uid = from->si_uid;
@@ -3367,31 +3362,15 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 		to->si_fd   = from->si_fd;
 		break;
 	case SIL_FAULT:
-		to->si_addr = compat_ptr(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		break;
 	case SIL_FAULT_MCEERR:
-		to->si_addr = compat_ptr(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		to->si_addr_lsb = from->si_addr_lsb;
 		break;
 	case SIL_FAULT_BNDERR:
-		to->si_addr = compat_ptr(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		to->si_lower = compat_ptr(from->si_lower);
 		to->si_upper = compat_ptr(from->si_upper);
 		break;
 	case SIL_FAULT_PKUERR:
-		to->si_addr = compat_ptr(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		to->si_pkey = from->si_pkey;
 		break;
 	case SIL_CHLD:
-- 
2.29.1.341.ge80a0c044ae-goog


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

* [PATCH v14 4/8] signal: deduplicate code dealing with common _sigfault fields
@ 2020-11-04 21:18   ` Peter Collingbourne
  0 siblings, 0 replies; 64+ messages in thread
From: Peter Collingbourne @ 2020-11-04 21:18 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,
	Richard Henderson

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

Signed-off-by: Peter Collingbourne <pcc@google.com>
Link: https://linux-review.googlesource.com/id/I4f56174e1b7b2bf4a3c8139e6879cbfd52750a24
---
 include/linux/signal.h |  13 ++++++
 kernel/signal.c        | 101 ++++++++++++++++-------------------------
 2 files changed, 53 insertions(+), 61 deletions(-)

diff --git a/include/linux/signal.h b/include/linux/signal.h
index b256f9c65661..e9fb05041e7a 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -50,6 +50,19 @@ enum siginfo_layout {
 
 enum siginfo_layout siginfo_layout(unsigned sig, int si_code);
 
+static inline bool siginfo_layout_is_fault(enum siginfo_layout layout)
+{
+	switch (layout) {
+	case SIL_FAULT:
+	case SIL_FAULT_MCEERR:
+	case SIL_FAULT_BNDERR:
+	case SIL_FAULT_PKUERR:
+		return true;
+	default:
+		return false;
+	}
+}
+
 /*
  * Define some primitives to manipulate sigset_t.
  */
diff --git a/kernel/signal.c b/kernel/signal.c
index ef8f2a28d37c..74e7315c24db 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1650,6 +1650,15 @@ void force_sigsegv(int sig)
 	force_sig(SIGSEGV);
 }
 
+static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
+				       int code, void __user *addr)
+{
+	info->si_signo = sig;
+	info->si_errno = 0;
+	info->si_code = code;
+	info->si_addr = addr;
+}
+
 int force_sig_fault_to_task(int sig, int code, void __user *addr
 	___ARCH_SI_TRAPNO(int trapno)
 	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
@@ -1658,10 +1667,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
 	struct kernel_siginfo info;
 
 	clear_siginfo(&info);
-	info.si_signo = sig;
-	info.si_errno = 0;
-	info.si_code  = code;
-	info.si_addr  = addr;
+	set_sigfault_common_fields(&info, sig, code, addr);
 #ifdef __ARCH_SI_TRAPNO
 	info.si_trapno = trapno;
 #endif
@@ -1690,10 +1696,7 @@ int send_sig_fault(int sig, int code, void __user *addr
 	struct kernel_siginfo info;
 
 	clear_siginfo(&info);
-	info.si_signo = sig;
-	info.si_errno = 0;
-	info.si_code  = code;
-	info.si_addr  = addr;
+	set_sigfault_common_fields(&info, sig, code, addr);
 #ifdef __ARCH_SI_TRAPNO
 	info.si_trapno = trapno;
 #endif
@@ -1711,10 +1714,7 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
 
 	WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
 	clear_siginfo(&info);
-	info.si_signo = SIGBUS;
-	info.si_errno = 0;
-	info.si_code = code;
-	info.si_addr = addr;
+	set_sigfault_common_fields(&info, SIGBUS, code, addr);
 	info.si_addr_lsb = lsb;
 	return force_sig_info(&info);
 }
@@ -1725,10 +1725,7 @@ int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *
 
 	WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
 	clear_siginfo(&info);
-	info.si_signo = SIGBUS;
-	info.si_errno = 0;
-	info.si_code = code;
-	info.si_addr = addr;
+	set_sigfault_common_fields(&info, SIGBUS, code, addr);
 	info.si_addr_lsb = lsb;
 	return send_sig_info(info.si_signo, &info, t);
 }
@@ -1739,10 +1736,7 @@ int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
 	struct kernel_siginfo info;
 
 	clear_siginfo(&info);
-	info.si_signo = SIGSEGV;
-	info.si_errno = 0;
-	info.si_code  = SEGV_BNDERR;
-	info.si_addr  = addr;
+	set_sigfault_common_fields(&info, SIGSEGV, SEGV_BNDERR, addr);
 	info.si_lower = lower;
 	info.si_upper = upper;
 	return force_sig_info(&info);
@@ -1754,10 +1748,7 @@ int force_sig_pkuerr(void __user *addr, u32 pkey)
 	struct kernel_siginfo info;
 
 	clear_siginfo(&info);
-	info.si_signo = SIGSEGV;
-	info.si_errno = 0;
-	info.si_code  = SEGV_PKUERR;
-	info.si_addr  = addr;
+	set_sigfault_common_fields(&info, SIGSEGV, SEGV_PKUERR, addr);
 	info.si_pkey  = pkey;
 	return force_sig_info(&info);
 }
@@ -1771,10 +1762,8 @@ int force_sig_ptrace_errno_trap(int errno, void __user *addr)
 	struct kernel_siginfo info;
 
 	clear_siginfo(&info);
-	info.si_signo = SIGTRAP;
+	set_sigfault_common_fields(&info, SIGTRAP, TRAP_HWBKPT, addr);
 	info.si_errno = errno;
-	info.si_code  = TRAP_HWBKPT;
-	info.si_addr  = addr;
 	return force_sig_info(&info);
 }
 
@@ -3267,12 +3256,23 @@ int copy_siginfo_from_user(kernel_siginfo_t *to, const siginfo_t __user *from)
 void copy_siginfo_to_external32(struct compat_siginfo *to,
 		const struct kernel_siginfo *from)
 {
+	enum siginfo_layout layout =
+		siginfo_layout(from->si_signo, from->si_code);
+
 	memset(to, 0, sizeof(*to));
 
 	to->si_signo = from->si_signo;
 	to->si_errno = from->si_errno;
 	to->si_code  = from->si_code;
-	switch(siginfo_layout(from->si_signo, from->si_code)) {
+
+	if (siginfo_layout_is_fault(layout)) {
+		to->si_addr = ptr_to_compat(from->si_addr);
+#ifdef __ARCH_SI_TRAPNO
+		to->si_trapno = from->si_trapno;
+#endif
+	}
+
+	switch (layout) {
 	case SIL_KILL:
 		to->si_pid = from->si_pid;
 		to->si_uid = from->si_uid;
@@ -3287,31 +3287,15 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
 		to->si_fd   = from->si_fd;
 		break;
 	case SIL_FAULT:
-		to->si_addr = ptr_to_compat(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		break;
 	case SIL_FAULT_MCEERR:
-		to->si_addr = ptr_to_compat(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		to->si_addr_lsb = from->si_addr_lsb;
 		break;
 	case SIL_FAULT_BNDERR:
-		to->si_addr = ptr_to_compat(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		to->si_lower = ptr_to_compat(from->si_lower);
 		to->si_upper = ptr_to_compat(from->si_upper);
 		break;
 	case SIL_FAULT_PKUERR:
-		to->si_addr = ptr_to_compat(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		to->si_pkey = from->si_pkey;
 		break;
 	case SIL_CHLD:
@@ -3348,11 +3332,22 @@ int __copy_siginfo_to_user32(struct compat_siginfo __user *to,
 static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 					 const struct compat_siginfo *from)
 {
+	enum siginfo_layout layout =
+		siginfo_layout(from->si_signo, from->si_code);
+
 	clear_siginfo(to);
 	to->si_signo = from->si_signo;
 	to->si_errno = from->si_errno;
 	to->si_code  = from->si_code;
-	switch(siginfo_layout(from->si_signo, from->si_code)) {
+
+	if (siginfo_layout_is_fault(layout)) {
+		to->si_addr = compat_ptr(from->si_addr);
+#ifdef __ARCH_SI_TRAPNO
+		to->si_trapno = from->si_trapno;
+#endif
+	}
+
+	switch (layout) {
 	case SIL_KILL:
 		to->si_pid = from->si_pid;
 		to->si_uid = from->si_uid;
@@ -3367,31 +3362,15 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 		to->si_fd   = from->si_fd;
 		break;
 	case SIL_FAULT:
-		to->si_addr = compat_ptr(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		break;
 	case SIL_FAULT_MCEERR:
-		to->si_addr = compat_ptr(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		to->si_addr_lsb = from->si_addr_lsb;
 		break;
 	case SIL_FAULT_BNDERR:
-		to->si_addr = compat_ptr(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		to->si_lower = compat_ptr(from->si_lower);
 		to->si_upper = compat_ptr(from->si_upper);
 		break;
 	case SIL_FAULT_PKUERR:
-		to->si_addr = compat_ptr(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-		to->si_trapno = from->si_trapno;
-#endif
 		to->si_pkey = from->si_pkey;
 		break;
 	case SIL_CHLD:
-- 
2.29.1.341.ge80a0c044ae-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] 64+ messages in thread

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

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

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

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

Link: [1] https://github.com/openbsd/src/blob/f634a6a4b5bf832e9c1de77f7894ae2625e74484/sys/kern/kern_sig.c#L278
Link: [2] https://github.com/illumos/illumos-gate/blob/76f19f5fdc974fe5be5c82a556e43a4df93f1de1/usr/src/uts/common/syscall/sigaction.c#L86
Link: [3] https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/kern/kern_sig.c#L480
Link: [4] https://github.com/freebsd/freebsd/blob/eded70c37057857c6e23fae51f86b8f8f43cd2d0/sys/kern/kern_sig.c#L699
Link: [5] https://github.com/NetBSD/src/blob/3365779becdcedfca206091a645a0e8e22b2946e/sys/kern/sys_sig.c#L473
Signed-off-by: Peter Collingbourne <pcc@google.com>
Reviewed-by: Dave Martin <Dave.Martin@arm.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 74e7315c24db..832b654dee8c 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -3964,6 +3964,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.1.341.ge80a0c044ae-goog


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

* [PATCH v14 5/8] signal: clear non-uapi flag bits when passing/returning sa_flags
@ 2020-11-04 21:18   ` Peter Collingbourne
  0 siblings, 0 replies; 64+ messages in thread
From: Peter Collingbourne @ 2020-11-04 21:18 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,
	Richard Henderson

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

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

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

Link: [1] https://github.com/openbsd/src/blob/f634a6a4b5bf832e9c1de77f7894ae2625e74484/sys/kern/kern_sig.c#L278
Link: [2] https://github.com/illumos/illumos-gate/blob/76f19f5fdc974fe5be5c82a556e43a4df93f1de1/usr/src/uts/common/syscall/sigaction.c#L86
Link: [3] https://github.com/apple/darwin-xnu/blob/a449c6a3b8014d9406c2ddbdc81795da24aa7443/bsd/kern/kern_sig.c#L480
Link: [4] https://github.com/freebsd/freebsd/blob/eded70c37057857c6e23fae51f86b8f8f43cd2d0/sys/kern/kern_sig.c#L699
Link: [5] https://github.com/NetBSD/src/blob/3365779becdcedfca206091a645a0e8e22b2946e/sys/kern/sys_sig.c#L473
Signed-off-by: Peter Collingbourne <pcc@google.com>
Reviewed-by: Dave Martin <Dave.Martin@arm.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 74e7315c24db..832b654dee8c 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -3964,6 +3964,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.1.341.ge80a0c044ae-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] 64+ messages in thread

* [PATCH v14 6/8] signal: define the SA_UNSUPPORTED bit in sa_flags
  2020-11-04 21:18 ` Peter Collingbourne
@ 2020-11-04 21:18   ` Peter Collingbourne
  -1 siblings, 0 replies; 64+ messages in thread
From: Peter Collingbourne @ 2020-11-04 21:18 UTC (permalink / raw)
  To: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	Eric W. Biederman, James E.J. Bottomley
  Cc: Peter Collingbourne, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-api, Helge Deller, David Spickett

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 832b654dee8c..d18930aafbf4 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -3964,6 +3964,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.1.341.ge80a0c044ae-goog


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

* [PATCH v14 6/8] signal: define the SA_UNSUPPORTED bit in sa_flags
@ 2020-11-04 21:18   ` Peter Collingbourne
  0 siblings, 0 replies; 64+ messages in thread
From: Peter Collingbourne @ 2020-11-04 21:18 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,
	Richard Henderson

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 832b654dee8c..d18930aafbf4 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -3964,6 +3964,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.1.341.ge80a0c044ae-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] 64+ messages in thread

* [PATCH v14 7/8] signal: define the field siginfo.si_faultflags
  2020-11-04 21:18 ` Peter Collingbourne
@ 2020-11-04 21:18   ` Peter Collingbourne
  -1 siblings, 0 replies; 64+ messages in thread
From: Peter Collingbourne @ 2020-11-04 21:18 UTC (permalink / raw)
  To: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	Eric W. Biederman, James E.J. Bottomley
  Cc: Peter Collingbourne, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-api, Helge Deller, David Spickett

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

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

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

- ptrace(PTRACE_SETSIGINFO)
- pidfd_send_signal
- rt_sigqueueinfo
- rt_tgsigqueueinfo

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

The last three cases can be handled by observing that each of these
syscalls fails if si_code >= 0. We also observe that kill(2) and
tgkill(2) may be used to send a signal where si_code == 0 (SI_USER),
so we define si_faultflags to only be valid if si_code > 0.

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

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

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

I considered making ia64's si_flags a generic field and having it
appear at the end of _sigfault (in the same place as this patch has
si_faultflags) on non-ia64, keeping it in the same place on ia64. ia64's
si_flags is a 32-bit field with only one flag bit allocated, so we
would have 31 bits to use if we do this. However, it seems simplest
to avoid entangling these fields.

Signed-off-by: Peter Collingbourne <pcc@google.com>
Link: https://linux-review.googlesource.com/id/Ide155ce29366c3eab2a944ae4c51205982e5b8b2
---
v14:
- make the padding explicit so we can easily use it later

v13:
- renamed si_xflags to si_faultflags
- use fallthrough macros in kernel/ptrace.c
- fixed a style warning pointed out by checkpatch.pl

v12:
- Change type of si_xflags to u32 to avoid increasing alignment
- Add si_xflags to signal_compat.c test cases

v11:
- update comment to say that si_code must > 0
- change ptrace(PTRACE_SETSIGINFO2) to take a flags argument

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

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

diff --git a/arch/powerpc/platforms/powernv/vas-fault.c b/arch/powerpc/platforms/powernv/vas-fault.c
index 3d21fce254b7..877e7d5fb4a2 100644
--- a/arch/powerpc/platforms/powernv/vas-fault.c
+++ b/arch/powerpc/platforms/powernv/vas-fault.c
@@ -154,6 +154,7 @@ static void update_csb(struct vas_window *window,
 	info.si_errno = EFAULT;
 	info.si_code = SEGV_MAPERR;
 	info.si_addr = csb_addr;
+	info.si_faultflags = 0;
 
 	/*
 	 * process will be polling on csb.flags after request is sent to
diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
index ddfd919be46c..222ff6178571 100644
--- a/arch/x86/kernel/signal_compat.c
+++ b/arch/x86/kernel/signal_compat.c
@@ -121,8 +121,8 @@ static inline void signal_compat_build_tests(void)
 #endif
 
 	CHECK_CSI_OFFSET(_sigfault);
-	CHECK_CSI_SIZE  (_sigfault, 4*sizeof(int));
-	CHECK_SI_SIZE   (_sigfault, 8*sizeof(int));
+	CHECK_CSI_SIZE  (_sigfault, 8*sizeof(int));
+	CHECK_SI_SIZE   (_sigfault, 16*sizeof(int));
 
 	BUILD_BUG_ON(offsetof(siginfo_t, si_addr) != 0x10);
 	BUILD_BUG_ON(offsetof(compat_siginfo_t, si_addr) != 0x0C);
@@ -138,6 +138,9 @@ static inline void signal_compat_build_tests(void)
 	BUILD_BUG_ON(offsetof(siginfo_t, si_pkey) != 0x20);
 	BUILD_BUG_ON(offsetof(compat_siginfo_t, si_pkey) != 0x14);
 
+	BUILD_BUG_ON(offsetof(siginfo_t, si_faultflags) != 0x48);
+	BUILD_BUG_ON(offsetof(compat_siginfo_t, si_faultflags) != 0x28);
+
 	CHECK_CSI_OFFSET(_sigpoll);
 	CHECK_CSI_SIZE  (_sigpoll, 2*sizeof(int));
 	CHECK_SI_SIZE   (_sigpoll, 4*sizeof(int));
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 14d514233e1d..84d3b72be701 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -236,7 +236,9 @@ typedef struct compat_siginfo {
 					char _dummy_pkey[__COMPAT_ADDR_BND_PKEY_PAD];
 					u32 _pkey;
 				} _addr_pkey;
+				compat_uptr_t _pad[6];
 			};
+			u32 _faultflags;
 		} _sigfault;
 
 		/* SIGPOLL */
diff --git a/include/linux/signal_types.h b/include/linux/signal_types.h
index a7887ad84d36..7501209eae33 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_FAULTFLAGS | __ARCH_UAPI_SA_FLAGS)
 
 #endif /* _LINUX_SIGNAL_TYPES_H */
diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
index 7aacf9389010..10a55aed9ede 100644
--- a/include/uapi/asm-generic/siginfo.h
+++ b/include/uapi/asm-generic/siginfo.h
@@ -91,7 +91,12 @@ union __sifields {
 				char _dummy_pkey[__ADDR_BND_PKEY_PAD];
 				__u32 _pkey;
 			} _addr_pkey;
+			void *_pad[6];
 		};
+		__u32 _faultflags;
+#ifdef __LP64__
+		__u32 _pad2; /* to be used if we add another 32-bit field */
+#endif
 	} _sigfault;
 
 	/* SIGPOLL */
@@ -152,6 +157,8 @@ typedef struct siginfo {
 #define si_trapno	_sifields._sigfault._trapno
 #endif
 #define si_addr_lsb	_sifields._sigfault._addr_lsb
+/* si_faultflags is only valid if 0 < si_code < SI_KERNEL */
+#define si_faultflags	_sifields._sigfault._faultflags
 #define si_lower	_sifields._sigfault._addr_bnd._lower
 #define si_upper	_sifields._sigfault._addr_bnd._upper
 #define si_pkey		_sifields._sigfault._addr_pkey._pkey
diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
index 0126ebda4d31..e27bf959d4c4 100644
--- a/include/uapi/asm-generic/signal-defs.h
+++ b/include/uapi/asm-generic/signal-defs.h
@@ -20,6 +20,9 @@
  * so this bit allows flag bit support to be detected from userspace while
  * allowing an old kernel to be distinguished from a kernel that supports every
  * flag bit.
+ * SA_FAULTFLAGS indicates that the signal handler requires the siginfo.si_faultflags
+ * field to be valid. Note that if the kernel supports SA_FAULTFLAGS, the field will
+ * be valid regardless of the value of this flag.
  *
  * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
  * Unix names RESETHAND and NODEFER respectively.
@@ -49,6 +52,7 @@
 #define SA_RESETHAND	0x80000000
 #endif
 #define SA_UNSUPPORTED	0x00000400
+#define SA_FAULTFLAGS	0x00000800
 
 #define SA_NOMASK	SA_NODEFER
 #define SA_ONESHOT	SA_RESETHAND
diff --git a/include/uapi/linux/ptrace.h b/include/uapi/linux/ptrace.h
index a71b6e3b03eb..722a2c8a4d3d 100644
--- a/include/uapi/linux/ptrace.h
+++ b/include/uapi/linux/ptrace.h
@@ -101,6 +101,18 @@ struct ptrace_syscall_info {
 	};
 };
 
+#define PTRACE_SETSIGINFO2	0x420f
+/*
+ * These flags are passed as the addr argument to ptrace.
+ */
+
+/*
+ * Asserts that the caller is aware of the field siginfo.si_faultflags. Prevents
+ * the kernel from automatically setting the field to 0 when the signal uses
+ * a sigfault layout.
+ */
+#define PTRACE_SIGINFO_FAULTFLAGS	0x1
+
 /*
  * These values are stored in task->ptrace_message
  * by tracehook_report_syscall_* to describe the current syscall-stop.
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 43d6179508d6..ab0618b4602c 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -687,18 +687,31 @@ static int ptrace_getsiginfo(struct task_struct *child, kernel_siginfo_t *info)
 	return error;
 }
 
-static int ptrace_setsiginfo(struct task_struct *child, const kernel_siginfo_t *info)
+static int ptrace_setsiginfo(struct task_struct *child, unsigned long flags,
+			     kernel_siginfo_t *info)
 {
-	unsigned long flags;
+	unsigned long lock_flags;
 	int error = -ESRCH;
 
-	if (lock_task_sighand(child, &flags)) {
+	if (flags & ~PTRACE_SIGINFO_FAULTFLAGS)
+		return -EINVAL;
+
+	/*
+	 * If the caller is unaware of si_faultflags and we're using a layout that
+	 * requires it, set it to 0 which means "no fields are available".
+	 */
+	if (!(flags & PTRACE_SIGINFO_FAULTFLAGS) &&
+	    siginfo_layout_is_fault(
+		    siginfo_layout(info->si_signo, info->si_code)))
+		info->si_faultflags = 0;
+
+	if (lock_task_sighand(child, &lock_flags)) {
 		error = -EINVAL;
 		if (likely(child->last_siginfo != NULL)) {
 			copy_siginfo(child->last_siginfo, info);
 			error = 0;
 		}
-		unlock_task_sighand(child, &flags);
+		unlock_task_sighand(child, &lock_flags);
 	}
 	return error;
 }
@@ -1038,9 +1051,13 @@ int ptrace_request(struct task_struct *child, long request,
 		break;
 
 	case PTRACE_SETSIGINFO:
+		addr = 0;
+		fallthrough;
+
+	case PTRACE_SETSIGINFO2:
 		ret = copy_siginfo_from_user(&siginfo, datavp);
 		if (!ret)
-			ret = ptrace_setsiginfo(child, &siginfo);
+			ret = ptrace_setsiginfo(child, addr, &siginfo);
 		break;
 
 	case PTRACE_GETSIGMASK: {
@@ -1347,10 +1364,14 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
 		break;
 
 	case PTRACE_SETSIGINFO:
+		addr = 0;
+		fallthrough;
+
+	case PTRACE_SETSIGINFO2:
 		ret = copy_siginfo_from_user32(
 			&siginfo, (struct compat_siginfo __user *) datap);
 		if (!ret)
-			ret = ptrace_setsiginfo(child, &siginfo);
+			ret = ptrace_setsiginfo(child, addr, &siginfo);
 		break;
 #ifdef CONFIG_HAVE_ARCH_TRACEHOOK
 	case PTRACE_GETREGSET:
diff --git a/kernel/signal.c b/kernel/signal.c
index d18930aafbf4..1fd1f0d12174 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1657,6 +1657,7 @@ static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
 	info->si_errno = 0;
 	info->si_code = code;
 	info->si_addr = addr;
+	info->si_faultflags = 0;
 }
 
 int force_sig_fault_to_task(int sig, int code, void __user *addr
@@ -3270,6 +3271,7 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
 #ifdef __ARCH_SI_TRAPNO
 		to->si_trapno = from->si_trapno;
 #endif
+		to->si_faultflags = from->si_faultflags;
 	}
 
 	switch (layout) {
@@ -3345,6 +3347,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 #ifdef __ARCH_SI_TRAPNO
 		to->si_trapno = from->si_trapno;
 #endif
+		to->si_faultflags = from->si_faultflags;
 	}
 
 	switch (layout) {
-- 
2.29.1.341.ge80a0c044ae-goog


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

* [PATCH v14 7/8] signal: define the field siginfo.si_faultflags
@ 2020-11-04 21:18   ` Peter Collingbourne
  0 siblings, 0 replies; 64+ messages in thread
From: Peter Collingbourne @ 2020-11-04 21:18 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,
	Richard Henderson

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

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

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

- ptrace(PTRACE_SETSIGINFO)
- pidfd_send_signal
- rt_sigqueueinfo
- rt_tgsigqueueinfo

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

The last three cases can be handled by observing that each of these
syscalls fails if si_code >= 0. We also observe that kill(2) and
tgkill(2) may be used to send a signal where si_code == 0 (SI_USER),
so we define si_faultflags to only be valid if si_code > 0.

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

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

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

I considered making ia64's si_flags a generic field and having it
appear at the end of _sigfault (in the same place as this patch has
si_faultflags) on non-ia64, keeping it in the same place on ia64. ia64's
si_flags is a 32-bit field with only one flag bit allocated, so we
would have 31 bits to use if we do this. However, it seems simplest
to avoid entangling these fields.

Signed-off-by: Peter Collingbourne <pcc@google.com>
Link: https://linux-review.googlesource.com/id/Ide155ce29366c3eab2a944ae4c51205982e5b8b2
---
v14:
- make the padding explicit so we can easily use it later

v13:
- renamed si_xflags to si_faultflags
- use fallthrough macros in kernel/ptrace.c
- fixed a style warning pointed out by checkpatch.pl

v12:
- Change type of si_xflags to u32 to avoid increasing alignment
- Add si_xflags to signal_compat.c test cases

v11:
- update comment to say that si_code must > 0
- change ptrace(PTRACE_SETSIGINFO2) to take a flags argument

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

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

diff --git a/arch/powerpc/platforms/powernv/vas-fault.c b/arch/powerpc/platforms/powernv/vas-fault.c
index 3d21fce254b7..877e7d5fb4a2 100644
--- a/arch/powerpc/platforms/powernv/vas-fault.c
+++ b/arch/powerpc/platforms/powernv/vas-fault.c
@@ -154,6 +154,7 @@ static void update_csb(struct vas_window *window,
 	info.si_errno = EFAULT;
 	info.si_code = SEGV_MAPERR;
 	info.si_addr = csb_addr;
+	info.si_faultflags = 0;
 
 	/*
 	 * process will be polling on csb.flags after request is sent to
diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
index ddfd919be46c..222ff6178571 100644
--- a/arch/x86/kernel/signal_compat.c
+++ b/arch/x86/kernel/signal_compat.c
@@ -121,8 +121,8 @@ static inline void signal_compat_build_tests(void)
 #endif
 
 	CHECK_CSI_OFFSET(_sigfault);
-	CHECK_CSI_SIZE  (_sigfault, 4*sizeof(int));
-	CHECK_SI_SIZE   (_sigfault, 8*sizeof(int));
+	CHECK_CSI_SIZE  (_sigfault, 8*sizeof(int));
+	CHECK_SI_SIZE   (_sigfault, 16*sizeof(int));
 
 	BUILD_BUG_ON(offsetof(siginfo_t, si_addr) != 0x10);
 	BUILD_BUG_ON(offsetof(compat_siginfo_t, si_addr) != 0x0C);
@@ -138,6 +138,9 @@ static inline void signal_compat_build_tests(void)
 	BUILD_BUG_ON(offsetof(siginfo_t, si_pkey) != 0x20);
 	BUILD_BUG_ON(offsetof(compat_siginfo_t, si_pkey) != 0x14);
 
+	BUILD_BUG_ON(offsetof(siginfo_t, si_faultflags) != 0x48);
+	BUILD_BUG_ON(offsetof(compat_siginfo_t, si_faultflags) != 0x28);
+
 	CHECK_CSI_OFFSET(_sigpoll);
 	CHECK_CSI_SIZE  (_sigpoll, 2*sizeof(int));
 	CHECK_SI_SIZE   (_sigpoll, 4*sizeof(int));
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 14d514233e1d..84d3b72be701 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -236,7 +236,9 @@ typedef struct compat_siginfo {
 					char _dummy_pkey[__COMPAT_ADDR_BND_PKEY_PAD];
 					u32 _pkey;
 				} _addr_pkey;
+				compat_uptr_t _pad[6];
 			};
+			u32 _faultflags;
 		} _sigfault;
 
 		/* SIGPOLL */
diff --git a/include/linux/signal_types.h b/include/linux/signal_types.h
index a7887ad84d36..7501209eae33 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_FAULTFLAGS | __ARCH_UAPI_SA_FLAGS)
 
 #endif /* _LINUX_SIGNAL_TYPES_H */
diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
index 7aacf9389010..10a55aed9ede 100644
--- a/include/uapi/asm-generic/siginfo.h
+++ b/include/uapi/asm-generic/siginfo.h
@@ -91,7 +91,12 @@ union __sifields {
 				char _dummy_pkey[__ADDR_BND_PKEY_PAD];
 				__u32 _pkey;
 			} _addr_pkey;
+			void *_pad[6];
 		};
+		__u32 _faultflags;
+#ifdef __LP64__
+		__u32 _pad2; /* to be used if we add another 32-bit field */
+#endif
 	} _sigfault;
 
 	/* SIGPOLL */
@@ -152,6 +157,8 @@ typedef struct siginfo {
 #define si_trapno	_sifields._sigfault._trapno
 #endif
 #define si_addr_lsb	_sifields._sigfault._addr_lsb
+/* si_faultflags is only valid if 0 < si_code < SI_KERNEL */
+#define si_faultflags	_sifields._sigfault._faultflags
 #define si_lower	_sifields._sigfault._addr_bnd._lower
 #define si_upper	_sifields._sigfault._addr_bnd._upper
 #define si_pkey		_sifields._sigfault._addr_pkey._pkey
diff --git a/include/uapi/asm-generic/signal-defs.h b/include/uapi/asm-generic/signal-defs.h
index 0126ebda4d31..e27bf959d4c4 100644
--- a/include/uapi/asm-generic/signal-defs.h
+++ b/include/uapi/asm-generic/signal-defs.h
@@ -20,6 +20,9 @@
  * so this bit allows flag bit support to be detected from userspace while
  * allowing an old kernel to be distinguished from a kernel that supports every
  * flag bit.
+ * SA_FAULTFLAGS indicates that the signal handler requires the siginfo.si_faultflags
+ * field to be valid. Note that if the kernel supports SA_FAULTFLAGS, the field will
+ * be valid regardless of the value of this flag.
  *
  * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
  * Unix names RESETHAND and NODEFER respectively.
@@ -49,6 +52,7 @@
 #define SA_RESETHAND	0x80000000
 #endif
 #define SA_UNSUPPORTED	0x00000400
+#define SA_FAULTFLAGS	0x00000800
 
 #define SA_NOMASK	SA_NODEFER
 #define SA_ONESHOT	SA_RESETHAND
diff --git a/include/uapi/linux/ptrace.h b/include/uapi/linux/ptrace.h
index a71b6e3b03eb..722a2c8a4d3d 100644
--- a/include/uapi/linux/ptrace.h
+++ b/include/uapi/linux/ptrace.h
@@ -101,6 +101,18 @@ struct ptrace_syscall_info {
 	};
 };
 
+#define PTRACE_SETSIGINFO2	0x420f
+/*
+ * These flags are passed as the addr argument to ptrace.
+ */
+
+/*
+ * Asserts that the caller is aware of the field siginfo.si_faultflags. Prevents
+ * the kernel from automatically setting the field to 0 when the signal uses
+ * a sigfault layout.
+ */
+#define PTRACE_SIGINFO_FAULTFLAGS	0x1
+
 /*
  * These values are stored in task->ptrace_message
  * by tracehook_report_syscall_* to describe the current syscall-stop.
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 43d6179508d6..ab0618b4602c 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -687,18 +687,31 @@ static int ptrace_getsiginfo(struct task_struct *child, kernel_siginfo_t *info)
 	return error;
 }
 
-static int ptrace_setsiginfo(struct task_struct *child, const kernel_siginfo_t *info)
+static int ptrace_setsiginfo(struct task_struct *child, unsigned long flags,
+			     kernel_siginfo_t *info)
 {
-	unsigned long flags;
+	unsigned long lock_flags;
 	int error = -ESRCH;
 
-	if (lock_task_sighand(child, &flags)) {
+	if (flags & ~PTRACE_SIGINFO_FAULTFLAGS)
+		return -EINVAL;
+
+	/*
+	 * If the caller is unaware of si_faultflags and we're using a layout that
+	 * requires it, set it to 0 which means "no fields are available".
+	 */
+	if (!(flags & PTRACE_SIGINFO_FAULTFLAGS) &&
+	    siginfo_layout_is_fault(
+		    siginfo_layout(info->si_signo, info->si_code)))
+		info->si_faultflags = 0;
+
+	if (lock_task_sighand(child, &lock_flags)) {
 		error = -EINVAL;
 		if (likely(child->last_siginfo != NULL)) {
 			copy_siginfo(child->last_siginfo, info);
 			error = 0;
 		}
-		unlock_task_sighand(child, &flags);
+		unlock_task_sighand(child, &lock_flags);
 	}
 	return error;
 }
@@ -1038,9 +1051,13 @@ int ptrace_request(struct task_struct *child, long request,
 		break;
 
 	case PTRACE_SETSIGINFO:
+		addr = 0;
+		fallthrough;
+
+	case PTRACE_SETSIGINFO2:
 		ret = copy_siginfo_from_user(&siginfo, datavp);
 		if (!ret)
-			ret = ptrace_setsiginfo(child, &siginfo);
+			ret = ptrace_setsiginfo(child, addr, &siginfo);
 		break;
 
 	case PTRACE_GETSIGMASK: {
@@ -1347,10 +1364,14 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
 		break;
 
 	case PTRACE_SETSIGINFO:
+		addr = 0;
+		fallthrough;
+
+	case PTRACE_SETSIGINFO2:
 		ret = copy_siginfo_from_user32(
 			&siginfo, (struct compat_siginfo __user *) datap);
 		if (!ret)
-			ret = ptrace_setsiginfo(child, &siginfo);
+			ret = ptrace_setsiginfo(child, addr, &siginfo);
 		break;
 #ifdef CONFIG_HAVE_ARCH_TRACEHOOK
 	case PTRACE_GETREGSET:
diff --git a/kernel/signal.c b/kernel/signal.c
index d18930aafbf4..1fd1f0d12174 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1657,6 +1657,7 @@ static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
 	info->si_errno = 0;
 	info->si_code = code;
 	info->si_addr = addr;
+	info->si_faultflags = 0;
 }
 
 int force_sig_fault_to_task(int sig, int code, void __user *addr
@@ -3270,6 +3271,7 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
 #ifdef __ARCH_SI_TRAPNO
 		to->si_trapno = from->si_trapno;
 #endif
+		to->si_faultflags = from->si_faultflags;
 	}
 
 	switch (layout) {
@@ -3345,6 +3347,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 #ifdef __ARCH_SI_TRAPNO
 		to->si_trapno = from->si_trapno;
 #endif
+		to->si_faultflags = from->si_faultflags;
 	}
 
 	switch (layout) {
-- 
2.29.1.341.ge80a0c044ae-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] 64+ messages in thread

* [PATCH v14 8/8] arm64: expose FAR_EL1 tag bits in siginfo
  2020-11-04 21:18 ` Peter Collingbourne
@ 2020-11-04 21:18   ` Peter Collingbourne
  -1 siblings, 0 replies; 64+ messages in thread
From: Peter Collingbourne @ 2020-11-04 21:18 UTC (permalink / raw)
  To: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	Eric W. Biederman, James E.J. Bottomley
  Cc: Peter Collingbourne, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-api, Helge Deller, David Spickett

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

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

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

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

Signed-off-by: Peter Collingbourne <pcc@google.com>
Link: https://linux-review.googlesource.com/id/Ia8876bad8c798e0a32df7c2ce1256c4771c81446
---
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 | 21 +++++---
 arch/arm64/include/asm/exception.h      |  2 +-
 arch/arm64/include/asm/signal.h         | 31 +++++++++++
 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/x86/kernel/signal_compat.c         |  9 +++-
 include/linux/compat.h                  |  2 +
 include/linux/signal.h                  | 16 ++++++
 include/uapi/asm-generic/siginfo.h      | 10 ++++
 kernel/signal.c                         | 18 ++++++-
 16 files changed, 160 insertions(+), 73 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..7d07987ad85a 100644
--- a/Documentation/arm64/tagged-pointers.rst
+++ b/Documentation/arm64/tagged-pointers.rst
@@ -53,12 +53,21 @@ visibility.
 Preserving tags
 ---------------
 
-Non-zero tags are not preserved when delivering signals. This means that
-signal handlers in applications making use of tags cannot rely on the
-tag information for user virtual addresses being maintained for fields
-inside siginfo_t. One exception to this rule is for signals raised in
-response to watchpoint debug exceptions, where the tag information will
-be preserved.
+Non-zero tags are not preserved in the fault address fields
+siginfo.si_addr or sigcontext.fault_address when delivering
+signals. This means that signal handlers in applications making use
+of tags cannot rely on the tag information for user virtual addresses
+being maintained in these fields. One exception to this rule is for
+signals raised in response to watchpoint debug exceptions, where the
+tag information will be preserved.
+
+The fault address tag is preserved in the si_addr_tag_bits field
+of siginfo, which is set for signals raised in response to data aborts
+and instruction aborts. The si_addr_tag_bits_mask field indicates
+which bits of the field are valid. The validity of these fields is
+indicated by the SIFAULTFLAG_ADDR_TAG_BITS flag in siginfo.si_faultflags,
+and the validity of si_faultflags in turn is indicated by the kernel
+indicating support for the sigaction.sa_flags flag SA_FAULTFLAGS.
 
 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..67d8e0899e9b
--- /dev/null
+++ b/arch/arm64/include/asm/signal.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ARM64_ASM_SIGNAL_H
+#define __ARM64_ASM_SIGNAL_H
+
+#include <uapi/asm/signal.h>
+#include <uapi/asm/siginfo.h>
+
+static inline unsigned long arch_addr_tag_bits_mask(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 not
+	 * follow this practice.
+	 */
+	if (sig == SIGTRAP && si_code == TRAP_BRKPT)
+		return 0;
+
+	/*
+	 * FAR_EL1[63:60] are UNKNOWN for tag check faults so reflect that in
+	 * the tag bits mask. The bits are already being masked out by
+	 * do_tag_check_fault so userspace won't see them in si_addr.
+	 */
+	if (sig == SIGSEGV && si_code == SEGV_MTESERR)
+		return 0xfUL << 56;
+
+	return 0xffUL << 56;
+}
+#define arch_addr_tag_bits_mask arch_addr_tag_bits_mask
+
+#endif
diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h
index 1ab63cfbbaf1..673be2d1263c 100644
--- a/arch/arm64/include/asm/system_misc.h
+++ b/arch/arm64/include/asm/system_misc.h
@@ -22,7 +22,7 @@ void die(const char *msg, struct pt_regs *regs, int err);
 
 struct siginfo;
 void arm64_notify_die(const char *str, struct pt_regs *regs,
-		      int signo, int sicode, void __user *addr,
+		      int signo, int sicode, unsigned long far,
 		      int err);
 
 void hook_debug_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h
index 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/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
index 222ff6178571..41cbef515b95 100644
--- a/arch/x86/kernel/signal_compat.c
+++ b/arch/x86/kernel/signal_compat.c
@@ -121,8 +121,8 @@ static inline void signal_compat_build_tests(void)
 #endif
 
 	CHECK_CSI_OFFSET(_sigfault);
-	CHECK_CSI_SIZE  (_sigfault, 8*sizeof(int));
-	CHECK_SI_SIZE   (_sigfault, 16*sizeof(int));
+	CHECK_CSI_SIZE  (_sigfault, 10*sizeof(int));
+	CHECK_SI_SIZE   (_sigfault, 20*sizeof(int));
 
 	BUILD_BUG_ON(offsetof(siginfo_t, si_addr) != 0x10);
 	BUILD_BUG_ON(offsetof(compat_siginfo_t, si_addr) != 0x0C);
@@ -141,6 +141,11 @@ static inline void signal_compat_build_tests(void)
 	BUILD_BUG_ON(offsetof(siginfo_t, si_faultflags) != 0x48);
 	BUILD_BUG_ON(offsetof(compat_siginfo_t, si_faultflags) != 0x28);
 
+	BUILD_BUG_ON(offsetof(siginfo_t, si_addr_tag_bits) != 0x50);
+	BUILD_BUG_ON(offsetof(siginfo_t, si_addr_tag_bits_mask) != 0x58);
+	BUILD_BUG_ON(offsetof(compat_siginfo_t, si_addr_tag_bits) != 0x2C);
+	BUILD_BUG_ON(offsetof(compat_siginfo_t, si_addr_tag_bits_mask) != 0x30);
+
 	CHECK_CSI_OFFSET(_sigpoll);
 	CHECK_CSI_SIZE  (_sigpoll, 2*sizeof(int));
 	CHECK_SI_SIZE   (_sigpoll, 4*sizeof(int));
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 84d3b72be701..f3c83a6d6623 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -239,6 +239,8 @@ typedef struct compat_siginfo {
 				compat_uptr_t _pad[6];
 			};
 			u32 _faultflags;
+			compat_uptr_t _addr_tag_bits;
+			compat_uptr_t _addr_tag_bits_mask;
 		} _sigfault;
 
 		/* SIGPOLL */
diff --git a/include/linux/signal.h b/include/linux/signal.h
index e9fb05041e7a..7fe7ce1d252e 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -482,4 +482,20 @@ struct seq_file;
 extern void render_sigset_t(struct seq_file *, const char *, sigset_t *);
 #endif
 
+#ifndef arch_addr_tag_bits_mask
+/*
+ * Given a signal and si_code which correspond to the _sigfault union member,
+ * if tag bits are present in the fault address which must appear in
+ * si_addr_tag_bits instead of si_addr, this hook must return a bitmask where 1
+ * corresponds to bits appearing in si_addr_tag_bits and 0 corresponds to bits
+ * appearing in si_addr. The value returned by this function will also be
+ * available in si_addr_tag_bits_mask.
+ */
+static inline unsigned long arch_addr_tag_bits_mask(unsigned long sig,
+						    unsigned long si_code)
+{
+	return 0;
+}
+#endif
+
 #endif /* _LINUX_SIGNAL_H */
diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
index 10a55aed9ede..df196ad74238 100644
--- a/include/uapi/asm-generic/siginfo.h
+++ b/include/uapi/asm-generic/siginfo.h
@@ -97,6 +97,8 @@ union __sifields {
 #ifdef __LP64__
 		__u32 _pad2; /* to be used if we add another 32-bit field */
 #endif
+		unsigned long _addr_tag_bits;
+		unsigned long _addr_tag_bits_mask;
 	} _sigfault;
 
 	/* SIGPOLL */
@@ -159,6 +161,8 @@ typedef struct siginfo {
 #define si_addr_lsb	_sifields._sigfault._addr_lsb
 /* si_faultflags is only valid if 0 < si_code < SI_KERNEL */
 #define si_faultflags	_sifields._sigfault._faultflags
+#define si_addr_tag_bits	_sifields._sigfault._addr_tag_bits
+#define si_addr_tag_bits_mask	_sifields._sigfault._addr_tag_bits_mask
 #define si_lower	_sifields._sigfault._addr_bnd._lower
 #define si_upper	_sifields._sigfault._addr_bnd._upper
 #define si_pkey		_sifields._sigfault._addr_pkey._pkey
@@ -301,6 +305,12 @@ typedef struct siginfo {
 #define EMT_TAGOVF	1	/* tag overflow */
 #define NSIGEMT		1
 
+/*
+ * SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT si_faultflags
+ */
+#define SIFAULTFLAG_ADDR_TAG_BITS	1
+/* si_addr_tag_bits{,_mask} fields valid */
+
 /*
  * sigevent definitions
  * 
diff --git a/kernel/signal.c b/kernel/signal.c
index 1fd1f0d12174..aa69dd312bd5 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1653,11 +1653,16 @@ void force_sigsegv(int sig)
 static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
 				       int code, void __user *addr)
 {
+	unsigned long addr_long = (unsigned long)addr;
+	unsigned long tag_bits_mask = arch_addr_tag_bits_mask(sig, code);
+
 	info->si_signo = sig;
 	info->si_errno = 0;
 	info->si_code = code;
-	info->si_addr = addr;
-	info->si_faultflags = 0;
+	info->si_addr = (void __user *)(addr_long & ~tag_bits_mask);
+	info->si_faultflags = SIFAULTFLAG_ADDR_TAG_BITS;
+	info->si_addr_tag_bits = addr_long & tag_bits_mask;
+	info->si_addr_tag_bits_mask = tag_bits_mask;
 }
 
 int force_sig_fault_to_task(int sig, int code, void __user *addr
@@ -3272,6 +3277,13 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
 		to->si_trapno = from->si_trapno;
 #endif
 		to->si_faultflags = from->si_faultflags;
+		/*
+		 * These assignments involve a truncation, but as with si_addr
+		 * they will be derived from a 32-bit fault address so we
+		 * should not expect any truncation in practice.
+		 */
+		to->si_addr_tag_bits = from->si_addr_tag_bits;
+		to->si_addr_tag_bits_mask = from->si_addr_tag_bits_mask;
 	}
 
 	switch (layout) {
@@ -3348,6 +3360,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 		to->si_trapno = from->si_trapno;
 #endif
 		to->si_faultflags = from->si_faultflags;
+		to->si_addr_tag_bits = from->si_addr_tag_bits;
+		to->si_addr_tag_bits_mask = from->si_addr_tag_bits_mask;
 	}
 
 	switch (layout) {
-- 
2.29.1.341.ge80a0c044ae-goog


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

* [PATCH v14 8/8] arm64: expose FAR_EL1 tag bits in siginfo
@ 2020-11-04 21:18   ` Peter Collingbourne
  0 siblings, 0 replies; 64+ messages in thread
From: Peter Collingbourne @ 2020-11-04 21:18 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,
	Richard Henderson

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

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

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

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

Signed-off-by: Peter Collingbourne <pcc@google.com>
Link: https://linux-review.googlesource.com/id/Ia8876bad8c798e0a32df7c2ce1256c4771c81446
---
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 | 21 +++++---
 arch/arm64/include/asm/exception.h      |  2 +-
 arch/arm64/include/asm/signal.h         | 31 +++++++++++
 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/x86/kernel/signal_compat.c         |  9 +++-
 include/linux/compat.h                  |  2 +
 include/linux/signal.h                  | 16 ++++++
 include/uapi/asm-generic/siginfo.h      | 10 ++++
 kernel/signal.c                         | 18 ++++++-
 16 files changed, 160 insertions(+), 73 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..7d07987ad85a 100644
--- a/Documentation/arm64/tagged-pointers.rst
+++ b/Documentation/arm64/tagged-pointers.rst
@@ -53,12 +53,21 @@ visibility.
 Preserving tags
 ---------------
 
-Non-zero tags are not preserved when delivering signals. This means that
-signal handlers in applications making use of tags cannot rely on the
-tag information for user virtual addresses being maintained for fields
-inside siginfo_t. One exception to this rule is for signals raised in
-response to watchpoint debug exceptions, where the tag information will
-be preserved.
+Non-zero tags are not preserved in the fault address fields
+siginfo.si_addr or sigcontext.fault_address when delivering
+signals. This means that signal handlers in applications making use
+of tags cannot rely on the tag information for user virtual addresses
+being maintained in these fields. One exception to this rule is for
+signals raised in response to watchpoint debug exceptions, where the
+tag information will be preserved.
+
+The fault address tag is preserved in the si_addr_tag_bits field
+of siginfo, which is set for signals raised in response to data aborts
+and instruction aborts. The si_addr_tag_bits_mask field indicates
+which bits of the field are valid. The validity of these fields is
+indicated by the SIFAULTFLAG_ADDR_TAG_BITS flag in siginfo.si_faultflags,
+and the validity of si_faultflags in turn is indicated by the kernel
+indicating support for the sigaction.sa_flags flag SA_FAULTFLAGS.
 
 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..67d8e0899e9b
--- /dev/null
+++ b/arch/arm64/include/asm/signal.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ARM64_ASM_SIGNAL_H
+#define __ARM64_ASM_SIGNAL_H
+
+#include <uapi/asm/signal.h>
+#include <uapi/asm/siginfo.h>
+
+static inline unsigned long arch_addr_tag_bits_mask(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 not
+	 * follow this practice.
+	 */
+	if (sig == SIGTRAP && si_code == TRAP_BRKPT)
+		return 0;
+
+	/*
+	 * FAR_EL1[63:60] are UNKNOWN for tag check faults so reflect that in
+	 * the tag bits mask. The bits are already being masked out by
+	 * do_tag_check_fault so userspace won't see them in si_addr.
+	 */
+	if (sig == SIGSEGV && si_code == SEGV_MTESERR)
+		return 0xfUL << 56;
+
+	return 0xffUL << 56;
+}
+#define arch_addr_tag_bits_mask arch_addr_tag_bits_mask
+
+#endif
diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h
index 1ab63cfbbaf1..673be2d1263c 100644
--- a/arch/arm64/include/asm/system_misc.h
+++ b/arch/arm64/include/asm/system_misc.h
@@ -22,7 +22,7 @@ void die(const char *msg, struct pt_regs *regs, int err);
 
 struct siginfo;
 void arm64_notify_die(const char *str, struct pt_regs *regs,
-		      int signo, int sicode, void __user *addr,
+		      int signo, int sicode, unsigned long far,
 		      int err);
 
 void hook_debug_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h
index 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/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c
index 222ff6178571..41cbef515b95 100644
--- a/arch/x86/kernel/signal_compat.c
+++ b/arch/x86/kernel/signal_compat.c
@@ -121,8 +121,8 @@ static inline void signal_compat_build_tests(void)
 #endif
 
 	CHECK_CSI_OFFSET(_sigfault);
-	CHECK_CSI_SIZE  (_sigfault, 8*sizeof(int));
-	CHECK_SI_SIZE   (_sigfault, 16*sizeof(int));
+	CHECK_CSI_SIZE  (_sigfault, 10*sizeof(int));
+	CHECK_SI_SIZE   (_sigfault, 20*sizeof(int));
 
 	BUILD_BUG_ON(offsetof(siginfo_t, si_addr) != 0x10);
 	BUILD_BUG_ON(offsetof(compat_siginfo_t, si_addr) != 0x0C);
@@ -141,6 +141,11 @@ static inline void signal_compat_build_tests(void)
 	BUILD_BUG_ON(offsetof(siginfo_t, si_faultflags) != 0x48);
 	BUILD_BUG_ON(offsetof(compat_siginfo_t, si_faultflags) != 0x28);
 
+	BUILD_BUG_ON(offsetof(siginfo_t, si_addr_tag_bits) != 0x50);
+	BUILD_BUG_ON(offsetof(siginfo_t, si_addr_tag_bits_mask) != 0x58);
+	BUILD_BUG_ON(offsetof(compat_siginfo_t, si_addr_tag_bits) != 0x2C);
+	BUILD_BUG_ON(offsetof(compat_siginfo_t, si_addr_tag_bits_mask) != 0x30);
+
 	CHECK_CSI_OFFSET(_sigpoll);
 	CHECK_CSI_SIZE  (_sigpoll, 2*sizeof(int));
 	CHECK_SI_SIZE   (_sigpoll, 4*sizeof(int));
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 84d3b72be701..f3c83a6d6623 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -239,6 +239,8 @@ typedef struct compat_siginfo {
 				compat_uptr_t _pad[6];
 			};
 			u32 _faultflags;
+			compat_uptr_t _addr_tag_bits;
+			compat_uptr_t _addr_tag_bits_mask;
 		} _sigfault;
 
 		/* SIGPOLL */
diff --git a/include/linux/signal.h b/include/linux/signal.h
index e9fb05041e7a..7fe7ce1d252e 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -482,4 +482,20 @@ struct seq_file;
 extern void render_sigset_t(struct seq_file *, const char *, sigset_t *);
 #endif
 
+#ifndef arch_addr_tag_bits_mask
+/*
+ * Given a signal and si_code which correspond to the _sigfault union member,
+ * if tag bits are present in the fault address which must appear in
+ * si_addr_tag_bits instead of si_addr, this hook must return a bitmask where 1
+ * corresponds to bits appearing in si_addr_tag_bits and 0 corresponds to bits
+ * appearing in si_addr. The value returned by this function will also be
+ * available in si_addr_tag_bits_mask.
+ */
+static inline unsigned long arch_addr_tag_bits_mask(unsigned long sig,
+						    unsigned long si_code)
+{
+	return 0;
+}
+#endif
+
 #endif /* _LINUX_SIGNAL_H */
diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
index 10a55aed9ede..df196ad74238 100644
--- a/include/uapi/asm-generic/siginfo.h
+++ b/include/uapi/asm-generic/siginfo.h
@@ -97,6 +97,8 @@ union __sifields {
 #ifdef __LP64__
 		__u32 _pad2; /* to be used if we add another 32-bit field */
 #endif
+		unsigned long _addr_tag_bits;
+		unsigned long _addr_tag_bits_mask;
 	} _sigfault;
 
 	/* SIGPOLL */
@@ -159,6 +161,8 @@ typedef struct siginfo {
 #define si_addr_lsb	_sifields._sigfault._addr_lsb
 /* si_faultflags is only valid if 0 < si_code < SI_KERNEL */
 #define si_faultflags	_sifields._sigfault._faultflags
+#define si_addr_tag_bits	_sifields._sigfault._addr_tag_bits
+#define si_addr_tag_bits_mask	_sifields._sigfault._addr_tag_bits_mask
 #define si_lower	_sifields._sigfault._addr_bnd._lower
 #define si_upper	_sifields._sigfault._addr_bnd._upper
 #define si_pkey		_sifields._sigfault._addr_pkey._pkey
@@ -301,6 +305,12 @@ typedef struct siginfo {
 #define EMT_TAGOVF	1	/* tag overflow */
 #define NSIGEMT		1
 
+/*
+ * SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT si_faultflags
+ */
+#define SIFAULTFLAG_ADDR_TAG_BITS	1
+/* si_addr_tag_bits{,_mask} fields valid */
+
 /*
  * sigevent definitions
  * 
diff --git a/kernel/signal.c b/kernel/signal.c
index 1fd1f0d12174..aa69dd312bd5 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1653,11 +1653,16 @@ void force_sigsegv(int sig)
 static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
 				       int code, void __user *addr)
 {
+	unsigned long addr_long = (unsigned long)addr;
+	unsigned long tag_bits_mask = arch_addr_tag_bits_mask(sig, code);
+
 	info->si_signo = sig;
 	info->si_errno = 0;
 	info->si_code = code;
-	info->si_addr = addr;
-	info->si_faultflags = 0;
+	info->si_addr = (void __user *)(addr_long & ~tag_bits_mask);
+	info->si_faultflags = SIFAULTFLAG_ADDR_TAG_BITS;
+	info->si_addr_tag_bits = addr_long & tag_bits_mask;
+	info->si_addr_tag_bits_mask = tag_bits_mask;
 }
 
 int force_sig_fault_to_task(int sig, int code, void __user *addr
@@ -3272,6 +3277,13 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
 		to->si_trapno = from->si_trapno;
 #endif
 		to->si_faultflags = from->si_faultflags;
+		/*
+		 * These assignments involve a truncation, but as with si_addr
+		 * they will be derived from a 32-bit fault address so we
+		 * should not expect any truncation in practice.
+		 */
+		to->si_addr_tag_bits = from->si_addr_tag_bits;
+		to->si_addr_tag_bits_mask = from->si_addr_tag_bits_mask;
 	}
 
 	switch (layout) {
@@ -3348,6 +3360,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 		to->si_trapno = from->si_trapno;
 #endif
 		to->si_faultflags = from->si_faultflags;
+		to->si_addr_tag_bits = from->si_addr_tag_bits;
+		to->si_addr_tag_bits_mask = from->si_addr_tag_bits_mask;
 	}
 
 	switch (layout) {
-- 
2.29.1.341.ge80a0c044ae-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] 64+ messages in thread

* Re: [PATCH v14 5/8] signal: clear non-uapi flag bits when passing/returning sa_flags
  2020-11-04 21:18   ` Peter Collingbourne
@ 2020-11-10  0:35     ` Eric W. Biederman
  -1 siblings, 0 replies; 64+ messages in thread
From: Eric W. Biederman @ 2020-11-10  0:35 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	James E.J. Bottomley, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-api, Helge Deller, David Spickett

Peter Collingbourne <pcc@google.com> writes:

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

Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>

Yes.  The x86_64 case and general good sense suggests that this patch
will be harmless.

I suspect we should at least try and take this one step farther
(with an additional patch) that causes an error if any new flags
are passed.  Or do we know of some userspace application that
currently passes bogus flags?



> 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>
> 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 74e7315c24db..832b654dee8c 100644
> --- a/kernel/signal.c
> +++ b/kernel/signal.c
> @@ -3964,6 +3964,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) {

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

* Re: [PATCH v14 5/8] signal: clear non-uapi flag bits when passing/returning sa_flags
@ 2020-11-10  0:35     ` Eric W. Biederman
  0 siblings, 0 replies; 64+ messages in thread
From: Eric W. Biederman @ 2020-11-10  0:35 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, Richard Henderson

Peter Collingbourne <pcc@google.com> writes:

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

Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>

Yes.  The x86_64 case and general good sense suggests that this patch
will be harmless.

I suspect we should at least try and take this one step farther
(with an additional patch) that causes an error if any new flags
are passed.  Or do we know of some userspace application that
currently passes bogus flags?



> 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>
> 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 74e7315c24db..832b654dee8c 100644
> --- a/kernel/signal.c
> +++ b/kernel/signal.c
> @@ -3964,6 +3964,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) {

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

* Re: [PATCH v14 4/8] signal: deduplicate code dealing with common _sigfault fields
  2020-11-04 21:18   ` Peter Collingbourne
@ 2020-11-10  0:41     ` Eric W. Biederman
  -1 siblings, 0 replies; 64+ messages in thread
From: Eric W. Biederman @ 2020-11-10  0:41 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	James E.J. Bottomley, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-api, Helge Deller, David Spickett

Peter Collingbourne <pcc@google.com> writes:

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

Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>


No real objection but I am wondering if it might be better to
introduce two small inline functions for setting common fields
instead of:

> +	if (siginfo_layout_is_fault(layout)) {
> +		to->si_addr = ptr_to_compat(from->si_addr);
> +#ifdef __ARCH_SI_TRAPNO
> +		to->si_trapno = from->si_trapno;
> +#endif
> +	}

and 

> +	if (siginfo_layout_is_fault(layout)) {
> +		to->si_addr = compat_ptr(from->si_addr);
> +#ifdef __ARCH_SI_TRAPNO
> +		to->si_trapno = from->si_trapno;
> +#endif
> +	}

perhaps called:
copy_sigfault_common_to_external32
post_copy_sigfault_common_from_user32

I have not benchmarked or anything but my gut says one less conditional
branch to worry about makes dealing with spectre easier and probably
produces faster code as well.  Possibly even smaller code.

Eric

> Signed-off-by: Peter Collingbourne <pcc@google.com>
> Link: https://linux-review.googlesource.com/id/I4f56174e1b7b2bf4a3c8139e6879cbfd52750a24
> ---
>  include/linux/signal.h |  13 ++++++
>  kernel/signal.c        | 101 ++++++++++++++++-------------------------
>  2 files changed, 53 insertions(+), 61 deletions(-)
>
> diff --git a/include/linux/signal.h b/include/linux/signal.h
> index b256f9c65661..e9fb05041e7a 100644
> --- a/include/linux/signal.h
> +++ b/include/linux/signal.h
> @@ -50,6 +50,19 @@ enum siginfo_layout {
>  
>  enum siginfo_layout siginfo_layout(unsigned sig, int si_code);
>  
> +static inline bool siginfo_layout_is_fault(enum siginfo_layout layout)
> +{
> +	switch (layout) {
> +	case SIL_FAULT:
> +	case SIL_FAULT_MCEERR:
> +	case SIL_FAULT_BNDERR:
> +	case SIL_FAULT_PKUERR:
> +		return true;
> +	default:
> +		return false;
> +	}
> +}
> +
>  /*
>   * Define some primitives to manipulate sigset_t.
>   */
> diff --git a/kernel/signal.c b/kernel/signal.c
> index ef8f2a28d37c..74e7315c24db 100644
> --- a/kernel/signal.c
> +++ b/kernel/signal.c
> @@ -1650,6 +1650,15 @@ void force_sigsegv(int sig)
>  	force_sig(SIGSEGV);
>  }
>  
> +static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
> +				       int code, void __user *addr)
> +{
> +	info->si_signo = sig;
> +	info->si_errno = 0;
> +	info->si_code = code;
> +	info->si_addr = addr;
> +}
> +
>  int force_sig_fault_to_task(int sig, int code, void __user *addr
>  	___ARCH_SI_TRAPNO(int trapno)
>  	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
> @@ -1658,10 +1667,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
>  	struct kernel_siginfo info;
>  
>  	clear_siginfo(&info);
> -	info.si_signo = sig;
> -	info.si_errno = 0;
> -	info.si_code  = code;
> -	info.si_addr  = addr;
> +	set_sigfault_common_fields(&info, sig, code, addr);
>  #ifdef __ARCH_SI_TRAPNO
>  	info.si_trapno = trapno;
>  #endif
> @@ -1690,10 +1696,7 @@ int send_sig_fault(int sig, int code, void __user *addr
>  	struct kernel_siginfo info;
>  
>  	clear_siginfo(&info);
> -	info.si_signo = sig;
> -	info.si_errno = 0;
> -	info.si_code  = code;
> -	info.si_addr  = addr;
> +	set_sigfault_common_fields(&info, sig, code, addr);
>  #ifdef __ARCH_SI_TRAPNO
>  	info.si_trapno = trapno;
>  #endif
> @@ -1711,10 +1714,7 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
>  
>  	WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
>  	clear_siginfo(&info);
> -	info.si_signo = SIGBUS;
> -	info.si_errno = 0;
> -	info.si_code = code;
> -	info.si_addr = addr;
> +	set_sigfault_common_fields(&info, SIGBUS, code, addr);
>  	info.si_addr_lsb = lsb;
>  	return force_sig_info(&info);
>  }
> @@ -1725,10 +1725,7 @@ int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *
>  
>  	WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
>  	clear_siginfo(&info);
> -	info.si_signo = SIGBUS;
> -	info.si_errno = 0;
> -	info.si_code = code;
> -	info.si_addr = addr;
> +	set_sigfault_common_fields(&info, SIGBUS, code, addr);
>  	info.si_addr_lsb = lsb;
>  	return send_sig_info(info.si_signo, &info, t);
>  }
> @@ -1739,10 +1736,7 @@ int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
>  	struct kernel_siginfo info;
>  
>  	clear_siginfo(&info);
> -	info.si_signo = SIGSEGV;
> -	info.si_errno = 0;
> -	info.si_code  = SEGV_BNDERR;
> -	info.si_addr  = addr;
> +	set_sigfault_common_fields(&info, SIGSEGV, SEGV_BNDERR, addr);
>  	info.si_lower = lower;
>  	info.si_upper = upper;
>  	return force_sig_info(&info);
> @@ -1754,10 +1748,7 @@ int force_sig_pkuerr(void __user *addr, u32 pkey)
>  	struct kernel_siginfo info;
>  
>  	clear_siginfo(&info);
> -	info.si_signo = SIGSEGV;
> -	info.si_errno = 0;
> -	info.si_code  = SEGV_PKUERR;
> -	info.si_addr  = addr;
> +	set_sigfault_common_fields(&info, SIGSEGV, SEGV_PKUERR, addr);
>  	info.si_pkey  = pkey;
>  	return force_sig_info(&info);
>  }
> @@ -1771,10 +1762,8 @@ int force_sig_ptrace_errno_trap(int errno, void __user *addr)
>  	struct kernel_siginfo info;
>  
>  	clear_siginfo(&info);
> -	info.si_signo = SIGTRAP;
> +	set_sigfault_common_fields(&info, SIGTRAP, TRAP_HWBKPT, addr);
>  	info.si_errno = errno;
> -	info.si_code  = TRAP_HWBKPT;
> -	info.si_addr  = addr;
>  	return force_sig_info(&info);
>  }
>  
> @@ -3267,12 +3256,23 @@ int copy_siginfo_from_user(kernel_siginfo_t *to, const siginfo_t __user *from)
>  void copy_siginfo_to_external32(struct compat_siginfo *to,
>  		const struct kernel_siginfo *from)
>  {
> +	enum siginfo_layout layout =
> +		siginfo_layout(from->si_signo, from->si_code);
> +
>  	memset(to, 0, sizeof(*to));
>  
>  	to->si_signo = from->si_signo;
>  	to->si_errno = from->si_errno;
>  	to->si_code  = from->si_code;
> -	switch(siginfo_layout(from->si_signo, from->si_code)) {
> +
> +	if (siginfo_layout_is_fault(layout)) {
> +		to->si_addr = ptr_to_compat(from->si_addr);
> +#ifdef __ARCH_SI_TRAPNO
> +		to->si_trapno = from->si_trapno;
> +#endif
> +	}
> +
> +	switch (layout) {
>  	case SIL_KILL:
>  		to->si_pid = from->si_pid;
>  		to->si_uid = from->si_uid;
> @@ -3287,31 +3287,15 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
>  		to->si_fd   = from->si_fd;
>  		break;
>  	case SIL_FAULT:
> -		to->si_addr = ptr_to_compat(from->si_addr);
> -#ifdef __ARCH_SI_TRAPNO
> -		to->si_trapno = from->si_trapno;
> -#endif
>  		break;
>  	case SIL_FAULT_MCEERR:
> -		to->si_addr = ptr_to_compat(from->si_addr);
> -#ifdef __ARCH_SI_TRAPNO
> -		to->si_trapno = from->si_trapno;
> -#endif
>  		to->si_addr_lsb = from->si_addr_lsb;
>  		break;
>  	case SIL_FAULT_BNDERR:
> -		to->si_addr = ptr_to_compat(from->si_addr);
> -#ifdef __ARCH_SI_TRAPNO
> -		to->si_trapno = from->si_trapno;
> -#endif
>  		to->si_lower = ptr_to_compat(from->si_lower);
>  		to->si_upper = ptr_to_compat(from->si_upper);
>  		break;
>  	case SIL_FAULT_PKUERR:
> -		to->si_addr = ptr_to_compat(from->si_addr);
> -#ifdef __ARCH_SI_TRAPNO
> -		to->si_trapno = from->si_trapno;
> -#endif
>  		to->si_pkey = from->si_pkey;
>  		break;
>  	case SIL_CHLD:
> @@ -3348,11 +3332,22 @@ int __copy_siginfo_to_user32(struct compat_siginfo __user *to,
>  static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
>  					 const struct compat_siginfo *from)
>  {
> +	enum siginfo_layout layout =
> +		siginfo_layout(from->si_signo, from->si_code);
> +
>  	clear_siginfo(to);
>  	to->si_signo = from->si_signo;
>  	to->si_errno = from->si_errno;
>  	to->si_code  = from->si_code;
> -	switch(siginfo_layout(from->si_signo, from->si_code)) {
> +
> +	if (siginfo_layout_is_fault(layout)) {
> +		to->si_addr = compat_ptr(from->si_addr);
> +#ifdef __ARCH_SI_TRAPNO
> +		to->si_trapno = from->si_trapno;
> +#endif
> +	}
> +
> +	switch (layout) {
>  	case SIL_KILL:
>  		to->si_pid = from->si_pid;
>  		to->si_uid = from->si_uid;
> @@ -3367,31 +3362,15 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
>  		to->si_fd   = from->si_fd;
>  		break;
>  	case SIL_FAULT:
> -		to->si_addr = compat_ptr(from->si_addr);
> -#ifdef __ARCH_SI_TRAPNO
> -		to->si_trapno = from->si_trapno;
> -#endif
>  		break;
>  	case SIL_FAULT_MCEERR:
> -		to->si_addr = compat_ptr(from->si_addr);
> -#ifdef __ARCH_SI_TRAPNO
> -		to->si_trapno = from->si_trapno;
> -#endif
>  		to->si_addr_lsb = from->si_addr_lsb;
>  		break;
>  	case SIL_FAULT_BNDERR:
> -		to->si_addr = compat_ptr(from->si_addr);
> -#ifdef __ARCH_SI_TRAPNO
> -		to->si_trapno = from->si_trapno;
> -#endif
>  		to->si_lower = compat_ptr(from->si_lower);
>  		to->si_upper = compat_ptr(from->si_upper);
>  		break;
>  	case SIL_FAULT_PKUERR:
> -		to->si_addr = compat_ptr(from->si_addr);
> -#ifdef __ARCH_SI_TRAPNO
> -		to->si_trapno = from->si_trapno;
> -#endif
>  		to->si_pkey = from->si_pkey;
>  		break;
>  	case SIL_CHLD:

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

* Re: [PATCH v14 4/8] signal: deduplicate code dealing with common _sigfault fields
@ 2020-11-10  0:41     ` Eric W. Biederman
  0 siblings, 0 replies; 64+ messages in thread
From: Eric W. Biederman @ 2020-11-10  0:41 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, Richard Henderson

Peter Collingbourne <pcc@google.com> writes:

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

Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>


No real objection but I am wondering if it might be better to
introduce two small inline functions for setting common fields
instead of:

> +	if (siginfo_layout_is_fault(layout)) {
> +		to->si_addr = ptr_to_compat(from->si_addr);
> +#ifdef __ARCH_SI_TRAPNO
> +		to->si_trapno = from->si_trapno;
> +#endif
> +	}

and 

> +	if (siginfo_layout_is_fault(layout)) {
> +		to->si_addr = compat_ptr(from->si_addr);
> +#ifdef __ARCH_SI_TRAPNO
> +		to->si_trapno = from->si_trapno;
> +#endif
> +	}

perhaps called:
copy_sigfault_common_to_external32
post_copy_sigfault_common_from_user32

I have not benchmarked or anything but my gut says one less conditional
branch to worry about makes dealing with spectre easier and probably
produces faster code as well.  Possibly even smaller code.

Eric

> Signed-off-by: Peter Collingbourne <pcc@google.com>
> Link: https://linux-review.googlesource.com/id/I4f56174e1b7b2bf4a3c8139e6879cbfd52750a24
> ---
>  include/linux/signal.h |  13 ++++++
>  kernel/signal.c        | 101 ++++++++++++++++-------------------------
>  2 files changed, 53 insertions(+), 61 deletions(-)
>
> diff --git a/include/linux/signal.h b/include/linux/signal.h
> index b256f9c65661..e9fb05041e7a 100644
> --- a/include/linux/signal.h
> +++ b/include/linux/signal.h
> @@ -50,6 +50,19 @@ enum siginfo_layout {
>  
>  enum siginfo_layout siginfo_layout(unsigned sig, int si_code);
>  
> +static inline bool siginfo_layout_is_fault(enum siginfo_layout layout)
> +{
> +	switch (layout) {
> +	case SIL_FAULT:
> +	case SIL_FAULT_MCEERR:
> +	case SIL_FAULT_BNDERR:
> +	case SIL_FAULT_PKUERR:
> +		return true;
> +	default:
> +		return false;
> +	}
> +}
> +
>  /*
>   * Define some primitives to manipulate sigset_t.
>   */
> diff --git a/kernel/signal.c b/kernel/signal.c
> index ef8f2a28d37c..74e7315c24db 100644
> --- a/kernel/signal.c
> +++ b/kernel/signal.c
> @@ -1650,6 +1650,15 @@ void force_sigsegv(int sig)
>  	force_sig(SIGSEGV);
>  }
>  
> +static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
> +				       int code, void __user *addr)
> +{
> +	info->si_signo = sig;
> +	info->si_errno = 0;
> +	info->si_code = code;
> +	info->si_addr = addr;
> +}
> +
>  int force_sig_fault_to_task(int sig, int code, void __user *addr
>  	___ARCH_SI_TRAPNO(int trapno)
>  	___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
> @@ -1658,10 +1667,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
>  	struct kernel_siginfo info;
>  
>  	clear_siginfo(&info);
> -	info.si_signo = sig;
> -	info.si_errno = 0;
> -	info.si_code  = code;
> -	info.si_addr  = addr;
> +	set_sigfault_common_fields(&info, sig, code, addr);
>  #ifdef __ARCH_SI_TRAPNO
>  	info.si_trapno = trapno;
>  #endif
> @@ -1690,10 +1696,7 @@ int send_sig_fault(int sig, int code, void __user *addr
>  	struct kernel_siginfo info;
>  
>  	clear_siginfo(&info);
> -	info.si_signo = sig;
> -	info.si_errno = 0;
> -	info.si_code  = code;
> -	info.si_addr  = addr;
> +	set_sigfault_common_fields(&info, sig, code, addr);
>  #ifdef __ARCH_SI_TRAPNO
>  	info.si_trapno = trapno;
>  #endif
> @@ -1711,10 +1714,7 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
>  
>  	WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
>  	clear_siginfo(&info);
> -	info.si_signo = SIGBUS;
> -	info.si_errno = 0;
> -	info.si_code = code;
> -	info.si_addr = addr;
> +	set_sigfault_common_fields(&info, SIGBUS, code, addr);
>  	info.si_addr_lsb = lsb;
>  	return force_sig_info(&info);
>  }
> @@ -1725,10 +1725,7 @@ int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *
>  
>  	WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
>  	clear_siginfo(&info);
> -	info.si_signo = SIGBUS;
> -	info.si_errno = 0;
> -	info.si_code = code;
> -	info.si_addr = addr;
> +	set_sigfault_common_fields(&info, SIGBUS, code, addr);
>  	info.si_addr_lsb = lsb;
>  	return send_sig_info(info.si_signo, &info, t);
>  }
> @@ -1739,10 +1736,7 @@ int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
>  	struct kernel_siginfo info;
>  
>  	clear_siginfo(&info);
> -	info.si_signo = SIGSEGV;
> -	info.si_errno = 0;
> -	info.si_code  = SEGV_BNDERR;
> -	info.si_addr  = addr;
> +	set_sigfault_common_fields(&info, SIGSEGV, SEGV_BNDERR, addr);
>  	info.si_lower = lower;
>  	info.si_upper = upper;
>  	return force_sig_info(&info);
> @@ -1754,10 +1748,7 @@ int force_sig_pkuerr(void __user *addr, u32 pkey)
>  	struct kernel_siginfo info;
>  
>  	clear_siginfo(&info);
> -	info.si_signo = SIGSEGV;
> -	info.si_errno = 0;
> -	info.si_code  = SEGV_PKUERR;
> -	info.si_addr  = addr;
> +	set_sigfault_common_fields(&info, SIGSEGV, SEGV_PKUERR, addr);
>  	info.si_pkey  = pkey;
>  	return force_sig_info(&info);
>  }
> @@ -1771,10 +1762,8 @@ int force_sig_ptrace_errno_trap(int errno, void __user *addr)
>  	struct kernel_siginfo info;
>  
>  	clear_siginfo(&info);
> -	info.si_signo = SIGTRAP;
> +	set_sigfault_common_fields(&info, SIGTRAP, TRAP_HWBKPT, addr);
>  	info.si_errno = errno;
> -	info.si_code  = TRAP_HWBKPT;
> -	info.si_addr  = addr;
>  	return force_sig_info(&info);
>  }
>  
> @@ -3267,12 +3256,23 @@ int copy_siginfo_from_user(kernel_siginfo_t *to, const siginfo_t __user *from)
>  void copy_siginfo_to_external32(struct compat_siginfo *to,
>  		const struct kernel_siginfo *from)
>  {
> +	enum siginfo_layout layout =
> +		siginfo_layout(from->si_signo, from->si_code);
> +
>  	memset(to, 0, sizeof(*to));
>  
>  	to->si_signo = from->si_signo;
>  	to->si_errno = from->si_errno;
>  	to->si_code  = from->si_code;
> -	switch(siginfo_layout(from->si_signo, from->si_code)) {
> +
> +	if (siginfo_layout_is_fault(layout)) {
> +		to->si_addr = ptr_to_compat(from->si_addr);
> +#ifdef __ARCH_SI_TRAPNO
> +		to->si_trapno = from->si_trapno;
> +#endif
> +	}
> +
> +	switch (layout) {
>  	case SIL_KILL:
>  		to->si_pid = from->si_pid;
>  		to->si_uid = from->si_uid;
> @@ -3287,31 +3287,15 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
>  		to->si_fd   = from->si_fd;
>  		break;
>  	case SIL_FAULT:
> -		to->si_addr = ptr_to_compat(from->si_addr);
> -#ifdef __ARCH_SI_TRAPNO
> -		to->si_trapno = from->si_trapno;
> -#endif
>  		break;
>  	case SIL_FAULT_MCEERR:
> -		to->si_addr = ptr_to_compat(from->si_addr);
> -#ifdef __ARCH_SI_TRAPNO
> -		to->si_trapno = from->si_trapno;
> -#endif
>  		to->si_addr_lsb = from->si_addr_lsb;
>  		break;
>  	case SIL_FAULT_BNDERR:
> -		to->si_addr = ptr_to_compat(from->si_addr);
> -#ifdef __ARCH_SI_TRAPNO
> -		to->si_trapno = from->si_trapno;
> -#endif
>  		to->si_lower = ptr_to_compat(from->si_lower);
>  		to->si_upper = ptr_to_compat(from->si_upper);
>  		break;
>  	case SIL_FAULT_PKUERR:
> -		to->si_addr = ptr_to_compat(from->si_addr);
> -#ifdef __ARCH_SI_TRAPNO
> -		to->si_trapno = from->si_trapno;
> -#endif
>  		to->si_pkey = from->si_pkey;
>  		break;
>  	case SIL_CHLD:
> @@ -3348,11 +3332,22 @@ int __copy_siginfo_to_user32(struct compat_siginfo __user *to,
>  static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
>  					 const struct compat_siginfo *from)
>  {
> +	enum siginfo_layout layout =
> +		siginfo_layout(from->si_signo, from->si_code);
> +
>  	clear_siginfo(to);
>  	to->si_signo = from->si_signo;
>  	to->si_errno = from->si_errno;
>  	to->si_code  = from->si_code;
> -	switch(siginfo_layout(from->si_signo, from->si_code)) {
> +
> +	if (siginfo_layout_is_fault(layout)) {
> +		to->si_addr = compat_ptr(from->si_addr);
> +#ifdef __ARCH_SI_TRAPNO
> +		to->si_trapno = from->si_trapno;
> +#endif
> +	}
> +
> +	switch (layout) {
>  	case SIL_KILL:
>  		to->si_pid = from->si_pid;
>  		to->si_uid = from->si_uid;
> @@ -3367,31 +3362,15 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
>  		to->si_fd   = from->si_fd;
>  		break;
>  	case SIL_FAULT:
> -		to->si_addr = compat_ptr(from->si_addr);
> -#ifdef __ARCH_SI_TRAPNO
> -		to->si_trapno = from->si_trapno;
> -#endif
>  		break;
>  	case SIL_FAULT_MCEERR:
> -		to->si_addr = compat_ptr(from->si_addr);
> -#ifdef __ARCH_SI_TRAPNO
> -		to->si_trapno = from->si_trapno;
> -#endif
>  		to->si_addr_lsb = from->si_addr_lsb;
>  		break;
>  	case SIL_FAULT_BNDERR:
> -		to->si_addr = compat_ptr(from->si_addr);
> -#ifdef __ARCH_SI_TRAPNO
> -		to->si_trapno = from->si_trapno;
> -#endif
>  		to->si_lower = compat_ptr(from->si_lower);
>  		to->si_upper = compat_ptr(from->si_upper);
>  		break;
>  	case SIL_FAULT_PKUERR:
> -		to->si_addr = compat_ptr(from->si_addr);
> -#ifdef __ARCH_SI_TRAPNO
> -		to->si_trapno = from->si_trapno;
> -#endif
>  		to->si_pkey = from->si_pkey;
>  		break;
>  	case SIL_CHLD:

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

* Re: [PATCH v14 8/8] arm64: expose FAR_EL1 tag bits in siginfo
  2020-11-04 21:18   ` Peter Collingbourne
@ 2020-11-10  1:13     ` Eric W. Biederman
  -1 siblings, 0 replies; 64+ messages in thread
From: Eric W. Biederman @ 2020-11-10  1:13 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	James E.J. Bottomley, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-api, Helge Deller, David Spickett

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, create a new pair of
> fields in siginfo._sigfault, and store the tag bits of FAR_EL1 there,
> together with a mask specifying which bits are valid.
>
> A flag is added to si_faultflags to allow userspace to determine whether
> the values in the fields are valid.

I think I am missing some things:

Today it is documented that the tag bits are cleared, and so we can't
use the highbits to hold the tag bits by default.

Why do you need to deliver which tag bits are valid?  That feels like an
implementation detail that is needed to setup the tag bits.  It feels
like it would be constant per process.  So I don't understand why the
siginfo needs to report information the process should already have.


Want prevents adding a sigaction sa_flag SA_EXPOSE_TABITS that when set
causes the high bits to be set, and when clear (the default) will have
the signal delivery code clear those bits.

That should be enough for code that wants the tag bits to ask for them.
As userspace would need to be updated to get the new bits

Even if you have chained handlers.  The chaining mechanism would need to
be updated and it could call the aware handlers first then clear the tag
bits and call the rest of the handlers.

It feels like always passing the tag bits in the address and then
clearing them in the copy to userspace if the signal handler is
not ready for them would be easier to maintain.

Eric

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

* Re: [PATCH v14 8/8] arm64: expose FAR_EL1 tag bits in siginfo
@ 2020-11-10  1:13     ` Eric W. Biederman
  0 siblings, 0 replies; 64+ messages in thread
From: Eric W. Biederman @ 2020-11-10  1:13 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, Richard Henderson

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, create a new pair of
> fields in siginfo._sigfault, and store the tag bits of FAR_EL1 there,
> together with a mask specifying which bits are valid.
>
> A flag is added to si_faultflags to allow userspace to determine whether
> the values in the fields are valid.

I think I am missing some things:

Today it is documented that the tag bits are cleared, and so we can't
use the highbits to hold the tag bits by default.

Why do you need to deliver which tag bits are valid?  That feels like an
implementation detail that is needed to setup the tag bits.  It feels
like it would be constant per process.  So I don't understand why the
siginfo needs to report information the process should already have.


Want prevents adding a sigaction sa_flag SA_EXPOSE_TABITS that when set
causes the high bits to be set, and when clear (the default) will have
the signal delivery code clear those bits.

That should be enough for code that wants the tag bits to ask for them.
As userspace would need to be updated to get the new bits

Even if you have chained handlers.  The chaining mechanism would need to
be updated and it could call the aware handlers first then clear the tag
bits and call the rest of the handlers.

It feels like always passing the tag bits in the address and then
clearing them in the copy to userspace if the signal handler is
not ready for them would be easier to maintain.

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

* Re: [PATCH v14 7/8] signal: define the field siginfo.si_faultflags
  2020-11-04 21:18   ` Peter Collingbourne
@ 2020-11-10  1:54     ` Eric W. Biederman
  -1 siblings, 0 replies; 64+ messages in thread
From: Eric W. Biederman @ 2020-11-10  1:54 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	James E.J. Bottomley, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-api, Helge Deller, David Spickett,
	Haren Myneni, Sukadev Bhattiprolu, Michael Ellerman


Peter you are patching buggy code for your siginfo extension can
you please ignore vas-fault.c.  The code in vas-fault.c should
be fixed separately.  Futher it uses clear_siginfo so you should
get well defined behavior even if your new field is not initialized.

I have copied the powerpc folks so hopefully this buggy code
can be fixed.

> diff --git a/arch/powerpc/platforms/powernv/vas-fault.c b/arch/powerpc/platforms/powernv/vas-fault.c
> index 3d21fce254b7..877e7d5fb4a2 100644
> --- a/arch/powerpc/platforms/powernv/vas-fault.c
> +++ b/arch/powerpc/platforms/powernv/vas-fault.c
> @@ -154,6 +154,7 @@ static void update_csb(struct vas_window *window,
>  	info.si_errno = EFAULT;
>  	info.si_code = SEGV_MAPERR;
>  	info.si_addr = csb_addr;
> +	info.si_faultflags = 0;


Powerpc folks.  This code was introduced in c96c4436aba4 ("powerpc/vas:
Update CSB and notify process for fault CRBs") and is badly buggy.

Let me count the bugs:

a) Using kill_pid_info.  That performs a permission check that
   does not make sense from a kernel thread.

b) Manually filling in struct siginfo.  Everyone gets it wrong
   and the powerpc code is no exception setting si_errno when
   that is something Linux as a rule does not do.

Technically we have send_sig_fault to handle sending
a fault from a non-sychrnous context but I am not convinced
it make sense in this case.

c) Sending an asynchronous SIGSEGV with the si_code set to SEGV_MAPERR.
   How can userspace detect it is an asynchronous signal?  What can
   userspace do if it detects an asynchronous signal?  If userspace is
   so buggered as to give your kernel thread a bogus address I suspect
   uncerimonious sending SIGKILL is probably the best you can do.

There are some additional questionable things in that code like taking a
task_struct reference simply to be able to test tsk->flags but no
locks are held to ensure that tsk->flags are meaningful.  Nor are
any tests performed to see if the task being tested still uses
the designated mm.  I suspect exec could have been called.

In which case the code needs to check the mm, or at least play with
exec_id to ensure you are not improperly signaling a process after exec.

None of this is to say that update_csb is fundmentally bad or hard to
correct just that it has some significant defects in it's implementation
right now that need to be corrected.  I am hoping a detailed accounting
and pointing out those defects will allow the bug to be fixed.

Thank you,
Eric

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

* Re: [PATCH v14 7/8] signal: define the field siginfo.si_faultflags
@ 2020-11-10  1:54     ` Eric W. Biederman
  0 siblings, 0 replies; 64+ messages in thread
From: Eric W. Biederman @ 2020-11-10  1:54 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Sukadev Bhattiprolu, Michael Ellerman, Catalin Marinas,
	Helge Deller, Kevin Brodsky, Haren Myneni, Oleg Nesterov,
	linux-api, James E.J. Bottomley, Kostya Serebryany, Linux ARM,
	Andrey Konovalov, David Spickett, Vincenzo Frascino, Will Deacon,
	Dave Martin, Evgenii Stepanov, Richard Henderson


Peter you are patching buggy code for your siginfo extension can
you please ignore vas-fault.c.  The code in vas-fault.c should
be fixed separately.  Futher it uses clear_siginfo so you should
get well defined behavior even if your new field is not initialized.

I have copied the powerpc folks so hopefully this buggy code
can be fixed.

> diff --git a/arch/powerpc/platforms/powernv/vas-fault.c b/arch/powerpc/platforms/powernv/vas-fault.c
> index 3d21fce254b7..877e7d5fb4a2 100644
> --- a/arch/powerpc/platforms/powernv/vas-fault.c
> +++ b/arch/powerpc/platforms/powernv/vas-fault.c
> @@ -154,6 +154,7 @@ static void update_csb(struct vas_window *window,
>  	info.si_errno = EFAULT;
>  	info.si_code = SEGV_MAPERR;
>  	info.si_addr = csb_addr;
> +	info.si_faultflags = 0;


Powerpc folks.  This code was introduced in c96c4436aba4 ("powerpc/vas:
Update CSB and notify process for fault CRBs") and is badly buggy.

Let me count the bugs:

a) Using kill_pid_info.  That performs a permission check that
   does not make sense from a kernel thread.

b) Manually filling in struct siginfo.  Everyone gets it wrong
   and the powerpc code is no exception setting si_errno when
   that is something Linux as a rule does not do.

Technically we have send_sig_fault to handle sending
a fault from a non-sychrnous context but I am not convinced
it make sense in this case.

c) Sending an asynchronous SIGSEGV with the si_code set to SEGV_MAPERR.
   How can userspace detect it is an asynchronous signal?  What can
   userspace do if it detects an asynchronous signal?  If userspace is
   so buggered as to give your kernel thread a bogus address I suspect
   uncerimonious sending SIGKILL is probably the best you can do.

There are some additional questionable things in that code like taking a
task_struct reference simply to be able to test tsk->flags but no
locks are held to ensure that tsk->flags are meaningful.  Nor are
any tests performed to see if the task being tested still uses
the designated mm.  I suspect exec could have been called.

In which case the code needs to check the mm, or at least play with
exec_id to ensure you are not improperly signaling a process after exec.

None of this is to say that update_csb is fundmentally bad or hard to
correct just that it has some significant defects in it's implementation
right now that need to be corrected.  I am hoping a detailed accounting
and pointing out those defects will allow the bug to be fixed.

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

* Re: [PATCH v14 7/8] signal: define the field siginfo.si_faultflags
  2020-11-04 21:18   ` Peter Collingbourne
@ 2020-11-10  1:57     ` Eric W. Biederman
  -1 siblings, 0 replies; 64+ messages in thread
From: Eric W. Biederman @ 2020-11-10  1:57 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	James E.J. Bottomley, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-api, Helge Deller, David Spickett

Peter Collingbourne <pcc@google.com> writes:

> This field will contain flags that may be used by signal handlers to
> determine whether other fields in the _sigfault portion of siginfo are
> valid. An example use case is the following patch, which introduces
> the si_addr_tag_bits{,_mask} fields.
>
> A new sigcontext flag, SA_FAULTFLAGS, is introduced in order to allow
> a signal handler to require the kernel to set the field (but note
> that the field will be set anyway if the kernel supports the flag,
> regardless of its value). In combination with the previous patches,
> this allows a userspace program to determine whether the kernel will
> set the field.
>
> It is possible for an si_faultflags-unaware program to cause a signal
> handler in an si_faultflags-aware program to be called with a provided
> siginfo data structure by using one of the following syscalls:
>
> - ptrace(PTRACE_SETSIGINFO)
> - pidfd_send_signal
> - rt_sigqueueinfo
> - rt_tgsigqueueinfo
>
> So we need to prevent the si_faultflags-unaware program from causing an
> uninitialized read of si_faultflags in the si_faultflags-aware program when
> it uses one of these syscalls.
>
> The last three cases can be handled by observing that each of these
> syscalls fails if si_code >= 0. We also observe that kill(2) and
> tgkill(2) may be used to send a signal where si_code == 0 (SI_USER),
> so we define si_faultflags to only be valid if si_code > 0.
>
> There is no such check on si_code in ptrace(PTRACE_SETSIGINFO), so
> we make ptrace(PTRACE_SETSIGINFO) clear the si_faultflags field if it
> detects that the signal would use the _sigfault layout, and introduce
> a new ptrace request type, PTRACE_SETSIGINFO2, that a si_faultflags-aware
> program may use to opt out of this behavior.

So I think while well intentioned this is misguided.

gdb and the like may use this but I expect the primary user is CRIU
which simply reads the signal out of one process saves it on disk
and then restores the signal as read into the new process (possibly
on a different machine).

At least for the CRIU usage PTRACE_SETSIGINFO need to remain a raw
pass through kind of operation.

Eric

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

* Re: [PATCH v14 7/8] signal: define the field siginfo.si_faultflags
@ 2020-11-10  1:57     ` Eric W. Biederman
  0 siblings, 0 replies; 64+ messages in thread
From: Eric W. Biederman @ 2020-11-10  1:57 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, Richard Henderson

Peter Collingbourne <pcc@google.com> writes:

> This field will contain flags that may be used by signal handlers to
> determine whether other fields in the _sigfault portion of siginfo are
> valid. An example use case is the following patch, which introduces
> the si_addr_tag_bits{,_mask} fields.
>
> A new sigcontext flag, SA_FAULTFLAGS, is introduced in order to allow
> a signal handler to require the kernel to set the field (but note
> that the field will be set anyway if the kernel supports the flag,
> regardless of its value). In combination with the previous patches,
> this allows a userspace program to determine whether the kernel will
> set the field.
>
> It is possible for an si_faultflags-unaware program to cause a signal
> handler in an si_faultflags-aware program to be called with a provided
> siginfo data structure by using one of the following syscalls:
>
> - ptrace(PTRACE_SETSIGINFO)
> - pidfd_send_signal
> - rt_sigqueueinfo
> - rt_tgsigqueueinfo
>
> So we need to prevent the si_faultflags-unaware program from causing an
> uninitialized read of si_faultflags in the si_faultflags-aware program when
> it uses one of these syscalls.
>
> The last three cases can be handled by observing that each of these
> syscalls fails if si_code >= 0. We also observe that kill(2) and
> tgkill(2) may be used to send a signal where si_code == 0 (SI_USER),
> so we define si_faultflags to only be valid if si_code > 0.
>
> There is no such check on si_code in ptrace(PTRACE_SETSIGINFO), so
> we make ptrace(PTRACE_SETSIGINFO) clear the si_faultflags field if it
> detects that the signal would use the _sigfault layout, and introduce
> a new ptrace request type, PTRACE_SETSIGINFO2, that a si_faultflags-aware
> program may use to opt out of this behavior.

So I think while well intentioned this is misguided.

gdb and the like may use this but I expect the primary user is CRIU
which simply reads the signal out of one process saves it on disk
and then restores the signal as read into the new process (possibly
on a different machine).

At least for the CRIU usage PTRACE_SETSIGINFO need to remain a raw
pass through kind of operation.

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

* Re: [PATCH v14 5/8] signal: clear non-uapi flag bits when passing/returning sa_flags
  2020-11-10  0:35     ` Eric W. Biederman
@ 2020-11-10  2:19       ` Peter Collingbourne
  -1 siblings, 0 replies; 64+ messages in thread
From: Peter Collingbourne @ 2020-11-10  2:19 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	James E.J. Bottomley, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, Linux API, Helge Deller, David Spickett

On Mon, Nov 9, 2020 at 4:35 PM Eric W. Biederman <ebiederm@xmission.com> wrote:
>
> Peter Collingbourne <pcc@google.com> writes:
>
> 2> 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.
>
> Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>
>
> Yes.  The x86_64 case and general good sense suggests that this patch
> will be harmless.

Thanks for the review.

> I suspect we should at least try and take this one step farther
> (with an additional patch) that causes an error if any new flags
> are passed.  Or do we know of some userspace application that
> currently passes bogus flags?

I'm not aware of any such userspace applications, but that doesn't
mean that there aren't any of course. Probably the most plausible way
in which I can see us ending up with userspace applications setting
bogus flags is if the application leaves sa_flags uninitialized and
installs a signal handler that doesn't care which flags were set as
long as the handler ends up being called somehow. I don't think it's
outside the realm of possibility that there is an application out
there on Android doing something like this, and if we discovered such
an application (which may happen long after we make the kernel
change), that may require us to change the behavior on Android at
least, which may have implications for flag support detection code
that is necessarily sensitive to sigaction's precise behavior, and may
create a divergence between Android and upstream Linux, which is
something that we really want to avoid. So I would be at least
slightly concerned about making such a change.

Another concern is that it would further complicate the flag support
detection protocol beyond what would be required if we assume success
on unknown flags. If we succeed on unknown flags we just need two
calls to sigaction (one to set the handler, and another to check
oldact), but if we fail on unknown flags I think we would need three
(or more, if the userspace code has multiple flags to test for). The
userspace code would look something like this:

// The next call will only succeed on kernels from before we started
// rejecting unknown flags. Therefore, if it succeeds, it should install the
// handler for old kernels.
struct sigaction sa = {};
sa.sa_flags = SA_SIGINFO | SA_UNSUPPORTED;
sa.sa_sigaction = old_kernel_handler;
if (sigaction(SIGSEGV, &sa, 0) < 0) {
  // Okay, we're on a kernel that rejects unknown flags.
  // The next call will only succeed if we have SA_FAULTFLAGS support,
  // so we try to install the handler for new kernels.
  sa.sa_flags = SA_SIGINFO | SA_FAULTFLAGS;
  sa.sa_sigaction = new_kernel_handler;
  if (sigaction(SIGSEGV, &sa, 0) < 0) {
    // We're on a kernel from between when we started rejecting unknown
    // flags and when we started supporting SA_FAULTFLAGS. Therefore
    // we need to install the handler for old kernels.
    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = old_kernel_handler;
    sigaction(SIGSEGV, &sa, 0);
  }
}

Peter

>
>
>
> > 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>
> > 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 74e7315c24db..832b654dee8c 100644
> > --- a/kernel/signal.c
> > +++ b/kernel/signal.c
> > @@ -3964,6 +3964,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) {

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

* Re: [PATCH v14 5/8] signal: clear non-uapi flag bits when passing/returning sa_flags
@ 2020-11-10  2:19       ` Peter Collingbourne
  0 siblings, 0 replies; 64+ messages in thread
From: Peter Collingbourne @ 2020-11-10  2:19 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, Richard Henderson

On Mon, Nov 9, 2020 at 4:35 PM Eric W. Biederman <ebiederm@xmission.com> wrote:
>
> Peter Collingbourne <pcc@google.com> writes:
>
> 2> 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.
>
> Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>
>
> Yes.  The x86_64 case and general good sense suggests that this patch
> will be harmless.

Thanks for the review.

> I suspect we should at least try and take this one step farther
> (with an additional patch) that causes an error if any new flags
> are passed.  Or do we know of some userspace application that
> currently passes bogus flags?

I'm not aware of any such userspace applications, but that doesn't
mean that there aren't any of course. Probably the most plausible way
in which I can see us ending up with userspace applications setting
bogus flags is if the application leaves sa_flags uninitialized and
installs a signal handler that doesn't care which flags were set as
long as the handler ends up being called somehow. I don't think it's
outside the realm of possibility that there is an application out
there on Android doing something like this, and if we discovered such
an application (which may happen long after we make the kernel
change), that may require us to change the behavior on Android at
least, which may have implications for flag support detection code
that is necessarily sensitive to sigaction's precise behavior, and may
create a divergence between Android and upstream Linux, which is
something that we really want to avoid. So I would be at least
slightly concerned about making such a change.

Another concern is that it would further complicate the flag support
detection protocol beyond what would be required if we assume success
on unknown flags. If we succeed on unknown flags we just need two
calls to sigaction (one to set the handler, and another to check
oldact), but if we fail on unknown flags I think we would need three
(or more, if the userspace code has multiple flags to test for). The
userspace code would look something like this:

// The next call will only succeed on kernels from before we started
// rejecting unknown flags. Therefore, if it succeeds, it should install the
// handler for old kernels.
struct sigaction sa = {};
sa.sa_flags = SA_SIGINFO | SA_UNSUPPORTED;
sa.sa_sigaction = old_kernel_handler;
if (sigaction(SIGSEGV, &sa, 0) < 0) {
  // Okay, we're on a kernel that rejects unknown flags.
  // The next call will only succeed if we have SA_FAULTFLAGS support,
  // so we try to install the handler for new kernels.
  sa.sa_flags = SA_SIGINFO | SA_FAULTFLAGS;
  sa.sa_sigaction = new_kernel_handler;
  if (sigaction(SIGSEGV, &sa, 0) < 0) {
    // We're on a kernel from between when we started rejecting unknown
    // flags and when we started supporting SA_FAULTFLAGS. Therefore
    // we need to install the handler for old kernels.
    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = old_kernel_handler;
    sigaction(SIGSEGV, &sa, 0);
  }
}

Peter

>
>
>
> > 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>
> > 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 74e7315c24db..832b654dee8c 100644
> > --- a/kernel/signal.c
> > +++ b/kernel/signal.c
> > @@ -3964,6 +3964,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) {

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

* Re: [PATCH v14 4/8] signal: deduplicate code dealing with common _sigfault fields
  2020-11-10  0:41     ` Eric W. Biederman
@ 2020-11-10  2:37       ` Peter Collingbourne
  -1 siblings, 0 replies; 64+ messages in thread
From: Peter Collingbourne @ 2020-11-10  2:37 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	James E.J. Bottomley, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, Linux API, Helge Deller, David Spickett

On Mon, Nov 9, 2020 at 4:41 PM Eric W. Biederman <ebiederm@xmission.com> wrote:
>
> Peter Collingbourne <pcc@google.com> writes:
>
> > We're about to add more common _sigfault fields, so deduplicate the
> > existing code for initializing _sigfault fields in {send,force}_sig_*,
> > and for copying _sigfault fields in copy_siginfo_to_external32 and
> > post_copy_siginfo_from_user32, to reduce the number of places that
> > will need to be updated by upcoming changes.
>
> Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>

Thanks for the review.

> No real objection but I am wondering if it might be better to
> introduce two small inline functions for setting common fields
> instead of:
>
> > +     if (siginfo_layout_is_fault(layout)) {
> > +             to->si_addr = ptr_to_compat(from->si_addr);
> > +#ifdef __ARCH_SI_TRAPNO
> > +             to->si_trapno = from->si_trapno;
> > +#endif
> > +     }
>
> and
>
> > +     if (siginfo_layout_is_fault(layout)) {
> > +             to->si_addr = compat_ptr(from->si_addr);
> > +#ifdef __ARCH_SI_TRAPNO
> > +             to->si_trapno = from->si_trapno;
> > +#endif
> > +     }
>
> perhaps called:
> copy_sigfault_common_to_external32
> post_copy_sigfault_common_from_user32
>
> I have not benchmarked or anything but my gut says one less conditional
> branch to worry about makes dealing with spectre easier and probably
> produces faster code as well.  Possibly even smaller code.

Dave made the same proposal on an earlier version of the patch which I
responded to in [1]. The main reason for keeping things as I
implemented them was because of the ptrace handling but if we do end
up dropping that as you proposed on the other patch then I think I'd
be happy to move the code into helper functions.

Peter

[1] https://lore.kernel.org/linux-parisc/CAMn1gO42arQKGBj1Nnbs86TGYyogpRR_t73H=GbTmQrbAbV30A@mail.gmail.com/

>
> Eric
>
> > Signed-off-by: Peter Collingbourne <pcc@google.com>
> > Link: https://linux-review.googlesource.com/id/I4f56174e1b7b2bf4a3c8139e6879cbfd52750a24
> > ---
> >  include/linux/signal.h |  13 ++++++
> >  kernel/signal.c        | 101 ++++++++++++++++-------------------------
> >  2 files changed, 53 insertions(+), 61 deletions(-)
> >
> > diff --git a/include/linux/signal.h b/include/linux/signal.h
> > index b256f9c65661..e9fb05041e7a 100644
> > --- a/include/linux/signal.h
> > +++ b/include/linux/signal.h
> > @@ -50,6 +50,19 @@ enum siginfo_layout {
> >
> >  enum siginfo_layout siginfo_layout(unsigned sig, int si_code);
> >
> > +static inline bool siginfo_layout_is_fault(enum siginfo_layout layout)
> > +{
> > +     switch (layout) {
> > +     case SIL_FAULT:
> > +     case SIL_FAULT_MCEERR:
> > +     case SIL_FAULT_BNDERR:
> > +     case SIL_FAULT_PKUERR:
> > +             return true;
> > +     default:
> > +             return false;
> > +     }
> > +}
> > +
> >  /*
> >   * Define some primitives to manipulate sigset_t.
> >   */
> > diff --git a/kernel/signal.c b/kernel/signal.c
> > index ef8f2a28d37c..74e7315c24db 100644
> > --- a/kernel/signal.c
> > +++ b/kernel/signal.c
> > @@ -1650,6 +1650,15 @@ void force_sigsegv(int sig)
> >       force_sig(SIGSEGV);
> >  }
> >
> > +static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
> > +                                    int code, void __user *addr)
> > +{
> > +     info->si_signo = sig;
> > +     info->si_errno = 0;
> > +     info->si_code = code;
> > +     info->si_addr = addr;
> > +}
> > +
> >  int force_sig_fault_to_task(int sig, int code, void __user *addr
> >       ___ARCH_SI_TRAPNO(int trapno)
> >       ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
> > @@ -1658,10 +1667,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
> >       struct kernel_siginfo info;
> >
> >       clear_siginfo(&info);
> > -     info.si_signo = sig;
> > -     info.si_errno = 0;
> > -     info.si_code  = code;
> > -     info.si_addr  = addr;
> > +     set_sigfault_common_fields(&info, sig, code, addr);
> >  #ifdef __ARCH_SI_TRAPNO
> >       info.si_trapno = trapno;
> >  #endif
> > @@ -1690,10 +1696,7 @@ int send_sig_fault(int sig, int code, void __user *addr
> >       struct kernel_siginfo info;
> >
> >       clear_siginfo(&info);
> > -     info.si_signo = sig;
> > -     info.si_errno = 0;
> > -     info.si_code  = code;
> > -     info.si_addr  = addr;
> > +     set_sigfault_common_fields(&info, sig, code, addr);
> >  #ifdef __ARCH_SI_TRAPNO
> >       info.si_trapno = trapno;
> >  #endif
> > @@ -1711,10 +1714,7 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
> >
> >       WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
> >       clear_siginfo(&info);
> > -     info.si_signo = SIGBUS;
> > -     info.si_errno = 0;
> > -     info.si_code = code;
> > -     info.si_addr = addr;
> > +     set_sigfault_common_fields(&info, SIGBUS, code, addr);
> >       info.si_addr_lsb = lsb;
> >       return force_sig_info(&info);
> >  }
> > @@ -1725,10 +1725,7 @@ int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *
> >
> >       WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
> >       clear_siginfo(&info);
> > -     info.si_signo = SIGBUS;
> > -     info.si_errno = 0;
> > -     info.si_code = code;
> > -     info.si_addr = addr;
> > +     set_sigfault_common_fields(&info, SIGBUS, code, addr);
> >       info.si_addr_lsb = lsb;
> >       return send_sig_info(info.si_signo, &info, t);
> >  }
> > @@ -1739,10 +1736,7 @@ int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
> >       struct kernel_siginfo info;
> >
> >       clear_siginfo(&info);
> > -     info.si_signo = SIGSEGV;
> > -     info.si_errno = 0;
> > -     info.si_code  = SEGV_BNDERR;
> > -     info.si_addr  = addr;
> > +     set_sigfault_common_fields(&info, SIGSEGV, SEGV_BNDERR, addr);
> >       info.si_lower = lower;
> >       info.si_upper = upper;
> >       return force_sig_info(&info);
> > @@ -1754,10 +1748,7 @@ int force_sig_pkuerr(void __user *addr, u32 pkey)
> >       struct kernel_siginfo info;
> >
> >       clear_siginfo(&info);
> > -     info.si_signo = SIGSEGV;
> > -     info.si_errno = 0;
> > -     info.si_code  = SEGV_PKUERR;
> > -     info.si_addr  = addr;
> > +     set_sigfault_common_fields(&info, SIGSEGV, SEGV_PKUERR, addr);
> >       info.si_pkey  = pkey;
> >       return force_sig_info(&info);
> >  }
> > @@ -1771,10 +1762,8 @@ int force_sig_ptrace_errno_trap(int errno, void __user *addr)
> >       struct kernel_siginfo info;
> >
> >       clear_siginfo(&info);
> > -     info.si_signo = SIGTRAP;
> > +     set_sigfault_common_fields(&info, SIGTRAP, TRAP_HWBKPT, addr);
> >       info.si_errno = errno;
> > -     info.si_code  = TRAP_HWBKPT;
> > -     info.si_addr  = addr;
> >       return force_sig_info(&info);
> >  }
> >
> > @@ -3267,12 +3256,23 @@ int copy_siginfo_from_user(kernel_siginfo_t *to, const siginfo_t __user *from)
> >  void copy_siginfo_to_external32(struct compat_siginfo *to,
> >               const struct kernel_siginfo *from)
> >  {
> > +     enum siginfo_layout layout =
> > +             siginfo_layout(from->si_signo, from->si_code);
> > +
> >       memset(to, 0, sizeof(*to));
> >
> >       to->si_signo = from->si_signo;
> >       to->si_errno = from->si_errno;
> >       to->si_code  = from->si_code;
> > -     switch(siginfo_layout(from->si_signo, from->si_code)) {
> > +
> > +     if (siginfo_layout_is_fault(layout)) {
> > +             to->si_addr = ptr_to_compat(from->si_addr);
> > +#ifdef __ARCH_SI_TRAPNO
> > +             to->si_trapno = from->si_trapno;
> > +#endif
> > +     }
> > +
> > +     switch (layout) {
> >       case SIL_KILL:
> >               to->si_pid = from->si_pid;
> >               to->si_uid = from->si_uid;
> > @@ -3287,31 +3287,15 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
> >               to->si_fd   = from->si_fd;
> >               break;
> >       case SIL_FAULT:
> > -             to->si_addr = ptr_to_compat(from->si_addr);
> > -#ifdef __ARCH_SI_TRAPNO
> > -             to->si_trapno = from->si_trapno;
> > -#endif
> >               break;
> >       case SIL_FAULT_MCEERR:
> > -             to->si_addr = ptr_to_compat(from->si_addr);
> > -#ifdef __ARCH_SI_TRAPNO
> > -             to->si_trapno = from->si_trapno;
> > -#endif
> >               to->si_addr_lsb = from->si_addr_lsb;
> >               break;
> >       case SIL_FAULT_BNDERR:
> > -             to->si_addr = ptr_to_compat(from->si_addr);
> > -#ifdef __ARCH_SI_TRAPNO
> > -             to->si_trapno = from->si_trapno;
> > -#endif
> >               to->si_lower = ptr_to_compat(from->si_lower);
> >               to->si_upper = ptr_to_compat(from->si_upper);
> >               break;
> >       case SIL_FAULT_PKUERR:
> > -             to->si_addr = ptr_to_compat(from->si_addr);
> > -#ifdef __ARCH_SI_TRAPNO
> > -             to->si_trapno = from->si_trapno;
> > -#endif
> >               to->si_pkey = from->si_pkey;
> >               break;
> >       case SIL_CHLD:
> > @@ -3348,11 +3332,22 @@ int __copy_siginfo_to_user32(struct compat_siginfo __user *to,
> >  static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> >                                        const struct compat_siginfo *from)
> >  {
> > +     enum siginfo_layout layout =
> > +             siginfo_layout(from->si_signo, from->si_code);
> > +
> >       clear_siginfo(to);
> >       to->si_signo = from->si_signo;
> >       to->si_errno = from->si_errno;
> >       to->si_code  = from->si_code;
> > -     switch(siginfo_layout(from->si_signo, from->si_code)) {
> > +
> > +     if (siginfo_layout_is_fault(layout)) {
> > +             to->si_addr = compat_ptr(from->si_addr);
> > +#ifdef __ARCH_SI_TRAPNO
> > +             to->si_trapno = from->si_trapno;
> > +#endif
> > +     }
> > +
> > +     switch (layout) {
> >       case SIL_KILL:
> >               to->si_pid = from->si_pid;
> >               to->si_uid = from->si_uid;
> > @@ -3367,31 +3362,15 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> >               to->si_fd   = from->si_fd;
> >               break;
> >       case SIL_FAULT:
> > -             to->si_addr = compat_ptr(from->si_addr);
> > -#ifdef __ARCH_SI_TRAPNO
> > -             to->si_trapno = from->si_trapno;
> > -#endif
> >               break;
> >       case SIL_FAULT_MCEERR:
> > -             to->si_addr = compat_ptr(from->si_addr);
> > -#ifdef __ARCH_SI_TRAPNO
> > -             to->si_trapno = from->si_trapno;
> > -#endif
> >               to->si_addr_lsb = from->si_addr_lsb;
> >               break;
> >       case SIL_FAULT_BNDERR:
> > -             to->si_addr = compat_ptr(from->si_addr);
> > -#ifdef __ARCH_SI_TRAPNO
> > -             to->si_trapno = from->si_trapno;
> > -#endif
> >               to->si_lower = compat_ptr(from->si_lower);
> >               to->si_upper = compat_ptr(from->si_upper);
> >               break;
> >       case SIL_FAULT_PKUERR:
> > -             to->si_addr = compat_ptr(from->si_addr);
> > -#ifdef __ARCH_SI_TRAPNO
> > -             to->si_trapno = from->si_trapno;
> > -#endif
> >               to->si_pkey = from->si_pkey;
> >               break;
> >       case SIL_CHLD:

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

* Re: [PATCH v14 4/8] signal: deduplicate code dealing with common _sigfault fields
@ 2020-11-10  2:37       ` Peter Collingbourne
  0 siblings, 0 replies; 64+ messages in thread
From: Peter Collingbourne @ 2020-11-10  2:37 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, Richard Henderson

On Mon, Nov 9, 2020 at 4:41 PM Eric W. Biederman <ebiederm@xmission.com> wrote:
>
> Peter Collingbourne <pcc@google.com> writes:
>
> > We're about to add more common _sigfault fields, so deduplicate the
> > existing code for initializing _sigfault fields in {send,force}_sig_*,
> > and for copying _sigfault fields in copy_siginfo_to_external32 and
> > post_copy_siginfo_from_user32, to reduce the number of places that
> > will need to be updated by upcoming changes.
>
> Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>

Thanks for the review.

> No real objection but I am wondering if it might be better to
> introduce two small inline functions for setting common fields
> instead of:
>
> > +     if (siginfo_layout_is_fault(layout)) {
> > +             to->si_addr = ptr_to_compat(from->si_addr);
> > +#ifdef __ARCH_SI_TRAPNO
> > +             to->si_trapno = from->si_trapno;
> > +#endif
> > +     }
>
> and
>
> > +     if (siginfo_layout_is_fault(layout)) {
> > +             to->si_addr = compat_ptr(from->si_addr);
> > +#ifdef __ARCH_SI_TRAPNO
> > +             to->si_trapno = from->si_trapno;
> > +#endif
> > +     }
>
> perhaps called:
> copy_sigfault_common_to_external32
> post_copy_sigfault_common_from_user32
>
> I have not benchmarked or anything but my gut says one less conditional
> branch to worry about makes dealing with spectre easier and probably
> produces faster code as well.  Possibly even smaller code.

Dave made the same proposal on an earlier version of the patch which I
responded to in [1]. The main reason for keeping things as I
implemented them was because of the ptrace handling but if we do end
up dropping that as you proposed on the other patch then I think I'd
be happy to move the code into helper functions.

Peter

[1] https://lore.kernel.org/linux-parisc/CAMn1gO42arQKGBj1Nnbs86TGYyogpRR_t73H=GbTmQrbAbV30A@mail.gmail.com/

>
> Eric
>
> > Signed-off-by: Peter Collingbourne <pcc@google.com>
> > Link: https://linux-review.googlesource.com/id/I4f56174e1b7b2bf4a3c8139e6879cbfd52750a24
> > ---
> >  include/linux/signal.h |  13 ++++++
> >  kernel/signal.c        | 101 ++++++++++++++++-------------------------
> >  2 files changed, 53 insertions(+), 61 deletions(-)
> >
> > diff --git a/include/linux/signal.h b/include/linux/signal.h
> > index b256f9c65661..e9fb05041e7a 100644
> > --- a/include/linux/signal.h
> > +++ b/include/linux/signal.h
> > @@ -50,6 +50,19 @@ enum siginfo_layout {
> >
> >  enum siginfo_layout siginfo_layout(unsigned sig, int si_code);
> >
> > +static inline bool siginfo_layout_is_fault(enum siginfo_layout layout)
> > +{
> > +     switch (layout) {
> > +     case SIL_FAULT:
> > +     case SIL_FAULT_MCEERR:
> > +     case SIL_FAULT_BNDERR:
> > +     case SIL_FAULT_PKUERR:
> > +             return true;
> > +     default:
> > +             return false;
> > +     }
> > +}
> > +
> >  /*
> >   * Define some primitives to manipulate sigset_t.
> >   */
> > diff --git a/kernel/signal.c b/kernel/signal.c
> > index ef8f2a28d37c..74e7315c24db 100644
> > --- a/kernel/signal.c
> > +++ b/kernel/signal.c
> > @@ -1650,6 +1650,15 @@ void force_sigsegv(int sig)
> >       force_sig(SIGSEGV);
> >  }
> >
> > +static void set_sigfault_common_fields(struct kernel_siginfo *info, int sig,
> > +                                    int code, void __user *addr)
> > +{
> > +     info->si_signo = sig;
> > +     info->si_errno = 0;
> > +     info->si_code = code;
> > +     info->si_addr = addr;
> > +}
> > +
> >  int force_sig_fault_to_task(int sig, int code, void __user *addr
> >       ___ARCH_SI_TRAPNO(int trapno)
> >       ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
> > @@ -1658,10 +1667,7 @@ int force_sig_fault_to_task(int sig, int code, void __user *addr
> >       struct kernel_siginfo info;
> >
> >       clear_siginfo(&info);
> > -     info.si_signo = sig;
> > -     info.si_errno = 0;
> > -     info.si_code  = code;
> > -     info.si_addr  = addr;
> > +     set_sigfault_common_fields(&info, sig, code, addr);
> >  #ifdef __ARCH_SI_TRAPNO
> >       info.si_trapno = trapno;
> >  #endif
> > @@ -1690,10 +1696,7 @@ int send_sig_fault(int sig, int code, void __user *addr
> >       struct kernel_siginfo info;
> >
> >       clear_siginfo(&info);
> > -     info.si_signo = sig;
> > -     info.si_errno = 0;
> > -     info.si_code  = code;
> > -     info.si_addr  = addr;
> > +     set_sigfault_common_fields(&info, sig, code, addr);
> >  #ifdef __ARCH_SI_TRAPNO
> >       info.si_trapno = trapno;
> >  #endif
> > @@ -1711,10 +1714,7 @@ int force_sig_mceerr(int code, void __user *addr, short lsb)
> >
> >       WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
> >       clear_siginfo(&info);
> > -     info.si_signo = SIGBUS;
> > -     info.si_errno = 0;
> > -     info.si_code = code;
> > -     info.si_addr = addr;
> > +     set_sigfault_common_fields(&info, SIGBUS, code, addr);
> >       info.si_addr_lsb = lsb;
> >       return force_sig_info(&info);
> >  }
> > @@ -1725,10 +1725,7 @@ int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *
> >
> >       WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
> >       clear_siginfo(&info);
> > -     info.si_signo = SIGBUS;
> > -     info.si_errno = 0;
> > -     info.si_code = code;
> > -     info.si_addr = addr;
> > +     set_sigfault_common_fields(&info, SIGBUS, code, addr);
> >       info.si_addr_lsb = lsb;
> >       return send_sig_info(info.si_signo, &info, t);
> >  }
> > @@ -1739,10 +1736,7 @@ int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
> >       struct kernel_siginfo info;
> >
> >       clear_siginfo(&info);
> > -     info.si_signo = SIGSEGV;
> > -     info.si_errno = 0;
> > -     info.si_code  = SEGV_BNDERR;
> > -     info.si_addr  = addr;
> > +     set_sigfault_common_fields(&info, SIGSEGV, SEGV_BNDERR, addr);
> >       info.si_lower = lower;
> >       info.si_upper = upper;
> >       return force_sig_info(&info);
> > @@ -1754,10 +1748,7 @@ int force_sig_pkuerr(void __user *addr, u32 pkey)
> >       struct kernel_siginfo info;
> >
> >       clear_siginfo(&info);
> > -     info.si_signo = SIGSEGV;
> > -     info.si_errno = 0;
> > -     info.si_code  = SEGV_PKUERR;
> > -     info.si_addr  = addr;
> > +     set_sigfault_common_fields(&info, SIGSEGV, SEGV_PKUERR, addr);
> >       info.si_pkey  = pkey;
> >       return force_sig_info(&info);
> >  }
> > @@ -1771,10 +1762,8 @@ int force_sig_ptrace_errno_trap(int errno, void __user *addr)
> >       struct kernel_siginfo info;
> >
> >       clear_siginfo(&info);
> > -     info.si_signo = SIGTRAP;
> > +     set_sigfault_common_fields(&info, SIGTRAP, TRAP_HWBKPT, addr);
> >       info.si_errno = errno;
> > -     info.si_code  = TRAP_HWBKPT;
> > -     info.si_addr  = addr;
> >       return force_sig_info(&info);
> >  }
> >
> > @@ -3267,12 +3256,23 @@ int copy_siginfo_from_user(kernel_siginfo_t *to, const siginfo_t __user *from)
> >  void copy_siginfo_to_external32(struct compat_siginfo *to,
> >               const struct kernel_siginfo *from)
> >  {
> > +     enum siginfo_layout layout =
> > +             siginfo_layout(from->si_signo, from->si_code);
> > +
> >       memset(to, 0, sizeof(*to));
> >
> >       to->si_signo = from->si_signo;
> >       to->si_errno = from->si_errno;
> >       to->si_code  = from->si_code;
> > -     switch(siginfo_layout(from->si_signo, from->si_code)) {
> > +
> > +     if (siginfo_layout_is_fault(layout)) {
> > +             to->si_addr = ptr_to_compat(from->si_addr);
> > +#ifdef __ARCH_SI_TRAPNO
> > +             to->si_trapno = from->si_trapno;
> > +#endif
> > +     }
> > +
> > +     switch (layout) {
> >       case SIL_KILL:
> >               to->si_pid = from->si_pid;
> >               to->si_uid = from->si_uid;
> > @@ -3287,31 +3287,15 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
> >               to->si_fd   = from->si_fd;
> >               break;
> >       case SIL_FAULT:
> > -             to->si_addr = ptr_to_compat(from->si_addr);
> > -#ifdef __ARCH_SI_TRAPNO
> > -             to->si_trapno = from->si_trapno;
> > -#endif
> >               break;
> >       case SIL_FAULT_MCEERR:
> > -             to->si_addr = ptr_to_compat(from->si_addr);
> > -#ifdef __ARCH_SI_TRAPNO
> > -             to->si_trapno = from->si_trapno;
> > -#endif
> >               to->si_addr_lsb = from->si_addr_lsb;
> >               break;
> >       case SIL_FAULT_BNDERR:
> > -             to->si_addr = ptr_to_compat(from->si_addr);
> > -#ifdef __ARCH_SI_TRAPNO
> > -             to->si_trapno = from->si_trapno;
> > -#endif
> >               to->si_lower = ptr_to_compat(from->si_lower);
> >               to->si_upper = ptr_to_compat(from->si_upper);
> >               break;
> >       case SIL_FAULT_PKUERR:
> > -             to->si_addr = ptr_to_compat(from->si_addr);
> > -#ifdef __ARCH_SI_TRAPNO
> > -             to->si_trapno = from->si_trapno;
> > -#endif
> >               to->si_pkey = from->si_pkey;
> >               break;
> >       case SIL_CHLD:
> > @@ -3348,11 +3332,22 @@ int __copy_siginfo_to_user32(struct compat_siginfo __user *to,
> >  static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> >                                        const struct compat_siginfo *from)
> >  {
> > +     enum siginfo_layout layout =
> > +             siginfo_layout(from->si_signo, from->si_code);
> > +
> >       clear_siginfo(to);
> >       to->si_signo = from->si_signo;
> >       to->si_errno = from->si_errno;
> >       to->si_code  = from->si_code;
> > -     switch(siginfo_layout(from->si_signo, from->si_code)) {
> > +
> > +     if (siginfo_layout_is_fault(layout)) {
> > +             to->si_addr = compat_ptr(from->si_addr);
> > +#ifdef __ARCH_SI_TRAPNO
> > +             to->si_trapno = from->si_trapno;
> > +#endif
> > +     }
> > +
> > +     switch (layout) {
> >       case SIL_KILL:
> >               to->si_pid = from->si_pid;
> >               to->si_uid = from->si_uid;
> > @@ -3367,31 +3362,15 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
> >               to->si_fd   = from->si_fd;
> >               break;
> >       case SIL_FAULT:
> > -             to->si_addr = compat_ptr(from->si_addr);
> > -#ifdef __ARCH_SI_TRAPNO
> > -             to->si_trapno = from->si_trapno;
> > -#endif
> >               break;
> >       case SIL_FAULT_MCEERR:
> > -             to->si_addr = compat_ptr(from->si_addr);
> > -#ifdef __ARCH_SI_TRAPNO
> > -             to->si_trapno = from->si_trapno;
> > -#endif
> >               to->si_addr_lsb = from->si_addr_lsb;
> >               break;
> >       case SIL_FAULT_BNDERR:
> > -             to->si_addr = compat_ptr(from->si_addr);
> > -#ifdef __ARCH_SI_TRAPNO
> > -             to->si_trapno = from->si_trapno;
> > -#endif
> >               to->si_lower = compat_ptr(from->si_lower);
> >               to->si_upper = compat_ptr(from->si_upper);
> >               break;
> >       case SIL_FAULT_PKUERR:
> > -             to->si_addr = compat_ptr(from->si_addr);
> > -#ifdef __ARCH_SI_TRAPNO
> > -             to->si_trapno = from->si_trapno;
> > -#endif
> >               to->si_pkey = from->si_pkey;
> >               break;
> >       case SIL_CHLD:

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

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

On Mon, Nov 9, 2020 at 5:13 PM Eric W. Biederman <ebiederm@xmission.com> 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, create a new pair of
> > fields in siginfo._sigfault, and store the tag bits of FAR_EL1 there,
> > together with a mask specifying which bits are valid.
> >
> > A flag is added to si_faultflags to allow userspace to determine whether
> > the values in the fields are valid.
>
> I think I am missing some things:
>
> Today it is documented that the tag bits are cleared, and so we can't
> use the highbits to hold the tag bits by default.
>
> Why do you need to deliver which tag bits are valid?  That feels like an
> implementation detail that is needed to setup the tag bits.  It feels
> like it would be constant per process.  So I don't understand why the
> siginfo needs to report information the process should already have.

It isn't constant as it may vary depending on the specific type of
fault being delivered. For example on arm64 the architecture only
provides us with bits 56-59 of the tag for tag check faults, while all
other data aborts also provide bits 60-63. Now although the user
program may distinguish the two cases by checking the si_code, we
would also like to allow future architecture extensions to provide
bits 60-63 for tag check faults as well and allow distinguishing
between "bits 60-63 were zero" and "bits 60-63 were unknown" (which is
important when providing error reports).

I suppose that you could imagine that, if the "bits 60-63 available"
extension ever comes to pass, it could be exposed via a bit in
getauxval(AT_HWCAP2) (or maybe something like AT_HWCAP3 depending on
how long it takes to arrive) and that would provide a way for
userspace to know which bits are valid. But it seems like allowing
this to vary per signal is relatively cheap, allows the information to
be made available trivially architecture independently and keeps our
options open for the future (because we don't know if some future
architecture will actually make this a per-signal attribute).

That being said, maybe we could solve this problem at the point at
which we do encounter such an architecture though.

> Want prevents adding a sigaction sa_flag SA_EXPOSE_TABITS that when set
> causes the high bits to be set, and when clear (the default) will have
> the signal delivery code clear those bits.
>
> That should be enough for code that wants the tag bits to ask for them.
> As userspace would need to be updated to get the new bits
>
> Even if you have chained handlers.  The chaining mechanism would need to
> be updated and it could call the aware handlers first then clear the tag
> bits and call the rest of the handlers.
>
> It feels like always passing the tag bits in the address and then
> clearing them in the copy to userspace if the signal handler is
> not ready for them would be easier to maintain.

I think that approach might work. Although it may make life harder for
callers of ptrace(PTRACE_SETSIGINFO) since they may need to know the
value of the bit in order to prepare a correct siginfo structure, if
we can reasonably expect them to always be delivering an exact copy of
a signal that was received before then maybe that is okay.

Assuming that this is an alternative to introducing
si_addr_tag_bits_mask, the userspace code would need to use the flag
bit support detection protocol for SA_EXPOSE_TAGBITS in order to be
able to distinguish between "no bits valid" and "some bits valid", and
then use an architecture-specific mechanism to determine exactly which
bits are valid. Is that okay for a generic feature?

Peter

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

* Re: [PATCH v14 8/8] arm64: expose FAR_EL1 tag bits in siginfo
@ 2020-11-10  3:49       ` Peter Collingbourne
  0 siblings, 0 replies; 64+ messages in thread
From: Peter Collingbourne @ 2020-11-10  3:49 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, Richard Henderson

On Mon, Nov 9, 2020 at 5:13 PM Eric W. Biederman <ebiederm@xmission.com> 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, create a new pair of
> > fields in siginfo._sigfault, and store the tag bits of FAR_EL1 there,
> > together with a mask specifying which bits are valid.
> >
> > A flag is added to si_faultflags to allow userspace to determine whether
> > the values in the fields are valid.
>
> I think I am missing some things:
>
> Today it is documented that the tag bits are cleared, and so we can't
> use the highbits to hold the tag bits by default.
>
> Why do you need to deliver which tag bits are valid?  That feels like an
> implementation detail that is needed to setup the tag bits.  It feels
> like it would be constant per process.  So I don't understand why the
> siginfo needs to report information the process should already have.

It isn't constant as it may vary depending on the specific type of
fault being delivered. For example on arm64 the architecture only
provides us with bits 56-59 of the tag for tag check faults, while all
other data aborts also provide bits 60-63. Now although the user
program may distinguish the two cases by checking the si_code, we
would also like to allow future architecture extensions to provide
bits 60-63 for tag check faults as well and allow distinguishing
between "bits 60-63 were zero" and "bits 60-63 were unknown" (which is
important when providing error reports).

I suppose that you could imagine that, if the "bits 60-63 available"
extension ever comes to pass, it could be exposed via a bit in
getauxval(AT_HWCAP2) (or maybe something like AT_HWCAP3 depending on
how long it takes to arrive) and that would provide a way for
userspace to know which bits are valid. But it seems like allowing
this to vary per signal is relatively cheap, allows the information to
be made available trivially architecture independently and keeps our
options open for the future (because we don't know if some future
architecture will actually make this a per-signal attribute).

That being said, maybe we could solve this problem at the point at
which we do encounter such an architecture though.

> Want prevents adding a sigaction sa_flag SA_EXPOSE_TABITS that when set
> causes the high bits to be set, and when clear (the default) will have
> the signal delivery code clear those bits.
>
> That should be enough for code that wants the tag bits to ask for them.
> As userspace would need to be updated to get the new bits
>
> Even if you have chained handlers.  The chaining mechanism would need to
> be updated and it could call the aware handlers first then clear the tag
> bits and call the rest of the handlers.
>
> It feels like always passing the tag bits in the address and then
> clearing them in the copy to userspace if the signal handler is
> not ready for them would be easier to maintain.

I think that approach might work. Although it may make life harder for
callers of ptrace(PTRACE_SETSIGINFO) since they may need to know the
value of the bit in order to prepare a correct siginfo structure, if
we can reasonably expect them to always be delivering an exact copy of
a signal that was received before then maybe that is okay.

Assuming that this is an alternative to introducing
si_addr_tag_bits_mask, the userspace code would need to use the flag
bit support detection protocol for SA_EXPOSE_TAGBITS in order to be
able to distinguish between "no bits valid" and "some bits valid", and
then use an architecture-specific mechanism to determine exactly which
bits are valid. Is that okay for a generic feature?

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

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

Peter Collingbourne <pcc@google.com> writes:

> On Mon, Nov 9, 2020 at 5:13 PM Eric W. Biederman <ebiederm@xmission.com> 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, create a new pair of
>> > fields in siginfo._sigfault, and store the tag bits of FAR_EL1 there,
>> > together with a mask specifying which bits are valid.
>> >
>> > A flag is added to si_faultflags to allow userspace to determine whether
>> > the values in the fields are valid.
>>
>> I think I am missing some things:
>>
>> Today it is documented that the tag bits are cleared, and so we can't
>> use the highbits to hold the tag bits by default.
>>
>> Why do you need to deliver which tag bits are valid?  That feels like an
>> implementation detail that is needed to setup the tag bits.  It feels
>> like it would be constant per process.  So I don't understand why the
>> siginfo needs to report information the process should already have.
>
> It isn't constant as it may vary depending on the specific type of
> fault being delivered. For example on arm64 the architecture only
> provides us with bits 56-59 of the tag for tag check faults, while all
> other data aborts also provide bits 60-63. Now although the user
> program may distinguish the two cases by checking the si_code, we
> would also like to allow future architecture extensions to provide
> bits 60-63 for tag check faults as well and allow distinguishing
> between "bits 60-63 were zero" and "bits 60-63 were unknown" (which is
> important when providing error reports).

Does that mean that bits 60-63 are effectively unusable as tag bits
if the tag check fault won't report them?

If you can use bits 60-63 as tag bits how does that work if they aren't
reported?

> I suppose that you could imagine that, if the "bits 60-63 available"
> extension ever comes to pass, it could be exposed via a bit in
> getauxval(AT_HWCAP2) (or maybe something like AT_HWCAP3 depending on
> how long it takes to arrive) and that would provide a way for
> userspace to know which bits are valid. But it seems like allowing
> this to vary per signal is relatively cheap, allows the information to
> be made available trivially architecture independently and keeps our
> options open for the future (because we don't know if some future
> architecture will actually make this a per-signal attribute).
>
> That being said, maybe we could solve this problem at the point at
> which we do encounter such an architecture though.

My goal would be to extend things to the minimum extent necessary to
handle today's reality well.  Usually architectures evolve in
unanticipated directions so simple and straight forward usually wins for
handling future evolution.  As there is simply less old baggage to carry
around.

However I don't understand if reporting the valid bits on a signal by
signal basis has a real advantage today or not.  If it helps today we
will find room for the field.


>> Want prevents adding a sigaction sa_flag SA_EXPOSE_TABITS that when set
>> causes the high bits to be set, and when clear (the default) will have
>> the signal delivery code clear those bits.
>>
>> That should be enough for code that wants the tag bits to ask for them.
>> As userspace would need to be updated to get the new bits
>>
>> Even if you have chained handlers.  The chaining mechanism would need to
>> be updated and it could call the aware handlers first then clear the tag
>> bits and call the rest of the handlers.
>>
>> It feels like always passing the tag bits in the address and then
>> clearing them in the copy to userspace if the signal handler is
>> not ready for them would be easier to maintain.
>
> I think that approach might work. Although it may make life harder for
> callers of ptrace(PTRACE_SETSIGINFO) since they may need to know the
> value of the bit in order to prepare a correct siginfo structure, if
> we can reasonably expect them to always be delivering an exact copy of
> a signal that was received before then maybe that is okay.

I think we can reasonably expect callers of PTRACE_SETSIGINFO to be able
to either deal the full reality of what is going on, or to only generate
signals that they fully understand.

Other than the use by CRIU it is a debugging facility and it is not
expected for ordinary usage.  The non-CRIU use case would really seem to
be what happens if I inject arbitrary signal X into process Y.  For that
you need the ability to inject an arbitrary signal.

My real sense with PTRACE_SETSIGINFO is that if we wind up with a
regression we can deal with it then.

> Assuming that this is an alternative to introducing
> si_addr_tag_bits_mask, the userspace code would need to use the flag
> bit support detection protocol for SA_EXPOSE_TAGBITS in order to be
> able to distinguish between "no bits valid" and "some bits valid", and
> then use an architecture-specific mechanism to determine exactly which
> bits are valid. Is that okay for a generic feature?

Unless I am mistaken setting the bits is already architecture specific
so having some architecture specific code in there should not be a big
problem.

But I really don't understand the arm case well enough to know if we can
get away without si_addr_tag_bits_mask, and in turn without the flags
field that indicates the si_addr_tag_bits_mask is present.

So I am asking questions so I can understand just what we get from
si_addr_tag_bits_mask.

Eric

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

* Re: [PATCH v14 8/8] arm64: expose FAR_EL1 tag bits in siginfo
@ 2020-11-10 15:12         ` Eric W. Biederman
  0 siblings, 0 replies; 64+ messages in thread
From: Eric W. Biederman @ 2020-11-10 15:12 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, Richard Henderson

Peter Collingbourne <pcc@google.com> writes:

> On Mon, Nov 9, 2020 at 5:13 PM Eric W. Biederman <ebiederm@xmission.com> 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, create a new pair of
>> > fields in siginfo._sigfault, and store the tag bits of FAR_EL1 there,
>> > together with a mask specifying which bits are valid.
>> >
>> > A flag is added to si_faultflags to allow userspace to determine whether
>> > the values in the fields are valid.
>>
>> I think I am missing some things:
>>
>> Today it is documented that the tag bits are cleared, and so we can't
>> use the highbits to hold the tag bits by default.
>>
>> Why do you need to deliver which tag bits are valid?  That feels like an
>> implementation detail that is needed to setup the tag bits.  It feels
>> like it would be constant per process.  So I don't understand why the
>> siginfo needs to report information the process should already have.
>
> It isn't constant as it may vary depending on the specific type of
> fault being delivered. For example on arm64 the architecture only
> provides us with bits 56-59 of the tag for tag check faults, while all
> other data aborts also provide bits 60-63. Now although the user
> program may distinguish the two cases by checking the si_code, we
> would also like to allow future architecture extensions to provide
> bits 60-63 for tag check faults as well and allow distinguishing
> between "bits 60-63 were zero" and "bits 60-63 were unknown" (which is
> important when providing error reports).

Does that mean that bits 60-63 are effectively unusable as tag bits
if the tag check fault won't report them?

If you can use bits 60-63 as tag bits how does that work if they aren't
reported?

> I suppose that you could imagine that, if the "bits 60-63 available"
> extension ever comes to pass, it could be exposed via a bit in
> getauxval(AT_HWCAP2) (or maybe something like AT_HWCAP3 depending on
> how long it takes to arrive) and that would provide a way for
> userspace to know which bits are valid. But it seems like allowing
> this to vary per signal is relatively cheap, allows the information to
> be made available trivially architecture independently and keeps our
> options open for the future (because we don't know if some future
> architecture will actually make this a per-signal attribute).
>
> That being said, maybe we could solve this problem at the point at
> which we do encounter such an architecture though.

My goal would be to extend things to the minimum extent necessary to
handle today's reality well.  Usually architectures evolve in
unanticipated directions so simple and straight forward usually wins for
handling future evolution.  As there is simply less old baggage to carry
around.

However I don't understand if reporting the valid bits on a signal by
signal basis has a real advantage today or not.  If it helps today we
will find room for the field.


>> Want prevents adding a sigaction sa_flag SA_EXPOSE_TABITS that when set
>> causes the high bits to be set, and when clear (the default) will have
>> the signal delivery code clear those bits.
>>
>> That should be enough for code that wants the tag bits to ask for them.
>> As userspace would need to be updated to get the new bits
>>
>> Even if you have chained handlers.  The chaining mechanism would need to
>> be updated and it could call the aware handlers first then clear the tag
>> bits and call the rest of the handlers.
>>
>> It feels like always passing the tag bits in the address and then
>> clearing them in the copy to userspace if the signal handler is
>> not ready for them would be easier to maintain.
>
> I think that approach might work. Although it may make life harder for
> callers of ptrace(PTRACE_SETSIGINFO) since they may need to know the
> value of the bit in order to prepare a correct siginfo structure, if
> we can reasonably expect them to always be delivering an exact copy of
> a signal that was received before then maybe that is okay.

I think we can reasonably expect callers of PTRACE_SETSIGINFO to be able
to either deal the full reality of what is going on, or to only generate
signals that they fully understand.

Other than the use by CRIU it is a debugging facility and it is not
expected for ordinary usage.  The non-CRIU use case would really seem to
be what happens if I inject arbitrary signal X into process Y.  For that
you need the ability to inject an arbitrary signal.

My real sense with PTRACE_SETSIGINFO is that if we wind up with a
regression we can deal with it then.

> Assuming that this is an alternative to introducing
> si_addr_tag_bits_mask, the userspace code would need to use the flag
> bit support detection protocol for SA_EXPOSE_TAGBITS in order to be
> able to distinguish between "no bits valid" and "some bits valid", and
> then use an architecture-specific mechanism to determine exactly which
> bits are valid. Is that okay for a generic feature?

Unless I am mistaken setting the bits is already architecture specific
so having some architecture specific code in there should not be a big
problem.

But I really don't understand the arm case well enough to know if we can
get away without si_addr_tag_bits_mask, and in turn without the flags
field that indicates the si_addr_tag_bits_mask is present.

So I am asking questions so I can understand just what we get from
si_addr_tag_bits_mask.

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

* Re: [PATCH v14 4/8] signal: deduplicate code dealing with common _sigfault fields
  2020-11-10  2:37       ` Peter Collingbourne
@ 2020-11-10 15:38         ` Eric W. Biederman
  -1 siblings, 0 replies; 64+ messages in thread
From: Eric W. Biederman @ 2020-11-10 15:38 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	James E.J. Bottomley, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, Linux API, Helge Deller, David Spickett

Peter Collingbourne <pcc@google.com> writes:

> On Mon, Nov 9, 2020 at 4:41 PM Eric W. Biederman <ebiederm@xmission.com> wrote:
>>
>> Peter Collingbourne <pcc@google.com> writes:
>>
>> > We're about to add more common _sigfault fields, so deduplicate the
>> > existing code for initializing _sigfault fields in {send,force}_sig_*,
>> > and for copying _sigfault fields in copy_siginfo_to_external32 and
>> > post_copy_siginfo_from_user32, to reduce the number of places that
>> > will need to be updated by upcoming changes.
>>
>> Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>
>
> Thanks for the review.
>
>> No real objection but I am wondering if it might be better to
>> introduce two small inline functions for setting common fields
>> instead of:
>>
>> > +     if (siginfo_layout_is_fault(layout)) {
>> > +             to->si_addr = ptr_to_compat(from->si_addr);
>> > +#ifdef __ARCH_SI_TRAPNO
>> > +             to->si_trapno = from->si_trapno;
>> > +#endif
>> > +     }
>>
>> and
>>
>> > +     if (siginfo_layout_is_fault(layout)) {
>> > +             to->si_addr = compat_ptr(from->si_addr);
>> > +#ifdef __ARCH_SI_TRAPNO
>> > +             to->si_trapno = from->si_trapno;
>> > +#endif
>> > +     }
>>
>> perhaps called:
>> copy_sigfault_common_to_external32
>> post_copy_sigfault_common_from_user32
>>
>> I have not benchmarked or anything but my gut says one less conditional
>> branch to worry about makes dealing with spectre easier and probably
>> produces faster code as well.  Possibly even smaller code.
>
> Dave made the same proposal on an earlier version of the patch which I
> responded to in [1]. The main reason for keeping things as I
> implemented them was because of the ptrace handling but if we do end
> up dropping that as you proposed on the other patch then I think I'd
> be happy to move the code into helper functions.
>
> Peter
>
> [1] https://lore.kernel.org/linux-parisc/CAMn1gO42arQKGBj1Nnbs86TGYyogpRR_t73H=GbTmQrbAbV30A@mail.gmail.com/

That makes sense.

Eric

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

* Re: [PATCH v14 4/8] signal: deduplicate code dealing with common _sigfault fields
@ 2020-11-10 15:38         ` Eric W. Biederman
  0 siblings, 0 replies; 64+ messages in thread
From: Eric W. Biederman @ 2020-11-10 15:38 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, Richard Henderson

Peter Collingbourne <pcc@google.com> writes:

> On Mon, Nov 9, 2020 at 4:41 PM Eric W. Biederman <ebiederm@xmission.com> wrote:
>>
>> Peter Collingbourne <pcc@google.com> writes:
>>
>> > We're about to add more common _sigfault fields, so deduplicate the
>> > existing code for initializing _sigfault fields in {send,force}_sig_*,
>> > and for copying _sigfault fields in copy_siginfo_to_external32 and
>> > post_copy_siginfo_from_user32, to reduce the number of places that
>> > will need to be updated by upcoming changes.
>>
>> Acked-by: "Eric W. Biederman" <ebiederm@xmission.com>
>
> Thanks for the review.
>
>> No real objection but I am wondering if it might be better to
>> introduce two small inline functions for setting common fields
>> instead of:
>>
>> > +     if (siginfo_layout_is_fault(layout)) {
>> > +             to->si_addr = ptr_to_compat(from->si_addr);
>> > +#ifdef __ARCH_SI_TRAPNO
>> > +             to->si_trapno = from->si_trapno;
>> > +#endif
>> > +     }
>>
>> and
>>
>> > +     if (siginfo_layout_is_fault(layout)) {
>> > +             to->si_addr = compat_ptr(from->si_addr);
>> > +#ifdef __ARCH_SI_TRAPNO
>> > +             to->si_trapno = from->si_trapno;
>> > +#endif
>> > +     }
>>
>> perhaps called:
>> copy_sigfault_common_to_external32
>> post_copy_sigfault_common_from_user32
>>
>> I have not benchmarked or anything but my gut says one less conditional
>> branch to worry about makes dealing with spectre easier and probably
>> produces faster code as well.  Possibly even smaller code.
>
> Dave made the same proposal on an earlier version of the patch which I
> responded to in [1]. The main reason for keeping things as I
> implemented them was because of the ptrace handling but if we do end
> up dropping that as you proposed on the other patch then I think I'd
> be happy to move the code into helper functions.
>
> Peter
>
> [1] https://lore.kernel.org/linux-parisc/CAMn1gO42arQKGBj1Nnbs86TGYyogpRR_t73H=GbTmQrbAbV30A@mail.gmail.com/

That makes sense.

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

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

On Tue, Nov 10, 2020 at 7:12 AM Eric W. Biederman <ebiederm@xmission.com> wrote:
>
> Peter Collingbourne <pcc@google.com> writes:
>
> > On Mon, Nov 9, 2020 at 5:13 PM Eric W. Biederman <ebiederm@xmission.com> 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, create a new pair of
> >> > fields in siginfo._sigfault, and store the tag bits of FAR_EL1 there,
> >> > together with a mask specifying which bits are valid.
> >> >
> >> > A flag is added to si_faultflags to allow userspace to determine whether
> >> > the values in the fields are valid.
> >>
> >> I think I am missing some things:
> >>
> >> Today it is documented that the tag bits are cleared, and so we can't
> >> use the highbits to hold the tag bits by default.
> >>
> >> Why do you need to deliver which tag bits are valid?  That feels like an
> >> implementation detail that is needed to setup the tag bits.  It feels
> >> like it would be constant per process.  So I don't understand why the
> >> siginfo needs to report information the process should already have.
> >
> > It isn't constant as it may vary depending on the specific type of
> > fault being delivered. For example on arm64 the architecture only
> > provides us with bits 56-59 of the tag for tag check faults, while all
> > other data aborts also provide bits 60-63. Now although the user
> > program may distinguish the two cases by checking the si_code, we
> > would also like to allow future architecture extensions to provide
> > bits 60-63 for tag check faults as well and allow distinguishing
> > between "bits 60-63 were zero" and "bits 60-63 were unknown" (which is
> > important when providing error reports).
>
> Does that mean that bits 60-63 are effectively unusable as tag bits
> if the tag check fault won't report them?

The hardware doesn't support tag checking on bits 60-63, only on bits
56-59, so in terms of hardware enforced memory tag checking they can't
be used as tag bits. But they are still subject to address tagging aka
top-byte-ignore so they could be used by userspace for other purposes
(e.g. if the allocator adds entropy to all 8 bits instead of just bits
56-59 they could in theory be used to allow better diagnostics with
more precise matching of an invalid access to a previous allocation).

> If you can use bits 60-63 as tag bits how does that work if they aren't
> reported?

It still works but we're limited in how many allocations we can match
accesses to (16 vs 256).

> > I suppose that you could imagine that, if the "bits 60-63 available"
> > extension ever comes to pass, it could be exposed via a bit in
> > getauxval(AT_HWCAP2) (or maybe something like AT_HWCAP3 depending on
> > how long it takes to arrive) and that would provide a way for
> > userspace to know which bits are valid. But it seems like allowing
> > this to vary per signal is relatively cheap, allows the information to
> > be made available trivially architecture independently and keeps our
> > options open for the future (because we don't know if some future
> > architecture will actually make this a per-signal attribute).
> >
> > That being said, maybe we could solve this problem at the point at
> > which we do encounter such an architecture though.
>
> My goal would be to extend things to the minimum extent necessary to
> handle today's reality well.  Usually architectures evolve in
> unanticipated directions so simple and straight forward usually wins for
> handling future evolution.  As there is simply less old baggage to carry
> around.
>
> However I don't understand if reporting the valid bits on a signal by
> signal basis has a real advantage today or not.  If it helps today we
> will find room for the field.

Okay, that makes sense. With the architecture as specified today I
don't think we would need it, since you can write a function that
operates on the siginfo and tells you what the si_addr_tag_bits_mask
would be without it.

> >> Want prevents adding a sigaction sa_flag SA_EXPOSE_TABITS that when set
> >> causes the high bits to be set, and when clear (the default) will have
> >> the signal delivery code clear those bits.
> >>
> >> That should be enough for code that wants the tag bits to ask for them.
> >> As userspace would need to be updated to get the new bits
> >>
> >> Even if you have chained handlers.  The chaining mechanism would need to
> >> be updated and it could call the aware handlers first then clear the tag
> >> bits and call the rest of the handlers.
> >>
> >> It feels like always passing the tag bits in the address and then
> >> clearing them in the copy to userspace if the signal handler is
> >> not ready for them would be easier to maintain.
> >
> > I think that approach might work. Although it may make life harder for
> > callers of ptrace(PTRACE_SETSIGINFO) since they may need to know the
> > value of the bit in order to prepare a correct siginfo structure, if
> > we can reasonably expect them to always be delivering an exact copy of
> > a signal that was received before then maybe that is okay.
>
> I think we can reasonably expect callers of PTRACE_SETSIGINFO to be able
> to either deal the full reality of what is going on, or to only generate
> signals that they fully understand.
>
> Other than the use by CRIU it is a debugging facility and it is not
> expected for ordinary usage.  The non-CRIU use case would really seem to
> be what happens if I inject arbitrary signal X into process Y.  For that
> you need the ability to inject an arbitrary signal.
>
> My real sense with PTRACE_SETSIGINFO is that if we wind up with a
> regression we can deal with it then.

Okay, that works for me.

> > Assuming that this is an alternative to introducing
> > si_addr_tag_bits_mask, the userspace code would need to use the flag
> > bit support detection protocol for SA_EXPOSE_TAGBITS in order to be
> > able to distinguish between "no bits valid" and "some bits valid", and
> > then use an architecture-specific mechanism to determine exactly which
> > bits are valid. Is that okay for a generic feature?
>
> Unless I am mistaken setting the bits is already architecture specific
> so having some architecture specific code in there should not be a big
> problem.
>
> But I really don't understand the arm case well enough to know if we can
> get away without si_addr_tag_bits_mask, and in turn without the flags
> field that indicates the si_addr_tag_bits_mask is present.
>
> So I am asking questions so I can understand just what we get from
> si_addr_tag_bits_mask.

If we allow the derivation of the mask to be architecture-specific
(which I'd be comfortable with) then I don't think we need it. What we
would end up with is:

- The tag bits mask is constant and architecturally defined (in
arm64's case it would be 0xff << 56).
- The valid tag bits mask specifies which bits of the tag bits mask in
the fault address are propagated to si_addr. It is defined in an
architecture-specific way based on the signal handler's
SA_EXPOSE_TAGBITS bit, the contents of siginfo and possibly global
information such as getauxval(AT_HWCAP*).
  - on arm64 this would currently be defined as:
    - if SA_EXPOSE_TAGBITS is not set then the mask is 0xff << 56 for
SIGTRAP/TRAP_BRKPT, 0 otherwise
    - if SA_EXPOSE_TAGBITS is set then the mask is 0xf << 56 for
SIGSEGV/SEGV_MTESERR, 0xff << 56 otherwise
- If SA_EXPOSE_TAGBITS is set then the bits in the tag bits mask that
are not also in the valid tag bits mask have an undefined value (this
would e.g. allow future expansion of arm64 to expose bits 60-63 on tag
check faults).
- If the kernel does not support SA_EXPOSE_TAGBITS (as determined
using the flag bit support detection protocol) then the behavior is as
if SA_EXPOSE_TAGBITS is not set.

So I think I'd be fine with dropping it but let me experiment with the
new approach so that I can confirm that it's practical on Android and
I'll get back to you.

Peter

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

* Re: [PATCH v14 8/8] arm64: expose FAR_EL1 tag bits in siginfo
@ 2020-11-10 22:06           ` Peter Collingbourne
  0 siblings, 0 replies; 64+ messages in thread
From: Peter Collingbourne @ 2020-11-10 22:06 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, Richard Henderson

On Tue, Nov 10, 2020 at 7:12 AM Eric W. Biederman <ebiederm@xmission.com> wrote:
>
> Peter Collingbourne <pcc@google.com> writes:
>
> > On Mon, Nov 9, 2020 at 5:13 PM Eric W. Biederman <ebiederm@xmission.com> 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, create a new pair of
> >> > fields in siginfo._sigfault, and store the tag bits of FAR_EL1 there,
> >> > together with a mask specifying which bits are valid.
> >> >
> >> > A flag is added to si_faultflags to allow userspace to determine whether
> >> > the values in the fields are valid.
> >>
> >> I think I am missing some things:
> >>
> >> Today it is documented that the tag bits are cleared, and so we can't
> >> use the highbits to hold the tag bits by default.
> >>
> >> Why do you need to deliver which tag bits are valid?  That feels like an
> >> implementation detail that is needed to setup the tag bits.  It feels
> >> like it would be constant per process.  So I don't understand why the
> >> siginfo needs to report information the process should already have.
> >
> > It isn't constant as it may vary depending on the specific type of
> > fault being delivered. For example on arm64 the architecture only
> > provides us with bits 56-59 of the tag for tag check faults, while all
> > other data aborts also provide bits 60-63. Now although the user
> > program may distinguish the two cases by checking the si_code, we
> > would also like to allow future architecture extensions to provide
> > bits 60-63 for tag check faults as well and allow distinguishing
> > between "bits 60-63 were zero" and "bits 60-63 were unknown" (which is
> > important when providing error reports).
>
> Does that mean that bits 60-63 are effectively unusable as tag bits
> if the tag check fault won't report them?

The hardware doesn't support tag checking on bits 60-63, only on bits
56-59, so in terms of hardware enforced memory tag checking they can't
be used as tag bits. But they are still subject to address tagging aka
top-byte-ignore so they could be used by userspace for other purposes
(e.g. if the allocator adds entropy to all 8 bits instead of just bits
56-59 they could in theory be used to allow better diagnostics with
more precise matching of an invalid access to a previous allocation).

> If you can use bits 60-63 as tag bits how does that work if they aren't
> reported?

It still works but we're limited in how many allocations we can match
accesses to (16 vs 256).

> > I suppose that you could imagine that, if the "bits 60-63 available"
> > extension ever comes to pass, it could be exposed via a bit in
> > getauxval(AT_HWCAP2) (or maybe something like AT_HWCAP3 depending on
> > how long it takes to arrive) and that would provide a way for
> > userspace to know which bits are valid. But it seems like allowing
> > this to vary per signal is relatively cheap, allows the information to
> > be made available trivially architecture independently and keeps our
> > options open for the future (because we don't know if some future
> > architecture will actually make this a per-signal attribute).
> >
> > That being said, maybe we could solve this problem at the point at
> > which we do encounter such an architecture though.
>
> My goal would be to extend things to the minimum extent necessary to
> handle today's reality well.  Usually architectures evolve in
> unanticipated directions so simple and straight forward usually wins for
> handling future evolution.  As there is simply less old baggage to carry
> around.
>
> However I don't understand if reporting the valid bits on a signal by
> signal basis has a real advantage today or not.  If it helps today we
> will find room for the field.

Okay, that makes sense. With the architecture as specified today I
don't think we would need it, since you can write a function that
operates on the siginfo and tells you what the si_addr_tag_bits_mask
would be without it.

> >> Want prevents adding a sigaction sa_flag SA_EXPOSE_TABITS that when set
> >> causes the high bits to be set, and when clear (the default) will have
> >> the signal delivery code clear those bits.
> >>
> >> That should be enough for code that wants the tag bits to ask for them.
> >> As userspace would need to be updated to get the new bits
> >>
> >> Even if you have chained handlers.  The chaining mechanism would need to
> >> be updated and it could call the aware handlers first then clear the tag
> >> bits and call the rest of the handlers.
> >>
> >> It feels like always passing the tag bits in the address and then
> >> clearing them in the copy to userspace if the signal handler is
> >> not ready for them would be easier to maintain.
> >
> > I think that approach might work. Although it may make life harder for
> > callers of ptrace(PTRACE_SETSIGINFO) since they may need to know the
> > value of the bit in order to prepare a correct siginfo structure, if
> > we can reasonably expect them to always be delivering an exact copy of
> > a signal that was received before then maybe that is okay.
>
> I think we can reasonably expect callers of PTRACE_SETSIGINFO to be able
> to either deal the full reality of what is going on, or to only generate
> signals that they fully understand.
>
> Other than the use by CRIU it is a debugging facility and it is not
> expected for ordinary usage.  The non-CRIU use case would really seem to
> be what happens if I inject arbitrary signal X into process Y.  For that
> you need the ability to inject an arbitrary signal.
>
> My real sense with PTRACE_SETSIGINFO is that if we wind up with a
> regression we can deal with it then.

Okay, that works for me.

> > Assuming that this is an alternative to introducing
> > si_addr_tag_bits_mask, the userspace code would need to use the flag
> > bit support detection protocol for SA_EXPOSE_TAGBITS in order to be
> > able to distinguish between "no bits valid" and "some bits valid", and
> > then use an architecture-specific mechanism to determine exactly which
> > bits are valid. Is that okay for a generic feature?
>
> Unless I am mistaken setting the bits is already architecture specific
> so having some architecture specific code in there should not be a big
> problem.
>
> But I really don't understand the arm case well enough to know if we can
> get away without si_addr_tag_bits_mask, and in turn without the flags
> field that indicates the si_addr_tag_bits_mask is present.
>
> So I am asking questions so I can understand just what we get from
> si_addr_tag_bits_mask.

If we allow the derivation of the mask to be architecture-specific
(which I'd be comfortable with) then I don't think we need it. What we
would end up with is:

- The tag bits mask is constant and architecturally defined (in
arm64's case it would be 0xff << 56).
- The valid tag bits mask specifies which bits of the tag bits mask in
the fault address are propagated to si_addr. It is defined in an
architecture-specific way based on the signal handler's
SA_EXPOSE_TAGBITS bit, the contents of siginfo and possibly global
information such as getauxval(AT_HWCAP*).
  - on arm64 this would currently be defined as:
    - if SA_EXPOSE_TAGBITS is not set then the mask is 0xff << 56 for
SIGTRAP/TRAP_BRKPT, 0 otherwise
    - if SA_EXPOSE_TAGBITS is set then the mask is 0xf << 56 for
SIGSEGV/SEGV_MTESERR, 0xff << 56 otherwise
- If SA_EXPOSE_TAGBITS is set then the bits in the tag bits mask that
are not also in the valid tag bits mask have an undefined value (this
would e.g. allow future expansion of arm64 to expose bits 60-63 on tag
check faults).
- If the kernel does not support SA_EXPOSE_TAGBITS (as determined
using the flag bit support detection protocol) then the behavior is as
if SA_EXPOSE_TAGBITS is not set.

So I think I'd be fine with dropping it but let me experiment with the
new approach so that I can confirm that it's practical on Android and
I'll get back to you.

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

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

Peter Collingbourne <pcc@google.com> writes:

> On Tue, Nov 10, 2020 at 7:12 AM Eric W. Biederman <ebiederm@xmission.com> wrote:
>>
>> Peter Collingbourne <pcc@google.com> writes:
>>
>> > On Mon, Nov 9, 2020 at 5:13 PM Eric W. Biederman <ebiederm@xmission.com> 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, create a new pair of
>> >> > fields in siginfo._sigfault, and store the tag bits of FAR_EL1 there,
>> >> > together with a mask specifying which bits are valid.
>> >> >
>> >> > A flag is added to si_faultflags to allow userspace to determine whether
>> >> > the values in the fields are valid.
>> >>
>> >> I think I am missing some things:
>> >>
>> >> Today it is documented that the tag bits are cleared, and so we can't
>> >> use the highbits to hold the tag bits by default.
>> >>
>> >> Why do you need to deliver which tag bits are valid?  That feels like an
>> >> implementation detail that is needed to setup the tag bits.  It feels
>> >> like it would be constant per process.  So I don't understand why the
>> >> siginfo needs to report information the process should already have.
>> >
>> > It isn't constant as it may vary depending on the specific type of
>> > fault being delivered. For example on arm64 the architecture only
>> > provides us with bits 56-59 of the tag for tag check faults, while all
>> > other data aborts also provide bits 60-63. Now although the user
>> > program may distinguish the two cases by checking the si_code, we
>> > would also like to allow future architecture extensions to provide
>> > bits 60-63 for tag check faults as well and allow distinguishing
>> > between "bits 60-63 were zero" and "bits 60-63 were unknown" (which is
>> > important when providing error reports).
>>
>> Does that mean that bits 60-63 are effectively unusable as tag bits
>> if the tag check fault won't report them?
>
> The hardware doesn't support tag checking on bits 60-63, only on bits
> 56-59, so in terms of hardware enforced memory tag checking they can't
> be used as tag bits. But they are still subject to address tagging aka
> top-byte-ignore so they could be used by userspace for other purposes
> (e.g. if the allocator adds entropy to all 8 bits instead of just bits
> 56-59 they could in theory be used to allow better diagnostics with
> more precise matching of an invalid access to a previous allocation).
>
>> If you can use bits 60-63 as tag bits how does that work if they aren't
>> reported?
>
> It still works but we're limited in how many allocations we can match
> accesses to (16 vs 256).
>
>> > I suppose that you could imagine that, if the "bits 60-63 available"
>> > extension ever comes to pass, it could be exposed via a bit in
>> > getauxval(AT_HWCAP2) (or maybe something like AT_HWCAP3 depending on
>> > how long it takes to arrive) and that would provide a way for
>> > userspace to know which bits are valid. But it seems like allowing
>> > this to vary per signal is relatively cheap, allows the information to
>> > be made available trivially architecture independently and keeps our
>> > options open for the future (because we don't know if some future
>> > architecture will actually make this a per-signal attribute).
>> >
>> > That being said, maybe we could solve this problem at the point at
>> > which we do encounter such an architecture though.
>>
>> My goal would be to extend things to the minimum extent necessary to
>> handle today's reality well.  Usually architectures evolve in
>> unanticipated directions so simple and straight forward usually wins for
>> handling future evolution.  As there is simply less old baggage to carry
>> around.
>>
>> However I don't understand if reporting the valid bits on a signal by
>> signal basis has a real advantage today or not.  If it helps today we
>> will find room for the field.
>
> Okay, that makes sense. With the architecture as specified today I
> don't think we would need it, since you can write a function that
> operates on the siginfo and tells you what the si_addr_tag_bits_mask
> would be without it.
>
>> >> Want prevents adding a sigaction sa_flag SA_EXPOSE_TABITS that when set
>> >> causes the high bits to be set, and when clear (the default) will have
>> >> the signal delivery code clear those bits.
>> >>
>> >> That should be enough for code that wants the tag bits to ask for them.
>> >> As userspace would need to be updated to get the new bits
>> >>
>> >> Even if you have chained handlers.  The chaining mechanism would need to
>> >> be updated and it could call the aware handlers first then clear the tag
>> >> bits and call the rest of the handlers.
>> >>
>> >> It feels like always passing the tag bits in the address and then
>> >> clearing them in the copy to userspace if the signal handler is
>> >> not ready for them would be easier to maintain.
>> >
>> > I think that approach might work. Although it may make life harder for
>> > callers of ptrace(PTRACE_SETSIGINFO) since they may need to know the
>> > value of the bit in order to prepare a correct siginfo structure, if
>> > we can reasonably expect them to always be delivering an exact copy of
>> > a signal that was received before then maybe that is okay.
>>
>> I think we can reasonably expect callers of PTRACE_SETSIGINFO to be able
>> to either deal the full reality of what is going on, or to only generate
>> signals that they fully understand.
>>
>> Other than the use by CRIU it is a debugging facility and it is not
>> expected for ordinary usage.  The non-CRIU use case would really seem to
>> be what happens if I inject arbitrary signal X into process Y.  For that
>> you need the ability to inject an arbitrary signal.
>>
>> My real sense with PTRACE_SETSIGINFO is that if we wind up with a
>> regression we can deal with it then.
>
> Okay, that works for me.
>
>> > Assuming that this is an alternative to introducing
>> > si_addr_tag_bits_mask, the userspace code would need to use the flag
>> > bit support detection protocol for SA_EXPOSE_TAGBITS in order to be
>> > able to distinguish between "no bits valid" and "some bits valid", and
>> > then use an architecture-specific mechanism to determine exactly which
>> > bits are valid. Is that okay for a generic feature?
>>
>> Unless I am mistaken setting the bits is already architecture specific
>> so having some architecture specific code in there should not be a big
>> problem.
>>
>> But I really don't understand the arm case well enough to know if we can
>> get away without si_addr_tag_bits_mask, and in turn without the flags
>> field that indicates the si_addr_tag_bits_mask is present.
>>
>> So I am asking questions so I can understand just what we get from
>> si_addr_tag_bits_mask.
>
> If we allow the derivation of the mask to be architecture-specific
> (which I'd be comfortable with) then I don't think we need it. What we
> would end up with is:
>
> - The tag bits mask is constant and architecturally defined (in
> arm64's case it would be 0xff << 56).
> - The valid tag bits mask specifies which bits of the tag bits mask in
> the fault address are propagated to si_addr. It is defined in an
> architecture-specific way based on the signal handler's
> SA_EXPOSE_TAGBITS bit, the contents of siginfo and possibly global
> information such as getauxval(AT_HWCAP*).
>   - on arm64 this would currently be defined as:
>     - if SA_EXPOSE_TAGBITS is not set then the mask is 0xff << 56 for
> SIGTRAP/TRAP_BRKPT, 0 otherwise
>     - if SA_EXPOSE_TAGBITS is set then the mask is 0xf << 56 for
> SIGSEGV/SEGV_MTESERR, 0xff << 56 otherwise
> - If SA_EXPOSE_TAGBITS is set then the bits in the tag bits mask that
> are not also in the valid tag bits mask have an undefined value (this
> would e.g. allow future expansion of arm64 to expose bits 60-63 on tag
> check faults).
> - If the kernel does not support SA_EXPOSE_TAGBITS (as determined
> using the flag bit support detection protocol) then the behavior is as
> if SA_EXPOSE_TAGBITS is not set.
>
> So I think I'd be fine with dropping it but let me experiment with the
> new approach so that I can confirm that it's practical on Android and
> I'll get back to you.

Sounds like a plan.

Eric


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

* Re: [PATCH v14 8/8] arm64: expose FAR_EL1 tag bits in siginfo
@ 2020-11-11  7:45             ` Eric W. Biederman
  0 siblings, 0 replies; 64+ messages in thread
From: Eric W. Biederman @ 2020-11-11  7:45 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, Richard Henderson

Peter Collingbourne <pcc@google.com> writes:

> On Tue, Nov 10, 2020 at 7:12 AM Eric W. Biederman <ebiederm@xmission.com> wrote:
>>
>> Peter Collingbourne <pcc@google.com> writes:
>>
>> > On Mon, Nov 9, 2020 at 5:13 PM Eric W. Biederman <ebiederm@xmission.com> 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, create a new pair of
>> >> > fields in siginfo._sigfault, and store the tag bits of FAR_EL1 there,
>> >> > together with a mask specifying which bits are valid.
>> >> >
>> >> > A flag is added to si_faultflags to allow userspace to determine whether
>> >> > the values in the fields are valid.
>> >>
>> >> I think I am missing some things:
>> >>
>> >> Today it is documented that the tag bits are cleared, and so we can't
>> >> use the highbits to hold the tag bits by default.
>> >>
>> >> Why do you need to deliver which tag bits are valid?  That feels like an
>> >> implementation detail that is needed to setup the tag bits.  It feels
>> >> like it would be constant per process.  So I don't understand why the
>> >> siginfo needs to report information the process should already have.
>> >
>> > It isn't constant as it may vary depending on the specific type of
>> > fault being delivered. For example on arm64 the architecture only
>> > provides us with bits 56-59 of the tag for tag check faults, while all
>> > other data aborts also provide bits 60-63. Now although the user
>> > program may distinguish the two cases by checking the si_code, we
>> > would also like to allow future architecture extensions to provide
>> > bits 60-63 for tag check faults as well and allow distinguishing
>> > between "bits 60-63 were zero" and "bits 60-63 were unknown" (which is
>> > important when providing error reports).
>>
>> Does that mean that bits 60-63 are effectively unusable as tag bits
>> if the tag check fault won't report them?
>
> The hardware doesn't support tag checking on bits 60-63, only on bits
> 56-59, so in terms of hardware enforced memory tag checking they can't
> be used as tag bits. But they are still subject to address tagging aka
> top-byte-ignore so they could be used by userspace for other purposes
> (e.g. if the allocator adds entropy to all 8 bits instead of just bits
> 56-59 they could in theory be used to allow better diagnostics with
> more precise matching of an invalid access to a previous allocation).
>
>> If you can use bits 60-63 as tag bits how does that work if they aren't
>> reported?
>
> It still works but we're limited in how many allocations we can match
> accesses to (16 vs 256).
>
>> > I suppose that you could imagine that, if the "bits 60-63 available"
>> > extension ever comes to pass, it could be exposed via a bit in
>> > getauxval(AT_HWCAP2) (or maybe something like AT_HWCAP3 depending on
>> > how long it takes to arrive) and that would provide a way for
>> > userspace to know which bits are valid. But it seems like allowing
>> > this to vary per signal is relatively cheap, allows the information to
>> > be made available trivially architecture independently and keeps our
>> > options open for the future (because we don't know if some future
>> > architecture will actually make this a per-signal attribute).
>> >
>> > That being said, maybe we could solve this problem at the point at
>> > which we do encounter such an architecture though.
>>
>> My goal would be to extend things to the minimum extent necessary to
>> handle today's reality well.  Usually architectures evolve in
>> unanticipated directions so simple and straight forward usually wins for
>> handling future evolution.  As there is simply less old baggage to carry
>> around.
>>
>> However I don't understand if reporting the valid bits on a signal by
>> signal basis has a real advantage today or not.  If it helps today we
>> will find room for the field.
>
> Okay, that makes sense. With the architecture as specified today I
> don't think we would need it, since you can write a function that
> operates on the siginfo and tells you what the si_addr_tag_bits_mask
> would be without it.
>
>> >> Want prevents adding a sigaction sa_flag SA_EXPOSE_TABITS that when set
>> >> causes the high bits to be set, and when clear (the default) will have
>> >> the signal delivery code clear those bits.
>> >>
>> >> That should be enough for code that wants the tag bits to ask for them.
>> >> As userspace would need to be updated to get the new bits
>> >>
>> >> Even if you have chained handlers.  The chaining mechanism would need to
>> >> be updated and it could call the aware handlers first then clear the tag
>> >> bits and call the rest of the handlers.
>> >>
>> >> It feels like always passing the tag bits in the address and then
>> >> clearing them in the copy to userspace if the signal handler is
>> >> not ready for them would be easier to maintain.
>> >
>> > I think that approach might work. Although it may make life harder for
>> > callers of ptrace(PTRACE_SETSIGINFO) since they may need to know the
>> > value of the bit in order to prepare a correct siginfo structure, if
>> > we can reasonably expect them to always be delivering an exact copy of
>> > a signal that was received before then maybe that is okay.
>>
>> I think we can reasonably expect callers of PTRACE_SETSIGINFO to be able
>> to either deal the full reality of what is going on, or to only generate
>> signals that they fully understand.
>>
>> Other than the use by CRIU it is a debugging facility and it is not
>> expected for ordinary usage.  The non-CRIU use case would really seem to
>> be what happens if I inject arbitrary signal X into process Y.  For that
>> you need the ability to inject an arbitrary signal.
>>
>> My real sense with PTRACE_SETSIGINFO is that if we wind up with a
>> regression we can deal with it then.
>
> Okay, that works for me.
>
>> > Assuming that this is an alternative to introducing
>> > si_addr_tag_bits_mask, the userspace code would need to use the flag
>> > bit support detection protocol for SA_EXPOSE_TAGBITS in order to be
>> > able to distinguish between "no bits valid" and "some bits valid", and
>> > then use an architecture-specific mechanism to determine exactly which
>> > bits are valid. Is that okay for a generic feature?
>>
>> Unless I am mistaken setting the bits is already architecture specific
>> so having some architecture specific code in there should not be a big
>> problem.
>>
>> But I really don't understand the arm case well enough to know if we can
>> get away without si_addr_tag_bits_mask, and in turn without the flags
>> field that indicates the si_addr_tag_bits_mask is present.
>>
>> So I am asking questions so I can understand just what we get from
>> si_addr_tag_bits_mask.
>
> If we allow the derivation of the mask to be architecture-specific
> (which I'd be comfortable with) then I don't think we need it. What we
> would end up with is:
>
> - The tag bits mask is constant and architecturally defined (in
> arm64's case it would be 0xff << 56).
> - The valid tag bits mask specifies which bits of the tag bits mask in
> the fault address are propagated to si_addr. It is defined in an
> architecture-specific way based on the signal handler's
> SA_EXPOSE_TAGBITS bit, the contents of siginfo and possibly global
> information such as getauxval(AT_HWCAP*).
>   - on arm64 this would currently be defined as:
>     - if SA_EXPOSE_TAGBITS is not set then the mask is 0xff << 56 for
> SIGTRAP/TRAP_BRKPT, 0 otherwise
>     - if SA_EXPOSE_TAGBITS is set then the mask is 0xf << 56 for
> SIGSEGV/SEGV_MTESERR, 0xff << 56 otherwise
> - If SA_EXPOSE_TAGBITS is set then the bits in the tag bits mask that
> are not also in the valid tag bits mask have an undefined value (this
> would e.g. allow future expansion of arm64 to expose bits 60-63 on tag
> check faults).
> - If the kernel does not support SA_EXPOSE_TAGBITS (as determined
> using the flag bit support detection protocol) then the behavior is as
> if SA_EXPOSE_TAGBITS is not set.
>
> So I think I'd be fine with dropping it but let me experiment with the
> new approach so that I can confirm that it's practical on Android and
> I'll get back to you.

Sounds like a plan.

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

* Re: [PATCH v14 7/8] signal: define the field siginfo.si_faultflags
  2020-11-10  1:54     ` Eric W. Biederman
@ 2020-11-11 11:10       ` Haren Myneni
  -1 siblings, 0 replies; 64+ messages in thread
From: Haren Myneni @ 2020-11-11 11:10 UTC (permalink / raw)
  To: Eric W. Biederman, Peter Collingbourne
  Cc: Catalin Marinas, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	James E.J. Bottomley, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-api, Helge Deller, David Spickett,
	Sukadev Bhattiprolu, Michael Ellerman, npiggin

On Mon, 2020-11-09 at 19:54 -0600, Eric W. Biederman wrote:
> Peter you are patching buggy code for your siginfo extension can
> you please ignore vas-fault.c.  The code in vas-fault.c should
> be fixed separately.  Futher it uses clear_siginfo so you should
> get well defined behavior even if your new field is not initialized.
> 
> I have copied the powerpc folks so hopefully this buggy code
> can be fixed.
> 
> > diff --git a/arch/powerpc/platforms/powernv/vas-fault.c
> > b/arch/powerpc/platforms/powernv/vas-fault.c
> > index 3d21fce254b7..877e7d5fb4a2 100644
> > --- a/arch/powerpc/platforms/powernv/vas-fault.c
> > +++ b/arch/powerpc/platforms/powernv/vas-fault.c
> > @@ -154,6 +154,7 @@ static void update_csb(struct vas_window
> > *window,
> >  	info.si_errno = EFAULT;
> >  	info.si_code = SEGV_MAPERR;
> >  	info.si_addr = csb_addr;
> > +	info.si_faultflags = 0;
> 

Thanks Eric for your comments and pointing possible issues.

Here is the NX coprocessor interaction with user space and kernel:

- Process opens NX window / channel. The user space sends requests to
NX without kernel involvement. This request contains data buffer and
status block called coprocessor status block (CSB). 
- if NX sees fault on the request buffer or on CSB address, issue an
interrupt to kernel
- kernel updates the CSB with the fault information and then the
process can reissue request.
- If the fault is on CSB address and is not a valid address, sending
SEGV signal so that the process assign proper CSB and reissue new
request
- We are not seeing the invalid CSB address in the process context, but
during handling the fault later. So thought about sending SEGV signal
instead of killing the process since it is not a standard segfault. 
- All these windows will be closed upon process exit, but waits
until all pending requests are completed. So process will not exit with
pending requests, means after all faults handled if any. 
- In the case of multithread applications, NX windows will be closed
with the last thread. Means other threads can still issue requests with
these windows. So to support in these applications, take PID and MM
references during window open and release them later in close. 

> Powerpc folks.  This code was introduced in c96c4436aba4
> ("powerpc/vas:
> Update CSB and notify process for fault CRBs") and is badly buggy.
> 
> Let me count the bugs:
> 
> a) Using kill_pid_info.  That performs a permission check that
>    does not make sense from a kernel thread.
> 
> b) Manually filling in struct siginfo.  Everyone gets it wrong
>    and the powerpc code is no exception setting si_errno when
>    that is something Linux as a rule does not do.
> 
> Technically we have send_sig_fault to handle sending
> a fault from a non-sychrnous context but I am not convinced
> it make sense in this case.

Yes, kill_pid_info() -> group_send_sig_info() checks permissions which
is an extra step.  I think send_sig_fault may be used to replace the
above steps.

> 
> c) Sending an asynchronous SIGSEGV with the si_code set to
> SEGV_MAPERR.
>    How can userspace detect it is an asynchronous signal?  What can
>    userspace do if it detects an asynchronous signal?  If userspace
> is
>    so buggered as to give your kernel thread a bogus address I
> suspect
>    uncerimonious sending SIGKILL is probably the best you can do.

Application can assign new CSB and send new request when it catches the
signal. For example it can use csb_addr passed in si_addr amd decide
whether this SEGV is due to to CSB fault. Since it is an async signal,
was thinking for the application to recover instead of killing theprocess.  

> 
> There are some additional questionable things in that code like
> taking a
> task_struct reference simply to be able to test tsk->flags but no
> locks are held to ensure that tsk->flags are meaningful.  Nor are
> any tests performed to see if the task being tested still uses
> the designated mm.  I suspect exec could have been called.

tsk->flags is used to make sure not to send a signal if the task is in
exiting. We access this task under get/put_task_struct(). Also
kill_pid_info() sends signal if pid_task() is available. Since we are
taken mm reference, it can not be freed. 

So the task has to be present until all NX windows are closed.

> 
> In which case the code needs to check the mm, or at least play with
> exec_id to ensure you are not improperly signaling a process after
> exec.
> 
> None of this is to say that update_csb is fundmentally bad or hard to
> correct just that it has some significant defects in it's
> implementation
> right now that need to be corrected.  I am hoping a detailed
> accounting
> and pointing out those defects will allow the bug to be fixed.
> 
> Thank you,
> Eric


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

* Re: [PATCH v14 7/8] signal: define the field siginfo.si_faultflags
@ 2020-11-11 11:10       ` Haren Myneni
  0 siblings, 0 replies; 64+ messages in thread
From: Haren Myneni @ 2020-11-11 11:10 UTC (permalink / raw)
  To: Eric W. Biederman, Peter Collingbourne
  Cc: Sukadev Bhattiprolu, Michael Ellerman, Catalin Marinas,
	Helge Deller, Kevin Brodsky, npiggin, Oleg Nesterov, linux-api,
	James E.J. Bottomley, Kostya Serebryany, Linux ARM,
	Andrey Konovalov, David Spickett, Vincenzo Frascino, Will Deacon,
	Dave Martin, Evgenii Stepanov, Richard Henderson

On Mon, 2020-11-09 at 19:54 -0600, Eric W. Biederman wrote:
> Peter you are patching buggy code for your siginfo extension can
> you please ignore vas-fault.c.  The code in vas-fault.c should
> be fixed separately.  Futher it uses clear_siginfo so you should
> get well defined behavior even if your new field is not initialized.
> 
> I have copied the powerpc folks so hopefully this buggy code
> can be fixed.
> 
> > diff --git a/arch/powerpc/platforms/powernv/vas-fault.c
> > b/arch/powerpc/platforms/powernv/vas-fault.c
> > index 3d21fce254b7..877e7d5fb4a2 100644
> > --- a/arch/powerpc/platforms/powernv/vas-fault.c
> > +++ b/arch/powerpc/platforms/powernv/vas-fault.c
> > @@ -154,6 +154,7 @@ static void update_csb(struct vas_window
> > *window,
> >  	info.si_errno = EFAULT;
> >  	info.si_code = SEGV_MAPERR;
> >  	info.si_addr = csb_addr;
> > +	info.si_faultflags = 0;
> 

Thanks Eric for your comments and pointing possible issues.

Here is the NX coprocessor interaction with user space and kernel:

- Process opens NX window / channel. The user space sends requests to
NX without kernel involvement. This request contains data buffer and
status block called coprocessor status block (CSB). 
- if NX sees fault on the request buffer or on CSB address, issue an
interrupt to kernel
- kernel updates the CSB with the fault information and then the
process can reissue request.
- If the fault is on CSB address and is not a valid address, sending
SEGV signal so that the process assign proper CSB and reissue new
request
- We are not seeing the invalid CSB address in the process context, but
during handling the fault later. So thought about sending SEGV signal
instead of killing the process since it is not a standard segfault. 
- All these windows will be closed upon process exit, but waits
until all pending requests are completed. So process will not exit with
pending requests, means after all faults handled if any. 
- In the case of multithread applications, NX windows will be closed
with the last thread. Means other threads can still issue requests with
these windows. So to support in these applications, take PID and MM
references during window open and release them later in close. 

> Powerpc folks.  This code was introduced in c96c4436aba4
> ("powerpc/vas:
> Update CSB and notify process for fault CRBs") and is badly buggy.
> 
> Let me count the bugs:
> 
> a) Using kill_pid_info.  That performs a permission check that
>    does not make sense from a kernel thread.
> 
> b) Manually filling in struct siginfo.  Everyone gets it wrong
>    and the powerpc code is no exception setting si_errno when
>    that is something Linux as a rule does not do.
> 
> Technically we have send_sig_fault to handle sending
> a fault from a non-sychrnous context but I am not convinced
> it make sense in this case.

Yes, kill_pid_info() -> group_send_sig_info() checks permissions which
is an extra step.  I think send_sig_fault may be used to replace the
above steps.

> 
> c) Sending an asynchronous SIGSEGV with the si_code set to
> SEGV_MAPERR.
>    How can userspace detect it is an asynchronous signal?  What can
>    userspace do if it detects an asynchronous signal?  If userspace
> is
>    so buggered as to give your kernel thread a bogus address I
> suspect
>    uncerimonious sending SIGKILL is probably the best you can do.

Application can assign new CSB and send new request when it catches the
signal. For example it can use csb_addr passed in si_addr amd decide
whether this SEGV is due to to CSB fault. Since it is an async signal,
was thinking for the application to recover instead of killing theprocess.  

> 
> There are some additional questionable things in that code like
> taking a
> task_struct reference simply to be able to test tsk->flags but no
> locks are held to ensure that tsk->flags are meaningful.  Nor are
> any tests performed to see if the task being tested still uses
> the designated mm.  I suspect exec could have been called.

tsk->flags is used to make sure not to send a signal if the task is in
exiting. We access this task under get/put_task_struct(). Also
kill_pid_info() sends signal if pid_task() is available. Since we are
taken mm reference, it can not be freed. 

So the task has to be present until all NX windows are closed.

> 
> In which case the code needs to check the mm, or at least play with
> exec_id to ensure you are not improperly signaling a process after
> exec.
> 
> None of this is to say that update_csb is fundmentally bad or hard to
> correct just that it has some significant defects in it's
> implementation
> right now that need to be corrected.  I am hoping a detailed
> accounting
> and pointing out those defects will allow the bug to be fixed.
> 
> 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] 64+ messages in thread

* Re: [PATCH v14 7/8] signal: define the field siginfo.si_faultflags
  2020-11-10  1:57     ` Eric W. Biederman
@ 2020-11-11 17:27       ` Dave Martin
  -1 siblings, 0 replies; 64+ messages in thread
From: Dave Martin @ 2020-11-11 17:27 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Peter Collingbourne, Catalin Marinas, Evgenii Stepanov,
	Kostya Serebryany, Vincenzo Frascino, Will Deacon, Oleg Nesterov,
	James E.J. Bottomley, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-api, Helge Deller, David Spickett

On Mon, Nov 09, 2020 at 07:57:33PM -0600, Eric W. Biederman wrote:
> Peter Collingbourne <pcc@google.com> writes:
> 
> > This field will contain flags that may be used by signal handlers to
> > determine whether other fields in the _sigfault portion of siginfo are
> > valid. An example use case is the following patch, which introduces
> > the si_addr_tag_bits{,_mask} fields.
> >
> > A new sigcontext flag, SA_FAULTFLAGS, is introduced in order to allow
> > a signal handler to require the kernel to set the field (but note
> > that the field will be set anyway if the kernel supports the flag,
> > regardless of its value). In combination with the previous patches,
> > this allows a userspace program to determine whether the kernel will
> > set the field.
> >
> > It is possible for an si_faultflags-unaware program to cause a signal
> > handler in an si_faultflags-aware program to be called with a provided
> > siginfo data structure by using one of the following syscalls:
> >
> > - ptrace(PTRACE_SETSIGINFO)
> > - pidfd_send_signal
> > - rt_sigqueueinfo
> > - rt_tgsigqueueinfo
> >
> > So we need to prevent the si_faultflags-unaware program from causing an
> > uninitialized read of si_faultflags in the si_faultflags-aware program when
> > it uses one of these syscalls.
> >
> > The last three cases can be handled by observing that each of these
> > syscalls fails if si_code >= 0. We also observe that kill(2) and
> > tgkill(2) may be used to send a signal where si_code == 0 (SI_USER),
> > so we define si_faultflags to only be valid if si_code > 0.
> >
> > There is no such check on si_code in ptrace(PTRACE_SETSIGINFO), so
> > we make ptrace(PTRACE_SETSIGINFO) clear the si_faultflags field if it
> > detects that the signal would use the _sigfault layout, and introduce
> > a new ptrace request type, PTRACE_SETSIGINFO2, that a si_faultflags-aware
> > program may use to opt out of this behavior.
> 
> So I think while well intentioned this is misguided.
> 
> gdb and the like may use this but I expect the primary user is CRIU
> which simply reads the signal out of one process saves it on disk
> and then restores the signal as read into the new process (possibly
> on a different machine).
> 
> At least for the CRIU usage PTRACE_SETSIGINFO need to remain a raw
> pass through kind of operation.

This is a problem, though.

How can we tell the difference between a siginfo that was generated by
the kernel and a siginfo that was generated (or altered) by a non-xflags
aware userspace?

Short of revving the whole API, I don't see a simple solution to this.

Although a bit of a hack, could we include some kind of checksum in the
siginfo?  If the checksum matches during PTRACE_SETSIGINFO, we could
accept the whole thing; xflags included.  Otherwise, we could silently
drop non-self-describing extensions.

If we only need to generate the checksum when PTRACE_GETSIGINFO is
called then it might be feasible to use a strong hash; otherwise, this
mechanism will be far from bulletproof.

A hash has the advantage that we don't need any other information
to validate it beyond a salt: if the hash matches, it's self-
validating.  We could also package other data with it to describe the
presence of extensions, but relying on this for regular sigaction()/
signal delivery use feels too high-overhead.

For debuggers, I suspect that PTRACE_SETSIGINFO2 is still useful:
userspace callers that want to write an extension field that they
knowingly generated themselves should have a way to express that.

Thoughts?

Cheers
---Dave

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

* Re: [PATCH v14 7/8] signal: define the field siginfo.si_faultflags
@ 2020-11-11 17:27       ` Dave Martin
  0 siblings, 0 replies; 64+ messages in thread
From: Dave Martin @ 2020-11-11 17:27 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,
	Richard Henderson

On Mon, Nov 09, 2020 at 07:57:33PM -0600, Eric W. Biederman wrote:
> Peter Collingbourne <pcc@google.com> writes:
> 
> > This field will contain flags that may be used by signal handlers to
> > determine whether other fields in the _sigfault portion of siginfo are
> > valid. An example use case is the following patch, which introduces
> > the si_addr_tag_bits{,_mask} fields.
> >
> > A new sigcontext flag, SA_FAULTFLAGS, is introduced in order to allow
> > a signal handler to require the kernel to set the field (but note
> > that the field will be set anyway if the kernel supports the flag,
> > regardless of its value). In combination with the previous patches,
> > this allows a userspace program to determine whether the kernel will
> > set the field.
> >
> > It is possible for an si_faultflags-unaware program to cause a signal
> > handler in an si_faultflags-aware program to be called with a provided
> > siginfo data structure by using one of the following syscalls:
> >
> > - ptrace(PTRACE_SETSIGINFO)
> > - pidfd_send_signal
> > - rt_sigqueueinfo
> > - rt_tgsigqueueinfo
> >
> > So we need to prevent the si_faultflags-unaware program from causing an
> > uninitialized read of si_faultflags in the si_faultflags-aware program when
> > it uses one of these syscalls.
> >
> > The last three cases can be handled by observing that each of these
> > syscalls fails if si_code >= 0. We also observe that kill(2) and
> > tgkill(2) may be used to send a signal where si_code == 0 (SI_USER),
> > so we define si_faultflags to only be valid if si_code > 0.
> >
> > There is no such check on si_code in ptrace(PTRACE_SETSIGINFO), so
> > we make ptrace(PTRACE_SETSIGINFO) clear the si_faultflags field if it
> > detects that the signal would use the _sigfault layout, and introduce
> > a new ptrace request type, PTRACE_SETSIGINFO2, that a si_faultflags-aware
> > program may use to opt out of this behavior.
> 
> So I think while well intentioned this is misguided.
> 
> gdb and the like may use this but I expect the primary user is CRIU
> which simply reads the signal out of one process saves it on disk
> and then restores the signal as read into the new process (possibly
> on a different machine).
> 
> At least for the CRIU usage PTRACE_SETSIGINFO need to remain a raw
> pass through kind of operation.

This is a problem, though.

How can we tell the difference between a siginfo that was generated by
the kernel and a siginfo that was generated (or altered) by a non-xflags
aware userspace?

Short of revving the whole API, I don't see a simple solution to this.

Although a bit of a hack, could we include some kind of checksum in the
siginfo?  If the checksum matches during PTRACE_SETSIGINFO, we could
accept the whole thing; xflags included.  Otherwise, we could silently
drop non-self-describing extensions.

If we only need to generate the checksum when PTRACE_GETSIGINFO is
called then it might be feasible to use a strong hash; otherwise, this
mechanism will be far from bulletproof.

A hash has the advantage that we don't need any other information
to validate it beyond a salt: if the hash matches, it's self-
validating.  We could also package other data with it to describe the
presence of extensions, but relying on this for regular sigaction()/
signal delivery use feels too high-overhead.

For debuggers, I suspect that PTRACE_SETSIGINFO2 is still useful:
userspace callers that want to write an extension field that they
knowingly generated themselves should have a way to express that.

Thoughts?

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

* Re: [PATCH v14 8/8] arm64: expose FAR_EL1 tag bits in siginfo
  2020-11-10 22:06           ` Peter Collingbourne
@ 2020-11-11 17:46             ` Dave Martin
  -1 siblings, 0 replies; 64+ messages in thread
From: Dave Martin @ 2020-11-11 17:46 UTC (permalink / raw)
  To: Peter Collingbourne
  Cc: Eric W. Biederman, Catalin Marinas, Evgenii Stepanov,
	Kostya Serebryany, Vincenzo Frascino, Will Deacon, Oleg Nesterov,
	James E.J. Bottomley, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, Linux API, Helge Deller, David Spickett

On Tue, Nov 10, 2020 at 02:06:21PM -0800, Peter Collingbourne wrote:
> On Tue, Nov 10, 2020 at 7:12 AM Eric W. Biederman <ebiederm@xmission.com> wrote:
> >
> > Peter Collingbourne <pcc@google.com> writes:
> >
> > > On Mon, Nov 9, 2020 at 5:13 PM Eric W. Biederman <ebiederm@xmission.com> 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, create a new pair of
> > >> > fields in siginfo._sigfault, and store the tag bits of FAR_EL1 there,
> > >> > together with a mask specifying which bits are valid.
> > >> >
> > >> > A flag is added to si_faultflags to allow userspace to determine whether
> > >> > the values in the fields are valid.
> > >>
> > >> I think I am missing some things:
> > >>
> > >> Today it is documented that the tag bits are cleared, and so we can't
> > >> use the highbits to hold the tag bits by default.
> > >>
> > >> Why do you need to deliver which tag bits are valid?  That feels like an
> > >> implementation detail that is needed to setup the tag bits.  It feels
> > >> like it would be constant per process.  So I don't understand why the
> > >> siginfo needs to report information the process should already have.
> > >
> > > It isn't constant as it may vary depending on the specific type of
> > > fault being delivered. For example on arm64 the architecture only
> > > provides us with bits 56-59 of the tag for tag check faults, while all
> > > other data aborts also provide bits 60-63. Now although the user
> > > program may distinguish the two cases by checking the si_code, we
> > > would also like to allow future architecture extensions to provide
> > > bits 60-63 for tag check faults as well and allow distinguishing
> > > between "bits 60-63 were zero" and "bits 60-63 were unknown" (which is
> > > important when providing error reports).
> >
> > Does that mean that bits 60-63 are effectively unusable as tag bits
> > if the tag check fault won't report them?
> 
> The hardware doesn't support tag checking on bits 60-63, only on bits
> 56-59, so in terms of hardware enforced memory tag checking they can't
> be used as tag bits. But they are still subject to address tagging aka
> top-byte-ignore so they could be used by userspace for other purposes
> (e.g. if the allocator adds entropy to all 8 bits instead of just bits
> 56-59 they could in theory be used to allow better diagnostics with
> more precise matching of an invalid access to a previous allocation).
> 
> > If you can use bits 60-63 as tag bits how does that work if they aren't
> > reported?
> 
> It still works but we're limited in how many allocations we can match
> accesses to (16 vs 256).

Not matching/reporting all the bits still has some value: if all 8 bits
are random per allocation, then it is statistically likely that the
hardware will detect mismatches.  Once you know there's a bug, you can
turn on software instrumentation to debug the issue further, which may
check the rest of the bits without relying on the signal mechansism,
though at a higher runtime cost.

(I'm not saying software will definitely do things this way, but it
seems a reasonable use case.)


> > > I suppose that you could imagine that, if the "bits 60-63 available"
> > > extension ever comes to pass, it could be exposed via a bit in
> > > getauxval(AT_HWCAP2) (or maybe something like AT_HWCAP3 depending on
> > > how long it takes to arrive) and that would provide a way for
> > > userspace to know which bits are valid. But it seems like allowing
> > > this to vary per signal is relatively cheap, allows the information to
> > > be made available trivially architecture independently and keeps our
> > > options open for the future (because we don't know if some future
> > > architecture will actually make this a per-signal attribute).
> > >
> > > That being said, maybe we could solve this problem at the point at
> > > which we do encounter such an architecture though.
> >
> > My goal would be to extend things to the minimum extent necessary to
> > handle today's reality well.  Usually architectures evolve in
> > unanticipated directions so simple and straight forward usually wins for
> > handling future evolution.  As there is simply less old baggage to carry
> > around.
> >
> > However I don't understand if reporting the valid bits on a signal by
> > signal basis has a real advantage today or not.  If it helps today we
> > will find room for the field.
> 
> Okay, that makes sense. With the architecture as specified today I
> don't think we would need it, since you can write a function that
> operates on the siginfo and tells you what the si_addr_tag_bits_mask
> would be without it.
> 
> > >> Want prevents adding a sigaction sa_flag SA_EXPOSE_TABITS that when set
> > >> causes the high bits to be set, and when clear (the default) will have
> > >> the signal delivery code clear those bits.
> > >>
> > >> That should be enough for code that wants the tag bits to ask for them.
> > >> As userspace would need to be updated to get the new bits
> > >>
> > >> Even if you have chained handlers.  The chaining mechanism would need to
> > >> be updated and it could call the aware handlers first then clear the tag
> > >> bits and call the rest of the handlers.
> > >>
> > >> It feels like always passing the tag bits in the address and then
> > >> clearing them in the copy to userspace if the signal handler is
> > >> not ready for them would be easier to maintain.
> > >
> > > I think that approach might work. Although it may make life harder for
> > > callers of ptrace(PTRACE_SETSIGINFO) since they may need to know the
> > > value of the bit in order to prepare a correct siginfo structure, if
> > > we can reasonably expect them to always be delivering an exact copy of
> > > a signal that was received before then maybe that is okay.
> >
> > I think we can reasonably expect callers of PTRACE_SETSIGINFO to be able
> > to either deal the full reality of what is going on, or to only generate
> > signals that they fully understand.
> >
> > Other than the use by CRIU it is a debugging facility and it is not
> > expected for ordinary usage.  The non-CRIU use case would really seem to
> > be what happens if I inject arbitrary signal X into process Y.  For that
> > you need the ability to inject an arbitrary signal.
> >
> > My real sense with PTRACE_SETSIGINFO is that if we wind up with a
> > regression we can deal with it then.
> 
> Okay, that works for me.
> 
> > > Assuming that this is an alternative to introducing
> > > si_addr_tag_bits_mask, the userspace code would need to use the flag
> > > bit support detection protocol for SA_EXPOSE_TAGBITS in order to be
> > > able to distinguish between "no bits valid" and "some bits valid", and
> > > then use an architecture-specific mechanism to determine exactly which
> > > bits are valid. Is that okay for a generic feature?
> >
> > Unless I am mistaken setting the bits is already architecture specific
> > so having some architecture specific code in there should not be a big
> > problem.
> >
> > But I really don't understand the arm case well enough to know if we can
> > get away without si_addr_tag_bits_mask, and in turn without the flags
> > field that indicates the si_addr_tag_bits_mask is present.
> >
> > So I am asking questions so I can understand just what we get from
> > si_addr_tag_bits_mask.
> 
> If we allow the derivation of the mask to be architecture-specific
> (which I'd be comfortable with) then I don't think we need it. What we
> would end up with is:

Note, the architecture-specificness can always be hidden under
sysconf(3) or similar, so it's probably not a huge deal if there's no
generic way of reporting that at the kernel level.


> - The tag bits mask is constant and architecturally defined (in
> arm64's case it would be 0xff << 56).
> - The valid tag bits mask specifies which bits of the tag bits mask in
> the fault address are propagated to si_addr. It is defined in an
> architecture-specific way based on the signal handler's
> SA_EXPOSE_TAGBITS bit, the contents of siginfo and possibly global
> information such as getauxval(AT_HWCAP*).
>   - on arm64 this would currently be defined as:
>     - if SA_EXPOSE_TAGBITS is not set then the mask is 0xff << 56 for
> SIGTRAP/TRAP_BRKPT, 0 otherwise
>     - if SA_EXPOSE_TAGBITS is set then the mask is 0xf << 56 for
> SIGSEGV/SEGV_MTESERR, 0xff << 56 otherwise

This feels very obscure, but since the use cases are equally obscure
this may not be a big problem.  I do sympathise with Eric's view that it
may be best not to over-abstract this.

An sa_flags based mechanism still won't play nice with interposition
frameworks where library registers a proxy handler and chains the user's
handler from it -- the xflags approach is potentially better there.  But
it would only be one more in a long list of existing issues.  People will
only be using SA_EXPOSE_TAGBITS if they explicitly need it (i.e.,
rarely).

> - If SA_EXPOSE_TAGBITS is set then the bits in the tag bits mask that
> are not also in the valid tag bits mask have an undefined value (this
> would e.g. allow future expansion of arm64 to expose bits 60-63 on tag
> check faults).
> - If the kernel does not support SA_EXPOSE_TAGBITS (as determined
> using the flag bit support detection protocol) then the behavior is as
> if SA_EXPOSE_TAGBITS is not set.
> 
> So I think I'd be fine with dropping it but let me experiment with the
> new approach so that I can confirm that it's practical on Android and
> I'll get back to you.


Is the xflags mechanism still required if we follow this model?

If not, that would be a significant simplification.

(@Eric: for context, the xflags mechanism arose before we had worked out
to make detection of support for new sa_flags work reliably...  If we
have accidentally made xflags obsolete in the process, I won't
complain!)

Cheers
---Dave

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

* Re: [PATCH v14 8/8] arm64: expose FAR_EL1 tag bits in siginfo
@ 2020-11-11 17:46             ` Dave Martin
  0 siblings, 0 replies; 64+ messages in thread
From: Dave Martin @ 2020-11-11 17:46 UTC (permalink / raw)
  To: Peter Collingbourne
  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,
	Richard Henderson

On Tue, Nov 10, 2020 at 02:06:21PM -0800, Peter Collingbourne wrote:
> On Tue, Nov 10, 2020 at 7:12 AM Eric W. Biederman <ebiederm@xmission.com> wrote:
> >
> > Peter Collingbourne <pcc@google.com> writes:
> >
> > > On Mon, Nov 9, 2020 at 5:13 PM Eric W. Biederman <ebiederm@xmission.com> 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, create a new pair of
> > >> > fields in siginfo._sigfault, and store the tag bits of FAR_EL1 there,
> > >> > together with a mask specifying which bits are valid.
> > >> >
> > >> > A flag is added to si_faultflags to allow userspace to determine whether
> > >> > the values in the fields are valid.
> > >>
> > >> I think I am missing some things:
> > >>
> > >> Today it is documented that the tag bits are cleared, and so we can't
> > >> use the highbits to hold the tag bits by default.
> > >>
> > >> Why do you need to deliver which tag bits are valid?  That feels like an
> > >> implementation detail that is needed to setup the tag bits.  It feels
> > >> like it would be constant per process.  So I don't understand why the
> > >> siginfo needs to report information the process should already have.
> > >
> > > It isn't constant as it may vary depending on the specific type of
> > > fault being delivered. For example on arm64 the architecture only
> > > provides us with bits 56-59 of the tag for tag check faults, while all
> > > other data aborts also provide bits 60-63. Now although the user
> > > program may distinguish the two cases by checking the si_code, we
> > > would also like to allow future architecture extensions to provide
> > > bits 60-63 for tag check faults as well and allow distinguishing
> > > between "bits 60-63 were zero" and "bits 60-63 were unknown" (which is
> > > important when providing error reports).
> >
> > Does that mean that bits 60-63 are effectively unusable as tag bits
> > if the tag check fault won't report them?
> 
> The hardware doesn't support tag checking on bits 60-63, only on bits
> 56-59, so in terms of hardware enforced memory tag checking they can't
> be used as tag bits. But they are still subject to address tagging aka
> top-byte-ignore so they could be used by userspace for other purposes
> (e.g. if the allocator adds entropy to all 8 bits instead of just bits
> 56-59 they could in theory be used to allow better diagnostics with
> more precise matching of an invalid access to a previous allocation).
> 
> > If you can use bits 60-63 as tag bits how does that work if they aren't
> > reported?
> 
> It still works but we're limited in how many allocations we can match
> accesses to (16 vs 256).

Not matching/reporting all the bits still has some value: if all 8 bits
are random per allocation, then it is statistically likely that the
hardware will detect mismatches.  Once you know there's a bug, you can
turn on software instrumentation to debug the issue further, which may
check the rest of the bits without relying on the signal mechansism,
though at a higher runtime cost.

(I'm not saying software will definitely do things this way, but it
seems a reasonable use case.)


> > > I suppose that you could imagine that, if the "bits 60-63 available"
> > > extension ever comes to pass, it could be exposed via a bit in
> > > getauxval(AT_HWCAP2) (or maybe something like AT_HWCAP3 depending on
> > > how long it takes to arrive) and that would provide a way for
> > > userspace to know which bits are valid. But it seems like allowing
> > > this to vary per signal is relatively cheap, allows the information to
> > > be made available trivially architecture independently and keeps our
> > > options open for the future (because we don't know if some future
> > > architecture will actually make this a per-signal attribute).
> > >
> > > That being said, maybe we could solve this problem at the point at
> > > which we do encounter such an architecture though.
> >
> > My goal would be to extend things to the minimum extent necessary to
> > handle today's reality well.  Usually architectures evolve in
> > unanticipated directions so simple and straight forward usually wins for
> > handling future evolution.  As there is simply less old baggage to carry
> > around.
> >
> > However I don't understand if reporting the valid bits on a signal by
> > signal basis has a real advantage today or not.  If it helps today we
> > will find room for the field.
> 
> Okay, that makes sense. With the architecture as specified today I
> don't think we would need it, since you can write a function that
> operates on the siginfo and tells you what the si_addr_tag_bits_mask
> would be without it.
> 
> > >> Want prevents adding a sigaction sa_flag SA_EXPOSE_TABITS that when set
> > >> causes the high bits to be set, and when clear (the default) will have
> > >> the signal delivery code clear those bits.
> > >>
> > >> That should be enough for code that wants the tag bits to ask for them.
> > >> As userspace would need to be updated to get the new bits
> > >>
> > >> Even if you have chained handlers.  The chaining mechanism would need to
> > >> be updated and it could call the aware handlers first then clear the tag
> > >> bits and call the rest of the handlers.
> > >>
> > >> It feels like always passing the tag bits in the address and then
> > >> clearing them in the copy to userspace if the signal handler is
> > >> not ready for them would be easier to maintain.
> > >
> > > I think that approach might work. Although it may make life harder for
> > > callers of ptrace(PTRACE_SETSIGINFO) since they may need to know the
> > > value of the bit in order to prepare a correct siginfo structure, if
> > > we can reasonably expect them to always be delivering an exact copy of
> > > a signal that was received before then maybe that is okay.
> >
> > I think we can reasonably expect callers of PTRACE_SETSIGINFO to be able
> > to either deal the full reality of what is going on, or to only generate
> > signals that they fully understand.
> >
> > Other than the use by CRIU it is a debugging facility and it is not
> > expected for ordinary usage.  The non-CRIU use case would really seem to
> > be what happens if I inject arbitrary signal X into process Y.  For that
> > you need the ability to inject an arbitrary signal.
> >
> > My real sense with PTRACE_SETSIGINFO is that if we wind up with a
> > regression we can deal with it then.
> 
> Okay, that works for me.
> 
> > > Assuming that this is an alternative to introducing
> > > si_addr_tag_bits_mask, the userspace code would need to use the flag
> > > bit support detection protocol for SA_EXPOSE_TAGBITS in order to be
> > > able to distinguish between "no bits valid" and "some bits valid", and
> > > then use an architecture-specific mechanism to determine exactly which
> > > bits are valid. Is that okay for a generic feature?
> >
> > Unless I am mistaken setting the bits is already architecture specific
> > so having some architecture specific code in there should not be a big
> > problem.
> >
> > But I really don't understand the arm case well enough to know if we can
> > get away without si_addr_tag_bits_mask, and in turn without the flags
> > field that indicates the si_addr_tag_bits_mask is present.
> >
> > So I am asking questions so I can understand just what we get from
> > si_addr_tag_bits_mask.
> 
> If we allow the derivation of the mask to be architecture-specific
> (which I'd be comfortable with) then I don't think we need it. What we
> would end up with is:

Note, the architecture-specificness can always be hidden under
sysconf(3) or similar, so it's probably not a huge deal if there's no
generic way of reporting that at the kernel level.


> - The tag bits mask is constant and architecturally defined (in
> arm64's case it would be 0xff << 56).
> - The valid tag bits mask specifies which bits of the tag bits mask in
> the fault address are propagated to si_addr. It is defined in an
> architecture-specific way based on the signal handler's
> SA_EXPOSE_TAGBITS bit, the contents of siginfo and possibly global
> information such as getauxval(AT_HWCAP*).
>   - on arm64 this would currently be defined as:
>     - if SA_EXPOSE_TAGBITS is not set then the mask is 0xff << 56 for
> SIGTRAP/TRAP_BRKPT, 0 otherwise
>     - if SA_EXPOSE_TAGBITS is set then the mask is 0xf << 56 for
> SIGSEGV/SEGV_MTESERR, 0xff << 56 otherwise

This feels very obscure, but since the use cases are equally obscure
this may not be a big problem.  I do sympathise with Eric's view that it
may be best not to over-abstract this.

An sa_flags based mechanism still won't play nice with interposition
frameworks where library registers a proxy handler and chains the user's
handler from it -- the xflags approach is potentially better there.  But
it would only be one more in a long list of existing issues.  People will
only be using SA_EXPOSE_TAGBITS if they explicitly need it (i.e.,
rarely).

> - If SA_EXPOSE_TAGBITS is set then the bits in the tag bits mask that
> are not also in the valid tag bits mask have an undefined value (this
> would e.g. allow future expansion of arm64 to expose bits 60-63 on tag
> check faults).
> - If the kernel does not support SA_EXPOSE_TAGBITS (as determined
> using the flag bit support detection protocol) then the behavior is as
> if SA_EXPOSE_TAGBITS is not set.
> 
> So I think I'd be fine with dropping it but let me experiment with the
> new approach so that I can confirm that it's practical on Android and
> I'll get back to you.


Is the xflags mechanism still required if we follow this model?

If not, that would be a significant simplification.

(@Eric: for context, the xflags mechanism arose before we had worked out
to make detection of support for new sa_flags work reliably...  If we
have accidentally made xflags obsolete in the process, I won't
complain!)

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

* Re: [PATCH v14 7/8] signal: define the field siginfo.si_faultflags
  2020-11-11 17:27       ` Dave Martin
@ 2020-11-11 20:15         ` Eric W. Biederman
  -1 siblings, 0 replies; 64+ messages in thread
From: Eric W. Biederman @ 2020-11-11 20:15 UTC (permalink / raw)
  To: Dave Martin
  Cc: Peter Collingbourne, Catalin Marinas, Evgenii Stepanov,
	Kostya Serebryany, Vincenzo Frascino, Will Deacon, Oleg Nesterov,
	James E.J. Bottomley, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-api, Helge Deller, David Spickett

Dave Martin <Dave.Martin@arm.com> writes:

> On Mon, Nov 09, 2020 at 07:57:33PM -0600, Eric W. Biederman wrote:
>> Peter Collingbourne <pcc@google.com> writes:
>> 
>> > This field will contain flags that may be used by signal handlers to
>> > determine whether other fields in the _sigfault portion of siginfo are
>> > valid. An example use case is the following patch, which introduces
>> > the si_addr_tag_bits{,_mask} fields.
>> >
>> > A new sigcontext flag, SA_FAULTFLAGS, is introduced in order to allow
>> > a signal handler to require the kernel to set the field (but note
>> > that the field will be set anyway if the kernel supports the flag,
>> > regardless of its value). In combination with the previous patches,
>> > this allows a userspace program to determine whether the kernel will
>> > set the field.
>> >
>> > It is possible for an si_faultflags-unaware program to cause a signal
>> > handler in an si_faultflags-aware program to be called with a provided
>> > siginfo data structure by using one of the following syscalls:
>> >
>> > - ptrace(PTRACE_SETSIGINFO)
>> > - pidfd_send_signal
>> > - rt_sigqueueinfo
>> > - rt_tgsigqueueinfo
>> >
>> > So we need to prevent the si_faultflags-unaware program from causing an
>> > uninitialized read of si_faultflags in the si_faultflags-aware program when
>> > it uses one of these syscalls.
>> >
>> > The last three cases can be handled by observing that each of these
>> > syscalls fails if si_code >= 0. We also observe that kill(2) and
>> > tgkill(2) may be used to send a signal where si_code == 0 (SI_USER),
>> > so we define si_faultflags to only be valid if si_code > 0.
>> >
>> > There is no such check on si_code in ptrace(PTRACE_SETSIGINFO), so
>> > we make ptrace(PTRACE_SETSIGINFO) clear the si_faultflags field if it
>> > detects that the signal would use the _sigfault layout, and introduce
>> > a new ptrace request type, PTRACE_SETSIGINFO2, that a si_faultflags-aware
>> > program may use to opt out of this behavior.
>> 
>> So I think while well intentioned this is misguided.
>> 
>> gdb and the like may use this but I expect the primary user is CRIU
>> which simply reads the signal out of one process saves it on disk
>> and then restores the signal as read into the new process (possibly
>> on a different machine).
>> 
>> At least for the CRIU usage PTRACE_SETSIGINFO need to remain a raw
>> pass through kind of operation.
>
> This is a problem, though.
>
> How can we tell the difference between a siginfo that was generated by
> the kernel and a siginfo that was generated (or altered) by a non-xflags
> aware userspace?
>
> Short of revving the whole API, I don't see a simple solution to this.

Unlike receiving a signal.  We do know that userspace old and new
always sends unused fields as zero into PTRACE_SETSIGINFO.

The split into kernel_siginfo verifies this and fails userspace if it
does something different.  No problems have been reported.

So in the case of xflags a non-xflags aware userspace would either pass
the siginfo from through from somewhere else (such as
PTRACE_GETSIGINFO), or it would simply generate a signal with all of
the xflags bits clear.  So everything should work regardless.

> Although a bit of a hack, could we include some kind of checksum in the
> siginfo?  If the checksum matches during PTRACE_SETSIGINFO, we could
> accept the whole thing; xflags included.  Otherwise, we could silently
> drop non-self-describing extensions.
>
> If we only need to generate the checksum when PTRACE_GETSIGINFO is
> called then it might be feasible to use a strong hash; otherwise, this
> mechanism will be far from bulletproof.
>
> A hash has the advantage that we don't need any other information
> to validate it beyond a salt: if the hash matches, it's self-
> validating.  We could also package other data with it to describe the
> presence of extensions, but relying on this for regular sigaction()/
> signal delivery use feels too high-overhead.
>
> For debuggers, I suspect that PTRACE_SETSIGINFO2 is still useful:
> userspace callers that want to write an extension field that they
> knowingly generated themselves should have a way to express that.
>
> Thoughts?

I think there are two cases:
1) CRIU  -- It is just a passthrough of PTRACE_GETSIGINFO
2) Creating a signal from nowhere -- Code that does not know about
   xflags would leave xflags at 0 so no problem.

Does anyone see any other cases I am missing?

Eric

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

* Re: [PATCH v14 7/8] signal: define the field siginfo.si_faultflags
@ 2020-11-11 20:15         ` Eric W. Biederman
  0 siblings, 0 replies; 64+ messages in thread
From: Eric W. Biederman @ 2020-11-11 20:15 UTC (permalink / raw)
  To: Dave Martin
  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,
	Richard Henderson

Dave Martin <Dave.Martin@arm.com> writes:

> On Mon, Nov 09, 2020 at 07:57:33PM -0600, Eric W. Biederman wrote:
>> Peter Collingbourne <pcc@google.com> writes:
>> 
>> > This field will contain flags that may be used by signal handlers to
>> > determine whether other fields in the _sigfault portion of siginfo are
>> > valid. An example use case is the following patch, which introduces
>> > the si_addr_tag_bits{,_mask} fields.
>> >
>> > A new sigcontext flag, SA_FAULTFLAGS, is introduced in order to allow
>> > a signal handler to require the kernel to set the field (but note
>> > that the field will be set anyway if the kernel supports the flag,
>> > regardless of its value). In combination with the previous patches,
>> > this allows a userspace program to determine whether the kernel will
>> > set the field.
>> >
>> > It is possible for an si_faultflags-unaware program to cause a signal
>> > handler in an si_faultflags-aware program to be called with a provided
>> > siginfo data structure by using one of the following syscalls:
>> >
>> > - ptrace(PTRACE_SETSIGINFO)
>> > - pidfd_send_signal
>> > - rt_sigqueueinfo
>> > - rt_tgsigqueueinfo
>> >
>> > So we need to prevent the si_faultflags-unaware program from causing an
>> > uninitialized read of si_faultflags in the si_faultflags-aware program when
>> > it uses one of these syscalls.
>> >
>> > The last three cases can be handled by observing that each of these
>> > syscalls fails if si_code >= 0. We also observe that kill(2) and
>> > tgkill(2) may be used to send a signal where si_code == 0 (SI_USER),
>> > so we define si_faultflags to only be valid if si_code > 0.
>> >
>> > There is no such check on si_code in ptrace(PTRACE_SETSIGINFO), so
>> > we make ptrace(PTRACE_SETSIGINFO) clear the si_faultflags field if it
>> > detects that the signal would use the _sigfault layout, and introduce
>> > a new ptrace request type, PTRACE_SETSIGINFO2, that a si_faultflags-aware
>> > program may use to opt out of this behavior.
>> 
>> So I think while well intentioned this is misguided.
>> 
>> gdb and the like may use this but I expect the primary user is CRIU
>> which simply reads the signal out of one process saves it on disk
>> and then restores the signal as read into the new process (possibly
>> on a different machine).
>> 
>> At least for the CRIU usage PTRACE_SETSIGINFO need to remain a raw
>> pass through kind of operation.
>
> This is a problem, though.
>
> How can we tell the difference between a siginfo that was generated by
> the kernel and a siginfo that was generated (or altered) by a non-xflags
> aware userspace?
>
> Short of revving the whole API, I don't see a simple solution to this.

Unlike receiving a signal.  We do know that userspace old and new
always sends unused fields as zero into PTRACE_SETSIGINFO.

The split into kernel_siginfo verifies this and fails userspace if it
does something different.  No problems have been reported.

So in the case of xflags a non-xflags aware userspace would either pass
the siginfo from through from somewhere else (such as
PTRACE_GETSIGINFO), or it would simply generate a signal with all of
the xflags bits clear.  So everything should work regardless.

> Although a bit of a hack, could we include some kind of checksum in the
> siginfo?  If the checksum matches during PTRACE_SETSIGINFO, we could
> accept the whole thing; xflags included.  Otherwise, we could silently
> drop non-self-describing extensions.
>
> If we only need to generate the checksum when PTRACE_GETSIGINFO is
> called then it might be feasible to use a strong hash; otherwise, this
> mechanism will be far from bulletproof.
>
> A hash has the advantage that we don't need any other information
> to validate it beyond a salt: if the hash matches, it's self-
> validating.  We could also package other data with it to describe the
> presence of extensions, but relying on this for regular sigaction()/
> signal delivery use feels too high-overhead.
>
> For debuggers, I suspect that PTRACE_SETSIGINFO2 is still useful:
> userspace callers that want to write an extension field that they
> knowingly generated themselves should have a way to express that.
>
> Thoughts?

I think there are two cases:
1) CRIU  -- It is just a passthrough of PTRACE_GETSIGINFO
2) Creating a signal from nowhere -- Code that does not know about
   xflags would leave xflags at 0 so no problem.

Does anyone see any other cases I am missing?

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

* Re: [PATCH v14 7/8] signal: define the field siginfo.si_faultflags
  2020-11-11 20:15         ` Eric W. Biederman
@ 2020-11-11 20:28           ` Eric W. Biederman
  -1 siblings, 0 replies; 64+ messages in thread
From: Eric W. Biederman @ 2020-11-11 20:28 UTC (permalink / raw)
  To: Dave Martin
  Cc: Peter Collingbourne, Catalin Marinas, Evgenii Stepanov,
	Kostya Serebryany, Vincenzo Frascino, Will Deacon, Oleg Nesterov,
	James E.J. Bottomley, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-api, Helge Deller, David Spickett

ebiederm@xmission.com (Eric W. Biederman) writes:

> Dave Martin <Dave.Martin@arm.com> writes:
>
>> On Mon, Nov 09, 2020 at 07:57:33PM -0600, Eric W. Biederman wrote:
>>> Peter Collingbourne <pcc@google.com> writes:
>>> 
>>> > This field will contain flags that may be used by signal handlers to
>>> > determine whether other fields in the _sigfault portion of siginfo are
>>> > valid. An example use case is the following patch, which introduces
>>> > the si_addr_tag_bits{,_mask} fields.
>>> >
>>> > A new sigcontext flag, SA_FAULTFLAGS, is introduced in order to allow
>>> > a signal handler to require the kernel to set the field (but note
>>> > that the field will be set anyway if the kernel supports the flag,
>>> > regardless of its value). In combination with the previous patches,
>>> > this allows a userspace program to determine whether the kernel will
>>> > set the field.
>>> >
>>> > It is possible for an si_faultflags-unaware program to cause a signal
>>> > handler in an si_faultflags-aware program to be called with a provided
>>> > siginfo data structure by using one of the following syscalls:
>>> >
>>> > - ptrace(PTRACE_SETSIGINFO)
>>> > - pidfd_send_signal
>>> > - rt_sigqueueinfo
>>> > - rt_tgsigqueueinfo
>>> >
>>> > So we need to prevent the si_faultflags-unaware program from causing an
>>> > uninitialized read of si_faultflags in the si_faultflags-aware program when
>>> > it uses one of these syscalls.
>>> >
>>> > The last three cases can be handled by observing that each of these
>>> > syscalls fails if si_code >= 0. We also observe that kill(2) and
>>> > tgkill(2) may be used to send a signal where si_code == 0 (SI_USER),
>>> > so we define si_faultflags to only be valid if si_code > 0.
>>> >
>>> > There is no such check on si_code in ptrace(PTRACE_SETSIGINFO), so
>>> > we make ptrace(PTRACE_SETSIGINFO) clear the si_faultflags field if it
>>> > detects that the signal would use the _sigfault layout, and introduce
>>> > a new ptrace request type, PTRACE_SETSIGINFO2, that a si_faultflags-aware
>>> > program may use to opt out of this behavior.
>>> 
>>> So I think while well intentioned this is misguided.
>>> 
>>> gdb and the like may use this but I expect the primary user is CRIU
>>> which simply reads the signal out of one process saves it on disk
>>> and then restores the signal as read into the new process (possibly
>>> on a different machine).
>>> 
>>> At least for the CRIU usage PTRACE_SETSIGINFO need to remain a raw
>>> pass through kind of operation.
>>
>> This is a problem, though.
>>
>> How can we tell the difference between a siginfo that was generated by
>> the kernel and a siginfo that was generated (or altered) by a non-xflags
>> aware userspace?
>>
>> Short of revving the whole API, I don't see a simple solution to this.
>
> Unlike receiving a signal.  We do know that userspace old and new
> always sends unused fields as zero into PTRACE_SETSIGINFO.
>
> The split into kernel_siginfo verifies this and fails userspace if it
> does something different.  No problems have been reported.
>
> So in the case of xflags a non-xflags aware userspace would either pass
> the siginfo from through from somewhere else (such as
> PTRACE_GETSIGINFO), or it would simply generate a signal with all of
> the xflags bits clear.  So everything should work regardless.
>
>> Although a bit of a hack, could we include some kind of checksum in the
>> siginfo?  If the checksum matches during PTRACE_SETSIGINFO, we could
>> accept the whole thing; xflags included.  Otherwise, we could silently
>> drop non-self-describing extensions.
>>
>> If we only need to generate the checksum when PTRACE_GETSIGINFO is
>> called then it might be feasible to use a strong hash; otherwise, this
>> mechanism will be far from bulletproof.
>>
>> A hash has the advantage that we don't need any other information
>> to validate it beyond a salt: if the hash matches, it's self-
>> validating.  We could also package other data with it to describe the
>> presence of extensions, but relying on this for regular sigaction()/
>> signal delivery use feels too high-overhead.
>>
>> For debuggers, I suspect that PTRACE_SETSIGINFO2 is still useful:
>> userspace callers that want to write an extension field that they
>> knowingly generated themselves should have a way to express that.
>>
>> Thoughts?
>
> I think there are two cases:
> 1) CRIU  -- It is just a passthrough of PTRACE_GETSIGINFO
> 2) Creating a signal from nowhere -- Code that does not know about
>    xflags would leave xflags at 0 so no problem.
>
> Does anyone see any other cases I am missing?
>

Zoinks.  I forgot to read and double check the code I wrote.

copy_siginfo_from_user only verifies against 0 when we don't know the
layout.  So I don't know if we can count on userspace providing the
extra data as 0 or not.

So if we do indeed continue to need xflags we might care.

It is currently an undefined non-sense case to provide non-zero fields
there.  So I think it is reasonable to expect even debuggers generating
signals to set those fields to know values such as 0.

Further I expect it is rare for debuggers to generate pretend faults.

So I would say perform whatever testing we can, so that there are no
obvious problem users of PTRACE_SETSIGINFO and then to simply not worry
about the PTRACE_SETSIGINFO unless someone reports a regression.

But fist let's see if we really need xflags at all.

Eric


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

* Re: [PATCH v14 7/8] signal: define the field siginfo.si_faultflags
@ 2020-11-11 20:28           ` Eric W. Biederman
  0 siblings, 0 replies; 64+ messages in thread
From: Eric W. Biederman @ 2020-11-11 20:28 UTC (permalink / raw)
  To: Dave Martin
  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,
	Richard Henderson

ebiederm@xmission.com (Eric W. Biederman) writes:

> Dave Martin <Dave.Martin@arm.com> writes:
>
>> On Mon, Nov 09, 2020 at 07:57:33PM -0600, Eric W. Biederman wrote:
>>> Peter Collingbourne <pcc@google.com> writes:
>>> 
>>> > This field will contain flags that may be used by signal handlers to
>>> > determine whether other fields in the _sigfault portion of siginfo are
>>> > valid. An example use case is the following patch, which introduces
>>> > the si_addr_tag_bits{,_mask} fields.
>>> >
>>> > A new sigcontext flag, SA_FAULTFLAGS, is introduced in order to allow
>>> > a signal handler to require the kernel to set the field (but note
>>> > that the field will be set anyway if the kernel supports the flag,
>>> > regardless of its value). In combination with the previous patches,
>>> > this allows a userspace program to determine whether the kernel will
>>> > set the field.
>>> >
>>> > It is possible for an si_faultflags-unaware program to cause a signal
>>> > handler in an si_faultflags-aware program to be called with a provided
>>> > siginfo data structure by using one of the following syscalls:
>>> >
>>> > - ptrace(PTRACE_SETSIGINFO)
>>> > - pidfd_send_signal
>>> > - rt_sigqueueinfo
>>> > - rt_tgsigqueueinfo
>>> >
>>> > So we need to prevent the si_faultflags-unaware program from causing an
>>> > uninitialized read of si_faultflags in the si_faultflags-aware program when
>>> > it uses one of these syscalls.
>>> >
>>> > The last three cases can be handled by observing that each of these
>>> > syscalls fails if si_code >= 0. We also observe that kill(2) and
>>> > tgkill(2) may be used to send a signal where si_code == 0 (SI_USER),
>>> > so we define si_faultflags to only be valid if si_code > 0.
>>> >
>>> > There is no such check on si_code in ptrace(PTRACE_SETSIGINFO), so
>>> > we make ptrace(PTRACE_SETSIGINFO) clear the si_faultflags field if it
>>> > detects that the signal would use the _sigfault layout, and introduce
>>> > a new ptrace request type, PTRACE_SETSIGINFO2, that a si_faultflags-aware
>>> > program may use to opt out of this behavior.
>>> 
>>> So I think while well intentioned this is misguided.
>>> 
>>> gdb and the like may use this but I expect the primary user is CRIU
>>> which simply reads the signal out of one process saves it on disk
>>> and then restores the signal as read into the new process (possibly
>>> on a different machine).
>>> 
>>> At least for the CRIU usage PTRACE_SETSIGINFO need to remain a raw
>>> pass through kind of operation.
>>
>> This is a problem, though.
>>
>> How can we tell the difference between a siginfo that was generated by
>> the kernel and a siginfo that was generated (or altered) by a non-xflags
>> aware userspace?
>>
>> Short of revving the whole API, I don't see a simple solution to this.
>
> Unlike receiving a signal.  We do know that userspace old and new
> always sends unused fields as zero into PTRACE_SETSIGINFO.
>
> The split into kernel_siginfo verifies this and fails userspace if it
> does something different.  No problems have been reported.
>
> So in the case of xflags a non-xflags aware userspace would either pass
> the siginfo from through from somewhere else (such as
> PTRACE_GETSIGINFO), or it would simply generate a signal with all of
> the xflags bits clear.  So everything should work regardless.
>
>> Although a bit of a hack, could we include some kind of checksum in the
>> siginfo?  If the checksum matches during PTRACE_SETSIGINFO, we could
>> accept the whole thing; xflags included.  Otherwise, we could silently
>> drop non-self-describing extensions.
>>
>> If we only need to generate the checksum when PTRACE_GETSIGINFO is
>> called then it might be feasible to use a strong hash; otherwise, this
>> mechanism will be far from bulletproof.
>>
>> A hash has the advantage that we don't need any other information
>> to validate it beyond a salt: if the hash matches, it's self-
>> validating.  We could also package other data with it to describe the
>> presence of extensions, but relying on this for regular sigaction()/
>> signal delivery use feels too high-overhead.
>>
>> For debuggers, I suspect that PTRACE_SETSIGINFO2 is still useful:
>> userspace callers that want to write an extension field that they
>> knowingly generated themselves should have a way to express that.
>>
>> Thoughts?
>
> I think there are two cases:
> 1) CRIU  -- It is just a passthrough of PTRACE_GETSIGINFO
> 2) Creating a signal from nowhere -- Code that does not know about
>    xflags would leave xflags at 0 so no problem.
>
> Does anyone see any other cases I am missing?
>

Zoinks.  I forgot to read and double check the code I wrote.

copy_siginfo_from_user only verifies against 0 when we don't know the
layout.  So I don't know if we can count on userspace providing the
extra data as 0 or not.

So if we do indeed continue to need xflags we might care.

It is currently an undefined non-sense case to provide non-zero fields
there.  So I think it is reasonable to expect even debuggers generating
signals to set those fields to know values such as 0.

Further I expect it is rare for debuggers to generate pretend faults.

So I would say perform whatever testing we can, so that there are no
obvious problem users of PTRACE_SETSIGINFO and then to simply not worry
about the PTRACE_SETSIGINFO unless someone reports a regression.

But fist let's see if we really need xflags at all.

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

* Re: [PATCH v14 7/8] signal: define the field siginfo.si_faultflags
  2020-11-11 11:10       ` Haren Myneni
@ 2020-11-11 20:46         ` Eric W. Biederman
  -1 siblings, 0 replies; 64+ messages in thread
From: Eric W. Biederman @ 2020-11-11 20:46 UTC (permalink / raw)
  To: Haren Myneni
  Cc: Peter Collingbourne, Catalin Marinas, Evgenii Stepanov,
	Kostya Serebryany, Vincenzo Frascino, Dave Martin, Will Deacon,
	Oleg Nesterov, James E.J. Bottomley, Linux ARM, Kevin Brodsky,
	Andrey Konovalov, Richard Henderson, linux-api, Helge Deller,
	David Spickett, Sukadev Bhattiprolu, Michael Ellerman, npiggin

Haren Myneni <haren@linux.ibm.com> writes:

> On Mon, 2020-11-09 at 19:54 -0600, Eric W. Biederman wrote:
>> Peter you are patching buggy code for your siginfo extension can
>> you please ignore vas-fault.c.  The code in vas-fault.c should
>> be fixed separately.  Futher it uses clear_siginfo so you should
>> get well defined behavior even if your new field is not initialized.
>> 
>> I have copied the powerpc folks so hopefully this buggy code
>> can be fixed.
>> 
>> > diff --git a/arch/powerpc/platforms/powernv/vas-fault.c
>> > b/arch/powerpc/platforms/powernv/vas-fault.c
>> > index 3d21fce254b7..877e7d5fb4a2 100644
>> > --- a/arch/powerpc/platforms/powernv/vas-fault.c
>> > +++ b/arch/powerpc/platforms/powernv/vas-fault.c
>> > @@ -154,6 +154,7 @@ static void update_csb(struct vas_window
>> > *window,
>> >  	info.si_errno = EFAULT;
>> >  	info.si_code = SEGV_MAPERR;
>> >  	info.si_addr = csb_addr;
>> > +	info.si_faultflags = 0;
>> 
>
> Thanks Eric for your comments and pointing possible issues.
>
> Here is the NX coprocessor interaction with user space and kernel:
>
> - Process opens NX window / channel. The user space sends requests to
> NX without kernel involvement. This request contains data buffer and
> status block called coprocessor status block (CSB). 
> - if NX sees fault on the request buffer or on CSB address, issue an
> interrupt to kernel
> - kernel updates the CSB with the fault information and then the
> process can reissue request.
> - If the fault is on CSB address and is not a valid address, sending
> SEGV signal so that the process assign proper CSB and reissue new
> request
> - We are not seeing the invalid CSB address in the process context, but
> during handling the fault later. So thought about sending SEGV signal
> instead of killing the process since it is not a standard segfault. 
> - All these windows will be closed upon process exit, but waits
> until all pending requests are completed. So process will not exit with
> pending requests, means after all faults handled if any.

I see a lot that doesn't seem to match that description.

Consider forking a child and having that child exit, but still have
the file descriptor open.  The release method will be called.

If you consider file descriptor passing there are much more interesting
cases involved.

> - In the case of multithread applications, NX windows will be closed
> with the last thread. Means other threads can still issue requests with
> these windows. So to support in these applications, take PID and MM
> references during window open and release them later in close. 
>
>> Powerpc folks.  This code was introduced in c96c4436aba4
>> ("powerpc/vas:
>> Update CSB and notify process for fault CRBs") and is badly buggy.
>> 
>> Let me count the bugs:
>> 
>> a) Using kill_pid_info.  That performs a permission check that
>>    does not make sense from a kernel thread.
>> 
>> b) Manually filling in struct siginfo.  Everyone gets it wrong
>>    and the powerpc code is no exception setting si_errno when
>>    that is something Linux as a rule does not do.
>> 
>> Technically we have send_sig_fault to handle sending
>> a fault from a non-sychrnous context but I am not convinced
>> it make sense in this case.
>
> Yes, kill_pid_info() -> group_send_sig_info() checks permissions which
> is an extra step.  I think send_sig_fault may be used to replace the
> above steps.

Make that change at a minimum, please.

>> c) Sending an asynchronous SIGSEGV with the si_code set to
>> SEGV_MAPERR.
>>    How can userspace detect it is an asynchronous signal?  What can
>>    userspace do if it detects an asynchronous signal?  If userspace
>> is
>>    so buggered as to give your kernel thread a bogus address I
>> suspect
>>    uncerimonious sending SIGKILL is probably the best you can do.
>
> Application can assign new CSB and send new request when it catches the
> signal. For example it can use csb_addr passed in si_addr amd decide
> whether this SEGV is due to to CSB fault. Since it is an async signal,
> was thinking for the application to recover instead of killing theprocess.  

An async signal the process can recover from is fine (caveats about
exec, exit, and file descripotr passing aside).

You want something to mark this as an asynchronous event so that
userspace can tell that signal from other signals.

If only a single coprocessor is possible it could be as simple
as using a special si_code for this case.

>> There are some additional questionable things in that code like
>> taking a
>> task_struct reference simply to be able to test tsk->flags but no
>> locks are held to ensure that tsk->flags are meaningful.  Nor are
>> any tests performed to see if the task being tested still uses
>> the designated mm.  I suspect exec could have been called.
>
> tsk->flags is used to make sure not to send a signal if the task is in
> exiting. We access this task under get/put_task_struct().

The thing ins get/put_task_struct is about a reference count.  It is not
a lock.  So the task can still set PF_EXITING after you have tested it
and before you call copy_to_user.   So testing PF_EXITING gets you
practically nothing.

Further the signal delivery code can already cop with attempting to send
a signal to a task that is in PF_EXITING so I don't see the point of
trying to avoid that situation.


> Also 
> kill_pid_info() sends signal if pid_task() is available. Since we are
> taken mm reference, it can not be freed.

But task->mm can be different if the task has called exec.

> So the task has to be present until all NX windows are closed.

I don't see how that follows from anything the code does or you have
said.  The lifetime of an mm and the lifetime of a pid are independent
of the lifetime of a task.  

>> In which case the code needs to check the mm, or at least play with
>> exec_id to ensure you are not improperly signaling a process after
>> exec.
>> 
>> None of this is to say that update_csb is fundmentally bad or hard to
>> correct just that it has some significant defects in it's
>> implementation
>> right now that need to be corrected.  I am hoping a detailed
>> accounting
>> and pointing out those defects will allow the bug to be fixed.
>> 
>> Thank you,
>> Eric

Eric

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

* Re: [PATCH v14 7/8] signal: define the field siginfo.si_faultflags
@ 2020-11-11 20:46         ` Eric W. Biederman
  0 siblings, 0 replies; 64+ messages in thread
From: Eric W. Biederman @ 2020-11-11 20:46 UTC (permalink / raw)
  To: Haren Myneni
  Cc: Sukadev Bhattiprolu, Will Deacon, Michael Ellerman,
	Catalin Marinas, Helge Deller, Kevin Brodsky, npiggin,
	Oleg Nesterov, linux-api, James E.J. Bottomley,
	Kostya Serebryany, Linux ARM, Andrey Konovalov, David Spickett,
	Vincenzo Frascino, Peter Collingbourne, Dave Martin,
	Evgenii Stepanov, Richard Henderson

Haren Myneni <haren@linux.ibm.com> writes:

> On Mon, 2020-11-09 at 19:54 -0600, Eric W. Biederman wrote:
>> Peter you are patching buggy code for your siginfo extension can
>> you please ignore vas-fault.c.  The code in vas-fault.c should
>> be fixed separately.  Futher it uses clear_siginfo so you should
>> get well defined behavior even if your new field is not initialized.
>> 
>> I have copied the powerpc folks so hopefully this buggy code
>> can be fixed.
>> 
>> > diff --git a/arch/powerpc/platforms/powernv/vas-fault.c
>> > b/arch/powerpc/platforms/powernv/vas-fault.c
>> > index 3d21fce254b7..877e7d5fb4a2 100644
>> > --- a/arch/powerpc/platforms/powernv/vas-fault.c
>> > +++ b/arch/powerpc/platforms/powernv/vas-fault.c
>> > @@ -154,6 +154,7 @@ static void update_csb(struct vas_window
>> > *window,
>> >  	info.si_errno = EFAULT;
>> >  	info.si_code = SEGV_MAPERR;
>> >  	info.si_addr = csb_addr;
>> > +	info.si_faultflags = 0;
>> 
>
> Thanks Eric for your comments and pointing possible issues.
>
> Here is the NX coprocessor interaction with user space and kernel:
>
> - Process opens NX window / channel. The user space sends requests to
> NX without kernel involvement. This request contains data buffer and
> status block called coprocessor status block (CSB). 
> - if NX sees fault on the request buffer or on CSB address, issue an
> interrupt to kernel
> - kernel updates the CSB with the fault information and then the
> process can reissue request.
> - If the fault is on CSB address and is not a valid address, sending
> SEGV signal so that the process assign proper CSB and reissue new
> request
> - We are not seeing the invalid CSB address in the process context, but
> during handling the fault later. So thought about sending SEGV signal
> instead of killing the process since it is not a standard segfault. 
> - All these windows will be closed upon process exit, but waits
> until all pending requests are completed. So process will not exit with
> pending requests, means after all faults handled if any.

I see a lot that doesn't seem to match that description.

Consider forking a child and having that child exit, but still have
the file descriptor open.  The release method will be called.

If you consider file descriptor passing there are much more interesting
cases involved.

> - In the case of multithread applications, NX windows will be closed
> with the last thread. Means other threads can still issue requests with
> these windows. So to support in these applications, take PID and MM
> references during window open and release them later in close. 
>
>> Powerpc folks.  This code was introduced in c96c4436aba4
>> ("powerpc/vas:
>> Update CSB and notify process for fault CRBs") and is badly buggy.
>> 
>> Let me count the bugs:
>> 
>> a) Using kill_pid_info.  That performs a permission check that
>>    does not make sense from a kernel thread.
>> 
>> b) Manually filling in struct siginfo.  Everyone gets it wrong
>>    and the powerpc code is no exception setting si_errno when
>>    that is something Linux as a rule does not do.
>> 
>> Technically we have send_sig_fault to handle sending
>> a fault from a non-sychrnous context but I am not convinced
>> it make sense in this case.
>
> Yes, kill_pid_info() -> group_send_sig_info() checks permissions which
> is an extra step.  I think send_sig_fault may be used to replace the
> above steps.

Make that change at a minimum, please.

>> c) Sending an asynchronous SIGSEGV with the si_code set to
>> SEGV_MAPERR.
>>    How can userspace detect it is an asynchronous signal?  What can
>>    userspace do if it detects an asynchronous signal?  If userspace
>> is
>>    so buggered as to give your kernel thread a bogus address I
>> suspect
>>    uncerimonious sending SIGKILL is probably the best you can do.
>
> Application can assign new CSB and send new request when it catches the
> signal. For example it can use csb_addr passed in si_addr amd decide
> whether this SEGV is due to to CSB fault. Since it is an async signal,
> was thinking for the application to recover instead of killing theprocess.  

An async signal the process can recover from is fine (caveats about
exec, exit, and file descripotr passing aside).

You want something to mark this as an asynchronous event so that
userspace can tell that signal from other signals.

If only a single coprocessor is possible it could be as simple
as using a special si_code for this case.

>> There are some additional questionable things in that code like
>> taking a
>> task_struct reference simply to be able to test tsk->flags but no
>> locks are held to ensure that tsk->flags are meaningful.  Nor are
>> any tests performed to see if the task being tested still uses
>> the designated mm.  I suspect exec could have been called.
>
> tsk->flags is used to make sure not to send a signal if the task is in
> exiting. We access this task under get/put_task_struct().

The thing ins get/put_task_struct is about a reference count.  It is not
a lock.  So the task can still set PF_EXITING after you have tested it
and before you call copy_to_user.   So testing PF_EXITING gets you
practically nothing.

Further the signal delivery code can already cop with attempting to send
a signal to a task that is in PF_EXITING so I don't see the point of
trying to avoid that situation.


> Also 
> kill_pid_info() sends signal if pid_task() is available. Since we are
> taken mm reference, it can not be freed.

But task->mm can be different if the task has called exec.

> So the task has to be present until all NX windows are closed.

I don't see how that follows from anything the code does or you have
said.  The lifetime of an mm and the lifetime of a pid are independent
of the lifetime of a task.  

>> In which case the code needs to check the mm, or at least play with
>> exec_id to ensure you are not improperly signaling a process after
>> exec.
>> 
>> None of this is to say that update_csb is fundmentally bad or hard to
>> correct just that it has some significant defects in it's
>> implementation
>> right now that need to be corrected.  I am hoping a detailed
>> accounting
>> and pointing out those defects will allow the bug to be fixed.
>> 
>> Thank you,
>> Eric

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

* Re: [PATCH v14 7/8] signal: define the field siginfo.si_faultflags
  2020-11-11 20:28           ` Eric W. Biederman
@ 2020-11-12 17:21             ` Dave Martin
  -1 siblings, 0 replies; 64+ messages in thread
From: Dave Martin @ 2020-11-12 17:21 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Peter Collingbourne, Catalin Marinas, Evgenii Stepanov,
	Kostya Serebryany, Vincenzo Frascino, Will Deacon, Oleg Nesterov,
	James E.J. Bottomley, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-api, Helge Deller, David Spickett

On Wed, Nov 11, 2020 at 02:28:38PM -0600, Eric W. Biederman wrote:
> ebiederm@xmission.com (Eric W. Biederman) writes:
> 
> > Dave Martin <Dave.Martin@arm.com> writes:
> >
> >> On Mon, Nov 09, 2020 at 07:57:33PM -0600, Eric W. Biederman wrote:
> >>> Peter Collingbourne <pcc@google.com> writes:
> >>> 
> >>> > This field will contain flags that may be used by signal handlers to
> >>> > determine whether other fields in the _sigfault portion of siginfo are
> >>> > valid. An example use case is the following patch, which introduces
> >>> > the si_addr_tag_bits{,_mask} fields.
> >>> >
> >>> > A new sigcontext flag, SA_FAULTFLAGS, is introduced in order to allow
> >>> > a signal handler to require the kernel to set the field (but note
> >>> > that the field will be set anyway if the kernel supports the flag,
> >>> > regardless of its value). In combination with the previous patches,
> >>> > this allows a userspace program to determine whether the kernel will
> >>> > set the field.
> >>> >
> >>> > It is possible for an si_faultflags-unaware program to cause a signal
> >>> > handler in an si_faultflags-aware program to be called with a provided
> >>> > siginfo data structure by using one of the following syscalls:
> >>> >
> >>> > - ptrace(PTRACE_SETSIGINFO)
> >>> > - pidfd_send_signal
> >>> > - rt_sigqueueinfo
> >>> > - rt_tgsigqueueinfo
> >>> >
> >>> > So we need to prevent the si_faultflags-unaware program from causing an
> >>> > uninitialized read of si_faultflags in the si_faultflags-aware program when
> >>> > it uses one of these syscalls.
> >>> >
> >>> > The last three cases can be handled by observing that each of these
> >>> > syscalls fails if si_code >= 0. We also observe that kill(2) and
> >>> > tgkill(2) may be used to send a signal where si_code == 0 (SI_USER),
> >>> > so we define si_faultflags to only be valid if si_code > 0.
> >>> >
> >>> > There is no such check on si_code in ptrace(PTRACE_SETSIGINFO), so
> >>> > we make ptrace(PTRACE_SETSIGINFO) clear the si_faultflags field if it
> >>> > detects that the signal would use the _sigfault layout, and introduce
> >>> > a new ptrace request type, PTRACE_SETSIGINFO2, that a si_faultflags-aware
> >>> > program may use to opt out of this behavior.
> >>> 
> >>> So I think while well intentioned this is misguided.
> >>> 
> >>> gdb and the like may use this but I expect the primary user is CRIU
> >>> which simply reads the signal out of one process saves it on disk
> >>> and then restores the signal as read into the new process (possibly
> >>> on a different machine).
> >>> 
> >>> At least for the CRIU usage PTRACE_SETSIGINFO need to remain a raw
> >>> pass through kind of operation.
> >>
> >> This is a problem, though.
> >>
> >> How can we tell the difference between a siginfo that was generated by
> >> the kernel and a siginfo that was generated (or altered) by a non-xflags
> >> aware userspace?
> >>
> >> Short of revving the whole API, I don't see a simple solution to this.
> >
> > Unlike receiving a signal.  We do know that userspace old and new
> > always sends unused fields as zero into PTRACE_SETSIGINFO.
> >
> > The split into kernel_siginfo verifies this and fails userspace if it
> > does something different.  No problems have been reported.
> >
> > So in the case of xflags a non-xflags aware userspace would either pass
> > the siginfo from through from somewhere else (such as
> > PTRACE_GETSIGINFO), or it would simply generate a signal with all of
> > the xflags bits clear.  So everything should work regardless.
> >
> >> Although a bit of a hack, could we include some kind of checksum in the
> >> siginfo?  If the checksum matches during PTRACE_SETSIGINFO, we could
> >> accept the whole thing; xflags included.  Otherwise, we could silently
> >> drop non-self-describing extensions.
> >>
> >> If we only need to generate the checksum when PTRACE_GETSIGINFO is
> >> called then it might be feasible to use a strong hash; otherwise, this
> >> mechanism will be far from bulletproof.
> >>
> >> A hash has the advantage that we don't need any other information
> >> to validate it beyond a salt: if the hash matches, it's self-
> >> validating.  We could also package other data with it to describe the
> >> presence of extensions, but relying on this for regular sigaction()/
> >> signal delivery use feels too high-overhead.
> >>
> >> For debuggers, I suspect that PTRACE_SETSIGINFO2 is still useful:
> >> userspace callers that want to write an extension field that they
> >> knowingly generated themselves should have a way to express that.
> >>
> >> Thoughts?
> >
> > I think there are two cases:
> > 1) CRIU  -- It is just a passthrough of PTRACE_GETSIGINFO
> > 2) Creating a signal from nowhere -- Code that does not know about
> >    xflags would leave xflags at 0 so no problem.
> >
> > Does anyone see any other cases I am missing?
> >
> 
> Zoinks.  I forgot to read and double check the code I wrote.
> 
> copy_siginfo_from_user only verifies against 0 when we don't know the
> layout.  So I don't know if we can count on userspace providing the
> extra data as 0 or not.
> 
> So if we do indeed continue to need xflags we might care.
>
> It is currently an undefined non-sense case to provide non-zero fields
> there.  So I think it is reasonable to expect even debuggers generating
> signals to set those fields to know values such as 0.

You may well be right that the only time extra fields coming from
userspace should be deliberately nonzero is in the passthrough case.

I'm still concerned about padding or type-punning issues causing
unallocated fields to be initialised with junk, even in the presence of
a memset(0).  I haven't actually seen this happen, but the language
standards seem to allow it and compilers may get more aggressive in the
future.

This is why I think we still want an explicit way for userspace to
indicate what extension fields initialised.

Am I missing something that eliminates the danger today?

> Further I expect it is rare for debuggers to generate pretend faults.

That seems a reasonable assumption.  Hand-rolling a fault siginfo seems
a pretty fragile thing to do, if it works reliably at all.

> So I would say perform whatever testing we can, so that there are no
> obvious problem users of PTRACE_SETSIGINFO and then to simply not worry
> about the PTRACE_SETSIGINFO unless someone reports a regression.
> 
> But fist let's see if we really need xflags at all.
> 
> Eric

Ack

Cheers
---Dave

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

* Re: [PATCH v14 7/8] signal: define the field siginfo.si_faultflags
@ 2020-11-12 17:21             ` Dave Martin
  0 siblings, 0 replies; 64+ messages in thread
From: Dave Martin @ 2020-11-12 17:21 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,
	Richard Henderson

On Wed, Nov 11, 2020 at 02:28:38PM -0600, Eric W. Biederman wrote:
> ebiederm@xmission.com (Eric W. Biederman) writes:
> 
> > Dave Martin <Dave.Martin@arm.com> writes:
> >
> >> On Mon, Nov 09, 2020 at 07:57:33PM -0600, Eric W. Biederman wrote:
> >>> Peter Collingbourne <pcc@google.com> writes:
> >>> 
> >>> > This field will contain flags that may be used by signal handlers to
> >>> > determine whether other fields in the _sigfault portion of siginfo are
> >>> > valid. An example use case is the following patch, which introduces
> >>> > the si_addr_tag_bits{,_mask} fields.
> >>> >
> >>> > A new sigcontext flag, SA_FAULTFLAGS, is introduced in order to allow
> >>> > a signal handler to require the kernel to set the field (but note
> >>> > that the field will be set anyway if the kernel supports the flag,
> >>> > regardless of its value). In combination with the previous patches,
> >>> > this allows a userspace program to determine whether the kernel will
> >>> > set the field.
> >>> >
> >>> > It is possible for an si_faultflags-unaware program to cause a signal
> >>> > handler in an si_faultflags-aware program to be called with a provided
> >>> > siginfo data structure by using one of the following syscalls:
> >>> >
> >>> > - ptrace(PTRACE_SETSIGINFO)
> >>> > - pidfd_send_signal
> >>> > - rt_sigqueueinfo
> >>> > - rt_tgsigqueueinfo
> >>> >
> >>> > So we need to prevent the si_faultflags-unaware program from causing an
> >>> > uninitialized read of si_faultflags in the si_faultflags-aware program when
> >>> > it uses one of these syscalls.
> >>> >
> >>> > The last three cases can be handled by observing that each of these
> >>> > syscalls fails if si_code >= 0. We also observe that kill(2) and
> >>> > tgkill(2) may be used to send a signal where si_code == 0 (SI_USER),
> >>> > so we define si_faultflags to only be valid if si_code > 0.
> >>> >
> >>> > There is no such check on si_code in ptrace(PTRACE_SETSIGINFO), so
> >>> > we make ptrace(PTRACE_SETSIGINFO) clear the si_faultflags field if it
> >>> > detects that the signal would use the _sigfault layout, and introduce
> >>> > a new ptrace request type, PTRACE_SETSIGINFO2, that a si_faultflags-aware
> >>> > program may use to opt out of this behavior.
> >>> 
> >>> So I think while well intentioned this is misguided.
> >>> 
> >>> gdb and the like may use this but I expect the primary user is CRIU
> >>> which simply reads the signal out of one process saves it on disk
> >>> and then restores the signal as read into the new process (possibly
> >>> on a different machine).
> >>> 
> >>> At least for the CRIU usage PTRACE_SETSIGINFO need to remain a raw
> >>> pass through kind of operation.
> >>
> >> This is a problem, though.
> >>
> >> How can we tell the difference between a siginfo that was generated by
> >> the kernel and a siginfo that was generated (or altered) by a non-xflags
> >> aware userspace?
> >>
> >> Short of revving the whole API, I don't see a simple solution to this.
> >
> > Unlike receiving a signal.  We do know that userspace old and new
> > always sends unused fields as zero into PTRACE_SETSIGINFO.
> >
> > The split into kernel_siginfo verifies this and fails userspace if it
> > does something different.  No problems have been reported.
> >
> > So in the case of xflags a non-xflags aware userspace would either pass
> > the siginfo from through from somewhere else (such as
> > PTRACE_GETSIGINFO), or it would simply generate a signal with all of
> > the xflags bits clear.  So everything should work regardless.
> >
> >> Although a bit of a hack, could we include some kind of checksum in the
> >> siginfo?  If the checksum matches during PTRACE_SETSIGINFO, we could
> >> accept the whole thing; xflags included.  Otherwise, we could silently
> >> drop non-self-describing extensions.
> >>
> >> If we only need to generate the checksum when PTRACE_GETSIGINFO is
> >> called then it might be feasible to use a strong hash; otherwise, this
> >> mechanism will be far from bulletproof.
> >>
> >> A hash has the advantage that we don't need any other information
> >> to validate it beyond a salt: if the hash matches, it's self-
> >> validating.  We could also package other data with it to describe the
> >> presence of extensions, but relying on this for regular sigaction()/
> >> signal delivery use feels too high-overhead.
> >>
> >> For debuggers, I suspect that PTRACE_SETSIGINFO2 is still useful:
> >> userspace callers that want to write an extension field that they
> >> knowingly generated themselves should have a way to express that.
> >>
> >> Thoughts?
> >
> > I think there are two cases:
> > 1) CRIU  -- It is just a passthrough of PTRACE_GETSIGINFO
> > 2) Creating a signal from nowhere -- Code that does not know about
> >    xflags would leave xflags at 0 so no problem.
> >
> > Does anyone see any other cases I am missing?
> >
> 
> Zoinks.  I forgot to read and double check the code I wrote.
> 
> copy_siginfo_from_user only verifies against 0 when we don't know the
> layout.  So I don't know if we can count on userspace providing the
> extra data as 0 or not.
> 
> So if we do indeed continue to need xflags we might care.
>
> It is currently an undefined non-sense case to provide non-zero fields
> there.  So I think it is reasonable to expect even debuggers generating
> signals to set those fields to know values such as 0.

You may well be right that the only time extra fields coming from
userspace should be deliberately nonzero is in the passthrough case.

I'm still concerned about padding or type-punning issues causing
unallocated fields to be initialised with junk, even in the presence of
a memset(0).  I haven't actually seen this happen, but the language
standards seem to allow it and compilers may get more aggressive in the
future.

This is why I think we still want an explicit way for userspace to
indicate what extension fields initialised.

Am I missing something that eliminates the danger today?

> Further I expect it is rare for debuggers to generate pretend faults.

That seems a reasonable assumption.  Hand-rolling a fault siginfo seems
a pretty fragile thing to do, if it works reliably at all.

> So I would say perform whatever testing we can, so that there are no
> obvious problem users of PTRACE_SETSIGINFO and then to simply not worry
> about the PTRACE_SETSIGINFO unless someone reports a regression.
> 
> But fist let's see if we really need xflags at all.
> 
> Eric

Ack

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

* Re: [PATCH v14 7/8] signal: define the field siginfo.si_faultflags
  2020-11-11 20:15         ` Eric W. Biederman
@ 2020-11-12 17:23           ` Dave Martin
  -1 siblings, 0 replies; 64+ messages in thread
From: Dave Martin @ 2020-11-12 17:23 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Peter Collingbourne, Catalin Marinas, Evgenii Stepanov,
	Kostya Serebryany, Vincenzo Frascino, Will Deacon, Oleg Nesterov,
	James E.J. Bottomley, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-api, Helge Deller, David Spickett

On Wed, Nov 11, 2020 at 02:15:15PM -0600, Eric W. Biederman wrote:
> Dave Martin <Dave.Martin@arm.com> writes:
> 
> > On Mon, Nov 09, 2020 at 07:57:33PM -0600, Eric W. Biederman wrote:
> >> Peter Collingbourne <pcc@google.com> writes:
> >> 
> >> > This field will contain flags that may be used by signal handlers to
> >> > determine whether other fields in the _sigfault portion of siginfo are
> >> > valid. An example use case is the following patch, which introduces
> >> > the si_addr_tag_bits{,_mask} fields.
> >> >
> >> > A new sigcontext flag, SA_FAULTFLAGS, is introduced in order to allow
> >> > a signal handler to require the kernel to set the field (but note
> >> > that the field will be set anyway if the kernel supports the flag,
> >> > regardless of its value). In combination with the previous patches,
> >> > this allows a userspace program to determine whether the kernel will
> >> > set the field.
> >> >
> >> > It is possible for an si_faultflags-unaware program to cause a signal
> >> > handler in an si_faultflags-aware program to be called with a provided
> >> > siginfo data structure by using one of the following syscalls:
> >> >
> >> > - ptrace(PTRACE_SETSIGINFO)
> >> > - pidfd_send_signal
> >> > - rt_sigqueueinfo
> >> > - rt_tgsigqueueinfo
> >> >
> >> > So we need to prevent the si_faultflags-unaware program from causing an
> >> > uninitialized read of si_faultflags in the si_faultflags-aware program when
> >> > it uses one of these syscalls.
> >> >
> >> > The last three cases can be handled by observing that each of these
> >> > syscalls fails if si_code >= 0. We also observe that kill(2) and
> >> > tgkill(2) may be used to send a signal where si_code == 0 (SI_USER),
> >> > so we define si_faultflags to only be valid if si_code > 0.
> >> >
> >> > There is no such check on si_code in ptrace(PTRACE_SETSIGINFO), so
> >> > we make ptrace(PTRACE_SETSIGINFO) clear the si_faultflags field if it
> >> > detects that the signal would use the _sigfault layout, and introduce
> >> > a new ptrace request type, PTRACE_SETSIGINFO2, that a si_faultflags-aware
> >> > program may use to opt out of this behavior.
> >> 
> >> So I think while well intentioned this is misguided.
> >> 
> >> gdb and the like may use this but I expect the primary user is CRIU
> >> which simply reads the signal out of one process saves it on disk
> >> and then restores the signal as read into the new process (possibly
> >> on a different machine).
> >> 
> >> At least for the CRIU usage PTRACE_SETSIGINFO need to remain a raw
> >> pass through kind of operation.
> >
> > This is a problem, though.
> >
> > How can we tell the difference between a siginfo that was generated by
> > the kernel and a siginfo that was generated (or altered) by a non-xflags
> > aware userspace?
> >
> > Short of revving the whole API, I don't see a simple solution to this.
> 
> Unlike receiving a signal.  We do know that userspace old and new
> always sends unused fields as zero into PTRACE_SETSIGINFO.
> 
> The split into kernel_siginfo verifies this and fails userspace if it
> does something different.  No problems have been reported.
> 
> So in the case of xflags a non-xflags aware userspace would either pass
> the siginfo from through from somewhere else (such as
> PTRACE_GETSIGINFO), or it would simply generate a signal with all of
> the xflags bits clear.  So everything should work regardless.
> 
> > Although a bit of a hack, could we include some kind of checksum in the
> > siginfo?  If the checksum matches during PTRACE_SETSIGINFO, we could
> > accept the whole thing; xflags included.  Otherwise, we could silently
> > drop non-self-describing extensions.
> >
> > If we only need to generate the checksum when PTRACE_GETSIGINFO is
> > called then it might be feasible to use a strong hash; otherwise, this
> > mechanism will be far from bulletproof.
> >
> > A hash has the advantage that we don't need any other information
> > to validate it beyond a salt: if the hash matches, it's self-
> > validating.  We could also package other data with it to describe the
> > presence of extensions, but relying on this for regular sigaction()/
> > signal delivery use feels too high-overhead.
> >
> > For debuggers, I suspect that PTRACE_SETSIGINFO2 is still useful:
> > userspace callers that want to write an extension field that they
> > knowingly generated themselves should have a way to express that.
> >
> > Thoughts?

Eric, did you have any view on the hash idea here?

Cheers
---Dave

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

* Re: [PATCH v14 7/8] signal: define the field siginfo.si_faultflags
@ 2020-11-12 17:23           ` Dave Martin
  0 siblings, 0 replies; 64+ messages in thread
From: Dave Martin @ 2020-11-12 17:23 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,
	Richard Henderson

On Wed, Nov 11, 2020 at 02:15:15PM -0600, Eric W. Biederman wrote:
> Dave Martin <Dave.Martin@arm.com> writes:
> 
> > On Mon, Nov 09, 2020 at 07:57:33PM -0600, Eric W. Biederman wrote:
> >> Peter Collingbourne <pcc@google.com> writes:
> >> 
> >> > This field will contain flags that may be used by signal handlers to
> >> > determine whether other fields in the _sigfault portion of siginfo are
> >> > valid. An example use case is the following patch, which introduces
> >> > the si_addr_tag_bits{,_mask} fields.
> >> >
> >> > A new sigcontext flag, SA_FAULTFLAGS, is introduced in order to allow
> >> > a signal handler to require the kernel to set the field (but note
> >> > that the field will be set anyway if the kernel supports the flag,
> >> > regardless of its value). In combination with the previous patches,
> >> > this allows a userspace program to determine whether the kernel will
> >> > set the field.
> >> >
> >> > It is possible for an si_faultflags-unaware program to cause a signal
> >> > handler in an si_faultflags-aware program to be called with a provided
> >> > siginfo data structure by using one of the following syscalls:
> >> >
> >> > - ptrace(PTRACE_SETSIGINFO)
> >> > - pidfd_send_signal
> >> > - rt_sigqueueinfo
> >> > - rt_tgsigqueueinfo
> >> >
> >> > So we need to prevent the si_faultflags-unaware program from causing an
> >> > uninitialized read of si_faultflags in the si_faultflags-aware program when
> >> > it uses one of these syscalls.
> >> >
> >> > The last three cases can be handled by observing that each of these
> >> > syscalls fails if si_code >= 0. We also observe that kill(2) and
> >> > tgkill(2) may be used to send a signal where si_code == 0 (SI_USER),
> >> > so we define si_faultflags to only be valid if si_code > 0.
> >> >
> >> > There is no such check on si_code in ptrace(PTRACE_SETSIGINFO), so
> >> > we make ptrace(PTRACE_SETSIGINFO) clear the si_faultflags field if it
> >> > detects that the signal would use the _sigfault layout, and introduce
> >> > a new ptrace request type, PTRACE_SETSIGINFO2, that a si_faultflags-aware
> >> > program may use to opt out of this behavior.
> >> 
> >> So I think while well intentioned this is misguided.
> >> 
> >> gdb and the like may use this but I expect the primary user is CRIU
> >> which simply reads the signal out of one process saves it on disk
> >> and then restores the signal as read into the new process (possibly
> >> on a different machine).
> >> 
> >> At least for the CRIU usage PTRACE_SETSIGINFO need to remain a raw
> >> pass through kind of operation.
> >
> > This is a problem, though.
> >
> > How can we tell the difference between a siginfo that was generated by
> > the kernel and a siginfo that was generated (or altered) by a non-xflags
> > aware userspace?
> >
> > Short of revving the whole API, I don't see a simple solution to this.
> 
> Unlike receiving a signal.  We do know that userspace old and new
> always sends unused fields as zero into PTRACE_SETSIGINFO.
> 
> The split into kernel_siginfo verifies this and fails userspace if it
> does something different.  No problems have been reported.
> 
> So in the case of xflags a non-xflags aware userspace would either pass
> the siginfo from through from somewhere else (such as
> PTRACE_GETSIGINFO), or it would simply generate a signal with all of
> the xflags bits clear.  So everything should work regardless.
> 
> > Although a bit of a hack, could we include some kind of checksum in the
> > siginfo?  If the checksum matches during PTRACE_SETSIGINFO, we could
> > accept the whole thing; xflags included.  Otherwise, we could silently
> > drop non-self-describing extensions.
> >
> > If we only need to generate the checksum when PTRACE_GETSIGINFO is
> > called then it might be feasible to use a strong hash; otherwise, this
> > mechanism will be far from bulletproof.
> >
> > A hash has the advantage that we don't need any other information
> > to validate it beyond a salt: if the hash matches, it's self-
> > validating.  We could also package other data with it to describe the
> > presence of extensions, but relying on this for regular sigaction()/
> > signal delivery use feels too high-overhead.
> >
> > For debuggers, I suspect that PTRACE_SETSIGINFO2 is still useful:
> > userspace callers that want to write an extension field that they
> > knowingly generated themselves should have a way to express that.
> >
> > Thoughts?

Eric, did you have any view on the hash idea here?

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

* Re: [PATCH v14 8/8] arm64: expose FAR_EL1 tag bits in siginfo
  2020-11-10  1:13     ` Eric W. Biederman
@ 2020-11-12 18:53       ` Catalin Marinas
  -1 siblings, 0 replies; 64+ messages in thread
From: Catalin Marinas @ 2020-11-12 18:53 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Peter Collingbourne, Evgenii Stepanov, Kostya Serebryany,
	Vincenzo Frascino, Dave Martin, Will Deacon, Oleg Nesterov,
	James E.J. Bottomley, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-api, Helge Deller, David Spickett

On Mon, Nov 09, 2020 at 07:13:08PM -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, create a new pair of
> > fields in siginfo._sigfault, and store the tag bits of FAR_EL1 there,
> > together with a mask specifying which bits are valid.
> >
> > A flag is added to si_faultflags to allow userspace to determine whether
> > the values in the fields are valid.
[...]
> What prevents adding a sigaction sa_flag SA_EXPOSE_TABITS that when set
> causes the high bits to be set, and when clear (the default) will have
> the signal delivery code clear those bits.

Thanks for the review so far Eric.

If the SA_EXPOSE_TAGBITS idea works, I'd much rather have that than the
ultra generic xflags approach.

Given that Peter is going to rework this part, could you please pick the
first clean-up patches via your tree? If there are dependencies with the
reworked arm64 patches, I'm also happy for them to go via your tree.

Thanks.

-- 
Catalin

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

* Re: [PATCH v14 8/8] arm64: expose FAR_EL1 tag bits in siginfo
@ 2020-11-12 18:53       ` Catalin Marinas
  0 siblings, 0 replies; 64+ messages in thread
From: Catalin Marinas @ 2020-11-12 18:53 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, Richard Henderson

On Mon, Nov 09, 2020 at 07:13:08PM -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, create a new pair of
> > fields in siginfo._sigfault, and store the tag bits of FAR_EL1 there,
> > together with a mask specifying which bits are valid.
> >
> > A flag is added to si_faultflags to allow userspace to determine whether
> > the values in the fields are valid.
[...]
> What prevents adding a sigaction sa_flag SA_EXPOSE_TABITS that when set
> causes the high bits to be set, and when clear (the default) will have
> the signal delivery code clear those bits.

Thanks for the review so far Eric.

If the SA_EXPOSE_TAGBITS idea works, I'd much rather have that than the
ultra generic xflags approach.

Given that Peter is going to rework this part, could you please pick the
first clean-up patches via your tree? If there are dependencies with the
reworked arm64 patches, I'm also happy for them to go via your tree.

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

* Re: [PATCH v14 7/8] signal: define the field siginfo.si_faultflags
  2020-11-12 17:23           ` Dave Martin
@ 2020-11-12 20:01             ` Eric W. Biederman
  -1 siblings, 0 replies; 64+ messages in thread
From: Eric W. Biederman @ 2020-11-12 20:01 UTC (permalink / raw)
  To: Dave Martin
  Cc: Peter Collingbourne, Catalin Marinas, Evgenii Stepanov,
	Kostya Serebryany, Vincenzo Frascino, Will Deacon, Oleg Nesterov,
	James E.J. Bottomley, Linux ARM, Kevin Brodsky, Andrey Konovalov,
	Richard Henderson, linux-api, Helge Deller, David Spickett

Dave Martin <Dave.Martin@arm.com> writes:

> On Wed, Nov 11, 2020 at 02:15:15PM -0600, Eric W. Biederman wrote:
>> Dave Martin <Dave.Martin@arm.com> writes:
>> 
>> > On Mon, Nov 09, 2020 at 07:57:33PM -0600, Eric W. Biederman wrote:
>> >> Peter Collingbourne <pcc@google.com> writes:
>> >> 
>> >> > This field will contain flags that may be used by signal handlers to
>> >> > determine whether other fields in the _sigfault portion of siginfo are
>> >> > valid. An example use case is the following patch, which introduces
>> >> > the si_addr_tag_bits{,_mask} fields.
>> >> >
>> >> > A new sigcontext flag, SA_FAULTFLAGS, is introduced in order to allow
>> >> > a signal handler to require the kernel to set the field (but note
>> >> > that the field will be set anyway if the kernel supports the flag,
>> >> > regardless of its value). In combination with the previous patches,
>> >> > this allows a userspace program to determine whether the kernel will
>> >> > set the field.
>> >> >
>> >> > It is possible for an si_faultflags-unaware program to cause a signal
>> >> > handler in an si_faultflags-aware program to be called with a provided
>> >> > siginfo data structure by using one of the following syscalls:
>> >> >
>> >> > - ptrace(PTRACE_SETSIGINFO)
>> >> > - pidfd_send_signal
>> >> > - rt_sigqueueinfo
>> >> > - rt_tgsigqueueinfo
>> >> >
>> >> > So we need to prevent the si_faultflags-unaware program from causing an
>> >> > uninitialized read of si_faultflags in the si_faultflags-aware program when
>> >> > it uses one of these syscalls.
>> >> >
>> >> > The last three cases can be handled by observing that each of these
>> >> > syscalls fails if si_code >= 0. We also observe that kill(2) and
>> >> > tgkill(2) may be used to send a signal where si_code == 0 (SI_USER),
>> >> > so we define si_faultflags to only be valid if si_code > 0.
>> >> >
>> >> > There is no such check on si_code in ptrace(PTRACE_SETSIGINFO), so
>> >> > we make ptrace(PTRACE_SETSIGINFO) clear the si_faultflags field if it
>> >> > detects that the signal would use the _sigfault layout, and introduce
>> >> > a new ptrace request type, PTRACE_SETSIGINFO2, that a si_faultflags-aware
>> >> > program may use to opt out of this behavior.
>> >> 
>> >> So I think while well intentioned this is misguided.
>> >> 
>> >> gdb and the like may use this but I expect the primary user is CRIU
>> >> which simply reads the signal out of one process saves it on disk
>> >> and then restores the signal as read into the new process (possibly
>> >> on a different machine).
>> >> 
>> >> At least for the CRIU usage PTRACE_SETSIGINFO need to remain a raw
>> >> pass through kind of operation.
>> >
>> > This is a problem, though.
>> >
>> > How can we tell the difference between a siginfo that was generated by
>> > the kernel and a siginfo that was generated (or altered) by a non-xflags
>> > aware userspace?
>> >
>> > Short of revving the whole API, I don't see a simple solution to this.
>> 
>> Unlike receiving a signal.  We do know that userspace old and new
>> always sends unused fields as zero into PTRACE_SETSIGINFO.
>> 
>> The split into kernel_siginfo verifies this and fails userspace if it
>> does something different.  No problems have been reported.
>> 
>> So in the case of xflags a non-xflags aware userspace would either pass
>> the siginfo from through from somewhere else (such as
>> PTRACE_GETSIGINFO), or it would simply generate a signal with all of
>> the xflags bits clear.  So everything should work regardless.
>> 
>> > Although a bit of a hack, could we include some kind of checksum in the
>> > siginfo?  If the checksum matches during PTRACE_SETSIGINFO, we could
>> > accept the whole thing; xflags included.  Otherwise, we could silently
>> > drop non-self-describing extensions.
>> >
>> > If we only need to generate the checksum when PTRACE_GETSIGINFO is
>> > called then it might be feasible to use a strong hash; otherwise, this
>> > mechanism will be far from bulletproof.
>> >
>> > A hash has the advantage that we don't need any other information
>> > to validate it beyond a salt: if the hash matches, it's self-
>> > validating.  We could also package other data with it to describe the
>> > presence of extensions, but relying on this for regular sigaction()/
>> > signal delivery use feels too high-overhead.
>> >
>> > For debuggers, I suspect that PTRACE_SETSIGINFO2 is still useful:
>> > userspace callers that want to write an extension field that they
>> > knowingly generated themselves should have a way to express that.
>> >
>> > Thoughts?
>
> Eric, did you have any view on the hash idea here?

I am not quite certain what you meant by salt.  A per kernel instance
secret I suspect.

Such a secret would break creating siginfo by hand and checkpointing
and restoring on a different machine.

If you don't go with full crypto security it sounds like it would work.

If we really need to deploy xflags I think it bears looking at, but
right now it feels like one thing too many.



Eric


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

* Re: [PATCH v14 7/8] signal: define the field siginfo.si_faultflags
@ 2020-11-12 20:01             ` Eric W. Biederman
  0 siblings, 0 replies; 64+ messages in thread
From: Eric W. Biederman @ 2020-11-12 20:01 UTC (permalink / raw)
  To: Dave Martin
  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,
	Richard Henderson

Dave Martin <Dave.Martin@arm.com> writes:

> On Wed, Nov 11, 2020 at 02:15:15PM -0600, Eric W. Biederman wrote:
>> Dave Martin <Dave.Martin@arm.com> writes:
>> 
>> > On Mon, Nov 09, 2020 at 07:57:33PM -0600, Eric W. Biederman wrote:
>> >> Peter Collingbourne <pcc@google.com> writes:
>> >> 
>> >> > This field will contain flags that may be used by signal handlers to
>> >> > determine whether other fields in the _sigfault portion of siginfo are
>> >> > valid. An example use case is the following patch, which introduces
>> >> > the si_addr_tag_bits{,_mask} fields.
>> >> >
>> >> > A new sigcontext flag, SA_FAULTFLAGS, is introduced in order to allow
>> >> > a signal handler to require the kernel to set the field (but note
>> >> > that the field will be set anyway if the kernel supports the flag,
>> >> > regardless of its value). In combination with the previous patches,
>> >> > this allows a userspace program to determine whether the kernel will
>> >> > set the field.
>> >> >
>> >> > It is possible for an si_faultflags-unaware program to cause a signal
>> >> > handler in an si_faultflags-aware program to be called with a provided
>> >> > siginfo data structure by using one of the following syscalls:
>> >> >
>> >> > - ptrace(PTRACE_SETSIGINFO)
>> >> > - pidfd_send_signal
>> >> > - rt_sigqueueinfo
>> >> > - rt_tgsigqueueinfo
>> >> >
>> >> > So we need to prevent the si_faultflags-unaware program from causing an
>> >> > uninitialized read of si_faultflags in the si_faultflags-aware program when
>> >> > it uses one of these syscalls.
>> >> >
>> >> > The last three cases can be handled by observing that each of these
>> >> > syscalls fails if si_code >= 0. We also observe that kill(2) and
>> >> > tgkill(2) may be used to send a signal where si_code == 0 (SI_USER),
>> >> > so we define si_faultflags to only be valid if si_code > 0.
>> >> >
>> >> > There is no such check on si_code in ptrace(PTRACE_SETSIGINFO), so
>> >> > we make ptrace(PTRACE_SETSIGINFO) clear the si_faultflags field if it
>> >> > detects that the signal would use the _sigfault layout, and introduce
>> >> > a new ptrace request type, PTRACE_SETSIGINFO2, that a si_faultflags-aware
>> >> > program may use to opt out of this behavior.
>> >> 
>> >> So I think while well intentioned this is misguided.
>> >> 
>> >> gdb and the like may use this but I expect the primary user is CRIU
>> >> which simply reads the signal out of one process saves it on disk
>> >> and then restores the signal as read into the new process (possibly
>> >> on a different machine).
>> >> 
>> >> At least for the CRIU usage PTRACE_SETSIGINFO need to remain a raw
>> >> pass through kind of operation.
>> >
>> > This is a problem, though.
>> >
>> > How can we tell the difference between a siginfo that was generated by
>> > the kernel and a siginfo that was generated (or altered) by a non-xflags
>> > aware userspace?
>> >
>> > Short of revving the whole API, I don't see a simple solution to this.
>> 
>> Unlike receiving a signal.  We do know that userspace old and new
>> always sends unused fields as zero into PTRACE_SETSIGINFO.
>> 
>> The split into kernel_siginfo verifies this and fails userspace if it
>> does something different.  No problems have been reported.
>> 
>> So in the case of xflags a non-xflags aware userspace would either pass
>> the siginfo from through from somewhere else (such as
>> PTRACE_GETSIGINFO), or it would simply generate a signal with all of
>> the xflags bits clear.  So everything should work regardless.
>> 
>> > Although a bit of a hack, could we include some kind of checksum in the
>> > siginfo?  If the checksum matches during PTRACE_SETSIGINFO, we could
>> > accept the whole thing; xflags included.  Otherwise, we could silently
>> > drop non-self-describing extensions.
>> >
>> > If we only need to generate the checksum when PTRACE_GETSIGINFO is
>> > called then it might be feasible to use a strong hash; otherwise, this
>> > mechanism will be far from bulletproof.
>> >
>> > A hash has the advantage that we don't need any other information
>> > to validate it beyond a salt: if the hash matches, it's self-
>> > validating.  We could also package other data with it to describe the
>> > presence of extensions, but relying on this for regular sigaction()/
>> > signal delivery use feels too high-overhead.
>> >
>> > For debuggers, I suspect that PTRACE_SETSIGINFO2 is still useful:
>> > userspace callers that want to write an extension field that they
>> > knowingly generated themselves should have a way to express that.
>> >
>> > Thoughts?
>
> Eric, did you have any view on the hash idea here?

I am not quite certain what you meant by salt.  A per kernel instance
secret I suspect.

Such a secret would break creating siginfo by hand and checkpointing
and restoring on a different machine.

If you don't go with full crypto security it sounds like it would work.

If we really need to deploy xflags I think it bears looking at, but
right now it feels like one thing too many.



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

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

On Wed, Nov 11, 2020 at 9:46 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Tue, Nov 10, 2020 at 02:06:21PM -0800, Peter Collingbourne wrote:
> > On Tue, Nov 10, 2020 at 7:12 AM Eric W. Biederman <ebiederm@xmission.com> wrote:
> > >
> > > Peter Collingbourne <pcc@google.com> writes:
> > >
> > > > On Mon, Nov 9, 2020 at 5:13 PM Eric W. Biederman <ebiederm@xmission.com> 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, create a new pair of
> > > >> > fields in siginfo._sigfault, and store the tag bits of FAR_EL1 there,
> > > >> > together with a mask specifying which bits are valid.
> > > >> >
> > > >> > A flag is added to si_faultflags to allow userspace to determine whether
> > > >> > the values in the fields are valid.
> > > >>
> > > >> I think I am missing some things:
> > > >>
> > > >> Today it is documented that the tag bits are cleared, and so we can't
> > > >> use the highbits to hold the tag bits by default.
> > > >>
> > > >> Why do you need to deliver which tag bits are valid?  That feels like an
> > > >> implementation detail that is needed to setup the tag bits.  It feels
> > > >> like it would be constant per process.  So I don't understand why the
> > > >> siginfo needs to report information the process should already have.
> > > >
> > > > It isn't constant as it may vary depending on the specific type of
> > > > fault being delivered. For example on arm64 the architecture only
> > > > provides us with bits 56-59 of the tag for tag check faults, while all
> > > > other data aborts also provide bits 60-63. Now although the user
> > > > program may distinguish the two cases by checking the si_code, we
> > > > would also like to allow future architecture extensions to provide
> > > > bits 60-63 for tag check faults as well and allow distinguishing
> > > > between "bits 60-63 were zero" and "bits 60-63 were unknown" (which is
> > > > important when providing error reports).
> > >
> > > Does that mean that bits 60-63 are effectively unusable as tag bits
> > > if the tag check fault won't report them?
> >
> > The hardware doesn't support tag checking on bits 60-63, only on bits
> > 56-59, so in terms of hardware enforced memory tag checking they can't
> > be used as tag bits. But they are still subject to address tagging aka
> > top-byte-ignore so they could be used by userspace for other purposes
> > (e.g. if the allocator adds entropy to all 8 bits instead of just bits
> > 56-59 they could in theory be used to allow better diagnostics with
> > more precise matching of an invalid access to a previous allocation).
> >
> > > If you can use bits 60-63 as tag bits how does that work if they aren't
> > > reported?
> >
> > It still works but we're limited in how many allocations we can match
> > accesses to (16 vs 256).
>
> Not matching/reporting all the bits still has some value: if all 8 bits
> are random per allocation, then it is statistically likely that the
> hardware will detect mismatches.  Once you know there's a bug, you can
> turn on software instrumentation to debug the issue further, which may
> check the rest of the bits without relying on the signal mechansism,
> though at a higher runtime cost.
>
> (I'm not saying software will definitely do things this way, but it
> seems a reasonable use case.)

I suppose that it's possible that you could do the tag checks in
software just so that you can get the upper 4 bits, but if you're
prepared to do something this elaborate then there may be a lower cost
overall approach (e.g. look for GPRs whose bits 56-59 matches bits
56-59 of the fault address, then your upper 4 bits will likely be
those of one of the registers where they match).

> > > > I suppose that you could imagine that, if the "bits 60-63 available"
> > > > extension ever comes to pass, it could be exposed via a bit in
> > > > getauxval(AT_HWCAP2) (or maybe something like AT_HWCAP3 depending on
> > > > how long it takes to arrive) and that would provide a way for
> > > > userspace to know which bits are valid. But it seems like allowing
> > > > this to vary per signal is relatively cheap, allows the information to
> > > > be made available trivially architecture independently and keeps our
> > > > options open for the future (because we don't know if some future
> > > > architecture will actually make this a per-signal attribute).
> > > >
> > > > That being said, maybe we could solve this problem at the point at
> > > > which we do encounter such an architecture though.
> > >
> > > My goal would be to extend things to the minimum extent necessary to
> > > handle today's reality well.  Usually architectures evolve in
> > > unanticipated directions so simple and straight forward usually wins for
> > > handling future evolution.  As there is simply less old baggage to carry
> > > around.
> > >
> > > However I don't understand if reporting the valid bits on a signal by
> > > signal basis has a real advantage today or not.  If it helps today we
> > > will find room for the field.
> >
> > Okay, that makes sense. With the architecture as specified today I
> > don't think we would need it, since you can write a function that
> > operates on the siginfo and tells you what the si_addr_tag_bits_mask
> > would be without it.
> >
> > > >> Want prevents adding a sigaction sa_flag SA_EXPOSE_TABITS that when set
> > > >> causes the high bits to be set, and when clear (the default) will have
> > > >> the signal delivery code clear those bits.
> > > >>
> > > >> That should be enough for code that wants the tag bits to ask for them.
> > > >> As userspace would need to be updated to get the new bits
> > > >>
> > > >> Even if you have chained handlers.  The chaining mechanism would need to
> > > >> be updated and it could call the aware handlers first then clear the tag
> > > >> bits and call the rest of the handlers.
> > > >>
> > > >> It feels like always passing the tag bits in the address and then
> > > >> clearing them in the copy to userspace if the signal handler is
> > > >> not ready for them would be easier to maintain.
> > > >
> > > > I think that approach might work. Although it may make life harder for
> > > > callers of ptrace(PTRACE_SETSIGINFO) since they may need to know the
> > > > value of the bit in order to prepare a correct siginfo structure, if
> > > > we can reasonably expect them to always be delivering an exact copy of
> > > > a signal that was received before then maybe that is okay.
> > >
> > > I think we can reasonably expect callers of PTRACE_SETSIGINFO to be able
> > > to either deal the full reality of what is going on, or to only generate
> > > signals that they fully understand.
> > >
> > > Other than the use by CRIU it is a debugging facility and it is not
> > > expected for ordinary usage.  The non-CRIU use case would really seem to
> > > be what happens if I inject arbitrary signal X into process Y.  For that
> > > you need the ability to inject an arbitrary signal.
> > >
> > > My real sense with PTRACE_SETSIGINFO is that if we wind up with a
> > > regression we can deal with it then.
> >
> > Okay, that works for me.
> >
> > > > Assuming that this is an alternative to introducing
> > > > si_addr_tag_bits_mask, the userspace code would need to use the flag
> > > > bit support detection protocol for SA_EXPOSE_TAGBITS in order to be
> > > > able to distinguish between "no bits valid" and "some bits valid", and
> > > > then use an architecture-specific mechanism to determine exactly which
> > > > bits are valid. Is that okay for a generic feature?
> > >
> > > Unless I am mistaken setting the bits is already architecture specific
> > > so having some architecture specific code in there should not be a big
> > > problem.
> > >
> > > But I really don't understand the arm case well enough to know if we can
> > > get away without si_addr_tag_bits_mask, and in turn without the flags
> > > field that indicates the si_addr_tag_bits_mask is present.
> > >
> > > So I am asking questions so I can understand just what we get from
> > > si_addr_tag_bits_mask.
> >
> > If we allow the derivation of the mask to be architecture-specific
> > (which I'd be comfortable with) then I don't think we need it. What we
> > would end up with is:
>
> Note, the architecture-specificness can always be hidden under
> sysconf(3) or similar, so it's probably not a huge deal if there's no
> generic way of reporting that at the kernel level.

That makes sense, and it could also accommodate architectures like
RISC-V which didn't start out with tag bits but may receive them later
as a result of architecture changes.

> > - The tag bits mask is constant and architecturally defined (in
> > arm64's case it would be 0xff << 56).
> > - The valid tag bits mask specifies which bits of the tag bits mask in
> > the fault address are propagated to si_addr. It is defined in an
> > architecture-specific way based on the signal handler's
> > SA_EXPOSE_TAGBITS bit, the contents of siginfo and possibly global
> > information such as getauxval(AT_HWCAP*).
> >   - on arm64 this would currently be defined as:
> >     - if SA_EXPOSE_TAGBITS is not set then the mask is 0xff << 56 for
> > SIGTRAP/TRAP_BRKPT, 0 otherwise
> >     - if SA_EXPOSE_TAGBITS is set then the mask is 0xf << 56 for
> > SIGSEGV/SEGV_MTESERR, 0xff << 56 otherwise
>
> This feels very obscure, but since the use cases are equally obscure
> this may not be a big problem.  I do sympathise with Eric's view that it
> may be best not to over-abstract this.
>
> An sa_flags based mechanism still won't play nice with interposition
> frameworks where library registers a proxy handler and chains the user's
> handler from it -- the xflags approach is potentially better there.  But
> it would only be one more in a long list of existing issues.  People will
> only be using SA_EXPOSE_TAGBITS if they explicitly need it (i.e.,
> rarely).

I think this is likely to work with interceptors, as long as the
interceptor either stashes the sa_flags unchanged (detected by callers
as an old kernel via SA_UNSUPPORTED) or passes them verbatim to the
kernel (detection will be consistent with the kernel version). Both
behaviors are likely to be safe (and the former is what libsigchain
implements), although I suppose that an interceptor that replaces
sa_sigaction but not sa_flags may now be exposed to the tag bits, but
odds of the stars aligning and causing a problem this way are much
less than for random userspace applications being exposed to the bits
unconditionally. As I've said before "likely to work" is probably the
best that we can hope for with unaware interceptors.

Of course, the user program may attempt to rely on SA_EXPOSE_TAGBITS
behavior without checking for support, but that's the case with or
without interceptors.

> > - If SA_EXPOSE_TAGBITS is set then the bits in the tag bits mask that
> > are not also in the valid tag bits mask have an undefined value (this
> > would e.g. allow future expansion of arm64 to expose bits 60-63 on tag
> > check faults).
> > - If the kernel does not support SA_EXPOSE_TAGBITS (as determined
> > using the flag bit support detection protocol) then the behavior is as
> > if SA_EXPOSE_TAGBITS is not set.
> >
> > So I think I'd be fine with dropping it but let me experiment with the
> > new approach so that I can confirm that it's practical on Android and
> > I'll get back to you.
>
>
> Is the xflags mechanism still required if we follow this model?
>
> If not, that would be a significant simplification.

No, it will not be necessary. In fact, no changes to the siginfo
structure are required, the only change is to the semantics of the
si_addr field.

After doing some experimentation on Android (including implementing
the change itself, and consequent changes to the tombstone signal
handler and libsigchain) I'm happy with the new approach and I'll send
a v15 with the new patches shortly.

Peter

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

* Re: [PATCH v14 8/8] arm64: expose FAR_EL1 tag bits in siginfo
@ 2020-11-12 23:20               ` Peter Collingbourne
  0 siblings, 0 replies; 64+ messages in thread
From: Peter Collingbourne @ 2020-11-12 23:20 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,
	Richard Henderson

On Wed, Nov 11, 2020 at 9:46 AM Dave Martin <Dave.Martin@arm.com> wrote:
>
> On Tue, Nov 10, 2020 at 02:06:21PM -0800, Peter Collingbourne wrote:
> > On Tue, Nov 10, 2020 at 7:12 AM Eric W. Biederman <ebiederm@xmission.com> wrote:
> > >
> > > Peter Collingbourne <pcc@google.com> writes:
> > >
> > > > On Mon, Nov 9, 2020 at 5:13 PM Eric W. Biederman <ebiederm@xmission.com> 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, create a new pair of
> > > >> > fields in siginfo._sigfault, and store the tag bits of FAR_EL1 there,
> > > >> > together with a mask specifying which bits are valid.
> > > >> >
> > > >> > A flag is added to si_faultflags to allow userspace to determine whether
> > > >> > the values in the fields are valid.
> > > >>
> > > >> I think I am missing some things:
> > > >>
> > > >> Today it is documented that the tag bits are cleared, and so we can't
> > > >> use the highbits to hold the tag bits by default.
> > > >>
> > > >> Why do you need to deliver which tag bits are valid?  That feels like an
> > > >> implementation detail that is needed to setup the tag bits.  It feels
> > > >> like it would be constant per process.  So I don't understand why the
> > > >> siginfo needs to report information the process should already have.
> > > >
> > > > It isn't constant as it may vary depending on the specific type of
> > > > fault being delivered. For example on arm64 the architecture only
> > > > provides us with bits 56-59 of the tag for tag check faults, while all
> > > > other data aborts also provide bits 60-63. Now although the user
> > > > program may distinguish the two cases by checking the si_code, we
> > > > would also like to allow future architecture extensions to provide
> > > > bits 60-63 for tag check faults as well and allow distinguishing
> > > > between "bits 60-63 were zero" and "bits 60-63 were unknown" (which is
> > > > important when providing error reports).
> > >
> > > Does that mean that bits 60-63 are effectively unusable as tag bits
> > > if the tag check fault won't report them?
> >
> > The hardware doesn't support tag checking on bits 60-63, only on bits
> > 56-59, so in terms of hardware enforced memory tag checking they can't
> > be used as tag bits. But they are still subject to address tagging aka
> > top-byte-ignore so they could be used by userspace for other purposes
> > (e.g. if the allocator adds entropy to all 8 bits instead of just bits
> > 56-59 they could in theory be used to allow better diagnostics with
> > more precise matching of an invalid access to a previous allocation).
> >
> > > If you can use bits 60-63 as tag bits how does that work if they aren't
> > > reported?
> >
> > It still works but we're limited in how many allocations we can match
> > accesses to (16 vs 256).
>
> Not matching/reporting all the bits still has some value: if all 8 bits
> are random per allocation, then it is statistically likely that the
> hardware will detect mismatches.  Once you know there's a bug, you can
> turn on software instrumentation to debug the issue further, which may
> check the rest of the bits without relying on the signal mechansism,
> though at a higher runtime cost.
>
> (I'm not saying software will definitely do things this way, but it
> seems a reasonable use case.)

I suppose that it's possible that you could do the tag checks in
software just so that you can get the upper 4 bits, but if you're
prepared to do something this elaborate then there may be a lower cost
overall approach (e.g. look for GPRs whose bits 56-59 matches bits
56-59 of the fault address, then your upper 4 bits will likely be
those of one of the registers where they match).

> > > > I suppose that you could imagine that, if the "bits 60-63 available"
> > > > extension ever comes to pass, it could be exposed via a bit in
> > > > getauxval(AT_HWCAP2) (or maybe something like AT_HWCAP3 depending on
> > > > how long it takes to arrive) and that would provide a way for
> > > > userspace to know which bits are valid. But it seems like allowing
> > > > this to vary per signal is relatively cheap, allows the information to
> > > > be made available trivially architecture independently and keeps our
> > > > options open for the future (because we don't know if some future
> > > > architecture will actually make this a per-signal attribute).
> > > >
> > > > That being said, maybe we could solve this problem at the point at
> > > > which we do encounter such an architecture though.
> > >
> > > My goal would be to extend things to the minimum extent necessary to
> > > handle today's reality well.  Usually architectures evolve in
> > > unanticipated directions so simple and straight forward usually wins for
> > > handling future evolution.  As there is simply less old baggage to carry
> > > around.
> > >
> > > However I don't understand if reporting the valid bits on a signal by
> > > signal basis has a real advantage today or not.  If it helps today we
> > > will find room for the field.
> >
> > Okay, that makes sense. With the architecture as specified today I
> > don't think we would need it, since you can write a function that
> > operates on the siginfo and tells you what the si_addr_tag_bits_mask
> > would be without it.
> >
> > > >> Want prevents adding a sigaction sa_flag SA_EXPOSE_TABITS that when set
> > > >> causes the high bits to be set, and when clear (the default) will have
> > > >> the signal delivery code clear those bits.
> > > >>
> > > >> That should be enough for code that wants the tag bits to ask for them.
> > > >> As userspace would need to be updated to get the new bits
> > > >>
> > > >> Even if you have chained handlers.  The chaining mechanism would need to
> > > >> be updated and it could call the aware handlers first then clear the tag
> > > >> bits and call the rest of the handlers.
> > > >>
> > > >> It feels like always passing the tag bits in the address and then
> > > >> clearing them in the copy to userspace if the signal handler is
> > > >> not ready for them would be easier to maintain.
> > > >
> > > > I think that approach might work. Although it may make life harder for
> > > > callers of ptrace(PTRACE_SETSIGINFO) since they may need to know the
> > > > value of the bit in order to prepare a correct siginfo structure, if
> > > > we can reasonably expect them to always be delivering an exact copy of
> > > > a signal that was received before then maybe that is okay.
> > >
> > > I think we can reasonably expect callers of PTRACE_SETSIGINFO to be able
> > > to either deal the full reality of what is going on, or to only generate
> > > signals that they fully understand.
> > >
> > > Other than the use by CRIU it is a debugging facility and it is not
> > > expected for ordinary usage.  The non-CRIU use case would really seem to
> > > be what happens if I inject arbitrary signal X into process Y.  For that
> > > you need the ability to inject an arbitrary signal.
> > >
> > > My real sense with PTRACE_SETSIGINFO is that if we wind up with a
> > > regression we can deal with it then.
> >
> > Okay, that works for me.
> >
> > > > Assuming that this is an alternative to introducing
> > > > si_addr_tag_bits_mask, the userspace code would need to use the flag
> > > > bit support detection protocol for SA_EXPOSE_TAGBITS in order to be
> > > > able to distinguish between "no bits valid" and "some bits valid", and
> > > > then use an architecture-specific mechanism to determine exactly which
> > > > bits are valid. Is that okay for a generic feature?
> > >
> > > Unless I am mistaken setting the bits is already architecture specific
> > > so having some architecture specific code in there should not be a big
> > > problem.
> > >
> > > But I really don't understand the arm case well enough to know if we can
> > > get away without si_addr_tag_bits_mask, and in turn without the flags
> > > field that indicates the si_addr_tag_bits_mask is present.
> > >
> > > So I am asking questions so I can understand just what we get from
> > > si_addr_tag_bits_mask.
> >
> > If we allow the derivation of the mask to be architecture-specific
> > (which I'd be comfortable with) then I don't think we need it. What we
> > would end up with is:
>
> Note, the architecture-specificness can always be hidden under
> sysconf(3) or similar, so it's probably not a huge deal if there's no
> generic way of reporting that at the kernel level.

That makes sense, and it could also accommodate architectures like
RISC-V which didn't start out with tag bits but may receive them later
as a result of architecture changes.

> > - The tag bits mask is constant and architecturally defined (in
> > arm64's case it would be 0xff << 56).
> > - The valid tag bits mask specifies which bits of the tag bits mask in
> > the fault address are propagated to si_addr. It is defined in an
> > architecture-specific way based on the signal handler's
> > SA_EXPOSE_TAGBITS bit, the contents of siginfo and possibly global
> > information such as getauxval(AT_HWCAP*).
> >   - on arm64 this would currently be defined as:
> >     - if SA_EXPOSE_TAGBITS is not set then the mask is 0xff << 56 for
> > SIGTRAP/TRAP_BRKPT, 0 otherwise
> >     - if SA_EXPOSE_TAGBITS is set then the mask is 0xf << 56 for
> > SIGSEGV/SEGV_MTESERR, 0xff << 56 otherwise
>
> This feels very obscure, but since the use cases are equally obscure
> this may not be a big problem.  I do sympathise with Eric's view that it
> may be best not to over-abstract this.
>
> An sa_flags based mechanism still won't play nice with interposition
> frameworks where library registers a proxy handler and chains the user's
> handler from it -- the xflags approach is potentially better there.  But
> it would only be one more in a long list of existing issues.  People will
> only be using SA_EXPOSE_TAGBITS if they explicitly need it (i.e.,
> rarely).

I think this is likely to work with interceptors, as long as the
interceptor either stashes the sa_flags unchanged (detected by callers
as an old kernel via SA_UNSUPPORTED) or passes them verbatim to the
kernel (detection will be consistent with the kernel version). Both
behaviors are likely to be safe (and the former is what libsigchain
implements), although I suppose that an interceptor that replaces
sa_sigaction but not sa_flags may now be exposed to the tag bits, but
odds of the stars aligning and causing a problem this way are much
less than for random userspace applications being exposed to the bits
unconditionally. As I've said before "likely to work" is probably the
best that we can hope for with unaware interceptors.

Of course, the user program may attempt to rely on SA_EXPOSE_TAGBITS
behavior without checking for support, but that's the case with or
without interceptors.

> > - If SA_EXPOSE_TAGBITS is set then the bits in the tag bits mask that
> > are not also in the valid tag bits mask have an undefined value (this
> > would e.g. allow future expansion of arm64 to expose bits 60-63 on tag
> > check faults).
> > - If the kernel does not support SA_EXPOSE_TAGBITS (as determined
> > using the flag bit support detection protocol) then the behavior is as
> > if SA_EXPOSE_TAGBITS is not set.
> >
> > So I think I'd be fine with dropping it but let me experiment with the
> > new approach so that I can confirm that it's practical on Android and
> > I'll get back to you.
>
>
> Is the xflags mechanism still required if we follow this model?
>
> If not, that would be a significant simplification.

No, it will not be necessary. In fact, no changes to the siginfo
structure are required, the only change is to the semantics of the
si_addr field.

After doing some experimentation on Android (including implementing
the change itself, and consequent changes to the tombstone signal
handler and libsigchain) I'm happy with the new approach and I'll send
a v15 with the new patches shortly.

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

end of thread, other threads:[~2020-11-12 23:21 UTC | newest]

Thread overview: 64+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-04 21:18 [PATCH v14 0/8] arm64: expose FAR_EL1 tag bits in siginfo Peter Collingbourne
2020-11-04 21:18 ` Peter Collingbourne
2020-11-04 21:18 ` [PATCH v14 1/8] parisc: Drop parisc special case for __sighandler_t Peter Collingbourne
2020-11-04 21:18   ` Peter Collingbourne
2020-11-04 21:18 ` [PATCH v14 2/8] parisc: start using signal-defs.h Peter Collingbourne
2020-11-04 21:18   ` Peter Collingbourne
2020-11-04 21:18 ` [PATCH v14 3/8] arch: move SA_* definitions to generic headers Peter Collingbourne
2020-11-04 21:18   ` Peter Collingbourne
2020-11-04 21:18 ` [PATCH v14 4/8] signal: deduplicate code dealing with common _sigfault fields Peter Collingbourne
2020-11-04 21:18   ` Peter Collingbourne
2020-11-10  0:41   ` Eric W. Biederman
2020-11-10  0:41     ` Eric W. Biederman
2020-11-10  2:37     ` Peter Collingbourne
2020-11-10  2:37       ` Peter Collingbourne
2020-11-10 15:38       ` Eric W. Biederman
2020-11-10 15:38         ` Eric W. Biederman
2020-11-04 21:18 ` [PATCH v14 5/8] signal: clear non-uapi flag bits when passing/returning sa_flags Peter Collingbourne
2020-11-04 21:18   ` Peter Collingbourne
2020-11-10  0:35   ` Eric W. Biederman
2020-11-10  0:35     ` Eric W. Biederman
2020-11-10  2:19     ` Peter Collingbourne
2020-11-10  2:19       ` Peter Collingbourne
2020-11-04 21:18 ` [PATCH v14 6/8] signal: define the SA_UNSUPPORTED bit in sa_flags Peter Collingbourne
2020-11-04 21:18   ` Peter Collingbourne
2020-11-04 21:18 ` [PATCH v14 7/8] signal: define the field siginfo.si_faultflags Peter Collingbourne
2020-11-04 21:18   ` Peter Collingbourne
2020-11-10  1:54   ` Eric W. Biederman
2020-11-10  1:54     ` Eric W. Biederman
2020-11-11 11:10     ` Haren Myneni
2020-11-11 11:10       ` Haren Myneni
2020-11-11 20:46       ` Eric W. Biederman
2020-11-11 20:46         ` Eric W. Biederman
2020-11-10  1:57   ` Eric W. Biederman
2020-11-10  1:57     ` Eric W. Biederman
2020-11-11 17:27     ` Dave Martin
2020-11-11 17:27       ` Dave Martin
2020-11-11 20:15       ` Eric W. Biederman
2020-11-11 20:15         ` Eric W. Biederman
2020-11-11 20:28         ` Eric W. Biederman
2020-11-11 20:28           ` Eric W. Biederman
2020-11-12 17:21           ` Dave Martin
2020-11-12 17:21             ` Dave Martin
2020-11-12 17:23         ` Dave Martin
2020-11-12 17:23           ` Dave Martin
2020-11-12 20:01           ` Eric W. Biederman
2020-11-12 20:01             ` Eric W. Biederman
2020-11-04 21:18 ` [PATCH v14 8/8] arm64: expose FAR_EL1 tag bits in siginfo Peter Collingbourne
2020-11-04 21:18   ` Peter Collingbourne
2020-11-10  1:13   ` Eric W. Biederman
2020-11-10  1:13     ` Eric W. Biederman
2020-11-10  3:49     ` Peter Collingbourne
2020-11-10  3:49       ` Peter Collingbourne
2020-11-10 15:12       ` Eric W. Biederman
2020-11-10 15:12         ` Eric W. Biederman
2020-11-10 22:06         ` Peter Collingbourne
2020-11-10 22:06           ` Peter Collingbourne
2020-11-11  7:45           ` Eric W. Biederman
2020-11-11  7:45             ` Eric W. Biederman
2020-11-11 17:46           ` Dave Martin
2020-11-11 17:46             ` Dave Martin
2020-11-12 23:20             ` Peter Collingbourne
2020-11-12 23:20               ` Peter Collingbourne
2020-11-12 18:53     ` Catalin Marinas
2020-11-12 18:53       ` Catalin Marinas

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