aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2013-07-26 13:25:36 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-08-29 12:47:33 -0400
commitdf89bf77ca930f69ba07fd459f735ec3cac69f8f (patch)
tree1558c0cf64c880d8555bc07154b5cdd755fc40a0 /kernel/trace
parentfdb65fe265a389144db73cca023266dd6d5ff8d9 (diff)
tracing: Change event_enable/disable_read() to verify i_private != NULL
commit bc6f6b08dee5645770efb4b76186ded313f23752 upstream. tracing_open_generic_file() is racy, ftrace_event_file can be already freed by rmdir or trace_remove_event_call(). Change event_enable_read() and event_disable_read() to read and verify "file = i_private" under event_mutex. This fixes nothing, but now we can change debugfs_remove("enable") callers to nullify ->i_private and fix the the problem. Link: http://lkml.kernel.org/r/20130726172536.GA3612@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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'kernel/trace')
-rw-r--r--kernel/trace/trace_events.c28
1 files changed, 19 insertions, 9 deletions
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index fd16a254173c..e8c445d1f190 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -682,13 +682,23 @@ static ssize_t
682event_enable_read(struct file *filp, char __user *ubuf, size_t cnt, 682event_enable_read(struct file *filp, char __user *ubuf, size_t cnt,
683 loff_t *ppos) 683 loff_t *ppos)
684{ 684{
685 struct ftrace_event_file *file = filp->private_data; 685 struct ftrace_event_file *file;
686 unsigned long flags;
686 char *buf; 687 char *buf;
687 688
688 if (file->flags & FTRACE_EVENT_FL_ENABLED) { 689 mutex_lock(&event_mutex);
689 if (file->flags & FTRACE_EVENT_FL_SOFT_DISABLED) 690 file = event_file_data(filp);
691 if (likely(file))
692 flags = file->flags;
693 mutex_unlock(&event_mutex);
694
695 if (!file)
696 return -ENODEV;
697
698 if (flags & FTRACE_EVENT_FL_ENABLED) {
699 if (flags & FTRACE_EVENT_FL_SOFT_DISABLED)
690 buf = "0*\n"; 700 buf = "0*\n";
691 else if (file->flags & FTRACE_EVENT_FL_SOFT_MODE) 701 else if (flags & FTRACE_EVENT_FL_SOFT_MODE)
692 buf = "1*\n"; 702 buf = "1*\n";
693 else 703 else
694 buf = "1\n"; 704 buf = "1\n";
@@ -702,13 +712,10 @@ static ssize_t
702event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt, 712event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
703 loff_t *ppos) 713 loff_t *ppos)
704{ 714{
705 struct ftrace_event_file *file = filp->private_data; 715 struct ftrace_event_file *file;
706 unsigned long val; 716 unsigned long val;
707 int ret; 717 int ret;
708 718
709 if (!file)
710 return -EINVAL;
711
712 ret = kstrtoul_from_user(ubuf, cnt, 10, &val); 719 ret = kstrtoul_from_user(ubuf, cnt, 10, &val);
713 if (ret) 720 if (ret)
714 return ret; 721 return ret;
@@ -720,8 +727,11 @@ event_enable_write(struct file *filp, const char __user *ubuf, size_t cnt,
720 switch (val) { 727 switch (val) {
721 case 0: 728 case 0:
722 case 1: 729 case 1:
730 ret = -ENODEV;
723 mutex_lock(&event_mutex); 731 mutex_lock(&event_mutex);
724 ret = ftrace_event_enable_disable(file, val); 732 file = event_file_data(filp);
733 if (likely(file))
734 ret = ftrace_event_enable_disable(file, val);
725 mutex_unlock(&event_mutex); 735 mutex_unlock(&event_mutex);
726 break; 736 break;
727 737