On 2 Feb 2023, at 09:48, Björn Töpel <bjorn@xxxxxxxxxx> wrote: > > Guo Ren <guoren@xxxxxxxxxx> writes: > >> On Wed, Feb 1, 2023 at 5:40 PM Björn Töpel <bjorn@xxxxxxxxxx> wrote: >>> >>> guoren@xxxxxxxxxx writes: >>> >>>> From: Guo Ren <guoren@xxxxxxxxxxxxxxxxx> >>>> >>>> The current kprobe would cause a misaligned load for the probe point. >>>> This patch fixup it with two half-word loads instead. >>>> >>>> Fixes: c22b0bcb1dd0 ("riscv: Add kprobes supported") >>>> Signed-off-by: Guo Ren <guoren@xxxxxxxxxxxxxxxxx> >>>> Signed-off-by: Guo Ren <guoren@xxxxxxxxxx> >>>> Link: https://lore.kernel.org/linux-riscv/878rhig9zj.fsf@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/ >>>> Reported-by: Bjorn Topel <bjorn.topel@xxxxxxxxx> >>>> --- >>>> arch/riscv/kernel/probes/kprobes.c | 4 +++- >>>> 1 file changed, 3 insertions(+), 1 deletion(-) >>>> >>>> diff --git a/arch/riscv/kernel/probes/kprobes.c b/arch/riscv/kernel/probes/kprobes.c >>>> index 41c7481afde3..c1160629cef4 100644 >>>> --- a/arch/riscv/kernel/probes/kprobes.c >>>> +++ b/arch/riscv/kernel/probes/kprobes.c >>>> @@ -74,7 +74,9 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) >>>> return -EILSEQ; >>>> >>>> /* copy instruction */ >>>> - p->opcode = *p->addr; >>>> + p->opcode = (kprobe_opcode_t)(*(u16 *)probe_addr); >>>> + if (GET_INSN_LENGTH(p->opcode) == 4) >>>> + p->opcode |= (kprobe_opcode_t)(*(u16 *)(probe_addr + 2)) >>>> << 16; >>> >>> Ugh, those casts. :-( What about the memcpy variant you had in the other >>> thread? >> The memcpy version would force load probe_addr + 2. This one would >> save an lh operation. The code text guarantees half-word alignment. No >> misaligned load happened. Second, kprobe wouldn't write the last half >> of 32b instruction. > > Ok, something more readable, like: > > diff --git a/arch/riscv/kernel/probes/kprobes.c b/arch/riscv/kernel/probes/kprobes.c > index f21592d20306..3602352ba175 100644 > --- a/arch/riscv/kernel/probes/kprobes.c > +++ b/arch/riscv/kernel/probes/kprobes.c > @@ -50,14 +50,16 @@ static void __kprobes arch_simulate_insn(struct kprobe *p, struct pt_regs *regs) > > int __kprobes arch_prepare_kprobe(struct kprobe *p) > { > - unsigned long probe_addr = (unsigned long)p->addr; > + u16 *insn = (u16 *)p->addr; > > - if (probe_addr & 0x1) > + if ((uintptr_t)insn & 0x1) > return -EILSEQ; > > /* copy instruction */ > - p->opcode = *p->addr; > - > + p->opcode = *insn++; > + if (GET_INSN_LENGTH(p->opcode) == 4) > + p->opcode |= *insn << 16; *insn gets promoted to int not unsigned so this is UB if bit 15 is set. Jess > + > /* decode instruction */ > switch (riscv_probe_decode_insn(p->addr, &p->ainsn.api)) { > case INSN_REJECTED: /* insn not supported */ > > > Björn > > _______________________________________________ > linux-riscv mailing list > linux-riscv@xxxxxxxxxxxxxxxxxxx > http://lists.infradead.org/mailman/listinfo/linux-riscv