From: Oleg Nesterov <oleg@redhat.com>
To: Steven Rostedt <rostedt@goodmis.org>,
Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Alexander Z Lam <azl@google.com>,
Arnaldo Carvalho de Melo <acme@ghostprotocols.net>,
David Sharp <dhsharp@google.com>,
Frederic Weisbecker <fweisbec@gmail.com>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Ingo Molnar <mingo@redhat.com>,
Peter Zijlstra <a.p.zijlstra@chello.nl>,
Srikar Dronamraju <srikar@linux.vnet.ibm.com>,
Vaibhav Nagarnaik <vnagarnaik@google.com>,
"zhangwei(Jovi)" <jovi.zhangwei@huawei.com>,
linux-kernel@vger.kernel.org
Subject: [PATCH v2 3/6] tracing: Change event_filter_read/write to verify i_private != NULL
Date: Fri, 26 Jul 2013 19:25:40 +0200 [thread overview]
Message-ID: <20130726172540.GA3619@redhat.com> (raw)
In-Reply-To: <20130726172513.GA3586@redhat.com>
event_filter_read/write() are racy, ftrace_event_call can be already
freed by trace_remove_event_call() callers.
1. Shift mutex_lock(event_mutex) from print/apply_event_filter to
the callers.
2. Change the callers, event_filter_read() and event_filter_write()
to read i_private under this mutex and abort if it is NULL.
This fixes nothing, but now we can change debugfs_remove("filter")
callers to nullify ->i_private and fix the the problem.
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
kernel/trace/trace_events.c | 28 +++++++++++++++++++---------
kernel/trace/trace_events_filter.c | 17 ++++++-----------
2 files changed, 25 insertions(+), 20 deletions(-)
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 39cb049..b5144c4 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -978,24 +978,30 @@ static ssize_t
event_filter_read(struct file *filp, char __user *ubuf, size_t cnt,
loff_t *ppos)
{
- struct ftrace_event_call *call = filp->private_data;
+ struct ftrace_event_call *call;
struct trace_seq *s;
- int r;
+ int r = -ENODEV;
if (*ppos)
return 0;
s = kmalloc(sizeof(*s), GFP_KERNEL);
+
if (!s)
return -ENOMEM;
trace_seq_init(s);
- print_event_filter(call, s);
- r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len);
+ mutex_lock(&event_mutex);
+ call = event_file_data(filp);
+ if (call)
+ print_event_filter(call, s);
+ mutex_unlock(&event_mutex);
- kfree(s);
+ if (call)
+ r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len);
+ kfree(s);
return r;
}
@@ -1003,9 +1009,9 @@ static ssize_t
event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt,
loff_t *ppos)
{
- struct ftrace_event_call *call = filp->private_data;
+ struct ftrace_event_call *call;
char *buf;
- int err;
+ int err = -ENODEV;
if (cnt >= PAGE_SIZE)
return -EINVAL;
@@ -1020,13 +1026,17 @@ event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt,
}
buf[cnt] = '\0';
- err = apply_event_filter(call, buf);
+ mutex_lock(&event_mutex);
+ call = event_file_data(filp);
+ if (call)
+ err = apply_event_filter(call, buf);
+ mutex_unlock(&event_mutex);
+
free_page((unsigned long) buf);
if (err < 0)
return err;
*ppos += cnt;
-
return cnt;
}
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index 0c7b75a..97daa8c 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -637,17 +637,15 @@ static void append_filter_err(struct filter_parse_state *ps,
free_page((unsigned long) buf);
}
+/* caller must hold event_mutex */
void print_event_filter(struct ftrace_event_call *call, struct trace_seq *s)
{
- struct event_filter *filter;
+ struct event_filter *filter = call->filter;
- mutex_lock(&event_mutex);
- filter = call->filter;
if (filter && filter->filter_string)
trace_seq_printf(s, "%s\n", filter->filter_string);
else
trace_seq_puts(s, "none\n");
- mutex_unlock(&event_mutex);
}
void print_subsystem_event_filter(struct event_subsystem *system,
@@ -1841,23 +1839,22 @@ static int create_system_filter(struct event_subsystem *system,
return err;
}
+/* caller must hold event_mutex */
int apply_event_filter(struct ftrace_event_call *call, char *filter_string)
{
struct event_filter *filter;
- int err = 0;
-
- mutex_lock(&event_mutex);
+ int err;
if (!strcmp(strstrip(filter_string), "0")) {
filter_disable(call);
filter = call->filter;
if (!filter)
- goto out_unlock;
+ return 0;
RCU_INIT_POINTER(call->filter, NULL);
/* Make sure the filter is not being used */
synchronize_sched();
__free_filter(filter);
- goto out_unlock;
+ return 0;
}
err = create_filter(call, filter_string, true, &filter);
@@ -1884,8 +1881,6 @@ int apply_event_filter(struct ftrace_event_call *call, char *filter_string)
__free_filter(tmp);
}
}
-out_unlock:
- mutex_unlock(&event_mutex);
return err;
}
--
1.5.5.1
next prev parent reply other threads:[~2013-07-26 17:31 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-07-26 17:25 [PATCH v2 0/6] tracing: open/delete fixes Oleg Nesterov
2013-07-26 17:25 ` [PATCH v2 1/6] tracing: Turn event/id->i_private into call->event.type Oleg Nesterov
2013-07-30 1:29 ` Masami Hiramatsu
2013-07-26 17:25 ` [PATCH v2 2/6] tracing: Change event_enable/disable_read() to verify i_private != NULL Oleg Nesterov
2013-07-30 1:31 ` Masami Hiramatsu
2013-07-30 1:42 ` Steven Rostedt
2013-07-26 17:25 ` Oleg Nesterov [this message]
2013-07-30 1:34 ` [PATCH v2 3/6] tracing: Change event_filter_read/write " Masami Hiramatsu
2013-07-26 17:25 ` [PATCH v2 4/6] tracing: Change f_start() to take event_mutex and " Oleg Nesterov
2013-07-30 1:33 ` Masami Hiramatsu
2013-07-26 17:25 ` [PATCH v2 5/6] tracing: Introduce remove_event_file_dir() Oleg Nesterov
2013-07-30 1:33 ` Masami Hiramatsu
2013-07-26 17:25 ` [PATCH v2 6/6] tracing: Change remove_event_file_dir() to clear "d_subdirs"->i_private Oleg Nesterov
2013-07-28 18:35 ` [PATCH v3 " Oleg Nesterov
2013-07-30 1:36 ` Masami Hiramatsu
2013-07-30 2:01 ` Steven Rostedt
2013-07-29 9:43 ` [PATCH v2 " Masami Hiramatsu
2013-07-29 14:21 ` Oleg Nesterov
2013-07-30 1:28 ` Masami Hiramatsu
2013-07-30 1:59 ` Steven Rostedt
2013-07-28 18:34 ` [PATCH v2 0/6] tracing: open/delete fixes Oleg Nesterov
2013-07-29 11:36 ` Masami Hiramatsu
2013-07-29 14:43 ` Oleg Nesterov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130726172540.GA3619@redhat.com \
--to=oleg@redhat.com \
--cc=a.p.zijlstra@chello.nl \
--cc=acme@ghostprotocols.net \
--cc=azl@google.com \
--cc=dhsharp@google.com \
--cc=fweisbec@gmail.com \
--cc=gregkh@linuxfoundation.org \
--cc=jovi.zhangwei@huawei.com \
--cc=linux-kernel@vger.kernel.org \
--cc=masami.hiramatsu.pt@hitachi.com \
--cc=mingo@redhat.com \
--cc=rostedt@goodmis.org \
--cc=srikar@linux.vnet.ibm.com \
--cc=vnagarnaik@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox