diff mbox series

riscv: kprobes: fix placement in arch_prepare_ss_slot

Message ID 20241216130544.706110-1-ben.dooks@codethink.co.uk (mailing list archive)
State New
Headers show
Series riscv: kprobes: fix placement in arch_prepare_ss_slot | expand

Checks

Context Check Description
conchuod/vmtest-for-next-PR success PR summary
conchuod/patch-1-test-1 success .github/scripts/patches/tests/build_rv32_defconfig.sh took 144.36s
conchuod/patch-1-test-2 success .github/scripts/patches/tests/build_rv64_clang_allmodconfig.sh took 1433.66s
conchuod/patch-1-test-3 success .github/scripts/patches/tests/build_rv64_gcc_allmodconfig.sh took 1673.05s
conchuod/patch-1-test-4 success .github/scripts/patches/tests/build_rv64_nommu_k210_defconfig.sh took 21.41s
conchuod/patch-1-test-5 success .github/scripts/patches/tests/build_rv64_nommu_virt_defconfig.sh took 23.25s
conchuod/patch-1-test-6 warning .github/scripts/patches/tests/checkpatch.sh took 0.48s
conchuod/patch-1-test-7 success .github/scripts/patches/tests/dtb_warn_rv64.sh took 44.60s
conchuod/patch-1-test-8 success .github/scripts/patches/tests/header_inline.sh took 0.00s
conchuod/patch-1-test-9 success .github/scripts/patches/tests/kdoc.sh took 0.57s
conchuod/patch-1-test-10 success .github/scripts/patches/tests/module_param.sh took 0.01s
conchuod/patch-1-test-11 success .github/scripts/patches/tests/verify_fixes.sh took 0.02s
conchuod/patch-1-test-12 success .github/scripts/patches/tests/verify_signedoff.sh took 0.03s

Commit Message

Ben Dooks Dec. 16, 2024, 1:05 p.m. UTC
The second patch_text_nosync() in arch_prepare_ss_slot should be pointing
after the first instruction, however p->ainsn.api.insn is a pointer to a
probe_opcode_t which is 4 bytes... this means an instruction of length 2
moves the pointer by 8 bytes.

This means a kprobe may fail to work and recurse into the bad instruction
handler (which then itself fails as the original lock still seems to be
held?)

Fixes: b1756750a397f36ddc857 ("riscv: kprobes: Use patch_text_nosync() for insn slots")
Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
Cc: Samuel Holland <samuel.holland@sifive.com>
---
 arch/riscv/kernel/probes/kprobes.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Alexandre Ghiti Dec. 16, 2024, 4:32 p.m. UTC | #1
Hi Ben,

On 16/12/2024 14:05, Ben Dooks wrote:
> The second patch_text_nosync() in arch_prepare_ss_slot should be pointing
> after the first instruction, however p->ainsn.api.insn is a pointer to a
> probe_opcode_t which is 4 bytes... this means an instruction of length 2
> moves the pointer by 8 bytes.
>
> This means a kprobe may fail to work and recurse into the bad instruction
> handler (which then itself fails as the original lock still seems to be
> held?)
>
> Fixes: b1756750a397f36ddc857 ("riscv: kprobes: Use patch_text_nosync() for insn slots")
> Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
> Cc: Samuel Holland <samuel.holland@sifive.com>
> ---
>   arch/riscv/kernel/probes/kprobes.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/arch/riscv/kernel/probes/kprobes.c b/arch/riscv/kernel/probes/kprobes.c
> index 380a0e8cecc0..c0738d6c6498 100644
> --- a/arch/riscv/kernel/probes/kprobes.c
> +++ b/arch/riscv/kernel/probes/kprobes.c
> @@ -30,7 +30,7 @@ static void __kprobes arch_prepare_ss_slot(struct kprobe *p)
>   	p->ainsn.api.restore = (unsigned long)p->addr + len;
>   
>   	patch_text_nosync(p->ainsn.api.insn, &p->opcode, len);
> -	patch_text_nosync(p->ainsn.api.insn + len, &insn, GET_INSN_LENGTH(insn));
> +	patch_text_nosync((void *)p->ainsn.api.insn + len, &insn, GET_INSN_LENGTH(insn));
>   }
>   
>   static void __kprobes arch_prepare_simulate(struct kprobe *p)


Nam already came up with the same fix a few weeks ago: 
https://lore.kernel.org/linux-riscv/20241119111056.2554419-1-namcao@linutronix.de/

Thanks anyway!

Alex
diff mbox series

Patch

diff --git a/arch/riscv/kernel/probes/kprobes.c b/arch/riscv/kernel/probes/kprobes.c
index 380a0e8cecc0..c0738d6c6498 100644
--- a/arch/riscv/kernel/probes/kprobes.c
+++ b/arch/riscv/kernel/probes/kprobes.c
@@ -30,7 +30,7 @@  static void __kprobes arch_prepare_ss_slot(struct kprobe *p)
 	p->ainsn.api.restore = (unsigned long)p->addr + len;
 
 	patch_text_nosync(p->ainsn.api.insn, &p->opcode, len);
-	patch_text_nosync(p->ainsn.api.insn + len, &insn, GET_INSN_LENGTH(insn));
+	patch_text_nosync((void *)p->ainsn.api.insn + len, &insn, GET_INSN_LENGTH(insn));
 }
 
 static void __kprobes arch_prepare_simulate(struct kprobe *p)