diff options
| author | Oleg Nesterov <oleg@redhat.com> | 2013-07-26 13:25:43 -0400 |
|---|---|---|
| committer | Steven Rostedt <rostedt@goodmis.org> | 2013-07-29 22:57:10 -0400 |
| commit | c5a44a1200c6eda2202434f25325e8ad19533fca (patch) | |
| tree | 4ac8699d7e7ce648d888a2f2fb4889380d9b02a6 /kernel | |
| parent | e2912b091c26b8ea95e5e00a43a7ac620f6c94a6 (diff) | |
tracing: Change f_start() to take event_mutex and verify i_private != NULL
trace_format_open() and trace_format_seq_ops are racy, nothing
protects ftrace_event_call from trace_remove_event_call().
Change f_start() to take event_mutex and verify i_private != NULL,
change f_stop() to drop this lock.
This fixes nothing, but now we can change debugfs_remove("format")
callers to nullify ->i_private and fix the the problem.
Note: the usage of event_mutex is sub-optimal but simple, we can
change this later.
Link: http://lkml.kernel.org/r/20130726172543.GA3622@redhat.com
Reviewed-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/trace/trace_events.c | 13 |
1 files changed, 9 insertions, 4 deletions
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 1d7b6d03cd51..50dc8b2e5435 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
| @@ -840,7 +840,7 @@ enum { | |||
| 840 | 840 | ||
| 841 | static void *f_next(struct seq_file *m, void *v, loff_t *pos) | 841 | static void *f_next(struct seq_file *m, void *v, loff_t *pos) |
| 842 | { | 842 | { |
| 843 | struct ftrace_event_call *call = m->private; | 843 | struct ftrace_event_call *call = event_file_data(m->private); |
| 844 | struct list_head *common_head = &ftrace_common_fields; | 844 | struct list_head *common_head = &ftrace_common_fields; |
| 845 | struct list_head *head = trace_get_fields(call); | 845 | struct list_head *head = trace_get_fields(call); |
| 846 | struct list_head *node = v; | 846 | struct list_head *node = v; |
| @@ -872,7 +872,7 @@ static void *f_next(struct seq_file *m, void *v, loff_t *pos) | |||
| 872 | 872 | ||
| 873 | static int f_show(struct seq_file *m, void *v) | 873 | static int f_show(struct seq_file *m, void *v) |
| 874 | { | 874 | { |
| 875 | struct ftrace_event_call *call = m->private; | 875 | struct ftrace_event_call *call = event_file_data(m->private); |
| 876 | struct ftrace_event_field *field; | 876 | struct ftrace_event_field *field; |
| 877 | const char *array_descriptor; | 877 | const char *array_descriptor; |
| 878 | 878 | ||
| @@ -925,6 +925,11 @@ static void *f_start(struct seq_file *m, loff_t *pos) | |||
| 925 | void *p = (void *)FORMAT_HEADER; | 925 | void *p = (void *)FORMAT_HEADER; |
| 926 | loff_t l = 0; | 926 | loff_t l = 0; |
| 927 | 927 | ||
| 928 | /* ->stop() is called even if ->start() fails */ | ||
| 929 | mutex_lock(&event_mutex); | ||
| 930 | if (!event_file_data(m->private)) | ||
| 931 | return ERR_PTR(-ENODEV); | ||
| 932 | |||
| 928 | while (l < *pos && p) | 933 | while (l < *pos && p) |
| 929 | p = f_next(m, p, &l); | 934 | p = f_next(m, p, &l); |
| 930 | 935 | ||
| @@ -933,6 +938,7 @@ static void *f_start(struct seq_file *m, loff_t *pos) | |||
| 933 | 938 | ||
| 934 | static void f_stop(struct seq_file *m, void *p) | 939 | static void f_stop(struct seq_file *m, void *p) |
| 935 | { | 940 | { |
| 941 | mutex_unlock(&event_mutex); | ||
| 936 | } | 942 | } |
| 937 | 943 | ||
| 938 | static const struct seq_operations trace_format_seq_ops = { | 944 | static const struct seq_operations trace_format_seq_ops = { |
| @@ -944,7 +950,6 @@ static const struct seq_operations trace_format_seq_ops = { | |||
| 944 | 950 | ||
| 945 | static int trace_format_open(struct inode *inode, struct file *file) | 951 | static int trace_format_open(struct inode *inode, struct file *file) |
| 946 | { | 952 | { |
| 947 | struct ftrace_event_call *call = inode->i_private; | ||
| 948 | struct seq_file *m; | 953 | struct seq_file *m; |
| 949 | int ret; | 954 | int ret; |
| 950 | 955 | ||
| @@ -953,7 +958,7 @@ static int trace_format_open(struct inode *inode, struct file *file) | |||
| 953 | return ret; | 958 | return ret; |
| 954 | 959 | ||
| 955 | m = file->private_data; | 960 | m = file->private_data; |
| 956 | m->private = call; | 961 | m->private = file; |
| 957 | 962 | ||
| 958 | return 0; | 963 | return 0; |
| 959 | } | 964 | } |
