]>
Commit | Line | Data |
---|---|---|
ba172962 SL |
1 | From 877c736480bb2e80d197a7632e474121961e5ff0 Mon Sep 17 00:00:00 2001 |
2 | From: Nicolai Stange <nstange@suse.de> | |
3 | Date: Tue, 22 Jan 2019 10:57:21 -0500 | |
4 | Subject: powerpc/64s: Clear on-stack exception marker upon exception return | |
5 | ||
6 | [ Upstream commit eddd0b332304d554ad6243942f87c2fcea98c56b ] | |
7 | ||
8 | The ppc64 specific implementation of the reliable stacktracer, | |
9 | save_stack_trace_tsk_reliable(), bails out and reports an "unreliable | |
10 | trace" whenever it finds an exception frame on the stack. Stack frames | |
11 | are classified as exception frames if the STACK_FRAME_REGS_MARKER | |
12 | magic, as written by exception prologues, is found at a particular | |
13 | location. | |
14 | ||
15 | However, as observed by Joe Lawrence, it is possible in practice that | |
16 | non-exception stack frames can alias with prior exception frames and | |
17 | thus, that the reliable stacktracer can find a stale | |
18 | STACK_FRAME_REGS_MARKER on the stack. It in turn falsely reports an | |
19 | unreliable stacktrace and blocks any live patching transition to | |
20 | finish. Said condition lasts until the stack frame is | |
21 | overwritten/initialized by function call or other means. | |
22 | ||
23 | In principle, we could mitigate this by making the exception frame | |
24 | classification condition in save_stack_trace_tsk_reliable() stronger: | |
25 | in addition to testing for STACK_FRAME_REGS_MARKER, we could also take | |
26 | into account that for all exceptions executing on the kernel stack | |
27 | - their stack frames's backlink pointers always match what is saved | |
28 | in their pt_regs instance's ->gpr[1] slot and that | |
29 | - their exception frame size equals STACK_INT_FRAME_SIZE, a value | |
30 | uncommonly large for non-exception frames. | |
31 | ||
32 | However, while these are currently true, relying on them would make | |
33 | the reliable stacktrace implementation more sensitive towards future | |
34 | changes in the exception entry code. Note that false negatives, i.e. | |
35 | not detecting exception frames, would silently break the live patching | |
36 | consistency model. | |
37 | ||
38 | Furthermore, certain other places (diagnostic stacktraces, perf, xmon) | |
39 | rely on STACK_FRAME_REGS_MARKER as well. | |
40 | ||
41 | Make the exception exit code clear the on-stack | |
42 | STACK_FRAME_REGS_MARKER for those exceptions running on the "normal" | |
43 | kernel stack and returning to kernelspace: because the topmost frame | |
44 | is ignored by the reliable stack tracer anyway, returns to userspace | |
45 | don't need to take care of clearing the marker. | |
46 | ||
47 | Furthermore, as I don't have the ability to test this on Book 3E or 32 | |
48 | bits, limit the change to Book 3S and 64 bits. | |
49 | ||
50 | Fixes: df78d3f61480 ("powerpc/livepatch: Implement reliable stack tracing for the consistency model") | |
51 | Reported-by: Joe Lawrence <joe.lawrence@redhat.com> | |
52 | Signed-off-by: Nicolai Stange <nstange@suse.de> | |
53 | Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com> | |
54 | Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> | |
55 | Signed-off-by: Sasha Levin <sashal@kernel.org> | |
56 | --- | |
57 | arch/powerpc/kernel/entry_64.S | 7 +++++++ | |
58 | 1 file changed, 7 insertions(+) | |
59 | ||
60 | diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S | |
61 | index c806a3c12592..7a46e0e57a36 100644 | |
62 | --- a/arch/powerpc/kernel/entry_64.S | |
63 | +++ b/arch/powerpc/kernel/entry_64.S | |
64 | @@ -994,6 +994,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) | |
65 | ld r2,_NIP(r1) | |
66 | mtspr SPRN_SRR0,r2 | |
67 | ||
68 | + /* | |
69 | + * Leaving a stale exception_marker on the stack can confuse | |
70 | + * the reliable stack unwinder later on. Clear it. | |
71 | + */ | |
72 | + li r2,0 | |
73 | + std r2,STACK_FRAME_OVERHEAD-16(r1) | |
74 | + | |
75 | ld r0,GPR0(r1) | |
76 | ld r2,GPR2(r1) | |
77 | ld r3,GPR3(r1) | |
78 | -- | |
79 | 2.19.1 | |
80 |