Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

signal: Deliver all of the siginfo perf data in _perf

Don't abuse si_errno and deliver all of the perf data in _perf member
of siginfo_t.

Note: The data field in the perf data structures in a u64 to allow a
pointer to be encoded without needed to implement a 32bit and 64bit
version of the same structure. There already exists a 32bit and 64bit
versions siginfo_t, and the 32bit version can not include a 64bit
member as it only has 32bit alignment. So unsigned long is used in
siginfo_t instead of a u64 as unsigned long can encode a pointer on
all architectures linux supports.

v1: https://lkml.kernel.org/r/m11rarqqx2.fsf_-_@fess.ebiederm.org
v2: https://lkml.kernel.org/r/20210503203814.25487-10-ebiederm@xmission.com
v3: https://lkml.kernel.org/r/20210505141101.11519-11-ebiederm@xmission.com
Link: https://lkml.kernel.org/r/20210517195748.8880-4-ebiederm@xmission.com
Reviewed-by: Marco Elver <elver@google.com>
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>

+41 -25
+2 -1
arch/m68k/kernel/signal.c
··· 623 623 BUILD_BUG_ON(offsetof(siginfo_t, si_pkey) != 0x12); 624 624 625 625 /* _sigfault._perf */ 626 - BUILD_BUG_ON(offsetof(siginfo_t, si_perf) != 0x10); 626 + BUILD_BUG_ON(offsetof(siginfo_t, si_perf_data) != 0x10); 627 + BUILD_BUG_ON(offsetof(siginfo_t, si_perf_type) != 0x14); 627 628 628 629 /* _sigpoll */ 629 630 BUILD_BUG_ON(offsetof(siginfo_t, si_band) != 0x0c);
+4 -2
arch/x86/kernel/signal_compat.c
··· 141 141 BUILD_BUG_ON(offsetof(siginfo_t, si_pkey) != 0x20); 142 142 BUILD_BUG_ON(offsetof(compat_siginfo_t, si_pkey) != 0x14); 143 143 144 - BUILD_BUG_ON(offsetof(siginfo_t, si_perf) != 0x18); 145 - BUILD_BUG_ON(offsetof(compat_siginfo_t, si_perf) != 0x10); 144 + BUILD_BUG_ON(offsetof(siginfo_t, si_perf_data) != 0x18); 145 + BUILD_BUG_ON(offsetof(siginfo_t, si_perf_type) != 0x20); 146 + BUILD_BUG_ON(offsetof(compat_siginfo_t, si_perf_data) != 0x10); 147 + BUILD_BUG_ON(offsetof(compat_siginfo_t, si_perf_type) != 0x14); 146 148 147 149 CHECK_CSI_OFFSET(_sigpoll); 148 150 CHECK_CSI_SIZE (_sigpoll, 2*sizeof(int));
+2 -1
fs/signalfd.c
··· 134 134 break; 135 135 case SIL_PERF_EVENT: 136 136 new.ssi_addr = (long) kinfo->si_addr; 137 - new.ssi_perf = kinfo->si_perf; 137 + new.ssi_perf_type = kinfo->si_perf_type; 138 + new.ssi_perf_data = kinfo->si_perf_data; 138 139 break; 139 140 case SIL_CHLD: 140 141 new.ssi_pid = kinfo->si_pid;
+4 -1
include/linux/compat.h
··· 236 236 u32 _pkey; 237 237 } _addr_pkey; 238 238 /* used when si_code=TRAP_PERF */ 239 - compat_ulong_t _perf; 239 + struct { 240 + compat_ulong_t _data; 241 + u32 _type; 242 + } _perf; 240 243 }; 241 244 } _sigfault; 242 245
+6 -2
include/uapi/asm-generic/siginfo.h
··· 91 91 __u32 _pkey; 92 92 } _addr_pkey; 93 93 /* used when si_code=TRAP_PERF */ 94 - unsigned long _perf; 94 + struct { 95 + unsigned long _data; 96 + __u32 _type; 97 + } _perf; 95 98 }; 96 99 } _sigfault; 97 100 ··· 157 154 #define si_lower _sifields._sigfault._addr_bnd._lower 158 155 #define si_upper _sifields._sigfault._addr_bnd._upper 159 156 #define si_pkey _sifields._sigfault._addr_pkey._pkey 160 - #define si_perf _sifields._sigfault._perf 157 + #define si_perf_data _sifields._sigfault._perf._data 158 + #define si_perf_type _sifields._sigfault._perf._type 161 159 #define si_band _sifields._sigpoll._band 162 160 #define si_fd _sifields._sigpoll._fd 163 161 #define si_call_addr _sifields._sigsys._call_addr
+1 -1
include/uapi/linux/perf_event.h
··· 464 464 465 465 /* 466 466 * User provided data if sigtrap=1, passed back to user via 467 - * siginfo_t::si_perf, e.g. to permit user to identify the event. 467 + * siginfo_t::si_perf_data, e.g. to permit user to identify the event. 468 468 */ 469 469 __u64 sig_data; 470 470 };
+2 -2
include/uapi/linux/signalfd.h
··· 39 39 __s32 ssi_syscall; 40 40 __u64 ssi_call_addr; 41 41 __u32 ssi_arch; 42 - __u32 __pad3; 43 - __u64 ssi_perf; 42 + __u32 ssi_perf_type; 43 + __u64 ssi_perf_data; 44 44 45 45 /* 46 46 * Pad strcture to 128 bytes. Remember to update the
+13 -8
kernel/signal.c
··· 1768 1768 struct kernel_siginfo info; 1769 1769 1770 1770 clear_siginfo(&info); 1771 - info.si_signo = SIGTRAP; 1772 - info.si_errno = type; 1773 - info.si_code = TRAP_PERF; 1774 - info.si_addr = addr; 1775 - info.si_perf = sig_data; 1771 + info.si_signo = SIGTRAP; 1772 + info.si_errno = 0; 1773 + info.si_code = TRAP_PERF; 1774 + info.si_addr = addr; 1775 + info.si_perf_data = sig_data; 1776 + info.si_perf_type = type; 1777 + 1776 1778 return force_sig_info(&info); 1777 1779 } 1778 1780 ··· 3358 3356 break; 3359 3357 case SIL_PERF_EVENT: 3360 3358 to->si_addr = ptr_to_compat(from->si_addr); 3361 - to->si_perf = from->si_perf; 3359 + to->si_perf_data = from->si_perf_data; 3360 + to->si_perf_type = from->si_perf_type; 3362 3361 break; 3363 3362 case SIL_CHLD: 3364 3363 to->si_pid = from->si_pid; ··· 3435 3432 break; 3436 3433 case SIL_PERF_EVENT: 3437 3434 to->si_addr = compat_ptr(from->si_addr); 3438 - to->si_perf = from->si_perf; 3435 + to->si_perf_data = from->si_perf_data; 3436 + to->si_perf_type = from->si_perf_type; 3439 3437 break; 3440 3438 case SIL_CHLD: 3441 3439 to->si_pid = from->si_pid; ··· 4619 4615 CHECK_OFFSET(si_lower); 4620 4616 CHECK_OFFSET(si_upper); 4621 4617 CHECK_OFFSET(si_pkey); 4622 - CHECK_OFFSET(si_perf); 4618 + CHECK_OFFSET(si_perf_data); 4619 + CHECK_OFFSET(si_perf_type); 4623 4620 4624 4621 /* sigpoll */ 4625 4622 CHECK_OFFSET(si_band);
+7 -7
tools/testing/selftests/perf_events/sigtrap_threads.c
··· 43 43 siginfo_t first_siginfo; /* First observed siginfo_t. */ 44 44 } ctx; 45 45 46 - /* Unique value to check si_perf is correctly set from perf_event_attr::sig_data. */ 46 + /* Unique value to check si_perf_data is correctly set from perf_event_attr::sig_data. */ 47 47 #define TEST_SIG_DATA(addr) (~(unsigned long)(addr)) 48 48 49 49 static struct perf_event_attr make_event_attr(bool enabled, volatile void *addr) ··· 164 164 EXPECT_EQ(ctx.signal_count, NUM_THREADS); 165 165 EXPECT_EQ(ctx.tids_want_signal, 0); 166 166 EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on); 167 - EXPECT_EQ(ctx.first_siginfo.si_errno, PERF_TYPE_BREAKPOINT); 168 - EXPECT_EQ(ctx.first_siginfo.si_perf, TEST_SIG_DATA(&ctx.iterate_on)); 167 + EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT); 168 + EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on)); 169 169 170 170 /* Check enabled for parent. */ 171 171 ctx.iterate_on = 0; ··· 183 183 EXPECT_EQ(ctx.signal_count, NUM_THREADS); 184 184 EXPECT_EQ(ctx.tids_want_signal, 0); 185 185 EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on); 186 - EXPECT_EQ(ctx.first_siginfo.si_errno, PERF_TYPE_BREAKPOINT); 187 - EXPECT_EQ(ctx.first_siginfo.si_perf, TEST_SIG_DATA(&ctx.iterate_on)); 186 + EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT); 187 + EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on)); 188 188 189 189 /* Check enabled for parent. */ 190 190 ctx.iterate_on = 0; ··· 203 203 EXPECT_EQ(ctx.signal_count, NUM_THREADS * ctx.iterate_on); 204 204 EXPECT_EQ(ctx.tids_want_signal, 0); 205 205 EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on); 206 - EXPECT_EQ(ctx.first_siginfo.si_errno, PERF_TYPE_BREAKPOINT); 207 - EXPECT_EQ(ctx.first_siginfo.si_perf, TEST_SIG_DATA(&ctx.iterate_on)); 206 + EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT); 207 + EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on)); 208 208 } 209 209 210 210 TEST_HARNESS_MAIN