On 3/14/24 10:17, Masami Hiramatsu (Google) wrote: > From: Masami Hiramatsu (Google) <mhira...@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.
IMHO there is a check on the address in kallsyms_lookup_size_offset to see if it is a kernel text address before arch_adjust_kprobe_addr is invoked. The call chain is: register_kprobe() _kprobe_addr() kallsyms_lookup_size_offset() <- check on addr is here arch_adjust_kprobe_addr() I wonder why this check was not able to capture the problem in this bug report (I cannot reproduce it locally). Thanks, --Jinghao > > Reported-by: Qiang Zhang <zzqq0103....@gmail.com> > Closes: > https://urldefense.com/v3/__https://lore.kernel.org/all/cakhosas2rof6vqvbw_lg_j3qnku0canzr2qmy4et7r5lo8m...@mail.gmail.com/__;!!DZ3fjg!_C9Dn6-GBlkyS2z34bDUBsEXkTkgWp45MNrd4Rl5I5slz2A3SrurXOxKupsxLMqxC2BMiySCTfB2-5fPhkLP1g$ > > Fixes: cc66bb914578 ("x86/ibt,kprobes: Cure sym+0 equals fentry woes") > Signed-off-by: Masami Hiramatsu (Google) <mhira...@kernel.org> > --- > Changes in v2: > - Fix to return NULL if failed to access the address. > --- > 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..95e4ebe5d514 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 NULL; > + > + if (is_endbr(insn)) { > *on_func_entry = !offset || offset == 4; > if (*on_func_entry) > offset = 4; >
OpenPGP_signature.asc
Description: OpenPGP digital signature