On Wed, 24 Mar 2021 at 15:01, Peter Zijlstra <peterz@xxxxxxxxxxxxx> wrote: > > One last try, I'll leave it alone now, I promise :-) This looks like it does what you suggested, thanks! :-) I'll still need to think about it, because of the potential problem with modify-signal-races and what the user's synchronization story would look like then. > --- a/include/linux/perf_event.h > +++ b/include/linux/perf_event.h > @@ -778,6 +778,9 @@ struct perf_event { > void *security; > #endif > struct list_head sb_list; > + > + unsigned long si_uattr; > + unsigned long si_data; > #endif /* CONFIG_PERF_EVENTS */ > }; > > --- a/kernel/events/core.c > +++ b/kernel/events/core.c > @@ -5652,13 +5652,17 @@ static long _perf_ioctl(struct perf_even > return perf_event_query_prog_array(event, (void __user *)arg); > > case PERF_EVENT_IOC_MODIFY_ATTRIBUTES: { > + struct perf_event_attr __user *uattr; > struct perf_event_attr new_attr; > - int err = perf_copy_attr((struct perf_event_attr __user *)arg, > - &new_attr); > + int err; > > + uattr = (struct perf_event_attr __user *)arg; > + err = perf_copy_attr(uattr, &new_attr); > if (err) > return err; > > + event->si_uattr = (unsigned long)uattr; > + > return perf_event_modify_attr(event, &new_attr); > } > default: > @@ -6399,7 +6403,12 @@ static void perf_sigtrap(struct perf_eve > clear_siginfo(&info); > info.si_signo = SIGTRAP; > info.si_code = TRAP_PERF; > - info.si_errno = event->attr.type; > + info.si_addr = (void *)event->si_data; > + > + info.si_perf = event->si_uattr; > + if (event->parent) > + info.si_perf = event->parent->si_uattr; > + > force_sig_info(&info); > } > > @@ -6414,8 +6423,8 @@ static void perf_pending_event_disable(s > WRITE_ONCE(event->pending_disable, -1); > > if (event->attr.sigtrap) { > - atomic_set(&event->event_limit, 1); /* rearm event */ > perf_sigtrap(event); > + atomic_set_release(&event->event_limit, 1); /* rearm event */ > return; > } > > @@ -9121,6 +9130,7 @@ static int __perf_event_overflow(struct > if (events && atomic_dec_and_test(&event->event_limit)) { > ret = 1; > event->pending_kill = POLL_HUP; > + event->si_data = data->addr; > > perf_event_disable_inatomic(event); > } > @@ -12011,6 +12021,8 @@ SYSCALL_DEFINE5(perf_event_open, > goto err_task; > } > > + event->si_uattr = (unsigned long)attr_uptr; > + > if (is_sampling_event(event)) { > if (event->pmu->capabilities & PERF_PMU_CAP_NO_INTERRUPT) { > err = -EOPNOTSUPP;