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 | } |