Skip to content

Commit b701f9e

Browse files
covanampalmer-dabbelt
authored andcommitted
riscv: provide riscv-specific is_trap_insn()
uprobes expects is_trap_insn() to return true for any trap instructions, not just the one used for installing uprobe. The current default implementation only returns true for 16-bit c.ebreak if C extension is enabled. This can confuse uprobes if a 32-bit ebreak generates a trap exception from userspace: uprobes asks is_trap_insn() who says there is no trap, so uprobes assume a probe was there before but has been removed, and return to the trap instruction. This causes an infinite loop of entering and exiting trap handler. Instead of using the default implementation, implement this function speficially for riscv with checks for both ebreak and c.ebreak. Fixes: 7478408 ("riscv: Add uprobes supported") Signed-off-by: Nam Cao <[email protected]> Tested-by: Björn Töpel <[email protected]> Reviewed-by: Guo Ren <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 3ce99bd commit b701f9e

File tree

1 file changed

+6
-0
lines changed

1 file changed

+6
-0
lines changed

arch/riscv/kernel/probes/uprobes.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <linux/highmem.h>
44
#include <linux/ptrace.h>
55
#include <linux/uprobes.h>
6+
#include <asm/insn.h>
67

78
#include "decode-insn.h"
89

@@ -17,6 +18,11 @@ bool is_swbp_insn(uprobe_opcode_t *insn)
1718
#endif
1819
}
1920

21+
bool is_trap_insn(uprobe_opcode_t *insn)
22+
{
23+
return riscv_insn_is_ebreak(*insn) || riscv_insn_is_c_ebreak(*insn);
24+
}
25+
2026
unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
2127
{
2228
return instruction_pointer(regs);

0 commit comments

Comments
 (0)