diff options
| -rw-r--r-- | kernel/events/internal.h | 2 | ||||
| -rw-r--r-- | kernel/events/ring_buffer.c | 22 |
2 files changed, 19 insertions, 5 deletions
diff --git a/kernel/events/internal.h b/kernel/events/internal.h index d56a64c99a8b..eb675c4d59df 100644 --- a/kernel/events/internal.h +++ b/kernel/events/internal.h | |||
| @@ -16,7 +16,7 @@ struct ring_buffer { | |||
| 16 | int page_order; /* allocation order */ | 16 | int page_order; /* allocation order */ |
| 17 | #endif | 17 | #endif |
| 18 | int nr_pages; /* nr of data pages */ | 18 | int nr_pages; /* nr of data pages */ |
| 19 | int writable; /* are we writable */ | 19 | int overwrite; /* can overwrite itself */ |
| 20 | 20 | ||
| 21 | atomic_t poll; /* POLL_ for wakeups */ | 21 | atomic_t poll; /* POLL_ for wakeups */ |
| 22 | 22 | ||
diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c index 23cb34ff3973..97fddb09762b 100644 --- a/kernel/events/ring_buffer.c +++ b/kernel/events/ring_buffer.c | |||
| @@ -18,12 +18,24 @@ | |||
| 18 | static bool perf_output_space(struct ring_buffer *rb, unsigned long tail, | 18 | static bool perf_output_space(struct ring_buffer *rb, unsigned long tail, |
| 19 | unsigned long offset, unsigned long head) | 19 | unsigned long offset, unsigned long head) |
| 20 | { | 20 | { |
| 21 | unsigned long mask; | 21 | unsigned long sz = perf_data_size(rb); |
| 22 | unsigned long mask = sz - 1; | ||
| 22 | 23 | ||
| 23 | if (!rb->writable) | 24 | /* |
| 25 | * check if user-writable | ||
| 26 | * overwrite : over-write its own tail | ||
| 27 | * !overwrite: buffer possibly drops events. | ||
| 28 | */ | ||
| 29 | if (rb->overwrite) | ||
| 24 | return true; | 30 | return true; |
| 25 | 31 | ||
| 26 | mask = perf_data_size(rb) - 1; | 32 | /* |
| 33 | * verify that payload is not bigger than buffer | ||
| 34 | * otherwise masking logic may fail to detect | ||
| 35 | * the "not enough space" condition | ||
| 36 | */ | ||
| 37 | if ((head - offset) > sz) | ||
| 38 | return false; | ||
| 27 | 39 | ||
| 28 | offset = (offset - tail) & mask; | 40 | offset = (offset - tail) & mask; |
| 29 | head = (head - tail) & mask; | 41 | head = (head - tail) & mask; |
| @@ -212,7 +224,9 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, int flags) | |||
| 212 | rb->watermark = max_size / 2; | 224 | rb->watermark = max_size / 2; |
| 213 | 225 | ||
| 214 | if (flags & RING_BUFFER_WRITABLE) | 226 | if (flags & RING_BUFFER_WRITABLE) |
| 215 | rb->writable = 1; | 227 | rb->overwrite = 0; |
| 228 | else | ||
| 229 | rb->overwrite = 1; | ||
| 216 | 230 | ||
| 217 | atomic_set(&rb->refcount, 1); | 231 | atomic_set(&rb->refcount, 1); |
| 218 | 232 | ||
