Skip to content

Commit b99610f

Browse files
mflemingpmundt
authored andcommitted
sh: Provide diagnostic kernel stack checks
Enable kernel stack checking code in both the dynamic ftrace and mcount code paths. Check the stack to see if it's overflowing and make sure that the stack pointer contains an address that's either in init_stack or after the bss. Signed-off-by: Matt Fleming <matt@console-pimps.org> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
1 parent c652d78 commit b99610f

File tree

3 files changed

+97
-0
lines changed

3 files changed

+97
-0
lines changed

arch/sh/Kconfig.debug

+11
Original file line numberDiff line numberDiff line change
@@ -123,4 +123,15 @@ config SH64_SR_WATCH
123123
bool "Debug: set SR.WATCH to enable hardware watchpoints and trace"
124124
depends on SUPERH64
125125

126+
config STACK_DEBUG
127+
bool "Enable diagnostic checks of the kernel stack"
128+
depends on FUNCTION_TRACER
129+
select DEBUG_STACKOVERFLOW
130+
default n
131+
help
132+
This option allows checks to be performed on the kernel stack
133+
at runtime. Saying Y here will add overhead to every function
134+
call and will therefore incur a major performance hit. Most
135+
users should say N.
136+
126137
endmenu

arch/sh/kernel/asm-offsets.c

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ int main(void)
2626
DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
2727
DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count));
2828
DEFINE(TI_RESTART_BLOCK,offsetof(struct thread_info, restart_block));
29+
DEFINE(TI_SIZE, sizeof(struct thread_info));
2930

3031
#ifdef CONFIG_HIBERNATION
3132
DEFINE(PBE_ADDRESS, offsetof(struct pbe, address));

arch/sh/lib/mcount.S

+85
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
* for more details.
1010
*/
1111
#include <asm/ftrace.h>
12+
#include <asm/thread_info.h>
13+
#include <asm/asm-offsets.h>
1214

1315
#define MCOUNT_ENTER() \
1416
mov.l r4, @-r15; \
@@ -28,6 +30,55 @@
2830
rts; \
2931
mov.l @r15+, r4
3032

33+
#ifdef CONFIG_STACK_DEBUG
34+
/*
35+
* Perform diagnostic checks on the state of the kernel stack.
36+
*
37+
* Check for stack overflow. If there is less than 1KB free
38+
* then it has overflowed.
39+
*
40+
* Make sure the stack pointer contains a valid address. Valid
41+
* addresses for kernel stacks are anywhere after the bss
42+
* (after _ebss) and anywhere in init_thread_union (init_stack).
43+
*/
44+
#define STACK_CHECK() \
45+
mov #(THREAD_SIZE >> 10), r0; \
46+
shll8 r0; \
47+
shll2 r0; \
48+
\
49+
/* r1 = sp & (THREAD_SIZE - 1) */ \
50+
mov #-1, r1; \
51+
add r0, r1; \
52+
and r15, r1; \
53+
\
54+
mov #TI_SIZE, r3; \
55+
mov #(STACK_WARN >> 8), r2; \
56+
shll8 r2; \
57+
add r3, r2; \
58+
\
59+
/* Is the stack overflowing? */ \
60+
cmp/hi r2, r1; \
61+
bf stack_panic; \
62+
\
63+
/* If sp > _ebss then we're OK. */ \
64+
mov.l .L_ebss, r1; \
65+
cmp/hi r1, r15; \
66+
bt 1f; \
67+
\
68+
/* If sp < init_stack, we're not OK. */ \
69+
mov.l .L_init_thread_union, r1; \
70+
cmp/hs r1, r15; \
71+
bf stack_panic; \
72+
\
73+
/* If sp > init_stack && sp < _ebss, not OK. */ \
74+
add r0, r1; \
75+
cmp/hs r1, r15; \
76+
bt stack_panic; \
77+
1:
78+
#else
79+
#define STACK_CHECK()
80+
#endif /* CONFIG_STACK_DEBUG */
81+
3182
.align 2
3283
.globl _mcount
3384
.type _mcount,@function
@@ -41,6 +92,8 @@ mcount:
4192
tst r0, r0
4293
bf ftrace_stub
4394
#endif
95+
STACK_CHECK()
96+
4497
MCOUNT_ENTER()
4598

4699
#ifdef CONFIG_DYNAMIC_FTRACE
@@ -73,6 +126,8 @@ ftrace_caller:
73126
tst r0, r0
74127
bf ftrace_stub
75128

129+
STACK_CHECK()
130+
76131
MCOUNT_ENTER()
77132

78133
.globl ftrace_call
@@ -100,6 +155,36 @@ ftrace_stub:
100155
rts
101156
nop
102157

158+
#ifdef CONFIG_STACK_DEBUG
159+
.globl stack_panic
160+
stack_panic:
161+
mov.l .Ldump_stack, r0
162+
jsr @r0
163+
nop
164+
165+
mov.l .Lpanic, r0
166+
jsr @r0
167+
mov.l .Lpanic_s, r4
168+
169+
rts
170+
nop
171+
103172
.align 2
104173
.Lfunction_trace_stop:
105174
.long function_trace_stop
175+
.L_ebss:
176+
.long _ebss
177+
.L_init_thread_union:
178+
.long init_thread_union
179+
.Lpanic:
180+
.long panic
181+
.Lpanic_s:
182+
.long .Lpanic_str
183+
.Ldump_stack:
184+
.long dump_stack
185+
186+
.section .rodata
187+
.align 2
188+
.Lpanic_str:
189+
.string "Stack error"
190+
#endif /* CONFIG_STACK_DEBUG */

0 commit comments

Comments
 (0)