mirror of https://gitee.com/openkylin/linux.git
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: fb6cc127e0
("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
This commit is contained in:
parent
32d35c4a96
commit
3ddb3fd8cd
|
@ -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;
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ union __sifields {
|
|||
__u32 _pkey;
|
||||
} _addr_pkey;
|
||||
/* used when si_code=TRAP_PERF */
|
||||
__u64 _perf;
|
||||
unsigned long _perf;
|
||||
};
|
||||
} _sigfault;
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue