]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/3.0.1/tracing-have-enable-file-use-refcounts-like-the-filter.patch
fixes for 4.19
[thirdparty/kernel/stable-queue.git] / releases / 3.0.1 / tracing-have-enable-file-use-refcounts-like-the-filter.patch
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"
5 file
6
7 From: Steven Rostedt <srostedt@redhat.com>
8
9 commit 40ee4dffff061399eb9358e0c8fcfbaf8de4c8fe upstream.
10
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.
15
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.
19
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
24 a freed pointer.
25
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.
29
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>
33
34 ---
35 kernel/trace/trace_events.c | 31 ++++++++++++++++++++++---------
36 1 file changed, 22 insertions(+), 9 deletions(-)
37
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
41 loff_t *ppos)
42 {
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;
47 char buf[2];
48 int set = 0;
49 @@ -568,7 +568,7 @@ system_enable_read(struct file *filp, ch
50 if (!call->name || !call->class || !call->class->reg)
51 continue;
52
53 - if (system && strcmp(call->class->system, system) != 0)
54 + if (system && strcmp(call->class->system, system->name) != 0)
55 continue;
56
57 /*
58 @@ -598,7 +598,8 @@ static ssize_t
59 system_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
60 loff_t *ppos)
61 {
62 - const char *system = filp->private_data;
63 + struct event_subsystem *system = filp->private_data;
64 + const char *name = NULL;
65 unsigned long val;
66 char buf[64];
67 ssize_t ret;
68 @@ -622,7 +623,14 @@ system_enable_write(struct file *filp, c
69 if (val != 0 && val != 1)
70 return -EINVAL;
71
72 - ret = __ftrace_set_clr_event(NULL, system, NULL, val);
73 + /*
74 + * Opening of "enable" adds a ref count to system,
75 + * so the name is safe to use.
76 + */
77 + if (system)
78 + name = system->name;
79 +
80 + ret = __ftrace_set_clr_event(NULL, name, NULL, val);
81 if (ret)
82 goto out;
83
84 @@ -862,6 +870,9 @@ static int subsystem_open(struct inode *
85 struct event_subsystem *system = NULL;
86 int ret;
87
88 + if (!inode->i_private)
89 + goto skip_search;
90 +
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)
96 return -ENODEV;
97
98 + skip_search:
99 ret = tracing_open_generic(inode, filp);
100 - if (ret < 0)
101 + if (ret < 0 && system)
102 put_system(system);
103
104 return ret;
105 @@ -891,7 +903,8 @@ static int subsystem_release(struct inod
106 {
107 struct event_subsystem *system = inode->i_private;
108
109 - put_system(system);
110 + if (system)
111 + put_system(system);
112
113 return 0;
114 }
115 @@ -1041,10 +1054,11 @@ static const struct file_operations ftra
116 };
117
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,
125 };
126
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);
130 }
131
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);
136
137 return system->entry;