Commit 6492334c authored by Steven Rostedt (Red Hat)'s avatar Steven Rostedt (Red Hat) Committed by Greg Kroah-Hartman

tracing: Get trace_array ref counts when accessing trace files

commit 7b85af63 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: default avatarAlexander Lam <azl@google.com>
Signed-off-by: default avatarSteven Rostedt <rostedt@goodmis.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 59d8f488
......@@ -2902,6 +2902,43 @@ int tracing_open_generic(struct inode *inode, struct file *filp)
return 0;
}
/*
* Open and update trace_array ref count.
* Must have the current trace_array passed to it.
*/
int tracing_open_generic_tr(struct inode *inode, struct file *filp)
{
struct trace_array *tr = inode->i_private;
if (tracing_disabled)
return -ENODEV;
if (trace_array_get(tr) < 0)
return -ENODEV;
filp->private_data = inode->i_private;
return 0;
}
int tracing_open_generic_tc(struct inode *inode, struct file *filp)
{
struct trace_cpu *tc = inode->i_private;
struct trace_array *tr = tc->tr;
if (tracing_disabled)
return -ENODEV;
if (trace_array_get(tr) < 0)
return -ENODEV;
filp->private_data = inode->i_private;
return 0;
}
static int tracing_release(struct inode *inode, struct file *file)
{
struct seq_file *m = file->private_data;
......@@ -2945,6 +2982,32 @@ static int tracing_release(struct inode *inode, struct file *file)
return 0;
}
static int tracing_release_generic_tr(struct inode *inode, struct file *file)
{
struct trace_array *tr = inode->i_private;
trace_array_put(tr);
return 0;
}
static int tracing_release_generic_tc(struct inode *inode, struct file *file)
{
struct trace_cpu *tc = inode->i_private;
struct trace_array *tr = tc->tr;
trace_array_put(tr);
return 0;
}
static int tracing_single_release_tr(struct inode *inode, struct file *file)
{
struct trace_array *tr = inode->i_private;
trace_array_put(tr);
return single_release(inode, file);
}
static int tracing_open(struct inode *inode, struct file *file)
{
struct trace_cpu *tc = inode->i_private;
......@@ -3331,9 +3394,14 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
static int tracing_trace_options_open(struct inode *inode, struct file *file)
{
struct trace_array *tr = inode->i_private;
if (tracing_disabled)
return -ENODEV;
if (trace_array_get(tr) < 0)
return -ENODEV;
return single_open(file, tracing_trace_options_show, inode->i_private);
}
......@@ -3341,7 +3409,7 @@ static const struct file_operations tracing_iter_fops = {
.open = tracing_trace_options_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.release = tracing_single_release_tr,
.write = tracing_trace_options_write,
};
......@@ -3829,6 +3897,9 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp)
if (tracing_disabled)
return -ENODEV;
if (trace_array_get(tr) < 0)
return -ENODEV;
mutex_lock(&trace_types_lock);
/* create a buffer to store the information to pass to userspace */
......@@ -3881,6 +3952,7 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp)
fail:
kfree(iter->trace);
kfree(iter);
__trace_array_put(tr);
mutex_unlock(&trace_types_lock);
return ret;
}
......@@ -3888,6 +3960,8 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp)
static int tracing_release_pipe(struct inode *inode, struct file *file)
{
struct trace_iterator *iter = file->private_data;
struct trace_cpu *tc = inode->i_private;
struct trace_array *tr = tc->tr;
mutex_lock(&trace_types_lock);
......@@ -3901,6 +3975,8 @@ static int tracing_release_pipe(struct inode *inode, struct file *file)
kfree(iter->trace);
kfree(iter);
trace_array_put(tr);
return 0;
}
......@@ -4358,6 +4434,8 @@ tracing_free_buffer_release(struct inode *inode, struct file *filp)
/* resize the ring buffer to 0 */
tracing_resize_ring_buffer(tr, 0, RING_BUFFER_ALL_CPUS);
trace_array_put(tr);
return 0;
}
......@@ -4534,10 +4612,20 @@ static ssize_t tracing_clock_write(struct file *filp, const char __user *ubuf,
static int tracing_clock_open(struct inode *inode, struct file *file)
{
struct trace_array *tr = inode->i_private;
int ret;
if (tracing_disabled)
return -ENODEV;
return single_open(file, tracing_clock_show, inode->i_private);
if (trace_array_get(tr))
return -ENODEV;
ret = single_open(file, tracing_clock_show, inode->i_private);
if (ret < 0)
trace_array_put(tr);
return ret;
}
struct ftrace_buffer_info {
......@@ -4733,34 +4821,38 @@ static const struct file_operations tracing_pipe_fops = {
};
static const struct file_operations tracing_entries_fops = {
.open = tracing_open_generic,
.open = tracing_open_generic_tc,
.read = tracing_entries_read,
.write = tracing_entries_write,
.llseek = generic_file_llseek,
.release = tracing_release_generic_tc,
};
static const struct file_operations tracing_total_entries_fops = {
.open = tracing_open_generic,
.open = tracing_open_generic_tr,
.read = tracing_total_entries_read,
.llseek = generic_file_llseek,
.release = tracing_release_generic_tr,
};
static const struct file_operations tracing_free_buffer_fops = {
.open = tracing_open_generic_tr,
.write = tracing_free_buffer_write,
.release = tracing_free_buffer_release,
};
static const struct file_operations tracing_mark_fops = {
.open = tracing_open_generic,
.open = tracing_open_generic_tr,
.write = tracing_mark_write,
.llseek = generic_file_llseek,
.release = tracing_release_generic_tr,
};
static const struct file_operations trace_clock_fops = {
.open = tracing_clock_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.release = tracing_single_release_tr,
.write = tracing_clock_write,
};
......@@ -4788,13 +4880,19 @@ static int tracing_buffers_open(struct inode *inode, struct file *filp)
struct trace_cpu *tc = inode->i_private;
struct trace_array *tr = tc->tr;
struct ftrace_buffer_info *info;
int ret;
if (tracing_disabled)
return -ENODEV;
if (trace_array_get(tr) < 0)
return -ENODEV;
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (!info)
if (!info) {
trace_array_put(tr);
return -ENOMEM;
}
mutex_lock(&trace_types_lock);
......@@ -4812,7 +4910,11 @@ static int tracing_buffers_open(struct inode *inode, struct file *filp)
mutex_unlock(&trace_types_lock);
return nonseekable_open(inode, filp);
ret = nonseekable_open(inode, filp);
if (ret < 0)
trace_array_put(tr);
return ret;
}
static unsigned int
......@@ -5707,9 +5809,10 @@ rb_simple_write(struct file *filp, const char __user *ubuf,
}
static const struct file_operations rb_simple_fops = {
.open = tracing_open_generic,
.open = tracing_open_generic_tr,
.read = rb_simple_read,
.write = rb_simple_write,
.release = tracing_release_generic_tr,
.llseek = default_llseek,
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment