Messages in this thread Patch in this message | | | From | Chen Guokai <> | Subject | [PATCH v6 10/13] riscv/kprobe: Add instruction boundary check for RVI/RVC hybrid kernel | Date | Fri, 27 Jan 2023 21:05:38 +0800 |
| |
From: Liao Chang <liaochang1@huawei.com>
Add instruction boundary check to ensure kprobe doesn't truncate any RVI instruction, which leads to kernel crash.
Signed-off-by: Liao Chang <liaochang1@huawei.com> --- arch/riscv/kernel/probes/kprobes.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/arch/riscv/kernel/probes/kprobes.c b/arch/riscv/kernel/probes/kprobes.c index e1856b04db04..91a6b46909cc 100644 --- a/arch/riscv/kernel/probes/kprobes.c +++ b/arch/riscv/kernel/probes/kprobes.c @@ -49,11 +49,33 @@ static void __kprobes arch_simulate_insn(struct kprobe *p, struct pt_regs *regs) post_kprobe_handler(p, kcb, regs); } +bool __kprobes riscv_insn_boundary_check(unsigned long paddr) +{ +#if defined(CONFIG_RISCV_ISA_C) + unsigned long size = 0, offs = 0, len = 0, entry = 0; + + if (!kallsyms_lookup_size_offset(paddr, &size, &offs)) + return false; + + /* + * Scan instructions from function entry ensure the kprobe address + * is aligned with RVI or RVC boundary. + */ + entry = paddr - offs; + while ((entry + len) < paddr) + len += GET_INSN_LENGTH(*(kprobe_opcode_t *)(entry + len)); + return (entry + len) == paddr; +#else + return true; +#endif +} + int __kprobes arch_prepare_kprobe(struct kprobe *p) { unsigned long probe_addr = (unsigned long)p->addr; - if (probe_addr & 0x1) + /* for RVI/RCV hybrid kernel, it needs instruction boundary check */ + if ((probe_addr & 0x1) || !riscv_insn_boundary_check(probe_addr)) return -EILSEQ; /* copy instruction */ -- 2.34.1
| |