aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace
diff options
context:
space:
mode:
authorSteven Rostedt (Red Hat) <rostedt@goodmis.org>2013-07-01 23:34:22 -0400
committerSteven Rostedt <rostedt@goodmis.org>2013-07-02 10:17:04 -0400
commit7b85af63034818e43aee6c1d7bf1c7c6796a9073 (patch)
tree4bc354897ff28147a5aedb7c318608a30d46e61b /kernel/trace
parentff451961a8b2a17667a7bfa39c86fb9b351445db (diff)
tracing: Get trace_array ref counts when accessing trace files
When a trace file is opened that may access a trace array, it must increment its ref count to prevent it from being deleted. Cc: stable@vger.kernel.org # 3.10 Reported-by: Alexander Lam <azl@google.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace')
-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 6be9df1aa513..6d9bd9b43e43 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -2965,6 +2965,43 @@ int tracing_open_generic(struct inode *inode, struct file *filp)
2965 return 0; 2965 return 0;
2966} 2966}
2967 2967
2968/*
2969 * Open and update trace_array ref count.
2970 * Must have the current trace_array passed to it.
2971 */
2972int tracing_open_generic_tr(struct inode *inode, struct file *filp)
2973{
2974 struct trace_array *tr = inode->i_private;
2975
2976 if (tracing_disabled)
2977 return -ENODEV;
2978
2979 if (trace_array_get(tr) < 0)
2980 return -ENODEV;
2981
2982 filp->private_data = inode->i_private;
2983
2984 return 0;
2985
2986}
2987
2988int tracing_open_generic_tc(struct inode *inode, struct file *filp)
2989{
2990 struct trace_cpu *tc = inode->i_private;
2991 struct trace_array *tr = tc->tr;
2992
2993 if (tracing_disabled)
2994 return -ENODEV;
2995
2996 if (trace_array_get(tr) < 0)
2997 return -ENODEV;
2998
2999 filp->private_data = inode->i_private;
3000
3001 return 0;
3002
3003}
3004
2968static int tracing_release(struct inode *inode, struct file *file) 3005static int tracing_release(struct inode *inode, struct file *file)
2969{ 3006{
2970 struct seq_file *m = file->private_data; 3007 struct seq_file *m = file->private_data;
@@ -3008,6 +3045,32 @@ static int tracing_release(struct inode *inode, struct file *file)
3008 return 0; 3045 return 0;
3009} 3046}
3010 3047
3048static int tracing_release_generic_tr(struct inode *inode, struct file *file)
3049{
3050 struct trace_array *tr = inode->i_private;
3051
3052 trace_array_put(tr);
3053 return 0;
3054}
3055
3056static int tracing_release_generic_tc(struct inode *inode, struct file *file)
3057{
3058 struct trace_cpu *tc = inode->i_private;
3059 struct trace_array *tr = tc->tr;
3060
3061 trace_array_put(tr);
3062 return 0;
3063}
3064
3065static int tracing_single_release_tr(struct inode *inode, struct file *file)
3066{
3067 struct trace_array *tr = inode->i_private;
3068
3069 trace_array_put(tr);
3070
3071 return single_release(inode, file);
3072}
3073
3011static int tracing_open(struct inode *inode, struct file *file) 3074static int tracing_open(struct inode *inode, struct file *file)
3012{ 3075{
3013 struct trace_cpu *tc = inode->i_private; 3076 struct trace_cpu *tc = inode->i_private;
@@ -3394,9 +3457,14 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
3394 3457
3395static int tracing_trace_options_open(struct inode *inode, struct file *file) 3458static int tracing_trace_options_open(struct inode *inode, struct file *file)
3396{ 3459{
3460 struct trace_array *tr = inode->i_private;
3461
3397 if (tracing_disabled) 3462 if (tracing_disabled)
3398 return -ENODEV; 3463 return -ENODEV;
3399 3464
3465 if (trace_array_get(tr) < 0)
3466 return -ENODEV;
3467
3400 return single_open(file, tracing_trace_options_show, inode->i_private); 3468 return single_open(file, tracing_trace_options_show, inode->i_private);
3401} 3469}
3402 3470
@@ -3404,7 +3472,7 @@ static const struct file_operations tracing_iter_fops = {
3404 .open = tracing_trace_options_open, 3472 .open = tracing_trace_options_open,
3405 .read = seq_read, 3473 .read = seq_read,
3406 .llseek = seq_lseek, 3474 .llseek = seq_lseek,
3407 .release = single_release, 3475 .release = tracing_single_release_tr,
3408 .write = tracing_trace_options_write, 3476 .write = tracing_trace_options_write,
3409}; 3477};
3410 3478
@@ -3892,6 +3960,9 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp)
3892 if (tracing_disabled) 3960 if (tracing_disabled)
3893 return -ENODEV; 3961 return -ENODEV;
3894 3962
3963 if (trace_array_get(tr) < 0)
3964 return -ENODEV;
3965
3895 mutex_lock(&trace_types_lock); 3966 mutex_lock(&trace_types_lock);
3896 3967
3897 /* create a buffer to store the information to pass to userspace */ 3968 /* create a buffer to store the information to pass to userspace */
@@ -3944,6 +4015,7 @@ out:
3944fail: 4015fail:
3945 kfree(iter->trace); 4016 kfree(iter->trace);
3946 kfree(iter); 4017 kfree(iter);
4018 __trace_array_put(tr);
3947 mutex_unlock(&trace_types_lock); 4019 mutex_unlock(&trace_types_lock);
3948 return ret; 4020 return ret;
3949} 4021}
@@ -3951,6 +4023,8 @@ fail:
3951static int tracing_release_pipe(struct inode *inode, struct file *file) 4023static int tracing_release_pipe(struct inode *inode, struct file *file)
3952{ 4024{
3953 struct trace_iterator *iter = file->private_data; 4025 struct trace_iterator *iter = file->private_data;
4026 struct trace_cpu *tc = inode->i_private;
4027 struct trace_array *tr = tc->tr;
3954 4028
3955 mutex_lock(&trace_types_lock); 4029 mutex_lock(&trace_types_lock);
3956 4030
@@ -3964,6 +4038,8 @@ static int tracing_release_pipe(struct inode *inode, struct file *file)
3964 kfree(iter->trace); 4038 kfree(iter->trace);
3965 kfree(iter); 4039 kfree(iter);
3966 4040
4041 trace_array_put(tr);
4042
3967 return 0; 4043 return 0;
3968} 4044}
3969 4045
@@ -4421,6 +4497,8 @@ tracing_free_buffer_release(struct inode *inode, struct file *filp)
4421 /* resize the ring buffer to 0 */ 4497 /* resize the ring buffer to 0 */
4422 tracing_resize_ring_buffer(tr, 0, RING_BUFFER_ALL_CPUS); 4498 tracing_resize_ring_buffer(tr, 0, RING_BUFFER_ALL_CPUS);
4423 4499
4500 trace_array_put(tr);
4501
4424 return 0; 4502 return 0;
4425} 4503}
4426 4504
@@ -4597,10 +4675,20 @@ static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf,
4597 4675
4598static int tracing_clock_open(struct inode *inode, struct file *file) 4676static int tracing_clock_open(struct inode *inode, struct file *file)
4599{ 4677{
4678 struct trace_array *tr = inode->i_private;
4679 int ret;
4680
4600 if (tracing_disabled) 4681 if (tracing_disabled)
4601 return -ENODEV; 4682 return -ENODEV;
4602 4683
4603 return single_open(file, tracing_clock_show, inode->i_private); 4684 if (trace_array_get(tr))
4685 return -ENODEV;
4686
4687 ret = single_open(file, tracing_clock_show, inode->i_private);
4688 if (ret < 0)
4689 trace_array_put(tr);
4690
4691 return ret;
4604} 4692}
4605 4693
4606struct ftrace_buffer_info { 4694struct ftrace_buffer_info {
@@ -4796,34 +4884,38 @@ static const struct file_operations tracing_pipe_fops = {
4796}; 4884};
4797 4885
4798static const struct file_operations tracing_entries_fops = { 4886static const struct file_operations tracing_entries_fops = {
4799 .open = tracing_open_generic, 4887 .open = tracing_open_generic_tc,
4800 .read = tracing_entries_read, 4888 .read = tracing_entries_read,
4801 .write = tracing_entries_write, 4889 .write = tracing_entries_write,
4802 .llseek = generic_file_llseek, 4890 .llseek = generic_file_llseek,
4891 .release = tracing_release_generic_tc,
4803}; 4892};
4804 4893
4805static const struct file_operations tracing_total_entries_fops = { 4894static const struct file_operations tracing_total_entries_fops = {
4806 .open = tracing_open_generic, 4895 .open = tracing_open_generic_tr,
4807 .read = tracing_total_entries_read, 4896 .read = tracing_total_entries_read,
4808 .llseek = generic_file_llseek, 4897 .llseek = generic_file_llseek,
4898 .release = tracing_release_generic_tr,
4809}; 4899};
4810 4900
4811static const struct file_operations tracing_free_buffer_fops = { 4901static const struct file_operations tracing_free_buffer_fops = {
4902 .open = tracing_open_generic_tr,
4812 .write = tracing_free_buffer_write, 4903 .write = tracing_free_buffer_write,
4813 .release = tracing_free_buffer_release, 4904 .release = tracing_free_buffer_release,
4814}; 4905};
4815 4906
4816static const struct file_operations tracing_mark_fops = { 4907static const struct file_operations tracing_mark_fops = {
4817 .open = tracing_open_generic, 4908 .open = tracing_open_generic_tr,
4818 .write = tracing_mark_write, 4909 .write = tracing_mark_write,
4819 .llseek = generic_file_llseek, 4910 .llseek = generic_file_llseek,
4911 .release = tracing_release_generic_tr,
4820}; 4912};
4821 4913
4822static const struct file_operations trace_clock_fops = { 4914static const struct file_operations trace_clock_fops = {
4823 .open = tracing_clock_open, 4915 .open = tracing_clock_open,
4824 .read = seq_read, 4916 .read = seq_read,
4825 .llseek = seq_lseek, 4917 .llseek = seq_lseek,
4826 .release = single_release, 4918 .release = tracing_single_release_tr,
4827 .write = tracing_clock_write, 4919 .write = tracing_clock_write,
4828}; 4920};
4829 4921
@@ -4851,13 +4943,19 @@ static int tracing_buffers_open(struct inode *inode, struct file *filp)
4851 struct trace_cpu *tc = inode->i_private; 4943 struct trace_cpu *tc = inode->i_private;
4852 struct trace_array *tr = tc->tr; 4944 struct trace_array *tr = tc->tr;
4853 struct ftrace_buffer_info *info; 4945 struct ftrace_buffer_info *info;
4946 int ret;
4854 4947
4855 if (tracing_disabled) 4948 if (tracing_disabled)
4856 return -ENODEV; 4949 return -ENODEV;
4857 4950
4951 if (trace_array_get(tr) < 0)
4952 return -ENODEV;
4953
4858 info = kzalloc(sizeof(*info), GFP_KERNEL); 4954 info = kzalloc(sizeof(*info), GFP_KERNEL);
4859 if (!info) 4955 if (!info) {
4956 trace_array_put(tr);
4860 return -ENOMEM; 4957 return -ENOMEM;
4958 }
4861 4959
4862 mutex_lock(&trace_types_lock); 4960 mutex_lock(&trace_types_lock);
4863 4961
@@ -4875,7 +4973,11 @@ static int tracing_buffers_open(struct inode *inode, struct file *filp)
4875 4973
4876 mutex_unlock(&trace_types_lock); 4974 mutex_unlock(&trace_types_lock);
4877 4975
4878 return nonseekable_open(inode, filp); 4976 ret = nonseekable_open(inode, filp);
4977 if (ret < 0)
4978 trace_array_put(tr);
4979
4980 return ret;
4879} 4981}
4880 4982
4881static unsigned int 4983static unsigned int
@@ -5765,9 +5867,10 @@ rb_simple_write(struct file *filp, const char __user *ubuf,
5765} 5867}
5766 5868
5767static const struct file_operations rb_simple_fops = { 5869static const struct file_operations rb_simple_fops = {
5768 .open = tracing_open_generic, 5870 .open = tracing_open_generic_tr,
5769 .read = rb_simple_read, 5871 .read = rb_simple_read,
5770 .write = rb_simple_write, 5872 .write = rb_simple_write,
5873 .release = tracing_release_generic_tr,
5771 .llseek = default_llseek, 5874 .llseek = default_llseek,
5772}; 5875};
5773 5876