linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH tip v2 1/2] signal, perf: Fix siginfo_t by avoiding u64 on 32-bit architectures
@ 2021-04-22 19:18 Marco Elver
  2021-04-22 19:18 ` [PATCH tip v2 2/2] signal, perf: Add missing TRAP_PERF case in siginfo_layout() Marco Elver
  2021-04-23  7:10 ` [tip: perf/core] signal, perf: Fix siginfo_t by avoiding u64 on 32-bit architectures tip-bot2 for Marco Elver
  0 siblings, 2 replies; 4+ messages in thread
From: Marco Elver @ 2021-04-22 19:18 UTC (permalink / raw)
  To: elver, peterz, mingo, tglx
  Cc: m.szyprowski, jonathanh, dvyukov, glider, arnd, christian, axboe,
	pcc, oleg, David.Laight, kasan-dev, linux-arch, linux-kernel,
	linux-arm-kernel

The alignment of a structure is that of its largest member. On
architectures like 32-bit Arm (but not e.g. 32-bit x86) 64-bit integers
will require 64-bit alignment and not its natural word size.

This means that there is no portable way to add 64-bit integers to
siginfo_t on 32-bit architectures without breaking the ABI, because
siginfo_t does not yet (and therefore likely never will) contain 64-bit
fields on 32-bit architectures. Adding a 64-bit integer could change the
alignment of the union after the 3 initial int si_signo, si_errno,
si_code, thus introducing 4 bytes of padding shifting the entire union,
which would break the ABI.

One alternative would be to use the __packed attribute, however, it is
non-standard C. Given siginfo_t has definitions outside the Linux kernel
in various standard libraries that can be compiled with any number of
different compilers (not just those we rely on), using non-standard
attributes on siginfo_t should be avoided to ensure portability.

In the case of the si_perf field, word size is sufficient since there is
no exact requirement on size, given the data it contains is user-defined
via perf_event_attr::sig_data. On 32-bit architectures, any excess bits
of perf_event_attr::sig_data will therefore be truncated when copying
into si_perf.

Since si_perf is intended to disambiguate events (e.g. encoding relevant
information if there are more events of the same type), 32 bits should
provide enough entropy to do so on 32-bit architectures.

For 64-bit architectures, no change is intended.

Fixes: fb6cc127e0b6 ("signal: Introduce TRAP_PERF si_code and si_perf to siginfo")
Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reported-by: Jon Hunter <jonathanh@nvidia.com>
Tested-by: Jon Hunter <jonathanh@nvidia.com>
Signed-off-by: Marco Elver <elver@google.com>
---
v2:
* Update commit message wording to be clearer and mentioned __packed, as
  pointed out by David Laight. I'm sure some time in the future somebody
  will wonder and perhaps run into the same issue, so let's try to give
  as much background as we can...

v1: https://lkml.kernel.org/r/20210422064437.3577327-1-elver@google.com

Note: I added static_assert()s to verify the siginfo_t layout to
arch/arm and arch/arm64, which caught the problem. I'll send them
separately to arm&arm64 maintainers respectively.
---
 include/linux/compat.h                                | 2 +-
 include/uapi/asm-generic/siginfo.h                    | 2 +-
 tools/testing/selftests/perf_events/sigtrap_threads.c | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/include/linux/compat.h b/include/linux/compat.h
index c8821d966812..f0d2dd35d408 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -237,7 +237,7 @@ typedef struct compat_siginfo {
 					u32 _pkey;
 				} _addr_pkey;
 				/* used when si_code=TRAP_PERF */
-				compat_u64 _perf;
+				compat_ulong_t _perf;
 			};
 		} _sigfault;
 
diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
index d0bb9125c853..03d6f6d2c1fe 100644
--- a/include/uapi/asm-generic/siginfo.h
+++ b/include/uapi/asm-generic/siginfo.h
@@ -92,7 +92,7 @@ union __sifields {
 				__u32 _pkey;
 			} _addr_pkey;
 			/* used when si_code=TRAP_PERF */
-			__u64 _perf;
+			unsigned long _perf;
 		};
 	} _sigfault;
 
diff --git a/tools/testing/selftests/perf_events/sigtrap_threads.c b/tools/testing/selftests/perf_events/sigtrap_threads.c
index 9c0fd442da60..78ddf5e11625 100644
--- a/tools/testing/selftests/perf_events/sigtrap_threads.c
+++ b/tools/testing/selftests/perf_events/sigtrap_threads.c
@@ -44,7 +44,7 @@ static struct {
 } ctx;
 
 /* Unique value to check si_perf is correctly set from perf_event_attr::sig_data. */
-#define TEST_SIG_DATA(addr) (~(uint64_t)(addr))
+#define TEST_SIG_DATA(addr) (~(unsigned long)(addr))
 
 static struct perf_event_attr make_event_attr(bool enabled, volatile void *addr)
 {
-- 
2.31.1.498.g6c1eba8ee3d-goog


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

* [PATCH tip v2 2/2] signal, perf: Add missing TRAP_PERF case in siginfo_layout()
  2021-04-22 19:18 [PATCH tip v2 1/2] signal, perf: Fix siginfo_t by avoiding u64 on 32-bit architectures Marco Elver
@ 2021-04-22 19:18 ` Marco Elver
  2021-04-23  7:10   ` [tip: perf/core] " tip-bot2 for Marco Elver
  2021-04-23  7:10 ` [tip: perf/core] signal, perf: Fix siginfo_t by avoiding u64 on 32-bit architectures tip-bot2 for Marco Elver
  1 sibling, 1 reply; 4+ messages in thread
From: Marco Elver @ 2021-04-22 19:18 UTC (permalink / raw)
  To: elver, peterz, mingo, tglx
  Cc: m.szyprowski, jonathanh, dvyukov, glider, arnd, christian, axboe,
	pcc, oleg, David.Laight, kasan-dev, linux-arch, linux-kernel,
	linux-arm-kernel

Add the missing TRAP_PERF case in siginfo_layout() for interpreting the
layout correctly as SIL_PERF_EVENT instead of just SIL_FAULT. This
ensures the si_perf field is copied and not just the si_addr field.

This was caught and tested by running the perf_events/sigtrap_threads
kselftest as a 32-bit binary with a 64-bit kernel.

Fixes: fb6cc127e0b6 ("signal: Introduce TRAP_PERF si_code and si_perf to siginfo")
Signed-off-by: Marco Elver <elver@google.com>
---
 kernel/signal.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/kernel/signal.c b/kernel/signal.c
index 9ed81ee4ff17..b354655a0e57 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -3251,6 +3251,8 @@ enum siginfo_layout siginfo_layout(unsigned sig, int si_code)
 			else if ((sig == SIGSEGV) && (si_code == SEGV_PKUERR))
 				layout = SIL_FAULT_PKUERR;
 #endif
+			else if ((sig == SIGTRAP) && (si_code == TRAP_PERF))
+				layout = SIL_PERF_EVENT;
 		}
 		else if (si_code <= NSIGPOLL)
 			layout = SIL_POLL;
-- 
2.31.1.498.g6c1eba8ee3d-goog


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

* [tip: perf/core] signal, perf: Add missing TRAP_PERF case in siginfo_layout()
  2021-04-22 19:18 ` [PATCH tip v2 2/2] signal, perf: Add missing TRAP_PERF case in siginfo_layout() Marco Elver
@ 2021-04-23  7:10   ` tip-bot2 for Marco Elver
  0 siblings, 0 replies; 4+ messages in thread
From: tip-bot2 for Marco Elver @ 2021-04-23  7:10 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Marco Elver, Peter Zijlstra (Intel), x86, linux-kernel

The following commit has been merged into the perf/core branch of tip:

Commit-ID:     ed8e50800bf4c2d904db9c75408a67085e6cca3d
Gitweb:        https://git.kernel.org/tip/ed8e50800bf4c2d904db9c75408a67085e6cca3d
Author:        Marco Elver <elver@google.com>
AuthorDate:    Thu, 22 Apr 2021 21:18:23 +02:00
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Fri, 23 Apr 2021 09:03:16 +02:00

signal, perf: Add missing TRAP_PERF case in siginfo_layout()

Add the missing TRAP_PERF case in siginfo_layout() for interpreting the
layout correctly as SIL_PERF_EVENT instead of just SIL_FAULT. This
ensures the si_perf field is copied and not just the si_addr field.

This was caught and tested by running the perf_events/sigtrap_threads
kselftest as a 32-bit binary with a 64-bit kernel.

Fixes: fb6cc127e0b6 ("signal: Introduce TRAP_PERF si_code and si_perf to siginfo")
Signed-off-by: Marco Elver <elver@google.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/20210422191823.79012-2-elver@google.com
---
 kernel/signal.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/kernel/signal.c b/kernel/signal.c
index f683518..343d87c 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -3206,6 +3206,8 @@ enum siginfo_layout siginfo_layout(unsigned sig, int si_code)
 			else if ((sig == SIGSEGV) && (si_code == SEGV_PKUERR))
 				layout = SIL_FAULT_PKUERR;
 #endif
+			else if ((sig == SIGTRAP) && (si_code == TRAP_PERF))
+				layout = SIL_PERF_EVENT;
 		}
 		else if (si_code <= NSIGPOLL)
 			layout = SIL_POLL;

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

* [tip: perf/core] signal, perf: Fix siginfo_t by avoiding u64 on 32-bit architectures
  2021-04-22 19:18 [PATCH tip v2 1/2] signal, perf: Fix siginfo_t by avoiding u64 on 32-bit architectures Marco Elver
  2021-04-22 19:18 ` [PATCH tip v2 2/2] signal, perf: Add missing TRAP_PERF case in siginfo_layout() Marco Elver
@ 2021-04-23  7:10 ` tip-bot2 for Marco Elver
  1 sibling, 0 replies; 4+ messages in thread
From: tip-bot2 for Marco Elver @ 2021-04-23  7:10 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Marek Szyprowski, Jon Hunter, Marco Elver, Peter Zijlstra (Intel),
	x86, linux-kernel

The following commit has been merged into the perf/core branch of tip:

Commit-ID:     3ddb3fd8cdb0a6c11b7c8d91ba42d84c4ea3cc43
Gitweb:        https://git.kernel.org/tip/3ddb3fd8cdb0a6c11b7c8d91ba42d84c4ea3cc43
Author:        Marco Elver <elver@google.com>
AuthorDate:    Thu, 22 Apr 2021 21:18:22 +02:00
Committer:     Peter Zijlstra <peterz@infradead.org>
CommitterDate: Fri, 23 Apr 2021 09:03:16 +02:00

signal, perf: Fix siginfo_t by avoiding u64 on 32-bit architectures

The alignment of a structure is that of its largest member. On
architectures like 32-bit Arm (but not e.g. 32-bit x86) 64-bit integers
will require 64-bit alignment and not its natural word size.

This means that there is no portable way to add 64-bit integers to
siginfo_t on 32-bit architectures without breaking the ABI, because
siginfo_t does not yet (and therefore likely never will) contain 64-bit
fields on 32-bit architectures. Adding a 64-bit integer could change the
alignment of the union after the 3 initial int si_signo, si_errno,
si_code, thus introducing 4 bytes of padding shifting the entire union,
which would break the ABI.

One alternative would be to use the __packed attribute, however, it is
non-standard C. Given siginfo_t has definitions outside the Linux kernel
in various standard libraries that can be compiled with any number of
different compilers (not just those we rely on), using non-standard
attributes on siginfo_t should be avoided to ensure portability.

In the case of the si_perf field, word size is sufficient since there is
no exact requirement on size, given the data it contains is user-defined
via perf_event_attr::sig_data. On 32-bit architectures, any excess bits
of perf_event_attr::sig_data will therefore be truncated when copying
into si_perf.

Since si_perf is intended to disambiguate events (e.g. encoding relevant
information if there are more events of the same type), 32 bits should
provide enough entropy to do so on 32-bit architectures.

For 64-bit architectures, no change is intended.

Fixes: fb6cc127e0b6 ("signal: Introduce TRAP_PERF si_code and si_perf to siginfo")
Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reported-by: Jon Hunter <jonathanh@nvidia.com>
Signed-off-by: Marco Elver <elver@google.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
Tested-by: Jon Hunter <jonathanh@nvidia.com>
Link: https://lkml.kernel.org/r/20210422191823.79012-1-elver@google.com
---
 include/linux/compat.h                                | 2 +-
 include/uapi/asm-generic/siginfo.h                    | 2 +-
 tools/testing/selftests/perf_events/sigtrap_threads.c | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/include/linux/compat.h b/include/linux/compat.h
index c8821d9..f0d2dd3 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -237,7 +237,7 @@ typedef struct compat_siginfo {
 					u32 _pkey;
 				} _addr_pkey;
 				/* used when si_code=TRAP_PERF */
-				compat_u64 _perf;
+				compat_ulong_t _perf;
 			};
 		} _sigfault;
 
diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
index d0bb912..03d6f6d 100644
--- a/include/uapi/asm-generic/siginfo.h
+++ b/include/uapi/asm-generic/siginfo.h
@@ -92,7 +92,7 @@ union __sifields {
 				__u32 _pkey;
 			} _addr_pkey;
 			/* used when si_code=TRAP_PERF */
-			__u64 _perf;
+			unsigned long _perf;
 		};
 	} _sigfault;
 
diff --git a/tools/testing/selftests/perf_events/sigtrap_threads.c b/tools/testing/selftests/perf_events/sigtrap_threads.c
index 9c0fd44..78ddf5e 100644
--- a/tools/testing/selftests/perf_events/sigtrap_threads.c
+++ b/tools/testing/selftests/perf_events/sigtrap_threads.c
@@ -44,7 +44,7 @@ static struct {
 } ctx;
 
 /* Unique value to check si_perf is correctly set from perf_event_attr::sig_data. */
-#define TEST_SIG_DATA(addr) (~(uint64_t)(addr))
+#define TEST_SIG_DATA(addr) (~(unsigned long)(addr))
 
 static struct perf_event_attr make_event_attr(bool enabled, volatile void *addr)
 {

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

end of thread, other threads:[~2021-04-23  7:10 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-22 19:18 [PATCH tip v2 1/2] signal, perf: Fix siginfo_t by avoiding u64 on 32-bit architectures Marco Elver
2021-04-22 19:18 ` [PATCH tip v2 2/2] signal, perf: Add missing TRAP_PERF case in siginfo_layout() Marco Elver
2021-04-23  7:10   ` [tip: perf/core] " tip-bot2 for Marco Elver
2021-04-23  7:10 ` [tip: perf/core] signal, perf: Fix siginfo_t by avoiding u64 on 32-bit architectures tip-bot2 for Marco Elver

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