diff options
Diffstat (limited to 'kernel/trace')
-rw-r--r-- | kernel/trace/trace.c | 32 | ||||
-rw-r--r-- | kernel/trace/trace_selftest.c | 1 |
2 files changed, 24 insertions, 9 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 3271916ff033..0567f51bbea4 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -249,24 +249,32 @@ __update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu) | |||
249 | tracing_record_cmdline(current); | 249 | tracing_record_cmdline(current); |
250 | } | 250 | } |
251 | 251 | ||
252 | #define CHECK_COND(cond) \ | ||
253 | if (unlikely(cond)) { \ | ||
254 | tracing_disabled = 1; \ | ||
255 | WARN_ON(1); \ | ||
256 | return -1; \ | ||
257 | } | ||
258 | |||
252 | /** | 259 | /** |
253 | * check_pages - integrity check of trace buffers | 260 | * check_pages - integrity check of trace buffers |
254 | * | 261 | * |
255 | * As a safty measure we check to make sure the data pages have not | 262 | * As a safty measure we check to make sure the data pages have not |
256 | * been corrupted. TODO: configure to disable this because it adds | 263 | * been corrupted. |
257 | * a bit of overhead. | ||
258 | */ | 264 | */ |
259 | void check_pages(struct trace_array_cpu *data) | 265 | int check_pages(struct trace_array_cpu *data) |
260 | { | 266 | { |
261 | struct page *page, *tmp; | 267 | struct page *page, *tmp; |
262 | 268 | ||
263 | BUG_ON(data->trace_pages.next->prev != &data->trace_pages); | 269 | CHECK_COND(data->trace_pages.next->prev != &data->trace_pages); |
264 | BUG_ON(data->trace_pages.prev->next != &data->trace_pages); | 270 | CHECK_COND(data->trace_pages.prev->next != &data->trace_pages); |
265 | 271 | ||
266 | list_for_each_entry_safe(page, tmp, &data->trace_pages, lru) { | 272 | list_for_each_entry_safe(page, tmp, &data->trace_pages, lru) { |
267 | BUG_ON(page->lru.next->prev != &page->lru); | 273 | CHECK_COND(page->lru.next->prev != &page->lru); |
268 | BUG_ON(page->lru.prev->next != &page->lru); | 274 | CHECK_COND(page->lru.prev->next != &page->lru); |
269 | } | 275 | } |
276 | |||
277 | return 0; | ||
270 | } | 278 | } |
271 | 279 | ||
272 | /** | 280 | /** |
@@ -280,7 +288,6 @@ void *head_page(struct trace_array_cpu *data) | |||
280 | { | 288 | { |
281 | struct page *page; | 289 | struct page *page; |
282 | 290 | ||
283 | check_pages(data); | ||
284 | if (list_empty(&data->trace_pages)) | 291 | if (list_empty(&data->trace_pages)) |
285 | return NULL; | 292 | return NULL; |
286 | 293 | ||
@@ -2566,7 +2573,7 @@ tracing_entries_write(struct file *filp, const char __user *ubuf, | |||
2566 | { | 2573 | { |
2567 | unsigned long val; | 2574 | unsigned long val; |
2568 | char buf[64]; | 2575 | char buf[64]; |
2569 | int ret; | 2576 | int i, ret; |
2570 | 2577 | ||
2571 | if (cnt >= sizeof(buf)) | 2578 | if (cnt >= sizeof(buf)) |
2572 | return -EINVAL; | 2579 | return -EINVAL; |
@@ -2635,8 +2642,15 @@ tracing_entries_write(struct file *filp, const char __user *ubuf, | |||
2635 | trace_free_page(); | 2642 | trace_free_page(); |
2636 | } | 2643 | } |
2637 | 2644 | ||
2645 | /* check integrity */ | ||
2646 | for_each_tracing_cpu(i) | ||
2647 | check_pages(global_trace.data[i]); | ||
2648 | |||
2638 | filp->f_pos += cnt; | 2649 | filp->f_pos += cnt; |
2639 | 2650 | ||
2651 | /* If check pages failed, return ENOMEM */ | ||
2652 | if (tracing_disabled) | ||
2653 | cnt = -ENOMEM; | ||
2640 | out: | 2654 | out: |
2641 | max_tr.entries = global_trace.entries; | 2655 | max_tr.entries = global_trace.entries; |
2642 | mutex_unlock(&trace_types_lock); | 2656 | mutex_unlock(&trace_types_lock); |
diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c index 3877dd9102f1..18c5423bc977 100644 --- a/kernel/trace/trace_selftest.c +++ b/kernel/trace/trace_selftest.c | |||
@@ -28,6 +28,7 @@ trace_test_buffer_cpu(struct trace_array *tr, struct trace_array_cpu *data) | |||
28 | page = list_entry(data->trace_pages.next, struct page, lru); | 28 | page = list_entry(data->trace_pages.next, struct page, lru); |
29 | entries = page_address(page); | 29 | entries = page_address(page); |
30 | 30 | ||
31 | check_pages(data); | ||
31 | if (head_page(data) != entries) | 32 | if (head_page(data) != entries) |
32 | goto failed; | 33 | goto failed; |
33 | 34 | ||