]>
Commit | Line | Data |
---|---|---|
0cb42a7c GKH |
1 | From 6bd288569b50bc89fa5513031086746968f585cb Mon Sep 17 00:00:00 2001 |
2 | From: Will Deacon <will.deacon@arm.com> | |
3 | Date: Fri, 1 Mar 2019 13:28:01 +0000 | |
4 | Subject: arm64: debug: Ensure debug handlers check triggering exception level | |
5 | ||
6 | From: Will Deacon <will.deacon@arm.com> | |
7 | ||
8 | commit 6bd288569b50bc89fa5513031086746968f585cb upstream. | |
9 | ||
10 | Debug exception handlers may be called for exceptions generated both by | |
11 | user and kernel code. In many cases, this is checked explicitly, but | |
12 | in other cases things either happen to work by happy accident or they | |
13 | go slightly wrong. For example, executing 'brk #4' from userspace will | |
14 | enter the kprobes code and be ignored, but the instruction will be | |
15 | retried forever in userspace instead of delivering a SIGTRAP. | |
16 | ||
17 | Fix this issue in the most stable-friendly fashion by simply adding | |
18 | explicit checks of the triggering exception level to all of our debug | |
19 | exception handlers. | |
20 | ||
21 | Cc: <stable@vger.kernel.org> | |
22 | Reviewed-by: Mark Rutland <mark.rutland@arm.com> | |
23 | Signed-off-by: Will Deacon <will.deacon@arm.com> | |
24 | Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> | |
25 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
26 | ||
27 | --- | |
28 | arch/arm64/kernel/kgdb.c | 14 ++++++++++---- | |
29 | arch/arm64/kernel/probes/kprobes.c | 6 ++++++ | |
30 | 2 files changed, 16 insertions(+), 4 deletions(-) | |
31 | ||
32 | --- a/arch/arm64/kernel/kgdb.c | |
33 | +++ b/arch/arm64/kernel/kgdb.c | |
34 | @@ -244,27 +244,33 @@ int kgdb_arch_handle_exception(int excep | |
35 | ||
36 | static int kgdb_brk_fn(struct pt_regs *regs, unsigned int esr) | |
37 | { | |
38 | + if (user_mode(regs)) | |
39 | + return DBG_HOOK_ERROR; | |
40 | + | |
41 | kgdb_handle_exception(1, SIGTRAP, 0, regs); | |
42 | - return 0; | |
43 | + return DBG_HOOK_HANDLED; | |
44 | } | |
45 | NOKPROBE_SYMBOL(kgdb_brk_fn) | |
46 | ||
47 | static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int esr) | |
48 | { | |
49 | + if (user_mode(regs)) | |
50 | + return DBG_HOOK_ERROR; | |
51 | + | |
52 | compiled_break = 1; | |
53 | kgdb_handle_exception(1, SIGTRAP, 0, regs); | |
54 | ||
55 | - return 0; | |
56 | + return DBG_HOOK_HANDLED; | |
57 | } | |
58 | NOKPROBE_SYMBOL(kgdb_compiled_brk_fn); | |
59 | ||
60 | static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned int esr) | |
61 | { | |
62 | - if (!kgdb_single_step) | |
63 | + if (user_mode(regs) || !kgdb_single_step) | |
64 | return DBG_HOOK_ERROR; | |
65 | ||
66 | kgdb_handle_exception(1, SIGTRAP, 0, regs); | |
67 | - return 0; | |
68 | + return DBG_HOOK_HANDLED; | |
69 | } | |
70 | NOKPROBE_SYMBOL(kgdb_step_brk_fn); | |
71 | ||
72 | --- a/arch/arm64/kernel/probes/kprobes.c | |
73 | +++ b/arch/arm64/kernel/probes/kprobes.c | |
74 | @@ -450,6 +450,9 @@ kprobe_single_step_handler(struct pt_reg | |
75 | struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); | |
76 | int retval; | |
77 | ||
78 | + if (user_mode(regs)) | |
79 | + return DBG_HOOK_ERROR; | |
80 | + | |
81 | /* return error if this is not our step */ | |
82 | retval = kprobe_ss_hit(kcb, instruction_pointer(regs)); | |
83 | ||
84 | @@ -466,6 +469,9 @@ kprobe_single_step_handler(struct pt_reg | |
85 | int __kprobes | |
86 | kprobe_breakpoint_handler(struct pt_regs *regs, unsigned int esr) | |
87 | { | |
88 | + if (user_mode(regs)) | |
89 | + return DBG_HOOK_ERROR; | |
90 | + | |
91 | kprobe_handler(regs); | |
92 | return DBG_HOOK_HANDLED; | |
93 | } |