mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-10-31 16:54:21 +00:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									af5eeab7e8
								
							
						
					
					
						commit
						0683b53197
					
				
					 9 changed files with 41 additions and 25 deletions
				
			
		|  | @ -623,7 +623,8 @@ static inline void siginfo_build_tests(void) | ||||||
| 	BUILD_BUG_ON(offsetof(siginfo_t, si_pkey) != 0x12); | 	BUILD_BUG_ON(offsetof(siginfo_t, si_pkey) != 0x12); | ||||||
| 
 | 
 | ||||||
| 	/* _sigfault._perf */ | 	/* _sigfault._perf */ | ||||||
| 	BUILD_BUG_ON(offsetof(siginfo_t, si_perf) != 0x10); | 	BUILD_BUG_ON(offsetof(siginfo_t, si_perf_data) != 0x10); | ||||||
|  | 	BUILD_BUG_ON(offsetof(siginfo_t, si_perf_type) != 0x14); | ||||||
| 
 | 
 | ||||||
| 	/* _sigpoll */ | 	/* _sigpoll */ | ||||||
| 	BUILD_BUG_ON(offsetof(siginfo_t, si_band)   != 0x0c); | 	BUILD_BUG_ON(offsetof(siginfo_t, si_band)   != 0x0c); | ||||||
|  |  | ||||||
|  | @ -141,8 +141,10 @@ static inline void signal_compat_build_tests(void) | ||||||
| 	BUILD_BUG_ON(offsetof(siginfo_t, si_pkey) != 0x20); | 	BUILD_BUG_ON(offsetof(siginfo_t, si_pkey) != 0x20); | ||||||
| 	BUILD_BUG_ON(offsetof(compat_siginfo_t, si_pkey) != 0x14); | 	BUILD_BUG_ON(offsetof(compat_siginfo_t, si_pkey) != 0x14); | ||||||
| 
 | 
 | ||||||
| 	BUILD_BUG_ON(offsetof(siginfo_t, si_perf) != 0x18); | 	BUILD_BUG_ON(offsetof(siginfo_t, si_perf_data) != 0x18); | ||||||
| 	BUILD_BUG_ON(offsetof(compat_siginfo_t, si_perf) != 0x10); | 	BUILD_BUG_ON(offsetof(siginfo_t, si_perf_type) != 0x20); | ||||||
|  | 	BUILD_BUG_ON(offsetof(compat_siginfo_t, si_perf_data) != 0x10); | ||||||
|  | 	BUILD_BUG_ON(offsetof(compat_siginfo_t, si_perf_type) != 0x14); | ||||||
| 
 | 
 | ||||||
| 	CHECK_CSI_OFFSET(_sigpoll); | 	CHECK_CSI_OFFSET(_sigpoll); | ||||||
| 	CHECK_CSI_SIZE  (_sigpoll, 2*sizeof(int)); | 	CHECK_CSI_SIZE  (_sigpoll, 2*sizeof(int)); | ||||||
|  |  | ||||||
|  | @ -134,7 +134,8 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo, | ||||||
| 		break; | 		break; | ||||||
| 	case SIL_PERF_EVENT: | 	case SIL_PERF_EVENT: | ||||||
| 		new.ssi_addr = (long) kinfo->si_addr; | 		new.ssi_addr = (long) kinfo->si_addr; | ||||||
| 		new.ssi_perf = kinfo->si_perf; | 		new.ssi_perf_type = kinfo->si_perf_type; | ||||||
|  | 		new.ssi_perf_data = kinfo->si_perf_data; | ||||||
| 		break; | 		break; | ||||||
| 	case SIL_CHLD: | 	case SIL_CHLD: | ||||||
| 		new.ssi_pid    = kinfo->si_pid; | 		new.ssi_pid    = kinfo->si_pid; | ||||||
|  |  | ||||||
|  | @ -236,7 +236,10 @@ typedef struct compat_siginfo { | ||||||
| 					u32 _pkey; | 					u32 _pkey; | ||||||
| 				} _addr_pkey; | 				} _addr_pkey; | ||||||
| 				/* used when si_code=TRAP_PERF */ | 				/* used when si_code=TRAP_PERF */ | ||||||
| 				compat_ulong_t _perf; | 				struct { | ||||||
|  | 					compat_ulong_t _data; | ||||||
|  | 					u32 _type; | ||||||
|  | 				} _perf; | ||||||
| 			}; | 			}; | ||||||
| 		} _sigfault; | 		} _sigfault; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -91,7 +91,10 @@ union __sifields { | ||||||
| 				__u32 _pkey; | 				__u32 _pkey; | ||||||
| 			} _addr_pkey; | 			} _addr_pkey; | ||||||
| 			/* used when si_code=TRAP_PERF */ | 			/* used when si_code=TRAP_PERF */ | ||||||
| 			unsigned long _perf; | 			struct { | ||||||
|  | 				unsigned long _data; | ||||||
|  | 				__u32 _type; | ||||||
|  | 			} _perf; | ||||||
| 		}; | 		}; | ||||||
| 	} _sigfault; | 	} _sigfault; | ||||||
| 
 | 
 | ||||||
|  | @ -154,7 +157,8 @@ typedef struct siginfo { | ||||||
| #define si_lower	_sifields._sigfault._addr_bnd._lower | #define si_lower	_sifields._sigfault._addr_bnd._lower | ||||||
| #define si_upper	_sifields._sigfault._addr_bnd._upper | #define si_upper	_sifields._sigfault._addr_bnd._upper | ||||||
| #define si_pkey		_sifields._sigfault._addr_pkey._pkey | #define si_pkey		_sifields._sigfault._addr_pkey._pkey | ||||||
| #define si_perf		_sifields._sigfault._perf | #define si_perf_data	_sifields._sigfault._perf._data | ||||||
|  | #define si_perf_type	_sifields._sigfault._perf._type | ||||||
| #define si_band		_sifields._sigpoll._band | #define si_band		_sifields._sigpoll._band | ||||||
| #define si_fd		_sifields._sigpoll._fd | #define si_fd		_sifields._sigpoll._fd | ||||||
| #define si_call_addr	_sifields._sigsys._call_addr | #define si_call_addr	_sifields._sigsys._call_addr | ||||||
|  |  | ||||||
|  | @ -464,7 +464,7 @@ struct perf_event_attr { | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * User provided data if sigtrap=1, passed back to user via | 	 * User provided data if sigtrap=1, passed back to user via | ||||||
| 	 * siginfo_t::si_perf, e.g. to permit user to identify the event. | 	 * siginfo_t::si_perf_data, e.g. to permit user to identify the event. | ||||||
| 	 */ | 	 */ | ||||||
| 	__u64	sig_data; | 	__u64	sig_data; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -39,8 +39,8 @@ struct signalfd_siginfo { | ||||||
| 	__s32 ssi_syscall; | 	__s32 ssi_syscall; | ||||||
| 	__u64 ssi_call_addr; | 	__u64 ssi_call_addr; | ||||||
| 	__u32 ssi_arch; | 	__u32 ssi_arch; | ||||||
| 	__u32 __pad3; | 	__u32 ssi_perf_type; | ||||||
| 	__u64 ssi_perf; | 	__u64 ssi_perf_data; | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
| 	 * Pad strcture to 128 bytes. Remember to update the | 	 * Pad strcture to 128 bytes. Remember to update the | ||||||
|  |  | ||||||
|  | @ -1769,10 +1769,12 @@ int force_sig_perf(void __user *addr, u32 type, u64 sig_data) | ||||||
| 
 | 
 | ||||||
| 	clear_siginfo(&info); | 	clear_siginfo(&info); | ||||||
| 	info.si_signo     = SIGTRAP; | 	info.si_signo     = SIGTRAP; | ||||||
| 	info.si_errno = type; | 	info.si_errno     = 0; | ||||||
| 	info.si_code      = TRAP_PERF; | 	info.si_code      = TRAP_PERF; | ||||||
| 	info.si_addr      = addr; | 	info.si_addr      = addr; | ||||||
| 	info.si_perf  = sig_data; | 	info.si_perf_data = sig_data; | ||||||
|  | 	info.si_perf_type = type; | ||||||
|  | 
 | ||||||
| 	return force_sig_info(&info); | 	return force_sig_info(&info); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -3356,7 +3358,8 @@ void copy_siginfo_to_external32(struct compat_siginfo *to, | ||||||
| 		break; | 		break; | ||||||
| 	case SIL_PERF_EVENT: | 	case SIL_PERF_EVENT: | ||||||
| 		to->si_addr = ptr_to_compat(from->si_addr); | 		to->si_addr = ptr_to_compat(from->si_addr); | ||||||
| 		to->si_perf = from->si_perf; | 		to->si_perf_data = from->si_perf_data; | ||||||
|  | 		to->si_perf_type = from->si_perf_type; | ||||||
| 		break; | 		break; | ||||||
| 	case SIL_CHLD: | 	case SIL_CHLD: | ||||||
| 		to->si_pid = from->si_pid; | 		to->si_pid = from->si_pid; | ||||||
|  | @ -3432,7 +3435,8 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to, | ||||||
| 		break; | 		break; | ||||||
| 	case SIL_PERF_EVENT: | 	case SIL_PERF_EVENT: | ||||||
| 		to->si_addr = compat_ptr(from->si_addr); | 		to->si_addr = compat_ptr(from->si_addr); | ||||||
| 		to->si_perf = from->si_perf; | 		to->si_perf_data = from->si_perf_data; | ||||||
|  | 		to->si_perf_type = from->si_perf_type; | ||||||
| 		break; | 		break; | ||||||
| 	case SIL_CHLD: | 	case SIL_CHLD: | ||||||
| 		to->si_pid    = from->si_pid; | 		to->si_pid    = from->si_pid; | ||||||
|  | @ -4615,7 +4619,8 @@ static inline void siginfo_buildtime_checks(void) | ||||||
| 	CHECK_OFFSET(si_lower); | 	CHECK_OFFSET(si_lower); | ||||||
| 	CHECK_OFFSET(si_upper); | 	CHECK_OFFSET(si_upper); | ||||||
| 	CHECK_OFFSET(si_pkey); | 	CHECK_OFFSET(si_pkey); | ||||||
| 	CHECK_OFFSET(si_perf); | 	CHECK_OFFSET(si_perf_data); | ||||||
|  | 	CHECK_OFFSET(si_perf_type); | ||||||
| 
 | 
 | ||||||
| 	/* sigpoll */ | 	/* sigpoll */ | ||||||
| 	CHECK_OFFSET(si_band); | 	CHECK_OFFSET(si_band); | ||||||
|  |  | ||||||
|  | @ -43,7 +43,7 @@ static struct { | ||||||
| 	siginfo_t first_siginfo;	/* First observed siginfo_t. */ | 	siginfo_t first_siginfo;	/* First observed siginfo_t. */ | ||||||
| } ctx; | } ctx; | ||||||
| 
 | 
 | ||||||
| /* Unique value to check si_perf is correctly set from perf_event_attr::sig_data. */ | /* Unique value to check si_perf_data is correctly set from perf_event_attr::sig_data. */ | ||||||
| #define TEST_SIG_DATA(addr) (~(unsigned long)(addr)) | #define TEST_SIG_DATA(addr) (~(unsigned long)(addr)) | ||||||
| 
 | 
 | ||||||
| static struct perf_event_attr make_event_attr(bool enabled, volatile void *addr) | static struct perf_event_attr make_event_attr(bool enabled, volatile void *addr) | ||||||
|  | @ -164,8 +164,8 @@ TEST_F(sigtrap_threads, enable_event) | ||||||
| 	EXPECT_EQ(ctx.signal_count, NUM_THREADS); | 	EXPECT_EQ(ctx.signal_count, NUM_THREADS); | ||||||
| 	EXPECT_EQ(ctx.tids_want_signal, 0); | 	EXPECT_EQ(ctx.tids_want_signal, 0); | ||||||
| 	EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on); | 	EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on); | ||||||
| 	EXPECT_EQ(ctx.first_siginfo.si_errno, PERF_TYPE_BREAKPOINT); | 	EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT); | ||||||
| 	EXPECT_EQ(ctx.first_siginfo.si_perf, TEST_SIG_DATA(&ctx.iterate_on)); | 	EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on)); | ||||||
| 
 | 
 | ||||||
| 	/* Check enabled for parent. */ | 	/* Check enabled for parent. */ | ||||||
| 	ctx.iterate_on = 0; | 	ctx.iterate_on = 0; | ||||||
|  | @ -183,8 +183,8 @@ TEST_F(sigtrap_threads, modify_and_enable_event) | ||||||
| 	EXPECT_EQ(ctx.signal_count, NUM_THREADS); | 	EXPECT_EQ(ctx.signal_count, NUM_THREADS); | ||||||
| 	EXPECT_EQ(ctx.tids_want_signal, 0); | 	EXPECT_EQ(ctx.tids_want_signal, 0); | ||||||
| 	EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on); | 	EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on); | ||||||
| 	EXPECT_EQ(ctx.first_siginfo.si_errno, PERF_TYPE_BREAKPOINT); | 	EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT); | ||||||
| 	EXPECT_EQ(ctx.first_siginfo.si_perf, TEST_SIG_DATA(&ctx.iterate_on)); | 	EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on)); | ||||||
| 
 | 
 | ||||||
| 	/* Check enabled for parent. */ | 	/* Check enabled for parent. */ | ||||||
| 	ctx.iterate_on = 0; | 	ctx.iterate_on = 0; | ||||||
|  | @ -203,8 +203,8 @@ TEST_F(sigtrap_threads, signal_stress) | ||||||
| 	EXPECT_EQ(ctx.signal_count, NUM_THREADS * ctx.iterate_on); | 	EXPECT_EQ(ctx.signal_count, NUM_THREADS * ctx.iterate_on); | ||||||
| 	EXPECT_EQ(ctx.tids_want_signal, 0); | 	EXPECT_EQ(ctx.tids_want_signal, 0); | ||||||
| 	EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on); | 	EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on); | ||||||
| 	EXPECT_EQ(ctx.first_siginfo.si_errno, PERF_TYPE_BREAKPOINT); | 	EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT); | ||||||
| 	EXPECT_EQ(ctx.first_siginfo.si_perf, TEST_SIG_DATA(&ctx.iterate_on)); | 	EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| TEST_HARNESS_MAIN | TEST_HARNESS_MAIN | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Eric W. Biederman
						Eric W. Biederman