Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0
2 : /*
3 : * trace binary printk
4 : *
5 : * Copyright (C) 2008 Lai Jiangshan <laijs@cn.fujitsu.com>
6 : *
7 : */
8 : #include <linux/seq_file.h>
9 : #include <linux/security.h>
10 : #include <linux/uaccess.h>
11 : #include <linux/kernel.h>
12 : #include <linux/ftrace.h>
13 : #include <linux/string.h>
14 : #include <linux/module.h>
15 : #include <linux/mutex.h>
16 : #include <linux/ctype.h>
17 : #include <linux/list.h>
18 : #include <linux/slab.h>
19 :
20 : #include "trace.h"
21 :
22 : #ifdef CONFIG_MODULES
23 :
24 : /*
25 : * modules trace_printk()'s formats are autosaved in struct trace_bprintk_fmt
26 : * which are queued on trace_bprintk_fmt_list.
27 : */
28 : static LIST_HEAD(trace_bprintk_fmt_list);
29 :
30 : /* serialize accesses to trace_bprintk_fmt_list */
31 : static DEFINE_MUTEX(btrace_mutex);
32 :
33 : struct trace_bprintk_fmt {
34 : struct list_head list;
35 : const char *fmt;
36 : };
37 :
38 : static inline struct trace_bprintk_fmt *lookup_format(const char *fmt)
39 : {
40 : struct trace_bprintk_fmt *pos;
41 :
42 : if (!fmt)
43 : return ERR_PTR(-EINVAL);
44 :
45 : list_for_each_entry(pos, &trace_bprintk_fmt_list, list) {
46 : if (!strcmp(pos->fmt, fmt))
47 : return pos;
48 : }
49 : return NULL;
50 : }
51 :
52 : static
53 : void hold_module_trace_bprintk_format(const char **start, const char **end)
54 : {
55 : const char **iter;
56 : char *fmt;
57 :
58 : /* allocate the trace_printk per cpu buffers */
59 : if (start != end)
60 : trace_printk_init_buffers();
61 :
62 : mutex_lock(&btrace_mutex);
63 : for (iter = start; iter < end; iter++) {
64 : struct trace_bprintk_fmt *tb_fmt = lookup_format(*iter);
65 : if (tb_fmt) {
66 : if (!IS_ERR(tb_fmt))
67 : *iter = tb_fmt->fmt;
68 : continue;
69 : }
70 :
71 : fmt = NULL;
72 : tb_fmt = kmalloc(sizeof(*tb_fmt), GFP_KERNEL);
73 : if (tb_fmt) {
74 : fmt = kmalloc(strlen(*iter) + 1, GFP_KERNEL);
75 : if (fmt) {
76 : list_add_tail(&tb_fmt->list, &trace_bprintk_fmt_list);
77 : strcpy(fmt, *iter);
78 : tb_fmt->fmt = fmt;
79 : } else
80 : kfree(tb_fmt);
81 : }
82 : *iter = fmt;
83 :
84 : }
85 : mutex_unlock(&btrace_mutex);
86 : }
87 :
88 : static int module_trace_bprintk_format_notify(struct notifier_block *self,
89 : unsigned long val, void *data)
90 : {
91 : struct module *mod = data;
92 : if (mod->num_trace_bprintk_fmt) {
93 : const char **start = mod->trace_bprintk_fmt_start;
94 : const char **end = start + mod->num_trace_bprintk_fmt;
95 :
96 : if (val == MODULE_STATE_COMING)
97 : hold_module_trace_bprintk_format(start, end);
98 : }
99 : return NOTIFY_OK;
100 : }
101 :
102 : /*
103 : * The debugfs/tracing/printk_formats file maps the addresses with
104 : * the ASCII formats that are used in the bprintk events in the
105 : * buffer. For userspace tools to be able to decode the events from
106 : * the buffer, they need to be able to map the address with the format.
107 : *
108 : * The addresses of the bprintk formats are in their own section
109 : * __trace_printk_fmt. But for modules we copy them into a link list.
110 : * The code to print the formats and their addresses passes around the
111 : * address of the fmt string. If the fmt address passed into the seq
112 : * functions is within the kernel core __trace_printk_fmt section, then
113 : * it simply uses the next pointer in the list.
114 : *
115 : * When the fmt pointer is outside the kernel core __trace_printk_fmt
116 : * section, then we need to read the link list pointers. The trick is
117 : * we pass the address of the string to the seq function just like
118 : * we do for the kernel core formats. To get back the structure that
119 : * holds the format, we simply use container_of() and then go to the
120 : * next format in the list.
121 : */
122 : static const char **
123 : find_next_mod_format(int start_index, void *v, const char **fmt, loff_t *pos)
124 : {
125 : struct trace_bprintk_fmt *mod_fmt;
126 :
127 : if (list_empty(&trace_bprintk_fmt_list))
128 : return NULL;
129 :
130 : /*
131 : * v will point to the address of the fmt record from t_next
132 : * v will be NULL from t_start.
133 : * If this is the first pointer or called from start
134 : * then we need to walk the list.
135 : */
136 : if (!v || start_index == *pos) {
137 : struct trace_bprintk_fmt *p;
138 :
139 : /* search the module list */
140 : list_for_each_entry(p, &trace_bprintk_fmt_list, list) {
141 : if (start_index == *pos)
142 : return &p->fmt;
143 : start_index++;
144 : }
145 : /* pos > index */
146 : return NULL;
147 : }
148 :
149 : /*
150 : * v points to the address of the fmt field in the mod list
151 : * structure that holds the module print format.
152 : */
153 : mod_fmt = container_of(v, typeof(*mod_fmt), fmt);
154 : if (mod_fmt->list.next == &trace_bprintk_fmt_list)
155 : return NULL;
156 :
157 : mod_fmt = container_of(mod_fmt->list.next, typeof(*mod_fmt), list);
158 :
159 : return &mod_fmt->fmt;
160 : }
161 :
162 : static void format_mod_start(void)
163 : {
164 : mutex_lock(&btrace_mutex);
165 : }
166 :
167 : static void format_mod_stop(void)
168 : {
169 : mutex_unlock(&btrace_mutex);
170 : }
171 :
172 : #else /* !CONFIG_MODULES */
173 : __init static int
174 : module_trace_bprintk_format_notify(struct notifier_block *self,
175 : unsigned long val, void *data)
176 : {
177 : return NOTIFY_OK;
178 : }
179 : static inline const char **
180 : find_next_mod_format(int start_index, void *v, const char **fmt, loff_t *pos)
181 : {
182 : return NULL;
183 : }
184 0 : static inline void format_mod_start(void) { }
185 0 : static inline void format_mod_stop(void) { }
186 : #endif /* CONFIG_MODULES */
187 :
188 : static bool __read_mostly trace_printk_enabled = true;
189 :
190 0 : void trace_printk_control(bool enabled)
191 : {
192 0 : trace_printk_enabled = enabled;
193 0 : }
194 :
195 : __initdata_or_module static
196 : struct notifier_block module_trace_bprintk_format_nb = {
197 : .notifier_call = module_trace_bprintk_format_notify,
198 : };
199 :
200 0 : int __trace_bprintk(unsigned long ip, const char *fmt, ...)
201 : {
202 0 : int ret;
203 0 : va_list ap;
204 :
205 0 : if (unlikely(!fmt))
206 : return 0;
207 :
208 0 : if (!trace_printk_enabled)
209 : return 0;
210 :
211 0 : va_start(ap, fmt);
212 0 : ret = trace_vbprintk(ip, fmt, ap);
213 0 : va_end(ap);
214 0 : return ret;
215 : }
216 : EXPORT_SYMBOL_GPL(__trace_bprintk);
217 :
218 0 : int __ftrace_vbprintk(unsigned long ip, const char *fmt, va_list ap)
219 : {
220 0 : if (unlikely(!fmt))
221 : return 0;
222 :
223 0 : if (!trace_printk_enabled)
224 : return 0;
225 :
226 0 : return trace_vbprintk(ip, fmt, ap);
227 : }
228 : EXPORT_SYMBOL_GPL(__ftrace_vbprintk);
229 :
230 0 : int __trace_printk(unsigned long ip, const char *fmt, ...)
231 : {
232 0 : int ret;
233 0 : va_list ap;
234 :
235 0 : if (!trace_printk_enabled)
236 : return 0;
237 :
238 0 : va_start(ap, fmt);
239 0 : ret = trace_vprintk(ip, fmt, ap);
240 0 : va_end(ap);
241 0 : return ret;
242 : }
243 : EXPORT_SYMBOL_GPL(__trace_printk);
244 :
245 0 : int __ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap)
246 : {
247 0 : if (!trace_printk_enabled)
248 : return 0;
249 :
250 0 : return trace_vprintk(ip, fmt, ap);
251 : }
252 : EXPORT_SYMBOL_GPL(__ftrace_vprintk);
253 :
254 0 : static const char **find_next(void *v, loff_t *pos)
255 : {
256 0 : const char **fmt = v;
257 0 : int start_index;
258 0 : int last_index;
259 :
260 0 : start_index = __stop___trace_bprintk_fmt - __start___trace_bprintk_fmt;
261 :
262 0 : if (*pos < start_index)
263 0 : return __start___trace_bprintk_fmt + *pos;
264 :
265 : /*
266 : * The __tracepoint_str section is treated the same as the
267 : * __trace_printk_fmt section. The difference is that the
268 : * __trace_printk_fmt section should only be used by trace_printk()
269 : * in a debugging environment, as if anything exists in that section
270 : * the trace_prink() helper buffers are allocated, which would just
271 : * waste space in a production environment.
272 : *
273 : * The __tracepoint_str sections on the other hand are used by
274 : * tracepoints which need to map pointers to their strings to
275 : * the ASCII text for userspace.
276 : */
277 0 : last_index = start_index;
278 0 : start_index = __stop___tracepoint_str - __start___tracepoint_str;
279 :
280 0 : if (*pos < last_index + start_index)
281 0 : return __start___tracepoint_str + (*pos - last_index);
282 :
283 : start_index += last_index;
284 0 : return find_next_mod_format(start_index, v, fmt, pos);
285 : }
286 :
287 : static void *
288 0 : t_start(struct seq_file *m, loff_t *pos)
289 : {
290 0 : format_mod_start();
291 0 : return find_next(NULL, pos);
292 : }
293 :
294 0 : static void *t_next(struct seq_file *m, void * v, loff_t *pos)
295 : {
296 0 : (*pos)++;
297 0 : return find_next(v, pos);
298 : }
299 :
300 0 : static int t_show(struct seq_file *m, void *v)
301 : {
302 0 : const char **fmt = v;
303 0 : const char *str = *fmt;
304 0 : int i;
305 :
306 0 : if (!*fmt)
307 : return 0;
308 :
309 0 : seq_printf(m, "0x%lx : \"", *(unsigned long *)fmt);
310 :
311 : /*
312 : * Tabs and new lines need to be converted.
313 : */
314 0 : for (i = 0; str[i]; i++) {
315 0 : switch (str[i]) {
316 0 : case '\n':
317 0 : seq_puts(m, "\\n");
318 0 : break;
319 0 : case '\t':
320 0 : seq_puts(m, "\\t");
321 0 : break;
322 0 : case '\\':
323 0 : seq_putc(m, '\\');
324 0 : break;
325 0 : case '"':
326 0 : seq_puts(m, "\\\"");
327 0 : break;
328 0 : default:
329 0 : seq_putc(m, str[i]);
330 : }
331 : }
332 0 : seq_puts(m, "\"\n");
333 :
334 0 : return 0;
335 : }
336 :
337 0 : static void t_stop(struct seq_file *m, void *p)
338 : {
339 0 : format_mod_stop();
340 0 : }
341 :
342 : static const struct seq_operations show_format_seq_ops = {
343 : .start = t_start,
344 : .next = t_next,
345 : .show = t_show,
346 : .stop = t_stop,
347 : };
348 :
349 : static int
350 0 : ftrace_formats_open(struct inode *inode, struct file *file)
351 : {
352 0 : int ret;
353 :
354 0 : ret = security_locked_down(LOCKDOWN_TRACEFS);
355 0 : if (ret)
356 : return ret;
357 :
358 0 : return seq_open(file, &show_format_seq_ops);
359 : }
360 :
361 : static const struct file_operations ftrace_formats_fops = {
362 : .open = ftrace_formats_open,
363 : .read = seq_read,
364 : .llseek = seq_lseek,
365 : .release = seq_release,
366 : };
367 :
368 1 : static __init int init_trace_printk_function_export(void)
369 : {
370 1 : int ret;
371 :
372 1 : ret = tracing_init_dentry();
373 1 : if (ret)
374 : return 0;
375 :
376 1 : trace_create_file("printk_formats", 0444, NULL,
377 : NULL, &ftrace_formats_fops);
378 :
379 1 : return 0;
380 : }
381 :
382 : fs_initcall(init_trace_printk_function_export);
383 :
384 1 : static __init int init_trace_printk(void)
385 : {
386 1 : return register_module_notifier(&module_trace_bprintk_format_nb);
387 : }
388 :
389 : early_initcall(init_trace_printk);
|