1 From 40ee4dffff061399eb9358e0c8fcfbaf8de4c8fe Mon Sep 17 00:00:00 2001
2 From: Steven Rostedt <srostedt@redhat.com>
3 Date: Tue, 5 Jul 2011 14:32:51 -0400
4 Subject: tracing: Have "enable" file use refcounts like the "filter"
7 From: Steven Rostedt <srostedt@redhat.com>
9 commit 40ee4dffff061399eb9358e0c8fcfbaf8de4c8fe upstream.
11 The "enable" file for the event system can be removed when a module
12 is unloaded and the event system only has events from that module.
13 As the event system nr_events count goes to zero, it may be freed
14 if its ref_count is also set to zero.
16 Like the "filter" file, the "enable" file may be opened by a task and
17 referenced later, after a module has been unloaded and the events for
18 that event system have been removed.
20 Although the "filter" file referenced the event system structure,
21 the "enable" file only references a pointer to the event system
22 name. Since the name is freed when the event system is removed,
23 it is possible that an access to the "enable" file may reference
26 Update the "enable" file to use the subsystem_open() routine that
27 the "filter" file uses, to keep a reference to the event system
28 structure while the "enable" file is opened.
30 Reported-by: Johannes Berg <johannes.berg@intel.com>
31 Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
32 Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
35 kernel/trace/trace_events.c | 31 ++++++++++++++++++++++---------
36 1 file changed, 22 insertions(+), 9 deletions(-)
38 --- a/kernel/trace/trace_events.c
39 +++ b/kernel/trace/trace_events.c
40 @@ -557,7 +557,7 @@ system_enable_read(struct file *filp, ch
43 const char set_to_char[4] = { '?', '0', '1', 'X' };
44 - const char *system = filp->private_data;
45 + struct event_subsystem *system = filp->private_data;
46 struct ftrace_event_call *call;
49 @@ -568,7 +568,7 @@ system_enable_read(struct file *filp, ch
50 if (!call->name || !call->class || !call->class->reg)
53 - if (system && strcmp(call->class->system, system) != 0)
54 + if (system && strcmp(call->class->system, system->name) != 0)
58 @@ -598,7 +598,8 @@ static ssize_t
59 system_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
62 - const char *system = filp->private_data;
63 + struct event_subsystem *system = filp->private_data;
64 + const char *name = NULL;
68 @@ -622,7 +623,14 @@ system_enable_write(struct file *filp, c
69 if (val != 0 && val != 1)
72 - ret = __ftrace_set_clr_event(NULL, system, NULL, val);
74 + * Opening of "enable" adds a ref count to system,
75 + * so the name is safe to use.
78 + name = system->name;
80 + ret = __ftrace_set_clr_event(NULL, name, NULL, val);
84 @@ -862,6 +870,9 @@ static int subsystem_open(struct inode *
85 struct event_subsystem *system = NULL;
88 + if (!inode->i_private)
91 /* Make sure the system still exists */
92 mutex_lock(&event_mutex);
93 list_for_each_entry(system, &event_subsystems, list) {
94 @@ -880,8 +891,9 @@ static int subsystem_open(struct inode *
95 if (system != inode->i_private)
99 ret = tracing_open_generic(inode, filp);
101 + if (ret < 0 && system)
105 @@ -891,7 +903,8 @@ static int subsystem_release(struct inod
107 struct event_subsystem *system = inode->i_private;
109 - put_system(system);
111 + put_system(system);
115 @@ -1041,10 +1054,11 @@ static const struct file_operations ftra
118 static const struct file_operations ftrace_system_enable_fops = {
119 - .open = tracing_open_generic,
120 + .open = subsystem_open,
121 .read = system_enable_read,
122 .write = system_enable_write,
123 .llseek = default_llseek,
124 + .release = subsystem_release,
127 static const struct file_operations ftrace_show_header_fops = {
128 @@ -1133,8 +1147,7 @@ event_subsystem_dir(const char *name, st
129 "'%s/filter' entry\n", name);
132 - trace_create_file("enable", 0644, system->entry,
133 - (void *)system->name,
134 + trace_create_file("enable", 0644, system->entry, system,
135 &ftrace_system_enable_fops);
137 return system->entry;