Skip to content

Commit 3ddb3fd

Browse files
melverPeter Zijlstra
authored and
Peter Zijlstra
committed
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: fb6cc12 ("signal: Introduce TRAP_PERF si_code and si_perf to siginfo") Reported-by: Marek Szyprowski <[email protected]> Reported-by: Jon Hunter <[email protected]> Signed-off-by: Marco Elver <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Tested-by: Marek Szyprowski <[email protected]> Tested-by: Jon Hunter <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 32d35c4 commit 3ddb3fd

File tree

3 files changed

+3
-3
lines changed

3 files changed

+3
-3
lines changed

include/linux/compat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ typedef struct compat_siginfo {
237237
u32 _pkey;
238238
} _addr_pkey;
239239
/* used when si_code=TRAP_PERF */
240-
compat_u64 _perf;
240+
compat_ulong_t _perf;
241241
};
242242
} _sigfault;
243243

include/uapi/asm-generic/siginfo.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ union __sifields {
9292
__u32 _pkey;
9393
} _addr_pkey;
9494
/* used when si_code=TRAP_PERF */
95-
__u64 _perf;
95+
unsigned long _perf;
9696
};
9797
} _sigfault;
9898

tools/testing/selftests/perf_events/sigtrap_threads.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ static struct {
4444
} ctx;
4545

4646
/* Unique value to check si_perf is correctly set from perf_event_attr::sig_data. */
47-
#define TEST_SIG_DATA(addr) (~(uint64_t)(addr))
47+
#define TEST_SIG_DATA(addr) (~(unsigned long)(addr))
4848

4949
static struct perf_event_attr make_event_attr(bool enabled, volatile void *addr)
5050
{

0 commit comments

Comments
 (0)