0001
0002
0003
0004
0005
0006 #include <linux/sched/debug.h>
0007 #include <linux/kallsyms.h>
0008 #include <linux/kprobes.h>
0009 #include <linux/uaccess.h>
0010 #include <linux/hardirq.h>
0011 #include <linux/kdebug.h>
0012 #include <linux/export.h>
0013 #include <linux/ptrace.h>
0014 #include <linux/kexec.h>
0015 #include <linux/sysfs.h>
0016 #include <linux/bug.h>
0017 #include <linux/nmi.h>
0018
0019 #include <asm/stacktrace.h>
0020
0021 const char *stack_type_name(enum stack_type type)
0022 {
0023 if (type == STACK_TYPE_IRQ)
0024 return "IRQ";
0025
0026 if (type == STACK_TYPE_SOFTIRQ)
0027 return "SOFTIRQ";
0028
0029 if (type == STACK_TYPE_ENTRY)
0030 return "ENTRY_TRAMPOLINE";
0031
0032 if (type == STACK_TYPE_EXCEPTION)
0033 return "#DF";
0034
0035 return NULL;
0036 }
0037
0038 static bool in_hardirq_stack(unsigned long *stack, struct stack_info *info)
0039 {
0040 unsigned long *begin = (unsigned long *)this_cpu_read(hardirq_stack_ptr);
0041 unsigned long *end = begin + (THREAD_SIZE / sizeof(long));
0042
0043
0044
0045
0046
0047 if (stack < begin || stack > end)
0048 return false;
0049
0050 info->type = STACK_TYPE_IRQ;
0051 info->begin = begin;
0052 info->end = end;
0053
0054
0055
0056
0057
0058 info->next_sp = (unsigned long *)*begin;
0059
0060 return true;
0061 }
0062
0063 static bool in_softirq_stack(unsigned long *stack, struct stack_info *info)
0064 {
0065 unsigned long *begin = (unsigned long *)this_cpu_read(softirq_stack_ptr);
0066 unsigned long *end = begin + (THREAD_SIZE / sizeof(long));
0067
0068
0069
0070
0071
0072 if (stack < begin || stack > end)
0073 return false;
0074
0075 info->type = STACK_TYPE_SOFTIRQ;
0076 info->begin = begin;
0077 info->end = end;
0078
0079
0080
0081
0082
0083 info->next_sp = (unsigned long *)*begin;
0084
0085 return true;
0086 }
0087
0088 static bool in_doublefault_stack(unsigned long *stack, struct stack_info *info)
0089 {
0090 struct cpu_entry_area *cea = get_cpu_entry_area(raw_smp_processor_id());
0091 struct doublefault_stack *ss = &cea->doublefault_stack;
0092
0093 void *begin = ss->stack;
0094 void *end = begin + sizeof(ss->stack);
0095
0096 if ((void *)stack < begin || (void *)stack >= end)
0097 return false;
0098
0099 info->type = STACK_TYPE_EXCEPTION;
0100 info->begin = begin;
0101 info->end = end;
0102 info->next_sp = (unsigned long *)this_cpu_read(cpu_tss_rw.x86_tss.sp);
0103
0104 return true;
0105 }
0106
0107
0108 int get_stack_info(unsigned long *stack, struct task_struct *task,
0109 struct stack_info *info, unsigned long *visit_mask)
0110 {
0111 if (!stack)
0112 goto unknown;
0113
0114 task = task ? : current;
0115
0116 if (in_task_stack(stack, task, info))
0117 goto recursion_check;
0118
0119 if (task != current)
0120 goto unknown;
0121
0122 if (in_entry_stack(stack, info))
0123 goto recursion_check;
0124
0125 if (in_hardirq_stack(stack, info))
0126 goto recursion_check;
0127
0128 if (in_softirq_stack(stack, info))
0129 goto recursion_check;
0130
0131 if (in_doublefault_stack(stack, info))
0132 goto recursion_check;
0133
0134 goto unknown;
0135
0136 recursion_check:
0137
0138
0139
0140
0141
0142 if (visit_mask) {
0143 if (*visit_mask & (1UL << info->type)) {
0144 printk_deferred_once(KERN_WARNING "WARNING: stack recursion on stack type %d\n", info->type);
0145 goto unknown;
0146 }
0147 *visit_mask |= 1UL << info->type;
0148 }
0149
0150 return 0;
0151
0152 unknown:
0153 info->type = STACK_TYPE_UNKNOWN;
0154 return -EINVAL;
0155 }