aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorSteven Rostedt (VMware) <rostedt@goodmis.org>2019-10-11 17:39:57 -0400
committerSteven Rostedt (VMware) <rostedt@goodmis.org>2019-10-12 20:44:07 -0400
commit8530dec63e7b486e3761cc3d74a22de301845ff5 (patch)
treebea5a6cbbfacf3b79428040486d3eb016d419289 /kernel
parentaa07d71f1bc7ea20e442e812b5de9d632b7f84c6 (diff)
tracing: Add tracing_check_open_get_tr()
Currently, most files in the tracefs directory test if tracing_disabled is set. If so, it should return -ENODEV. The tracing_disabled is called when tracing is found to be broken. Originally it was done in case the ring buffer was found to be corrupted, and we wanted to prevent reading it from crashing the kernel. But it's also called if a tracing selftest fails on boot. It's a one way switch. That is, once it is triggered, tracing is disabled until reboot. As most tracefs files can also be used by instances in the tracefs directory, they need to be carefully done. Each instance has a trace_array associated to it, and when the instance is removed, the trace_array is freed. But if an instance is opened with a reference to the trace_array, then it requires looking up the trace_array to get its ref counter (as there could be a race with it being deleted and the open itself). Once it is found, a reference is added to prevent the instance from being removed (and the trace_array associated with it freed). Combine the two checks (tracing_disabled and trace_array_get()) into a single helper function. This will also make it easier to add lockdown to tracefs later. Link: http://lkml.kernel.org/r/20191011135458.7399da44@gandalf.local.home Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/ftrace.c7
-rw-r--r--kernel/trace/trace.c117
-rw-r--r--kernel/trace/trace.h1
-rw-r--r--kernel/trace/trace_dynevent.c4
-rw-r--r--kernel/trace/trace_events.c10
-rw-r--r--kernel/trace/trace_events_hist.c2
6 files changed, 81 insertions, 60 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 32c2eb167de0..8b765a55e01c 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -3547,7 +3547,7 @@ ftrace_regex_open(struct ftrace_ops *ops, int flag,
3547 if (unlikely(ftrace_disabled)) 3547 if (unlikely(ftrace_disabled))
3548 return -ENODEV; 3548 return -ENODEV;
3549 3549
3550 if (tr && trace_array_get(tr) < 0) 3550 if (tracing_check_open_get_tr(tr))
3551 return -ENODEV; 3551 return -ENODEV;
3552 3552
3553 iter = kzalloc(sizeof(*iter), GFP_KERNEL); 3553 iter = kzalloc(sizeof(*iter), GFP_KERNEL);
@@ -6546,8 +6546,9 @@ ftrace_pid_open(struct inode *inode, struct file *file)
6546 struct seq_file *m; 6546 struct seq_file *m;
6547 int ret = 0; 6547 int ret = 0;
6548 6548
6549 if (trace_array_get(tr) < 0) 6549 ret = tracing_check_open_get_tr(tr);
6550 return -ENODEV; 6550 if (ret)
6551 return ret;
6551 6552
6552 if ((file->f_mode & FMODE_WRITE) && 6553 if ((file->f_mode & FMODE_WRITE) &&
6553 (file->f_flags & O_TRUNC)) 6554 (file->f_flags & O_TRUNC))
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 94f1b9124939..26ee280f852b 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -304,6 +304,17 @@ void trace_array_put(struct trace_array *this_tr)
304 mutex_unlock(&trace_types_lock); 304 mutex_unlock(&trace_types_lock);
305} 305}
306 306
307int tracing_check_open_get_tr(struct trace_array *tr)
308{
309 if (tracing_disabled)
310 return -ENODEV;
311
312 if (tr && trace_array_get(tr) < 0)
313 return -ENODEV;
314
315 return 0;
316}
317
307int call_filter_check_discard(struct trace_event_call *call, void *rec, 318int call_filter_check_discard(struct trace_event_call *call, void *rec,
308 struct ring_buffer *buffer, 319 struct ring_buffer *buffer,
309 struct ring_buffer_event *event) 320 struct ring_buffer_event *event)
@@ -4140,8 +4151,11 @@ release:
4140 4151
4141int tracing_open_generic(struct inode *inode, struct file *filp) 4152int tracing_open_generic(struct inode *inode, struct file *filp)
4142{ 4153{
4143 if (tracing_disabled) 4154 int ret;
4144 return -ENODEV; 4155
4156 ret = tracing_check_open_get_tr(NULL);
4157 if (ret)
4158 return ret;
4145 4159
4146 filp->private_data = inode->i_private; 4160 filp->private_data = inode->i_private;
4147 return 0; 4161 return 0;
@@ -4159,12 +4173,11 @@ bool tracing_is_disabled(void)
4159int tracing_open_generic_tr(struct inode *inode, struct file *filp) 4173int tracing_open_generic_tr(struct inode *inode, struct file *filp)
4160{ 4174{
4161 struct trace_array *tr = inode->i_private; 4175 struct trace_array *tr = inode->i_private;
4176 int ret;
4162 4177
4163 if (tracing_disabled) 4178 ret = tracing_check_open_get_tr(tr);
4164 return -ENODEV; 4179 if (ret)
4165 4180 return ret;
4166 if (trace_array_get(tr) < 0)
4167 return -ENODEV;
4168 4181
4169 filp->private_data = inode->i_private; 4182 filp->private_data = inode->i_private;
4170 4183
@@ -4233,10 +4246,11 @@ static int tracing_open(struct inode *inode, struct file *file)
4233{ 4246{
4234 struct trace_array *tr = inode->i_private; 4247 struct trace_array *tr = inode->i_private;
4235 struct trace_iterator *iter; 4248 struct trace_iterator *iter;
4236 int ret = 0; 4249 int ret;
4237 4250
4238 if (trace_array_get(tr) < 0) 4251 ret = tracing_check_open_get_tr(tr);
4239 return -ENODEV; 4252 if (ret)
4253 return ret;
4240 4254
4241 /* If this file was open for write, then erase contents */ 4255 /* If this file was open for write, then erase contents */
4242 if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) { 4256 if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) {
@@ -4352,11 +4366,9 @@ static int show_traces_open(struct inode *inode, struct file *file)
4352 struct seq_file *m; 4366 struct seq_file *m;
4353 int ret; 4367 int ret;
4354 4368
4355 if (tracing_disabled) 4369 ret = tracing_check_open_get_tr(tr);
4356 return -ENODEV; 4370 if (ret)
4357 4371 return ret;
4358 if (trace_array_get(tr) < 0)
4359 return -ENODEV;
4360 4372
4361 ret = seq_open(file, &show_traces_seq_ops); 4373 ret = seq_open(file, &show_traces_seq_ops);
4362 if (ret) { 4374 if (ret) {
@@ -4710,11 +4722,9 @@ static int tracing_trace_options_open(struct inode *inode, struct file *file)
4710 struct trace_array *tr = inode->i_private; 4722 struct trace_array *tr = inode->i_private;
4711 int ret; 4723 int ret;
4712 4724
4713 if (tracing_disabled) 4725 ret = tracing_check_open_get_tr(tr);
4714 return -ENODEV; 4726 if (ret)
4715 4727 return ret;
4716 if (trace_array_get(tr) < 0)
4717 return -ENODEV;
4718 4728
4719 ret = single_open(file, tracing_trace_options_show, inode->i_private); 4729 ret = single_open(file, tracing_trace_options_show, inode->i_private);
4720 if (ret < 0) 4730 if (ret < 0)
@@ -5051,8 +5061,11 @@ static const struct seq_operations tracing_saved_tgids_seq_ops = {
5051 5061
5052static int tracing_saved_tgids_open(struct inode *inode, struct file *filp) 5062static int tracing_saved_tgids_open(struct inode *inode, struct file *filp)
5053{ 5063{
5054 if (tracing_disabled) 5064 int ret;
5055 return -ENODEV; 5065
5066 ret = tracing_check_open_get_tr(NULL);
5067 if (ret)
5068 return ret;
5056 5069
5057 return seq_open(filp, &tracing_saved_tgids_seq_ops); 5070 return seq_open(filp, &tracing_saved_tgids_seq_ops);
5058} 5071}
@@ -5128,8 +5141,11 @@ static const struct seq_operations tracing_saved_cmdlines_seq_ops = {
5128 5141
5129static int tracing_saved_cmdlines_open(struct inode *inode, struct file *filp) 5142static int tracing_saved_cmdlines_open(struct inode *inode, struct file *filp)
5130{ 5143{
5131 if (tracing_disabled) 5144 int ret;
5132 return -ENODEV; 5145
5146 ret = tracing_check_open_get_tr(NULL);
5147 if (ret)
5148 return ret;
5133 5149
5134 return seq_open(filp, &tracing_saved_cmdlines_seq_ops); 5150 return seq_open(filp, &tracing_saved_cmdlines_seq_ops);
5135} 5151}
@@ -5293,8 +5309,11 @@ static const struct seq_operations tracing_eval_map_seq_ops = {
5293 5309
5294static int tracing_eval_map_open(struct inode *inode, struct file *filp) 5310static int tracing_eval_map_open(struct inode *inode, struct file *filp)
5295{ 5311{
5296 if (tracing_disabled) 5312 int ret;
5297 return -ENODEV; 5313
5314 ret = tracing_check_open_get_tr(NULL);
5315 if (ret)
5316 return ret;
5298 5317
5299 return seq_open(filp, &tracing_eval_map_seq_ops); 5318 return seq_open(filp, &tracing_eval_map_seq_ops);
5300} 5319}
@@ -5817,13 +5836,11 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp)
5817{ 5836{
5818 struct trace_array *tr = inode->i_private; 5837 struct trace_array *tr = inode->i_private;
5819 struct trace_iterator *iter; 5838 struct trace_iterator *iter;
5820 int ret = 0; 5839 int ret;
5821
5822 if (tracing_disabled)
5823 return -ENODEV;
5824 5840
5825 if (trace_array_get(tr) < 0) 5841 ret = tracing_check_open_get_tr(tr);
5826 return -ENODEV; 5842 if (ret)
5843 return ret;
5827 5844
5828 mutex_lock(&trace_types_lock); 5845 mutex_lock(&trace_types_lock);
5829 5846
@@ -6560,11 +6577,9 @@ static int tracing_clock_open(struct inode *inode, struct file *file)
6560 struct trace_array *tr = inode->i_private; 6577 struct trace_array *tr = inode->i_private;
6561 int ret; 6578 int ret;
6562 6579
6563 if (tracing_disabled) 6580 ret = tracing_check_open_get_tr(tr);
6564 return -ENODEV; 6581 if (ret)
6565 6582 return ret;
6566 if (trace_array_get(tr))
6567 return -ENODEV;
6568 6583
6569 ret = single_open(file, tracing_clock_show, inode->i_private); 6584 ret = single_open(file, tracing_clock_show, inode->i_private);
6570 if (ret < 0) 6585 if (ret < 0)
@@ -6594,11 +6609,9 @@ static int tracing_time_stamp_mode_open(struct inode *inode, struct file *file)
6594 struct trace_array *tr = inode->i_private; 6609 struct trace_array *tr = inode->i_private;
6595 int ret; 6610 int ret;
6596 6611
6597 if (tracing_disabled) 6612 ret = tracing_check_open_get_tr(tr);
6598 return -ENODEV; 6613 if (ret)
6599 6614 return ret;
6600 if (trace_array_get(tr))
6601 return -ENODEV;
6602 6615
6603 ret = single_open(file, tracing_time_stamp_mode_show, inode->i_private); 6616 ret = single_open(file, tracing_time_stamp_mode_show, inode->i_private);
6604 if (ret < 0) 6617 if (ret < 0)
@@ -6651,10 +6664,11 @@ static int tracing_snapshot_open(struct inode *inode, struct file *file)
6651 struct trace_array *tr = inode->i_private; 6664 struct trace_array *tr = inode->i_private;
6652 struct trace_iterator *iter; 6665 struct trace_iterator *iter;
6653 struct seq_file *m; 6666 struct seq_file *m;
6654 int ret = 0; 6667 int ret;
6655 6668
6656 if (trace_array_get(tr) < 0) 6669 ret = tracing_check_open_get_tr(tr);
6657 return -ENODEV; 6670 if (ret)
6671 return ret;
6658 6672
6659 if (file->f_mode & FMODE_READ) { 6673 if (file->f_mode & FMODE_READ) {
6660 iter = __tracing_open(inode, file, true); 6674 iter = __tracing_open(inode, file, true);
@@ -7118,8 +7132,9 @@ static int tracing_err_log_open(struct inode *inode, struct file *file)
7118 struct trace_array *tr = inode->i_private; 7132 struct trace_array *tr = inode->i_private;
7119 int ret = 0; 7133 int ret = 0;
7120 7134
7121 if (trace_array_get(tr) < 0) 7135 ret = tracing_check_open_get_tr(tr);
7122 return -ENODEV; 7136 if (ret)
7137 return ret;
7123 7138
7124 /* If this file was opened for write, then erase contents */ 7139 /* If this file was opened for write, then erase contents */
7125 if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) 7140 if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC))
@@ -7170,11 +7185,9 @@ static int tracing_buffers_open(struct inode *inode, struct file *filp)
7170 struct ftrace_buffer_info *info; 7185 struct ftrace_buffer_info *info;
7171 int ret; 7186 int ret;
7172 7187
7173 if (tracing_disabled) 7188 ret = tracing_check_open_get_tr(tr);
7174 return -ENODEV; 7189 if (ret)
7175 7190 return ret;
7176 if (trace_array_get(tr) < 0)
7177 return -ENODEV;
7178 7191
7179 info = kzalloc(sizeof(*info), GFP_KERNEL); 7192 info = kzalloc(sizeof(*info), GFP_KERNEL);
7180 if (!info) { 7193 if (!info) {
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 854dbf4050f8..d685c61085c0 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -338,6 +338,7 @@ extern struct mutex trace_types_lock;
338 338
339extern int trace_array_get(struct trace_array *tr); 339extern int trace_array_get(struct trace_array *tr);
340extern void trace_array_put(struct trace_array *tr); 340extern void trace_array_put(struct trace_array *tr);
341extern int tracing_check_open_get_tr(struct trace_array *tr);
341 342
342extern int tracing_set_time_stamp_abs(struct trace_array *tr, bool abs); 343extern int tracing_set_time_stamp_abs(struct trace_array *tr, bool abs);
343extern int tracing_set_clock(struct trace_array *tr, const char *clockstr); 344extern int tracing_set_clock(struct trace_array *tr, const char *clockstr);
diff --git a/kernel/trace/trace_dynevent.c b/kernel/trace/trace_dynevent.c
index a41fed46c285..89779eb84a07 100644
--- a/kernel/trace/trace_dynevent.c
+++ b/kernel/trace/trace_dynevent.c
@@ -174,6 +174,10 @@ static int dyn_event_open(struct inode *inode, struct file *file)
174{ 174{
175 int ret; 175 int ret;
176 176
177 ret = tracing_check_open_get_tr(NULL);
178 if (ret)
179 return ret;
180
177 if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) { 181 if ((file->f_mode & FMODE_WRITE) && (file->f_flags & O_TRUNC)) {
178 ret = dyn_events_release_all(NULL); 182 ret = dyn_events_release_all(NULL);
179 if (ret < 0) 183 if (ret < 0)
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 9613a757c902..71ab0a3660f4 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -1794,8 +1794,9 @@ ftrace_event_set_open(struct inode *inode, struct file *file)
1794 struct trace_array *tr = inode->i_private; 1794 struct trace_array *tr = inode->i_private;
1795 int ret; 1795 int ret;
1796 1796
1797 if (trace_array_get(tr) < 0) 1797 ret = tracing_check_open_get_tr(tr);
1798 return -ENODEV; 1798 if (ret)
1799 return ret;
1799 1800
1800 if ((file->f_mode & FMODE_WRITE) && 1801 if ((file->f_mode & FMODE_WRITE) &&
1801 (file->f_flags & O_TRUNC)) 1802 (file->f_flags & O_TRUNC))
@@ -1814,8 +1815,9 @@ ftrace_event_set_pid_open(struct inode *inode, struct file *file)
1814 struct trace_array *tr = inode->i_private; 1815 struct trace_array *tr = inode->i_private;
1815 int ret; 1816 int ret;
1816 1817
1817 if (trace_array_get(tr) < 0) 1818 ret = tracing_check_open_get_tr(tr);
1818 return -ENODEV; 1819 if (ret)
1820 return ret;
1819 1821
1820 if ((file->f_mode & FMODE_WRITE) && 1822 if ((file->f_mode & FMODE_WRITE) &&
1821 (file->f_flags & O_TRUNC)) 1823 (file->f_flags & O_TRUNC))
diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
index 9468bd8d44a2..dd18d76bf1bd 100644
--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -1680,7 +1680,7 @@ static int save_hist_vars(struct hist_trigger_data *hist_data)
1680 if (var_data) 1680 if (var_data)
1681 return 0; 1681 return 0;
1682 1682
1683 if (trace_array_get(tr) < 0) 1683 if (tracing_check_open_get_tr(tr))
1684 return -ENODEV; 1684 return -ENODEV;
1685 1685
1686 var_data = kzalloc(sizeof(*var_data), GFP_KERNEL); 1686 var_data = kzalloc(sizeof(*var_data), GFP_KERNEL);