diff options
author | Steven Rostedt (Red Hat) <rostedt@goodmis.org> | 2013-07-01 23:34:22 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-07-25 17:07:43 -0400 |
commit | 6492334c86dfb441af456337dc3217c2a430f141 (patch) | |
tree | d653bfe42570741bafe76da2b438e0e737c2709f | |
parent | 59d8f48855856c5e2e112bab78f1b1e6a14c216b (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.c | 121 |
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 | */ | ||
2909 | int 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 | |||
2925 | int 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 | |||
2905 | static int tracing_release(struct inode *inode, struct file *file) | 2942 | static 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 | ||
2985 | static 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 | |||
2993 | static 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 | |||
3002 | static 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 | |||
2948 | static int tracing_open(struct inode *inode, struct file *file) | 3011 | static 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 | ||
3332 | static int tracing_trace_options_open(struct inode *inode, struct file *file) | 3395 | static 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: | |||
3881 | fail: | 3952 | fail: |
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: | |||
3888 | static int tracing_release_pipe(struct inode *inode, struct file *file) | 3960 | static 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 | ||
4535 | static int tracing_clock_open(struct inode *inode, struct file *file) | 4613 | static 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 | ||
4543 | struct ftrace_buffer_info { | 4631 | struct ftrace_buffer_info { |
@@ -4733,34 +4821,38 @@ static const struct file_operations tracing_pipe_fops = { | |||
4733 | }; | 4821 | }; |
4734 | 4822 | ||
4735 | static const struct file_operations tracing_entries_fops = { | 4823 | static 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 | ||
4742 | static const struct file_operations tracing_total_entries_fops = { | 4831 | static 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 | ||
4748 | static const struct file_operations tracing_free_buffer_fops = { | 4838 | static 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 | ||
4753 | static const struct file_operations tracing_mark_fops = { | 4844 | static 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 | ||
4759 | static const struct file_operations trace_clock_fops = { | 4851 | static 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 | ||
4818 | static unsigned int | 4920 | static unsigned int |
@@ -5707,9 +5809,10 @@ rb_simple_write(struct file *filp, const char __user *ubuf, | |||
5707 | } | 5809 | } |
5708 | 5810 | ||
5709 | static const struct file_operations rb_simple_fops = { | 5811 | static 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 | ||