"Eric W. Beiderman" <ebiederm@xxxxxxxxxxxx> writes: > From: "Eric W. Biederman" <ebiederm@xxxxxxxxxxxx> > > The si_perf code really wants to add a u64 field. This change enables > that by reorganizing the definition of siginfo_t, so that a 64bit > field can be added without increasing the alignment of other fields. I decided to include this change because it is not that complicated, and it allows si_perf_data to have the definition that was originally desired. If this looks difficult to make in the userspace definitions, or is otherwise a problem I don't mind dropping this change. I just figured since it was not too difficult and we are changing things anyway I should try for everything. Eric > Signed-off-by: "Eric W. Biederman" <ebiederm@xxxxxxxxxxxx> > --- > arch/x86/kernel/signal_compat.c | 9 +++---- > include/linux/compat.h | 28 +++++++++++++------- > include/uapi/asm-generic/siginfo.h | 42 ++++++++++++++++++++---------- > 3 files changed, 49 insertions(+), 30 deletions(-) > > diff --git a/arch/x86/kernel/signal_compat.c b/arch/x86/kernel/signal_compat.c > index a9fcabd8a5e5..a5cd01c52dfb 100644 > --- a/arch/x86/kernel/signal_compat.c > +++ b/arch/x86/kernel/signal_compat.c > @@ -17,8 +17,6 @@ > */ > static inline void signal_compat_build_tests(void) > { > - int _sifields_offset = offsetof(compat_siginfo_t, _sifields); > - > /* > * If adding a new si_code, there is probably new data in > * the siginfo. Make sure folks bumping the si_code > @@ -40,8 +38,7 @@ static inline void signal_compat_build_tests(void) > * in the ABI, of course. Make sure none of them ever > * move and are always at the beginning: > */ > - BUILD_BUG_ON(offsetof(compat_siginfo_t, _sifields) != 3 * sizeof(int)); > -#define CHECK_CSI_OFFSET(name) BUILD_BUG_ON(_sifields_offset != offsetof(compat_siginfo_t, _sifields.name)) > +#define CHECK_CSI_OFFSET(name) BUILD_BUG_ON(0 != offsetof(compat_siginfo_t, _sifields.name)) > > BUILD_BUG_ON(offsetof(siginfo_t, si_signo) != 0); > BUILD_BUG_ON(offsetof(siginfo_t, si_errno) != 4); > @@ -63,8 +60,8 @@ static inline void signal_compat_build_tests(void) > * structure stays within the padding size (checked > * above). > */ > -#define CHECK_CSI_SIZE(name, size) BUILD_BUG_ON(size != sizeof(((compat_siginfo_t *)0)->_sifields.name)) > -#define CHECK_SI_SIZE(name, size) BUILD_BUG_ON(size != sizeof(((siginfo_t *)0)->_sifields.name)) > +#define CHECK_CSI_SIZE(name, size) BUILD_BUG_ON(((3*sizeof(int))+(size)) != sizeof(((compat_siginfo_t *)0)->_sifields.name)) > +#define CHECK_SI_SIZE(name, size) BUILD_BUG_ON(((4*sizeof(int))+(size)) != sizeof(((siginfo_t *)0)->_sifields.name)) > > CHECK_CSI_OFFSET(_kill); > CHECK_CSI_SIZE (_kill, 2*sizeof(int)); > diff --git a/include/linux/compat.h b/include/linux/compat.h > index 6af7bef15e94..d81493248bf3 100644 > --- a/include/linux/compat.h > +++ b/include/linux/compat.h > @@ -158,27 +158,28 @@ typedef union compat_sigval { > compat_uptr_t sival_ptr; > } compat_sigval_t; > > -typedef struct compat_siginfo { > - int si_signo; > -#ifndef __ARCH_HAS_SWAPPED_SIGINFO > - int si_errno; > - int si_code; > -#else > - int si_code; > - int si_errno; > -#endif > +#define __COMPAT_SIGINFO_COMMON \ > + ___SIGINFO_COMMON; \ > + int _common_pad[__alignof__(compat_uptr_t) != __alignof__(int)] > > +typedef struct compat_siginfo { > + union { > + struct { > + __COMPAT_SIGINFO_COMMON; > + }; > union { > - int _pad[128/sizeof(int) - 3]; > + int _pad[128/sizeof(int)]; > > /* kill() */ > struct { > + __COMPAT_SIGINFO_COMMON; > compat_pid_t _pid; /* sender's pid */ > __compat_uid32_t _uid; /* sender's uid */ > } _kill; > > /* POSIX.1b timers */ > struct { > + __COMPAT_SIGINFO_COMMON; > compat_timer_t _tid; /* timer id */ > int _overrun; /* overrun count */ > compat_sigval_t _sigval; /* same as below */ > @@ -186,6 +187,7 @@ typedef struct compat_siginfo { > > /* POSIX.1b signals */ > struct { > + __COMPAT_SIGINFO_COMMON; > compat_pid_t _pid; /* sender's pid */ > __compat_uid32_t _uid; /* sender's uid */ > compat_sigval_t _sigval; > @@ -193,6 +195,7 @@ typedef struct compat_siginfo { > > /* SIGCHLD */ > struct { > + __COMPAT_SIGINFO_COMMON; > compat_pid_t _pid; /* which child */ > __compat_uid32_t _uid; /* sender's uid */ > int _status; /* exit code */ > @@ -203,6 +206,7 @@ typedef struct compat_siginfo { > #ifdef CONFIG_X86_X32_ABI > /* SIGCHLD (x32 version) */ > struct { > + __COMPAT_SIGINFO_COMMON; > compat_pid_t _pid; /* which child */ > __compat_uid32_t _uid; /* sender's uid */ > int _status; /* exit code */ > @@ -213,6 +217,7 @@ typedef struct compat_siginfo { > > /* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT */ > struct { > + __COMPAT_SIGINFO_COMMON; > compat_uptr_t _addr; /* faulting insn/memory ref. */ > #define __COMPAT_ADDR_BND_PKEY_PAD (__alignof__(compat_uptr_t) < sizeof(short) ? \ > sizeof(short) : __alignof__(compat_uptr_t)) > @@ -242,16 +247,19 @@ typedef struct compat_siginfo { > > /* SIGPOLL */ > struct { > + __COMPAT_SIGINFO_COMMON; > compat_long_t _band; /* POLL_IN, POLL_OUT, POLL_MSG */ > int _fd; > } _sigpoll; > > struct { > + __COMPAT_SIGINFO_COMMON; > compat_uptr_t _call_addr; /* calling user insn */ > int _syscall; /* triggering system call number */ > unsigned int _arch; /* AUDIT_ARCH_* of syscall */ > } _sigsys; > } _sifields; > + }; > } compat_siginfo_t; > > struct compat_rlimit { > diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h > index e663bf117b46..1fcede623a73 100644 > --- a/include/uapi/asm-generic/siginfo.h > +++ b/include/uapi/asm-generic/siginfo.h > @@ -29,15 +29,33 @@ typedef union sigval { > #define __ARCH_SI_ATTRIBUTES > #endif > > +#ifndef __ARCH_HAS_SWAPPED_SIGINFO > +#define ___SIGINFO_COMMON \ > + int si_signo; \ > + int si_errno; \ > + int si_code > +#else > +#define ___SIGINFO_COMMON \ > + int si_signo; \ > + int si_code; \ > + int si_errno > +#endif /* __ARCH_HAS_SWAPPED_SIGINFO */ > + > +#define __SIGINFO_COMMON \ > + ___SIGINFO_COMMON; \ > + int _common_pad[__alignof__(void *) != __alignof(int)] > + > union __sifields { > /* kill() */ > struct { > + __SIGINFO_COMMON; > __kernel_pid_t _pid; /* sender's pid */ > __kernel_uid32_t _uid; /* sender's uid */ > } _kill; > > /* POSIX.1b timers */ > struct { > + __SIGINFO_COMMON; > __kernel_timer_t _tid; /* timer id */ > int _overrun; /* overrun count */ > sigval_t _sigval; /* same as below */ > @@ -46,6 +64,7 @@ union __sifields { > > /* POSIX.1b signals */ > struct { > + __SIGINFO_COMMON; > __kernel_pid_t _pid; /* sender's pid */ > __kernel_uid32_t _uid; /* sender's uid */ > sigval_t _sigval; > @@ -53,6 +72,7 @@ union __sifields { > > /* SIGCHLD */ > struct { > + __SIGINFO_COMMON; > __kernel_pid_t _pid; /* which child */ > __kernel_uid32_t _uid; /* sender's uid */ > int _status; /* exit code */ > @@ -62,6 +82,7 @@ union __sifields { > > /* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT */ > struct { > + __SIGINFO_COMMON; > void __user *_addr; /* faulting insn/memory ref. */ > #ifdef __ia64__ > int _imm; /* immediate value for "break" */ > @@ -97,35 +118,28 @@ union __sifields { > > /* SIGPOLL */ > struct { > + __SIGINFO_COMMON; > __ARCH_SI_BAND_T _band; /* POLL_IN, POLL_OUT, POLL_MSG */ > int _fd; > } _sigpoll; > > /* SIGSYS */ > struct { > + __SIGINFO_COMMON; > void __user *_call_addr; /* calling user insn */ > int _syscall; /* triggering system call number */ > unsigned int _arch; /* AUDIT_ARCH_* of syscall */ > } _sigsys; > }; > > -#ifndef __ARCH_HAS_SWAPPED_SIGINFO > -#define __SIGINFO \ > -struct { \ > - int si_signo; \ > - int si_errno; \ > - int si_code; \ > - union __sifields _sifields; \ > -} > -#else > + > #define __SIGINFO \ > -struct { \ > - int si_signo; \ > - int si_code; \ > - int si_errno; \ > +union { \ > + struct { \ > + __SIGINFO_COMMON; \ > + }; \ > union __sifields _sifields; \ > } > -#endif /* __ARCH_HAS_SWAPPED_SIGINFO */ > > typedef struct siginfo { > union {