Message ID | 171042914997.151113.2962249725455796854.stgit@devnote2 (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | kprobes/x86: Use copy_from_kernel_nofault() to read from unsafe address | expand |
On Fri, 15 Mar 2024 00:12:30 +0900 "Masami Hiramatsu (Google)" <mhiramat@kernel.org> wrote: > From: Masami Hiramatsu (Google) <mhiramat@kernel.org> > > Read from an unsafe address with copy_from_kernel_nofault() in > arch_adjust_kprobe_addr() because this function is used before checking > the address is in text or not. Syzcaller bot found a bug and reported > the case if user specifies inaccessible data area, > arch_adjust_kprobe_addr() will cause a kernel panic. > > > Reported-by: Qiang Zhang <zzqq0103.hey@gmail.com> > Closes: https://lore.kernel.org/all/CAKHoSAs2rof6vQVBw_Lg_j3QNku0CANZR2qmy4eT7R5Lo8MFbg@mail.gmail.com/ > Fixes: cc66bb914578 ("x86/ibt,kprobes: Cure sym+0 equals fentry woes") > Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org> > --- > arch/x86/kernel/kprobes/core.c | 11 ++++++++++- > 1 file changed, 10 insertions(+), 1 deletion(-) > > diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c > index a0ce46c0a2d8..a885eea3bd34 100644 > --- a/arch/x86/kernel/kprobes/core.c > +++ b/arch/x86/kernel/kprobes/core.c > @@ -335,7 +335,16 @@ static int can_probe(unsigned long paddr) > kprobe_opcode_t *arch_adjust_kprobe_addr(unsigned long addr, unsigned long offset, > bool *on_func_entry) > { > - if (is_endbr(*(u32 *)addr)) { > + u32 insn; > + > + /* > + * Since addr is not guaranteed to be safely accessed yet, use > + * copy_from_kernel_nofault() to get the instruction. > + */ > + if (copy_from_kernel_nofault(&insn, (void *)addr, sizeof(u32))) > + return 0; Oops, it should be NULL. > + > + if (is_endbr(insn)) { > *on_func_entry = !offset || offset == 4; > if (*on_func_entry) > offset = 4; >
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index a0ce46c0a2d8..a885eea3bd34 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c @@ -335,7 +335,16 @@ static int can_probe(unsigned long paddr) kprobe_opcode_t *arch_adjust_kprobe_addr(unsigned long addr, unsigned long offset, bool *on_func_entry) { - if (is_endbr(*(u32 *)addr)) { + u32 insn; + + /* + * Since addr is not guaranteed to be safely accessed yet, use + * copy_from_kernel_nofault() to get the instruction. + */ + if (copy_from_kernel_nofault(&insn, (void *)addr, sizeof(u32))) + return 0; + + if (is_endbr(insn)) { *on_func_entry = !offset || offset == 4; if (*on_func_entry) offset = 4;