]>
Commit | Line | Data |
---|---|---|
1 | From 70c8217acd4383e069fe1898bbad36ea4fcdbdcc Mon Sep 17 00:00:00 2001 | |
2 | From: "Steven Rostedt (Red Hat)" <rostedt@goodmis.org> | |
3 | Date: Fri, 17 Jun 2016 16:10:42 -0400 | |
4 | Subject: tracing: Handle NULL formats in hold_module_trace_bprintk_format() | |
5 | ||
6 | From: Steven Rostedt (Red Hat) <rostedt@goodmis.org> | |
7 | ||
8 | commit 70c8217acd4383e069fe1898bbad36ea4fcdbdcc upstream. | |
9 | ||
10 | If a task uses a non constant string for the format parameter in | |
11 | trace_printk(), then the trace_printk_fmt variable is set to NULL. This | |
12 | variable is then saved in the __trace_printk_fmt section. | |
13 | ||
14 | The function hold_module_trace_bprintk_format() checks to see if duplicate | |
15 | formats are used by modules, and reuses them if so (saves them to the list | |
16 | if it is new). But this function calls lookup_format() that does a strcmp() | |
17 | to the value (which is now NULL) and can cause a kernel oops. | |
18 | ||
19 | This wasn't an issue till 3debb0a9ddb ("tracing: Fix trace_printk() to print | |
20 | when not using bprintk()") which added "__used" to the trace_printk_fmt | |
21 | variable, and before that, the kernel simply optimized it out (no NULL value | |
22 | was saved). | |
23 | ||
24 | The fix is simply to handle the NULL pointer in lookup_format() and have the | |
25 | caller ignore the value if it was NULL. | |
26 | ||
27 | Link: http://lkml.kernel.org/r/1464769870-18344-1-git-send-email-zhengjun.xing@intel.com | |
28 | ||
29 | Reported-by: xingzhen <zhengjun.xing@intel.com> | |
30 | Acked-by: Namhyung Kim <namhyung@kernel.org> | |
31 | Fixes: 3debb0a9ddb ("tracing: Fix trace_printk() to print when not using bprintk()") | |
32 | Signed-off-by: Steven Rostedt <rostedt@goodmis.org> | |
33 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
34 | ||
35 | --- | |
36 | kernel/trace/trace_printk.c | 7 ++++++- | |
37 | 1 file changed, 6 insertions(+), 1 deletion(-) | |
38 | ||
39 | --- a/kernel/trace/trace_printk.c | |
40 | +++ b/kernel/trace/trace_printk.c | |
41 | @@ -36,6 +36,10 @@ struct trace_bprintk_fmt { | |
42 | static inline struct trace_bprintk_fmt *lookup_format(const char *fmt) | |
43 | { | |
44 | struct trace_bprintk_fmt *pos; | |
45 | + | |
46 | + if (!fmt) | |
47 | + return ERR_PTR(-EINVAL); | |
48 | + | |
49 | list_for_each_entry(pos, &trace_bprintk_fmt_list, list) { | |
50 | if (!strcmp(pos->fmt, fmt)) | |
51 | return pos; | |
52 | @@ -57,7 +61,8 @@ void hold_module_trace_bprintk_format(co | |
53 | for (iter = start; iter < end; iter++) { | |
54 | struct trace_bprintk_fmt *tb_fmt = lookup_format(*iter); | |
55 | if (tb_fmt) { | |
56 | - *iter = tb_fmt->fmt; | |
57 | + if (!IS_ERR(tb_fmt)) | |
58 | + *iter = tb_fmt->fmt; | |
59 | continue; | |
60 | } | |
61 |