diff options
author | Oleg Nesterov <oleg@redhat.com> | 2013-07-23 11:26:03 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@rostedt.homelinux.com> | 2013-07-24 11:22:52 -0400 |
commit | 4d3435b8a4c3357695e09c5e7a3bf73a19fca5b0 (patch) | |
tree | 6f9032ea0dd88228e864fbfdfd29bba08f80f9e8 | |
parent | 46ef2be0d1d5ccea0c41bb606143586daadd537c (diff) |
tracing: Change tracing_stats_fops to rely on tracing_get_cpu()
tracing_open_generic_tc() is racy, the memory inode->i_private
points to can be already freed.
1. Change one of its users, tracing_stats_fops, to use
tracing_*_generic_tr() instead.
2. Change trace_create_cpu_file("stats", data) to pass "data = tr".
3. Change tracing_stats_read() to use tracing_get_cpu().
Link: http://lkml.kernel.org/r/20130723152603.GA23727@redhat.com
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r-- | kernel/trace/trace.c | 13 |
1 files changed, 6 insertions, 7 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 30c058a56ffb..e29dc8f69aac 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -2982,7 +2982,6 @@ static int tracing_open_generic_tr(struct inode *inode, struct file *filp) | |||
2982 | filp->private_data = inode->i_private; | 2982 | filp->private_data = inode->i_private; |
2983 | 2983 | ||
2984 | return 0; | 2984 | return 0; |
2985 | |||
2986 | } | 2985 | } |
2987 | 2986 | ||
2988 | static int tracing_open_generic_tc(struct inode *inode, struct file *filp) | 2987 | static int tracing_open_generic_tc(struct inode *inode, struct file *filp) |
@@ -5285,14 +5284,14 @@ static ssize_t | |||
5285 | tracing_stats_read(struct file *filp, char __user *ubuf, | 5284 | tracing_stats_read(struct file *filp, char __user *ubuf, |
5286 | size_t count, loff_t *ppos) | 5285 | size_t count, loff_t *ppos) |
5287 | { | 5286 | { |
5288 | struct trace_cpu *tc = filp->private_data; | 5287 | struct inode *inode = file_inode(filp); |
5289 | struct trace_array *tr = tc->tr; | 5288 | struct trace_array *tr = inode->i_private; |
5290 | struct trace_buffer *trace_buf = &tr->trace_buffer; | 5289 | struct trace_buffer *trace_buf = &tr->trace_buffer; |
5290 | int cpu = tracing_get_cpu(inode); | ||
5291 | struct trace_seq *s; | 5291 | struct trace_seq *s; |
5292 | unsigned long cnt; | 5292 | unsigned long cnt; |
5293 | unsigned long long t; | 5293 | unsigned long long t; |
5294 | unsigned long usec_rem; | 5294 | unsigned long usec_rem; |
5295 | int cpu = tc->cpu; | ||
5296 | 5295 | ||
5297 | s = kmalloc(sizeof(*s), GFP_KERNEL); | 5296 | s = kmalloc(sizeof(*s), GFP_KERNEL); |
5298 | if (!s) | 5297 | if (!s) |
@@ -5345,10 +5344,10 @@ tracing_stats_read(struct file *filp, char __user *ubuf, | |||
5345 | } | 5344 | } |
5346 | 5345 | ||
5347 | static const struct file_operations tracing_stats_fops = { | 5346 | static const struct file_operations tracing_stats_fops = { |
5348 | .open = tracing_open_generic_tc, | 5347 | .open = tracing_open_generic_tr, |
5349 | .read = tracing_stats_read, | 5348 | .read = tracing_stats_read, |
5350 | .llseek = generic_file_llseek, | 5349 | .llseek = generic_file_llseek, |
5351 | .release = tracing_release_generic_tc, | 5350 | .release = tracing_release_generic_tr, |
5352 | }; | 5351 | }; |
5353 | 5352 | ||
5354 | #ifdef CONFIG_DYNAMIC_FTRACE | 5353 | #ifdef CONFIG_DYNAMIC_FTRACE |
@@ -5578,7 +5577,7 @@ tracing_init_debugfs_percpu(struct trace_array *tr, long cpu) | |||
5578 | tr, cpu, &tracing_buffers_fops); | 5577 | tr, cpu, &tracing_buffers_fops); |
5579 | 5578 | ||
5580 | trace_create_cpu_file("stats", 0444, d_cpu, | 5579 | trace_create_cpu_file("stats", 0444, d_cpu, |
5581 | &data->trace_cpu, cpu, &tracing_stats_fops); | 5580 | tr, cpu, &tracing_stats_fops); |
5582 | 5581 | ||
5583 | trace_create_cpu_file("buffer_size_kb", 0444, d_cpu, | 5582 | trace_create_cpu_file("buffer_size_kb", 0444, d_cpu, |
5584 | &data->trace_cpu, cpu, &tracing_entries_fops); | 5583 | &data->trace_cpu, cpu, &tracing_entries_fops); |