aboutsummaryrefslogtreecommitdiffstats
path: root/mm/kasan
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-05-06 16:11:48 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-05-06 16:11:48 -0400
commit2c6a392cddacde153865b15e8295ad0a35ed3c02 (patch)
tree558c34595f8987c87d26fc0fa0dc644fca9ef2cd /mm/kasan
parent0a499fc5c37e6db096969a83534fd98a2bf2b36c (diff)
parent3599fe12a125fa7118da2bcc5033d7741fb5f3a1 (diff)
Merge branch 'core-stacktrace-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull stack trace updates from Ingo Molnar: "So Thomas looked at the stacktrace code recently and noticed a few weirdnesses, and we all know how such stories of crummy kernel code meeting German engineering perfection end: a 45-patch series to clean it all up! :-) Here's the changes in Thomas's words: 'Struct stack_trace is a sinkhole for input and output parameters which is largely pointless for most usage sites. In fact if embedded into other data structures it creates indirections and extra storage overhead for no benefit. Looking at all usage sites makes it clear that they just require an interface which is based on a storage array. That array is either on stack, global or embedded into some other data structure. Some of the stack depot usage sites are outright wrong, but fortunately the wrongness just causes more stack being used for nothing and does not have functional impact. Another oddity is the inconsistent termination of the stack trace with ULONG_MAX. It's pointless as the number of entries is what determines the length of the stored trace. In fact quite some call sites remove the ULONG_MAX marker afterwards with or without nasty comments about it. Not all architectures do that and those which do, do it inconsistenly either conditional on nr_entries == 0 or unconditionally. The following series cleans that up by: 1) Removing the ULONG_MAX termination in the architecture code 2) Removing the ULONG_MAX fixups at the call sites 3) Providing plain storage array based interfaces for stacktrace and stackdepot. 4) Cleaning up the mess at the callsites including some related cleanups. 5) Removing the struct stack_trace based interfaces This is not changing the struct stack_trace interfaces at the architecture level, but it removes the exposure to the generic code'" * 'core-stacktrace-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (45 commits) x86/stacktrace: Use common infrastructure stacktrace: Provide common infrastructure lib/stackdepot: Remove obsolete functions stacktrace: Remove obsolete functions livepatch: Simplify stack trace retrieval tracing: Remove the last struct stack_trace usage tracing: Simplify stack trace retrieval tracing: Make ftrace_trace_userstack() static and conditional tracing: Use percpu stack trace buffer more intelligently tracing: Simplify stacktrace retrieval in histograms lockdep: Simplify stack trace handling lockdep: Remove save argument from check_prev_add() lockdep: Remove unused trace argument from print_circular_bug() drm: Simplify stacktrace handling dm persistent data: Simplify stack trace handling dm bufio: Simplify stack trace retrieval btrfs: ref-verify: Simplify stack trace retrieval dma/debug: Simplify stracktrace retrieval fault-inject: Simplify stacktrace retrieval mm/page_owner: Simplify stack trace handling ...
Diffstat (limited to 'mm/kasan')
-rw-r--r--mm/kasan/common.c35
-rw-r--r--mm/kasan/report.c7
2 files changed, 17 insertions, 25 deletions
diff --git a/mm/kasan/common.c b/mm/kasan/common.c
index 09c586474511..36afcf64e016 100644
--- a/mm/kasan/common.c
+++ b/mm/kasan/common.c
@@ -49,37 +49,28 @@ static inline int in_irqentry_text(unsigned long ptr)
49 ptr < (unsigned long)&__softirqentry_text_end); 49 ptr < (unsigned long)&__softirqentry_text_end);
50} 50}
51 51
52static inline void filter_irq_stacks(struct stack_trace *trace) 52static inline unsigned int filter_irq_stacks(unsigned long *entries,
53 unsigned int nr_entries)
53{ 54{
54 int i; 55 unsigned int i;
55 56
56 if (!trace->nr_entries) 57 for (i = 0; i < nr_entries; i++) {
57 return; 58 if (in_irqentry_text(entries[i])) {
58 for (i = 0; i < trace->nr_entries; i++)
59 if (in_irqentry_text(trace->entries[i])) {
60 /* Include the irqentry function into the stack. */ 59 /* Include the irqentry function into the stack. */
61 trace->nr_entries = i + 1; 60 return i + 1;
62 break;
63 } 61 }
62 }
63 return nr_entries;
64} 64}
65 65
66static inline depot_stack_handle_t save_stack(gfp_t flags) 66static inline depot_stack_handle_t save_stack(gfp_t flags)
67{ 67{
68 unsigned long entries[KASAN_STACK_DEPTH]; 68 unsigned long entries[KASAN_STACK_DEPTH];
69 struct stack_trace trace = { 69 unsigned int nr_entries;
70 .nr_entries = 0, 70
71 .entries = entries, 71 nr_entries = stack_trace_save(entries, ARRAY_SIZE(entries), 0);
72 .max_entries = KASAN_STACK_DEPTH, 72 nr_entries = filter_irq_stacks(entries, nr_entries);
73 .skip = 0 73 return stack_depot_save(entries, nr_entries, flags);
74 };
75
76 save_stack_trace(&trace);
77 filter_irq_stacks(&trace);
78 if (trace.nr_entries != 0 &&
79 trace.entries[trace.nr_entries-1] == ULONG_MAX)
80 trace.nr_entries--;
81
82 return depot_save_stack(&trace, flags);
83} 74}
84 75
85static inline void set_track(struct kasan_track *track, gfp_t flags) 76static inline void set_track(struct kasan_track *track, gfp_t flags)
diff --git a/mm/kasan/report.c b/mm/kasan/report.c
index 0772820ad098..03a443579386 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -100,10 +100,11 @@ static void print_track(struct kasan_track *track, const char *prefix)
100{ 100{
101 pr_err("%s by task %u:\n", prefix, track->pid); 101 pr_err("%s by task %u:\n", prefix, track->pid);
102 if (track->stack) { 102 if (track->stack) {
103 struct stack_trace trace; 103 unsigned long *entries;
104 unsigned int nr_entries;
104 105
105 depot_fetch_stack(track->stack, &trace); 106 nr_entries = stack_depot_fetch(track->stack, &entries);
106 print_stack_trace(&trace, 0); 107 stack_trace_print(entries, nr_entries, 0);
107 } else { 108 } else {
108 pr_err("(stack is not available)\n"); 109 pr_err("(stack is not available)\n");
109 } 110 }