diff options
author | Steven Rostedt (Red Hat) <rostedt@goodmis.org> | 2013-07-01 23:34:22 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2013-07-02 10:17:04 -0400 |
commit | 7b85af63034818e43aee6c1d7bf1c7c6796a9073 (patch) | |
tree | 4bc354897ff28147a5aedb7c318608a30d46e61b /kernel/trace | |
parent | ff451961a8b2a17667a7bfa39c86fb9b351445db (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.c | 121 |
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 | */ | ||
2972 | int 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 | |||
2988 | int 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 | |||
2968 | static int tracing_release(struct inode *inode, struct file *file) | 3005 | static 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 | ||
3048 | static 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 | |||
3056 | static 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 | |||
3065 | static 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 | |||
3011 | static int tracing_open(struct inode *inode, struct file *file) | 3074 | static 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 | ||
3395 | static int tracing_trace_options_open(struct inode *inode, struct file *file) | 3458 | static 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: | |||
3944 | fail: | 4015 | fail: |
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: | |||
3951 | static int tracing_release_pipe(struct inode *inode, struct file *file) | 4023 | static 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 | ||
4598 | static int tracing_clock_open(struct inode *inode, struct file *file) | 4676 | static 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 | ||
4606 | struct ftrace_buffer_info { | 4694 | struct ftrace_buffer_info { |
@@ -4796,34 +4884,38 @@ static const struct file_operations tracing_pipe_fops = { | |||
4796 | }; | 4884 | }; |
4797 | 4885 | ||
4798 | static const struct file_operations tracing_entries_fops = { | 4886 | static 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 | ||
4805 | static const struct file_operations tracing_total_entries_fops = { | 4894 | static 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 | ||
4811 | static const struct file_operations tracing_free_buffer_fops = { | 4901 | static 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 | ||
4816 | static const struct file_operations tracing_mark_fops = { | 4907 | static 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 | ||
4822 | static const struct file_operations trace_clock_fops = { | 4914 | static 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 | ||
4881 | static unsigned int | 4983 | static unsigned int |
@@ -5765,9 +5867,10 @@ rb_simple_write(struct file *filp, const char __user *ubuf, | |||
5765 | } | 5867 | } |
5766 | 5868 | ||
5767 | static const struct file_operations rb_simple_fops = { | 5869 | static 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 | ||