Branch data 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 : 0 : static inline struct trace_bprintk_fmt *lookup_format(const char *fmt) 39 : : { 40 : : struct trace_bprintk_fmt *pos; 41 : : 42 : 0 : if (!fmt) 43 : : return ERR_PTR(-EINVAL); 44 : : 45 : 0 : list_for_each_entry(pos, &trace_bprintk_fmt_list, list) { 46 : 0 : if (!strcmp(pos->fmt, fmt)) 47 : 0 : return pos; 48 : : } 49 : : return NULL; 50 : : } 51 : : 52 : : static 53 : 0 : 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 : 0 : if (start != end) 60 : 0 : trace_printk_init_buffers(); 61 : : 62 : 0 : mutex_lock(&btrace_mutex); 63 : 0 : for (iter = start; iter < end; iter++) { 64 : 0 : struct trace_bprintk_fmt *tb_fmt = lookup_format(*iter); 65 : 0 : if (tb_fmt) { 66 : 0 : if (!IS_ERR(tb_fmt)) 67 : 0 : *iter = tb_fmt->fmt; 68 : 0 : continue; 69 : : } 70 : : 71 : : fmt = NULL; 72 : : tb_fmt = kmalloc(sizeof(*tb_fmt), GFP_KERNEL); 73 : 0 : if (tb_fmt) { 74 : 0 : fmt = kmalloc(strlen(*iter) + 1, GFP_KERNEL); 75 : 0 : if (fmt) { 76 : 0 : list_add_tail(&tb_fmt->list, &trace_bprintk_fmt_list); 77 : 0 : strcpy(fmt, *iter); 78 : 0 : tb_fmt->fmt = fmt; 79 : : } else 80 : 0 : kfree(tb_fmt); 81 : : } 82 : 0 : *iter = fmt; 83 : : 84 : : } 85 : 0 : mutex_unlock(&btrace_mutex); 86 : 0 : } 87 : : 88 : 3 : static int module_trace_bprintk_format_notify(struct notifier_block *self, 89 : : unsigned long val, void *data) 90 : : { 91 : : struct module *mod = data; 92 : 3 : if (mod->num_trace_bprintk_fmt) { 93 : 0 : const char **start = mod->trace_bprintk_fmt_start; 94 : 0 : const char **end = start + mod->num_trace_bprintk_fmt; 95 : : 96 : 0 : if (val == MODULE_STATE_COMING) 97 : 0 : hold_module_trace_bprintk_format(start, end); 98 : : } 99 : 3 : return 0; 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 : 0 : 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 : 0 : 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 : 0 : if (!v || start_index == *pos) { 137 : : struct trace_bprintk_fmt *p; 138 : : 139 : : /* search the module list */ 140 : 0 : list_for_each_entry(p, &trace_bprintk_fmt_list, list) { 141 : 0 : if (start_index == *pos) 142 : 0 : return &p->fmt; 143 : 0 : 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 : 0 : 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 : 0 : return &mod_fmt->fmt; 160 : : } 161 : : 162 : : static void format_mod_start(void) 163 : : { 164 : 0 : mutex_lock(&btrace_mutex); 165 : : } 166 : : 167 : : static void format_mod_stop(void) 168 : : { 169 : 0 : 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 0; 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 : : static inline void format_mod_start(void) { } 185 : : 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 : : int ret; 203 : : 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 : : int ret; 233 : : 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 : : const char **fmt = v; 257 : : int start_index; 258 : : 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 : : 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 : : 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 : : const char **fmt = v; 303 : 0 : const char *str = *fmt; 304 : : 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 : : case '\n': 317 : 0 : seq_puts(m, "\\n"); 318 : 0 : break; 319 : : case '\t': 320 : 0 : seq_puts(m, "\\t"); 321 : 0 : break; 322 : : case '\\': 323 : 0 : seq_putc(m, '\\'); 324 : 0 : break; 325 : : case '"': 326 : 0 : seq_puts(m, "\\\""); 327 : 0 : break; 328 : : 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 : : 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 : : 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 : 3 : static __init int init_trace_printk_function_export(void) 369 : : { 370 : : struct dentry *d_tracer; 371 : : 372 : 3 : d_tracer = tracing_init_dentry(); 373 : 3 : if (IS_ERR(d_tracer)) 374 : : return 0; 375 : : 376 : 3 : trace_create_file("printk_formats", 0444, d_tracer, 377 : : NULL, &ftrace_formats_fops); 378 : : 379 : 3 : return 0; 380 : : } 381 : : 382 : : fs_initcall(init_trace_printk_function_export); 383 : : 384 : 3 : static __init int init_trace_printk(void) 385 : : { 386 : 3 : return register_module_notifier(&module_trace_bprintk_format_nb); 387 : : } 388 : : 389 : : early_initcall(init_trace_printk);