aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt (Red Hat) <rostedt@goodmis.org>2013-07-01 23:34:22 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-07-25 17:07:43 -0400
commit6492334c86dfb441af456337dc3217c2a430f141 (patch)
treed653bfe42570741bafe76da2b438e0e737c2709f
parent59d8f48855856c5e2e112bab78f1b1e6a14c216b (diff)
tracing: Get trace_array ref counts when accessing trace files
commit 7b85af63034818e43aee6c1d7bf1c7c6796a9073 upstream. When a trace file is opened that may access a trace array, it must increment its ref count to prevent it from being deleted. Reported-by: Alexander Lam <azl@google.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--kernel/trace/trace.c121
1 files changed, 112 insertions, 9 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 9d076a1ffa0b..0b936d806659 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -2902,6 +2902,43 @@ int tracing_open_generic(struct inode *inode, struct file *filp)
2902 return 0; 2902 return 0;
2903} 2903}
2904 2904
2905/*
2906 * Open and update trace_array ref count.
2907 * Must have the current trace_array passed to it.
2908 */
2909int tracing_open_generic_tr(struct inode *inode, struct file *filp)
2910{
2911 struct trace_array *tr = inode->i_private;
2912
2913 if (tracing_disabled)
2914 return -ENODEV;
2915
2916 if (trace_array_get(tr) < 0)
2917 return -ENODEV;
2918
2919 filp->private_data = inode->i_private;
2920
2921 return 0;
2922
2923}
2924
2925int tracing_open_generic_tc(struct inode *inode, struct file *filp)
2926{
2927 struct trace_cpu *tc = inode->i_private;
2928 struct trace_array *tr = tc->tr;
2929
2930 if (tracing_disabled)
2931 return -ENODEV;
2932
2933 if (trace_array_get(tr) < 0)
2934 return -ENODEV;
2935
2936 filp->private_data = inode->i_private;
2937
2938 return 0;
2939
2940}
2941
2905static int tracing_release(struct inode *inode, struct file *file) 2942static int tracing_release(struct inode *inode, struct file *file)
2906{ 2943{
2907 struct seq_file *m = file->private_data; 2944 struct seq_file *m = file->private_data;
@@ -2945,6 +2982,32 @@ static int tracing_release(struct inode *inode, struct file *file)
2945 return 0; 2982 return 0;
2946} 2983}
2947 2984
2985static int tracing_release_generic_tr(struct inode *inode, struct file *file)
2986{
2987 struct trace_array *tr = inode->i_private;
2988
2989 trace_array_put(tr);
2990 return 0;
2991}
2992
2993static int tracing_release_generic_tc(struct inode *inode, struct file *file)
2994{
2995 struct trace_cpu *tc = inode->i_private;
2996 struct trace_array *tr = tc->tr;
2997
2998 trace_array_put(tr);
2999 return 0;
3000}
3001
3002static int tracing_single_release_tr(struct inode *inode, struct file *file)
3003{
3004 struct trace_array *tr = inode->i_private;
3005
3006 trace_array_put(tr);
3007
3008 return single_release(inode, file);
3009}
3010
2948static int tracing_open(struct inode *inode, struct file *file) 3011static int tracing_open(struct inode *inode, struct file *file)
2949{ 3012{
2950 struct trace_cpu *tc = inode->i_private; 3013 struct trace_cpu *tc = inode->i_private;
@@ -3331,9 +3394,14 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
3331 3394
3332static int tracing_trace_options_open(struct inode *inode, struct file *file) 3395static int tracing_trace_options_open(struct inode *inode, struct file *file)
3333{ 3396{
3397 struct trace_array *tr = inode->i_private;
3398
3334 if (tracing_disabled) 3399 if (tracing_disabled)
3335 return -ENODEV; 3400 return -ENODEV;
3336 3401
3402 if (trace_array_get(tr) < 0)
3403 return -ENODEV;
3404
3337 return single_open(file, tracing_trace_options_show, inode->i_private); 3405 return single_open(file, tracing_trace_options_show, inode->i_private);
3338} 3406}
3339 3407
@@ -3341,7 +3409,7 @@ static const struct file_operations tracing_iter_fops = {
3341 .open = tracing_trace_options_open, 3409 .open = tracing_trace_options_open,
3342 .read = seq_read, 3410 .read = seq_read,
3343 .llseek = seq_lseek, 3411 .llseek = seq_lseek,
3344 .release = single_release, 3412 .release = tracing_single_release_tr,
3345 .write = tracing_trace_options_write, 3413 .write = tracing_trace_options_write,
3346}; 3414};
3347 3415
@@ -3829,6 +3897,9 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp)
3829 if (tracing_disabled) 3897 if (tracing_disabled)
3830 return -ENODEV; 3898 return -ENODEV;
3831 3899
3900 if (trace_array_get(tr) < 0)
3901 return -ENODEV;
3902
3832 mutex_lock(&trace_types_lock); 3903 mutex_lock(&trace_types_lock);
3833 3904
3834 /* create a buffer to store the information to pass to userspace */ 3905 /* create a buffer to store the information to pass to userspace */
@@ -3881,6 +3952,7 @@ out:
3881fail: 3952fail:
3882 kfree(iter->trace); 3953 kfree(iter->trace);
3883 kfree(iter); 3954 kfree(iter);
3955 __trace_array_put(tr);
3884 mutex_unlock(&trace_types_lock); 3956 mutex_unlock(&trace_types_lock);
3885 return ret; 3957 return ret;
3886} 3958}
@@ -3888,6 +3960,8 @@ fail:
3888static int tracing_release_pipe(struct inode *inode, struct file *file) 3960static int tracing_release_pipe(struct inode *inode, struct file *file)
3889{ 3961{
3890 struct trace_iterator *iter = file->private_data; 3962 struct trace_iterator *iter = file->private_data;
3963 struct trace_cpu *tc = inode->i_private;
3964 struct trace_array *tr = tc->tr;
3891 3965
3892 mutex_lock(&trace_types_lock); 3966 mutex_lock(&trace_types_lock);
3893 3967
@@ -3901,6 +3975,8 @@ static int tracing_release_pipe(struct inode *inode, struct file *file)
3901 kfree(iter->trace); 3975 kfree(iter->trace);
3902 kfree(iter); 3976 kfree(iter);
3903 3977
3978 trace_array_put(tr);
3979
3904 return 0; 3980 return 0;
3905} 3981}
3906 3982
@@ -4358,6 +4434,8 @@ tracing_free_buffer_release(struct inode *inode, struct file *filp)
4358 /* resize the ring buffer to 0 */ 4434 /* resize the ring buffer to 0 */
4359 tracing_resize_ring_buffer(tr, 0, RING_BUFFER_ALL_CPUS); 4435 tracing_resize_ring_buffer(tr, 0, RING_BUFFER_ALL_CPUS);
4360 4436
4437 trace_array_put(tr);
4438
4361 return 0; 4439 return 0;
4362} 4440}
4363 4441
@@ -4534,10 +4612,20 @@ static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf,
4534 4612
4535static int tracing_clock_open(struct inode *inode, struct file *file) 4613static int tracing_clock_open(struct inode *inode, struct file *file)
4536{ 4614{
4615 struct trace_array *tr = inode->i_private;
4616 int ret;
4617
4537 if (tracing_disabled) 4618 if (tracing_disabled)
4538 return -ENODEV; 4619 return -ENODEV;
4539 4620
4540 return single_open(file, tracing_clock_show, inode->i_private); 4621 if (trace_array_get(tr))
4622 return -ENODEV;
4623
4624 ret = single_open(file, tracing_clock_show, inode->i_private);
4625 if (ret < 0)
4626 trace_array_put(tr);
4627
4628 return ret;
4541} 4629}
4542 4630
4543struct ftrace_buffer_info { 4631struct ftrace_buffer_info {
@@ -4733,34 +4821,38 @@ static const struct file_operations tracing_pipe_fops = {
4733}; 4821};
4734 4822
4735static const struct file_operations tracing_entries_fops = { 4823static const struct file_operations tracing_entries_fops = {
4736 .open = tracing_open_generic, 4824 .open = tracing_open_generic_tc,
4737 .read = tracing_entries_read, 4825 .read = tracing_entries_read,
4738 .write = tracing_entries_write, 4826 .write = tracing_entries_write,
4739 .llseek = generic_file_llseek, 4827 .llseek = generic_file_llseek,
4828 .release = tracing_release_generic_tc,
4740}; 4829};
4741 4830
4742static const struct file_operations tracing_total_entries_fops = { 4831static const struct file_operations tracing_total_entries_fops = {
4743 .open = tracing_open_generic, 4832 .open = tracing_open_generic_tr,
4744 .read = tracing_total_entries_read, 4833 .read = tracing_total_entries_read,
4745 .llseek = generic_file_llseek, 4834 .llseek = generic_file_llseek,
4835 .release = tracing_release_generic_tr,
4746}; 4836};
4747 4837
4748static const struct file_operations tracing_free_buffer_fops = { 4838static const struct file_operations tracing_free_buffer_fops = {
4839 .open = tracing_open_generic_tr,
4749 .write = tracing_free_buffer_write, 4840 .write = tracing_free_buffer_write,
4750 .release = tracing_free_buffer_release, 4841 .release = tracing_free_buffer_release,
4751}; 4842};
4752 4843
4753static const struct file_operations tracing_mark_fops = { 4844static const struct file_operations tracing_mark_fops = {
4754 .open = tracing_open_generic, 4845 .open = tracing_open_generic_tr,
4755 .write = tracing_mark_write, 4846 .write = tracing_mark_write,
4756 .llseek = generic_file_llseek, 4847 .llseek = generic_file_llseek,
4848 .release = tracing_release_generic_tr,
4757}; 4849};
4758 4850
4759static const struct file_operations trace_clock_fops = { 4851static const struct file_operations trace_clock_fops = {
4760 .open = tracing_clock_open, 4852 .open = tracing_clock_open,
4761 .read = seq_read, 4853 .read = seq_read,
4762 .llseek = seq_lseek, 4854 .llseek = seq_lseek,
4763 .release = single_release, 4855 .release = tracing_single_release_tr,
4764 .write = tracing_clock_write, 4856 .write = tracing_clock_write,
4765}; 4857};
4766 4858
@@ -4788,13 +4880,19 @@ static int tracing_buffers_open(struct inode *inode, struct file *filp)
4788 struct trace_cpu *tc = inode->i_private; 4880 struct trace_cpu *tc = inode->i_private;
4789 struct trace_array *tr = tc->tr; 4881 struct trace_array *tr = tc->tr;
4790 struct ftrace_buffer_info *info; 4882 struct ftrace_buffer_info *info;
4883 int ret;
4791 4884
4792 if (tracing_disabled) 4885 if (tracing_disabled)
4793 return -ENODEV; 4886 return -ENODEV;
4794 4887
4888 if (trace_array_get(tr) < 0)
4889 return -ENODEV;
4890
4795 info = kzalloc(sizeof(*info), GFP_KERNEL); 4891 info = kzalloc(sizeof(*info), GFP_KERNEL);
4796 if (!info) 4892 if (!info) {
4893 trace_array_put(tr);
4797 return -ENOMEM; 4894 return -ENOMEM;
4895 }
4798 4896
4799 mutex_lock(&trace_types_lock); 4897 mutex_lock(&trace_types_lock);
4800 4898
@@ -4812,7 +4910,11 @@ static int tracing_buffers_open(struct inode *inode, struct file *filp)
4812 4910
4813 mutex_unlock(&trace_types_lock); 4911 mutex_unlock(&trace_types_lock);
4814 4912
4815 return nonseekable_open(inode, filp); 4913 ret = nonseekable_open(inode, filp);
4914 if (ret < 0)
4915 trace_array_put(tr);
4916
4917 return ret;
4816} 4918}
4817 4919
4818static unsigned int 4920static unsigned int
@@ -5707,9 +5809,10 @@ rb_simple_write(struct file *filp, const char __user *ubuf,
5707} 5809}
5708 5810
5709static const struct file_operations rb_simple_fops = { 5811static const struct file_operations rb_simple_fops = {
5710 .open = tracing_open_generic, 5812 .open = tracing_open_generic_tr,
5711 .read = rb_simple_read, 5813 .read = rb_simple_read,
5712 .write = rb_simple_write, 5814 .write = rb_simple_write,
5815 .release = tracing_release_generic_tr,
5713 .llseek = default_llseek, 5816 .llseek = default_llseek,
5714}; 5817};
5715 5818