0001
0002
0003
0004
0005
0006 #include <linux/sched/task_stack.h>
0007 #include <linux/stacktrace.h>
0008 #include <linux/security.h>
0009 #include <linux/kallsyms.h>
0010 #include <linux/seq_file.h>
0011 #include <linux/spinlock.h>
0012 #include <linux/uaccess.h>
0013 #include <linux/ftrace.h>
0014 #include <linux/module.h>
0015 #include <linux/sysctl.h>
0016 #include <linux/init.h>
0017
0018 #include <asm/setup.h>
0019
0020 #include "trace.h"
0021
0022 #define STACK_TRACE_ENTRIES 500
0023
0024 static unsigned long stack_dump_trace[STACK_TRACE_ENTRIES];
0025 static unsigned stack_trace_index[STACK_TRACE_ENTRIES];
0026
0027 static unsigned int stack_trace_nr_entries;
0028 static unsigned long stack_trace_max_size;
0029 static arch_spinlock_t stack_trace_max_lock =
0030 (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED;
0031
0032 DEFINE_PER_CPU(int, disable_stack_tracer);
0033 static DEFINE_MUTEX(stack_sysctl_mutex);
0034
0035 int stack_tracer_enabled;
0036
0037 static void print_max_stack(void)
0038 {
0039 long i;
0040 int size;
0041
0042 pr_emerg(" Depth Size Location (%d entries)\n"
0043 " ----- ---- --------\n",
0044 stack_trace_nr_entries);
0045
0046 for (i = 0; i < stack_trace_nr_entries; i++) {
0047 if (i + 1 == stack_trace_nr_entries)
0048 size = stack_trace_index[i];
0049 else
0050 size = stack_trace_index[i] - stack_trace_index[i+1];
0051
0052 pr_emerg("%3ld) %8d %5d %pS\n", i, stack_trace_index[i],
0053 size, (void *)stack_dump_trace[i]);
0054 }
0055 }
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155 static void check_stack(unsigned long ip, unsigned long *stack)
0156 {
0157 unsigned long this_size, flags; unsigned long *p, *top, *start;
0158 static int tracer_frame;
0159 int frame_size = READ_ONCE(tracer_frame);
0160 int i, x;
0161
0162 this_size = ((unsigned long)stack) & (THREAD_SIZE-1);
0163 this_size = THREAD_SIZE - this_size;
0164
0165 this_size -= frame_size;
0166
0167 if (this_size <= stack_trace_max_size)
0168 return;
0169
0170
0171 if (!object_is_on_stack(stack))
0172 return;
0173
0174
0175 if (in_nmi())
0176 return;
0177
0178 local_irq_save(flags);
0179 arch_spin_lock(&stack_trace_max_lock);
0180
0181
0182 if (unlikely(!frame_size))
0183 this_size -= tracer_frame;
0184
0185
0186 if (this_size <= stack_trace_max_size)
0187 goto out;
0188
0189 stack_trace_max_size = this_size;
0190
0191 stack_trace_nr_entries = stack_trace_save(stack_dump_trace,
0192 ARRAY_SIZE(stack_dump_trace) - 1,
0193 0);
0194
0195
0196 for (i = 0; i < stack_trace_nr_entries; i++) {
0197 if (stack_dump_trace[i] == ip)
0198 break;
0199 }
0200
0201
0202
0203
0204
0205 if (i == stack_trace_nr_entries)
0206 i = 0;
0207
0208
0209
0210
0211 x = 0;
0212 start = stack;
0213 top = (unsigned long *)
0214 (((unsigned long)start & ~(THREAD_SIZE-1)) + THREAD_SIZE);
0215
0216
0217
0218
0219
0220
0221
0222
0223 while (i < stack_trace_nr_entries) {
0224 int found = 0;
0225
0226 stack_trace_index[x] = this_size;
0227 p = start;
0228
0229 for (; p < top && i < stack_trace_nr_entries; p++) {
0230
0231
0232
0233
0234 if ((READ_ONCE_NOCHECK(*p)) == stack_dump_trace[i]) {
0235 stack_dump_trace[x] = stack_dump_trace[i++];
0236 this_size = stack_trace_index[x++] =
0237 (top - p) * sizeof(unsigned long);
0238 found = 1;
0239
0240 start = p + 1;
0241
0242
0243
0244
0245
0246
0247
0248 if (unlikely(!tracer_frame)) {
0249 tracer_frame = (p - stack) *
0250 sizeof(unsigned long);
0251 stack_trace_max_size -= tracer_frame;
0252 }
0253 }
0254 }
0255
0256 if (!found)
0257 i++;
0258 }
0259
0260 #ifdef ARCH_FTRACE_SHIFT_STACK_TRACER
0261
0262
0263
0264
0265
0266
0267 if (x > 1) {
0268 memmove(&stack_trace_index[0], &stack_trace_index[1],
0269 sizeof(stack_trace_index[0]) * (x - 1));
0270 x--;
0271 }
0272 #endif
0273
0274 stack_trace_nr_entries = x;
0275
0276 if (task_stack_end_corrupted(current)) {
0277 print_max_stack();
0278 BUG();
0279 }
0280
0281 out:
0282 arch_spin_unlock(&stack_trace_max_lock);
0283 local_irq_restore(flags);
0284 }
0285
0286
0287 #ifndef MCOUNT_INSN_SIZE
0288 # define MCOUNT_INSN_SIZE 0
0289 #endif
0290
0291 static void
0292 stack_trace_call(unsigned long ip, unsigned long parent_ip,
0293 struct ftrace_ops *op, struct ftrace_regs *fregs)
0294 {
0295 unsigned long stack;
0296
0297 preempt_disable_notrace();
0298
0299
0300 __this_cpu_inc(disable_stack_tracer);
0301 if (__this_cpu_read(disable_stack_tracer) != 1)
0302 goto out;
0303
0304
0305 if (!rcu_is_watching())
0306 goto out;
0307
0308 ip += MCOUNT_INSN_SIZE;
0309
0310 check_stack(ip, &stack);
0311
0312 out:
0313 __this_cpu_dec(disable_stack_tracer);
0314
0315 preempt_enable_notrace();
0316 }
0317
0318 static struct ftrace_ops trace_ops __read_mostly =
0319 {
0320 .func = stack_trace_call,
0321 };
0322
0323 static ssize_t
0324 stack_max_size_read(struct file *filp, char __user *ubuf,
0325 size_t count, loff_t *ppos)
0326 {
0327 unsigned long *ptr = filp->private_data;
0328 char buf[64];
0329 int r;
0330
0331 r = snprintf(buf, sizeof(buf), "%ld\n", *ptr);
0332 if (r > sizeof(buf))
0333 r = sizeof(buf);
0334 return simple_read_from_buffer(ubuf, count, ppos, buf, r);
0335 }
0336
0337 static ssize_t
0338 stack_max_size_write(struct file *filp, const char __user *ubuf,
0339 size_t count, loff_t *ppos)
0340 {
0341 long *ptr = filp->private_data;
0342 unsigned long val, flags;
0343 int ret;
0344
0345 ret = kstrtoul_from_user(ubuf, count, 10, &val);
0346 if (ret)
0347 return ret;
0348
0349 local_irq_save(flags);
0350
0351
0352
0353
0354
0355
0356 __this_cpu_inc(disable_stack_tracer);
0357
0358 arch_spin_lock(&stack_trace_max_lock);
0359 *ptr = val;
0360 arch_spin_unlock(&stack_trace_max_lock);
0361
0362 __this_cpu_dec(disable_stack_tracer);
0363 local_irq_restore(flags);
0364
0365 return count;
0366 }
0367
0368 static const struct file_operations stack_max_size_fops = {
0369 .open = tracing_open_generic,
0370 .read = stack_max_size_read,
0371 .write = stack_max_size_write,
0372 .llseek = default_llseek,
0373 };
0374
0375 static void *
0376 __next(struct seq_file *m, loff_t *pos)
0377 {
0378 long n = *pos - 1;
0379
0380 if (n >= stack_trace_nr_entries)
0381 return NULL;
0382
0383 m->private = (void *)n;
0384 return &m->private;
0385 }
0386
0387 static void *
0388 t_next(struct seq_file *m, void *v, loff_t *pos)
0389 {
0390 (*pos)++;
0391 return __next(m, pos);
0392 }
0393
0394 static void *t_start(struct seq_file *m, loff_t *pos)
0395 {
0396 local_irq_disable();
0397
0398 __this_cpu_inc(disable_stack_tracer);
0399
0400 arch_spin_lock(&stack_trace_max_lock);
0401
0402 if (*pos == 0)
0403 return SEQ_START_TOKEN;
0404
0405 return __next(m, pos);
0406 }
0407
0408 static void t_stop(struct seq_file *m, void *p)
0409 {
0410 arch_spin_unlock(&stack_trace_max_lock);
0411
0412 __this_cpu_dec(disable_stack_tracer);
0413
0414 local_irq_enable();
0415 }
0416
0417 static void trace_lookup_stack(struct seq_file *m, long i)
0418 {
0419 unsigned long addr = stack_dump_trace[i];
0420
0421 seq_printf(m, "%pS\n", (void *)addr);
0422 }
0423
0424 static void print_disabled(struct seq_file *m)
0425 {
0426 seq_puts(m, "#\n"
0427 "# Stack tracer disabled\n"
0428 "#\n"
0429 "# To enable the stack tracer, either add 'stacktrace' to the\n"
0430 "# kernel command line\n"
0431 "# or 'echo 1 > /proc/sys/kernel/stack_tracer_enabled'\n"
0432 "#\n");
0433 }
0434
0435 static int t_show(struct seq_file *m, void *v)
0436 {
0437 long i;
0438 int size;
0439
0440 if (v == SEQ_START_TOKEN) {
0441 seq_printf(m, " Depth Size Location"
0442 " (%d entries)\n"
0443 " ----- ---- --------\n",
0444 stack_trace_nr_entries);
0445
0446 if (!stack_tracer_enabled && !stack_trace_max_size)
0447 print_disabled(m);
0448
0449 return 0;
0450 }
0451
0452 i = *(long *)v;
0453
0454 if (i >= stack_trace_nr_entries)
0455 return 0;
0456
0457 if (i + 1 == stack_trace_nr_entries)
0458 size = stack_trace_index[i];
0459 else
0460 size = stack_trace_index[i] - stack_trace_index[i+1];
0461
0462 seq_printf(m, "%3ld) %8d %5d ", i, stack_trace_index[i], size);
0463
0464 trace_lookup_stack(m, i);
0465
0466 return 0;
0467 }
0468
0469 static const struct seq_operations stack_trace_seq_ops = {
0470 .start = t_start,
0471 .next = t_next,
0472 .stop = t_stop,
0473 .show = t_show,
0474 };
0475
0476 static int stack_trace_open(struct inode *inode, struct file *file)
0477 {
0478 int ret;
0479
0480 ret = security_locked_down(LOCKDOWN_TRACEFS);
0481 if (ret)
0482 return ret;
0483
0484 return seq_open(file, &stack_trace_seq_ops);
0485 }
0486
0487 static const struct file_operations stack_trace_fops = {
0488 .open = stack_trace_open,
0489 .read = seq_read,
0490 .llseek = seq_lseek,
0491 .release = seq_release,
0492 };
0493
0494 #ifdef CONFIG_DYNAMIC_FTRACE
0495
0496 static int
0497 stack_trace_filter_open(struct inode *inode, struct file *file)
0498 {
0499 struct ftrace_ops *ops = inode->i_private;
0500
0501
0502 return ftrace_regex_open(ops, FTRACE_ITER_FILTER,
0503 inode, file);
0504 }
0505
0506 static const struct file_operations stack_trace_filter_fops = {
0507 .open = stack_trace_filter_open,
0508 .read = seq_read,
0509 .write = ftrace_filter_write,
0510 .llseek = tracing_lseek,
0511 .release = ftrace_regex_release,
0512 };
0513
0514 #endif
0515
0516 int
0517 stack_trace_sysctl(struct ctl_table *table, int write, void *buffer,
0518 size_t *lenp, loff_t *ppos)
0519 {
0520 int was_enabled;
0521 int ret;
0522
0523 mutex_lock(&stack_sysctl_mutex);
0524 was_enabled = !!stack_tracer_enabled;
0525
0526 ret = proc_dointvec(table, write, buffer, lenp, ppos);
0527
0528 if (ret || !write || (was_enabled == !!stack_tracer_enabled))
0529 goto out;
0530
0531 if (stack_tracer_enabled)
0532 register_ftrace_function(&trace_ops);
0533 else
0534 unregister_ftrace_function(&trace_ops);
0535 out:
0536 mutex_unlock(&stack_sysctl_mutex);
0537 return ret;
0538 }
0539
0540 static char stack_trace_filter_buf[COMMAND_LINE_SIZE+1] __initdata;
0541
0542 static __init int enable_stacktrace(char *str)
0543 {
0544 int len;
0545
0546 if ((len = str_has_prefix(str, "_filter=")))
0547 strncpy(stack_trace_filter_buf, str + len, COMMAND_LINE_SIZE);
0548
0549 stack_tracer_enabled = 1;
0550 return 1;
0551 }
0552 __setup("stacktrace", enable_stacktrace);
0553
0554 static __init int stack_trace_init(void)
0555 {
0556 int ret;
0557
0558 ret = tracing_init_dentry();
0559 if (ret)
0560 return 0;
0561
0562 trace_create_file("stack_max_size", TRACE_MODE_WRITE, NULL,
0563 &stack_trace_max_size, &stack_max_size_fops);
0564
0565 trace_create_file("stack_trace", TRACE_MODE_READ, NULL,
0566 NULL, &stack_trace_fops);
0567
0568 #ifdef CONFIG_DYNAMIC_FTRACE
0569 trace_create_file("stack_trace_filter", TRACE_MODE_WRITE, NULL,
0570 &trace_ops, &stack_trace_filter_fops);
0571 #endif
0572
0573 if (stack_trace_filter_buf[0])
0574 ftrace_set_early_filter(&trace_ops, stack_trace_filter_buf, 1);
0575
0576 if (stack_tracer_enabled)
0577 register_ftrace_function(&trace_ops);
0578
0579 return 0;
0580 }
0581
0582 device_initcall(stack_trace_init);