diff options
Diffstat (limited to 'kernel/events/core.c')
| -rw-r--r-- | kernel/events/core.c | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c index 6e75a5c9412d..6c4e523dc1e2 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c | |||
| @@ -7316,6 +7316,21 @@ int perf_event_account_interrupt(struct perf_event *event) | |||
| 7316 | return __perf_event_account_interrupt(event, 1); | 7316 | return __perf_event_account_interrupt(event, 1); |
| 7317 | } | 7317 | } |
| 7318 | 7318 | ||
| 7319 | static bool sample_is_allowed(struct perf_event *event, struct pt_regs *regs) | ||
| 7320 | { | ||
| 7321 | /* | ||
| 7322 | * Due to interrupt latency (AKA "skid"), we may enter the | ||
| 7323 | * kernel before taking an overflow, even if the PMU is only | ||
| 7324 | * counting user events. | ||
| 7325 | * To avoid leaking information to userspace, we must always | ||
| 7326 | * reject kernel samples when exclude_kernel is set. | ||
| 7327 | */ | ||
| 7328 | if (event->attr.exclude_kernel && !user_mode(regs)) | ||
| 7329 | return false; | ||
| 7330 | |||
| 7331 | return true; | ||
| 7332 | } | ||
| 7333 | |||
| 7319 | /* | 7334 | /* |
| 7320 | * Generic event overflow handling, sampling. | 7335 | * Generic event overflow handling, sampling. |
| 7321 | */ | 7336 | */ |
| @@ -7337,6 +7352,12 @@ static int __perf_event_overflow(struct perf_event *event, | |||
| 7337 | ret = __perf_event_account_interrupt(event, throttle); | 7352 | ret = __perf_event_account_interrupt(event, throttle); |
| 7338 | 7353 | ||
| 7339 | /* | 7354 | /* |
| 7355 | * For security, drop the skid kernel samples if necessary. | ||
| 7356 | */ | ||
| 7357 | if (!sample_is_allowed(event, regs)) | ||
| 7358 | return ret; | ||
| 7359 | |||
| 7360 | /* | ||
| 7340 | * XXX event_limit might not quite work as expected on inherited | 7361 | * XXX event_limit might not quite work as expected on inherited |
| 7341 | * events | 7362 | * events |
| 7342 | */ | 7363 | */ |
