diff options
author | Oleg Nesterov <oleg@redhat.com> | 2014-06-27 13:01:46 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2014-06-30 13:22:33 -0400 |
commit | fb6bab6a5ad46d00b5ffa22268f21df1cd7c59df (patch) | |
tree | cf20fd01e563ee6a4b659d30ab48de0fb015f584 /kernel/trace/trace_uprobe.c | |
parent | f786106e8081bbec57053fec7fcf25dc25d02144 (diff) |
tracing/uprobes: Fix the usage of uprobe_buffer_enable() in probe_event_enable()
The usage of uprobe_buffer_enable() added by dcad1a20 is very wrong,
1. uprobe_buffer_enable() and uprobe_buffer_disable() are not balanced,
_enable() should be called only if !enabled.
2. If uprobe_buffer_enable() fails probe_event_enable() should clear
tp.flags and free event_file_link.
3. If uprobe_register() fails it should do uprobe_buffer_disable().
Link: http://lkml.kernel.org/p/20140627170146.GA18332@redhat.com
Acked-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Reviewed-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Fixes: dcad1a204f72 "tracing/uprobes: Fetch args before reserving a ring buffer"
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace/trace_uprobe.c')
-rw-r--r-- | kernel/trace/trace_uprobe.c | 31 |
1 files changed, 19 insertions, 12 deletions
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c index c4cf0abd60ba..3c9b97e6b1f4 100644 --- a/kernel/trace/trace_uprobe.c +++ b/kernel/trace/trace_uprobe.c | |||
@@ -911,26 +911,33 @@ probe_event_enable(struct trace_uprobe *tu, struct ftrace_event_file *file, | |||
911 | tu->tp.flags |= TP_FLAG_PROFILE; | 911 | tu->tp.flags |= TP_FLAG_PROFILE; |
912 | } | 912 | } |
913 | 913 | ||
914 | ret = uprobe_buffer_enable(); | ||
915 | if (ret < 0) | ||
916 | return ret; | ||
917 | |||
918 | WARN_ON(!uprobe_filter_is_empty(&tu->filter)); | 914 | WARN_ON(!uprobe_filter_is_empty(&tu->filter)); |
919 | 915 | ||
920 | if (enabled) | 916 | if (enabled) |
921 | return 0; | 917 | return 0; |
922 | 918 | ||
919 | ret = uprobe_buffer_enable(); | ||
920 | if (ret) | ||
921 | goto err_flags; | ||
922 | |||
923 | tu->consumer.filter = filter; | 923 | tu->consumer.filter = filter; |
924 | ret = uprobe_register(tu->inode, tu->offset, &tu->consumer); | 924 | ret = uprobe_register(tu->inode, tu->offset, &tu->consumer); |
925 | if (ret) { | 925 | if (ret) |
926 | if (file) { | 926 | goto err_buffer; |
927 | list_del(&link->list); | ||
928 | kfree(link); | ||
929 | tu->tp.flags &= ~TP_FLAG_TRACE; | ||
930 | } else | ||
931 | tu->tp.flags &= ~TP_FLAG_PROFILE; | ||
932 | } | ||
933 | 927 | ||
928 | return 0; | ||
929 | |||
930 | err_buffer: | ||
931 | uprobe_buffer_disable(); | ||
932 | |||
933 | err_flags: | ||
934 | if (file) { | ||
935 | list_del(&link->list); | ||
936 | kfree(link); | ||
937 | tu->tp.flags &= ~TP_FLAG_TRACE; | ||
938 | } else { | ||
939 | tu->tp.flags &= ~TP_FLAG_PROFILE; | ||
940 | } | ||
934 | return ret; | 941 | return ret; |
935 | } | 942 | } |
936 | 943 | ||