aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64/kernel/probes
diff options
context:
space:
mode:
authorPratyush Anand <panand@redhat.com>2016-08-22 02:46:00 -0400
committerWill Deacon <will.deacon@arm.com>2016-08-25 13:00:20 -0400
commit7419333fa15ec958d12845fcc79b7bdd16de06ec (patch)
treef6bb681d6dcbd28e4e93566fb44b70ebe1655868 /arch/arm64/kernel/probes
parentaea73abb90265110ed59281e370289316fd689f3 (diff)
arm64: kprobe: Always clear pstate.D in breakpoint exception handler
Whenever we are hitting a kprobe from a none-kprobe debug exception handler, we hit an infinite occurrences of "Unexpected kernel single-step exception at EL1" PSTATE.D is debug exception mask bit. It is set whenever we enter into an exception mode. When it is set then Watchpoint, Breakpoint, and Software Step exceptions are masked. However, software Breakpoint Instruction exceptions can never be masked. Therefore, if we ever execute a BRK instruction, irrespective of D-bit setting, we will be receiving a corresponding breakpoint exception. For example: - We are executing kprobe pre/post handler, and kprobe has been inserted in one of the instruction of a function called by handler. So, it executes BRK instruction and we land into the case of KPROBE_REENTER. (This case is already handled by current code) - We are executing uprobe handler or any other BRK handler such as in WARN_ON (BRK BUG_BRK_IMM), and we trace that path using kprobe.So, we enter into kprobe breakpoint handler,from another BRK handler.(This case is not being handled currently) In all such cases kprobe breakpoint exception will be raised when we were already in debug exception mode. SPSR's D bit (bit 9) shows the value of PSTATE.D immediately before the exception was taken. So, in above example cases we would find it set in kprobe breakpoint handler. Single step exception will always be followed by a kprobe breakpoint exception.However, it will only be raised gracefully if we clear D bit while returning from breakpoint exception. If D bit is set then, it results into undefined exception and when it's handler enables dbg then single step exception is generated, however it will never be handled(because address does not match and therefore treated as unexpected). This patch clears D-flag unconditionally in setup_singlestep, so that we can always get single step exception correctly after returning from breakpoint exception. Additionally, it also removes D-flag set statement for KPROBE_REENTER return path, because debug exception for KPROBE_REENTER will always take place in a debug exception state. So, D-flag will already be set in this case. Acked-by: Sandeepa Prabhu <sandeepa.s.prabhu@gmail.com> Acked-by: Masami Hiramatsu <mhiramat@kernel.org> Signed-off-by: Pratyush Anand <panand@redhat.com> Signed-off-by: Will Deacon <will.deacon@arm.com>
Diffstat (limited to 'arch/arm64/kernel/probes')
-rw-r--r--arch/arm64/kernel/probes/kprobes.c29
1 files changed, 13 insertions, 16 deletions
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index c6b0f40620d8..0354ffeb2ed5 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -166,13 +166,18 @@ static void __kprobes set_current_kprobe(struct kprobe *p)
166} 166}
167 167
168/* 168/*
169 * The D-flag (Debug mask) is set (masked) upon debug exception entry. 169 * When PSTATE.D is set (masked), then software step exceptions can not be
170 * Kprobes needs to clear (unmask) D-flag -ONLY- in case of recursive 170 * generated.
171 * probe i.e. when probe hit from kprobe handler context upon 171 * SPSR's D bit shows the value of PSTATE.D immediately before the
172 * executing the pre/post handlers. In this case we return with 172 * exception was taken. PSTATE.D is set while entering into any exception
173 * D-flag clear so that single-stepping can be carried-out. 173 * mode, however software clears it for any normal (none-debug-exception)
174 * 174 * mode in the exception entry. Therefore, when we are entering into kprobe
175 * Leave D-flag set in all other cases. 175 * breakpoint handler from any normal mode then SPSR.D bit is already
176 * cleared, however it is set when we are entering from any debug exception
177 * mode.
178 * Since we always need to generate single step exception after a kprobe
179 * breakpoint exception therefore we need to clear it unconditionally, when
180 * we become sure that the current breakpoint exception is for kprobe.
176 */ 181 */
177static void __kprobes 182static void __kprobes
178spsr_set_debug_flag(struct pt_regs *regs, int mask) 183spsr_set_debug_flag(struct pt_regs *regs, int mask)
@@ -245,10 +250,7 @@ static void __kprobes setup_singlestep(struct kprobe *p,
245 250
246 set_ss_context(kcb, slot); /* mark pending ss */ 251 set_ss_context(kcb, slot); /* mark pending ss */
247 252
248 if (kcb->kprobe_status == KPROBE_REENTER) 253 spsr_set_debug_flag(regs, 0);
249 spsr_set_debug_flag(regs, 0);
250 else
251 WARN_ON(regs->pstate & PSR_D_BIT);
252 254
253 /* IRQs and single stepping do not mix well. */ 255 /* IRQs and single stepping do not mix well. */
254 kprobes_save_local_irqflag(kcb, regs); 256 kprobes_save_local_irqflag(kcb, regs);
@@ -333,8 +335,6 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr)
333 BUG(); 335 BUG();
334 336
335 kernel_disable_single_step(); 337 kernel_disable_single_step();
336 if (kcb->kprobe_status == KPROBE_REENTER)
337 spsr_set_debug_flag(regs, 1);
338 338
339 if (kcb->kprobe_status == KPROBE_REENTER) 339 if (kcb->kprobe_status == KPROBE_REENTER)
340 restore_previous_kprobe(kcb); 340 restore_previous_kprobe(kcb);
@@ -457,9 +457,6 @@ kprobe_single_step_handler(struct pt_regs *regs, unsigned int esr)
457 kprobes_restore_local_irqflag(kcb, regs); 457 kprobes_restore_local_irqflag(kcb, regs);
458 kernel_disable_single_step(); 458 kernel_disable_single_step();
459 459
460 if (kcb->kprobe_status == KPROBE_REENTER)
461 spsr_set_debug_flag(regs, 1);
462
463 post_kprobe_handler(kcb, regs); 460 post_kprobe_handler(kcb, regs);
464 } 461 }
465 462