Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AC439C54E94 for ; Thu, 26 Jan 2023 13:05:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236359AbjAZNF2 (ORCPT ); Thu, 26 Jan 2023 08:05:28 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:45324 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231428AbjAZNFW (ORCPT ); Thu, 26 Jan 2023 08:05:22 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8F59165AE for ; Thu, 26 Jan 2023 05:05:21 -0800 (PST) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 26705617D0 for ; Thu, 26 Jan 2023 13:05:21 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 7E9C4C433EF; Thu, 26 Jan 2023 13:05:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1674738320; bh=tDQ+nCHdEwE/4jiYgtIlBrjarZhJE5C4ooQwzB7BIf4=; h=From:To:Cc:Subject:Date:From; b=CSHNJpitMu0/yXRFWW+6TrTMmKV5hUhWXvvXbrsL+cXA2qRwC1LAHlyfqY1szKbig QUmwimRD7tEgZnDLzjUKDsb6AxckOuQ/VX2TYdm9xRmatcWxMbdaW09vIr25sAG/SE Zj9/k6DdQDcc2X7dc/BgleeTZvC62doY0ENOomR74YAl3XmVk1BJ2drxdQJj93Lhq1 dvFkU8Nza2YUscbNKlvmksg+V14Z1A9QsgQFIznVOuaGLTDuJq2d8Q/3uW8KVoIbK7 pIuVGbKYbCiKadpG5yHqs4Pb/tGwJ764uDcNA7FWRQ8m9reP0eSHHWBehMt26Sjvzz tCMUtyPuoda1w== From: guoren@kernel.org To: guoren@kernel.org, palmer@dabbelt.com, paul.walmsley@sifive.com, mhiramat@kernel.org, conor.dooley@microchip.com, penberg@kernel.org, mark.rutland@arm.com Cc: linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org, Guo Ren Subject: [PATCH] riscv: kprobe: Fixup kernel panic when probing an illegal position Date: Thu, 26 Jan 2023 08:05:09 -0500 Message-Id: <20230126130509.1418251-1-guoren@kernel.org> X-Mailer: git-send-email 2.36.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Guo Ren The kernel would panic when probed for an illegal position. eg: (CONFIG_RISCV_ISA_C=n) echo 'p:hello kernel_clone+0x16 a0=%a0' >> kprobe_events echo 1 > events/kprobes/hello/enable cat trace Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: __do_sys_newfstatat+0xb8/0xb8 CPU: 0 PID: 111 Comm: sh Not tainted 6.2.0-rc1-00027-g2d398fe49a4d #490 Hardware name: riscv-virtio,qemu (DT) Call Trace: [] dump_backtrace+0x38/0x48 [] show_stack+0x50/0x68 [] dump_stack_lvl+0x60/0x84 [] dump_stack+0x20/0x30 [] panic+0x160/0x374 [] generic_handle_arch_irq+0x0/0xa8 [] sys_newstat+0x0/0x30 [] sys_clone+0x20/0x30 [] ret_from_syscall+0x0/0x4 ---[ end Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: __do_sys_newfstatat+0xb8/0xb8 ]--- That is because the kprobe's ebreak instruction broke the kernel's original code. The user should guarantee the correction of the probe position, but it couldn't make the kernel panic. This patch adds arch_check_kprobe in arch_prepare_kprobe to prevent an illegal position (Such as the middle of an instruction). Fixes: c22b0bcb1dd0 ("riscv: Add kprobes supported") Signed-off-by: Guo Ren Signed-off-by: Guo Ren --- arch/riscv/kernel/probes/kprobes.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/riscv/kernel/probes/kprobes.c b/arch/riscv/kernel/probes/kprobes.c index f21592d20306..475989f06d6d 100644 --- a/arch/riscv/kernel/probes/kprobes.c +++ b/arch/riscv/kernel/probes/kprobes.c @@ -48,6 +48,21 @@ static void __kprobes arch_simulate_insn(struct kprobe *p, struct pt_regs *regs) post_kprobe_handler(p, kcb, regs); } +static bool __kprobes arch_check_kprobe(struct kprobe *p) +{ + unsigned long tmp = (unsigned long)p->addr - p->offset; + unsigned long addr = (unsigned long)p->addr; + + while (tmp <= addr) { + if (tmp == addr) + return true; + + tmp += GET_INSN_LENGTH(*(kprobe_opcode_t *)tmp); + } + + return false; +} + int __kprobes arch_prepare_kprobe(struct kprobe *p) { unsigned long probe_addr = (unsigned long)p->addr; @@ -55,6 +70,9 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) if (probe_addr & 0x1) return -EILSEQ; + if (!arch_check_kprobe(p)) + return -EILSEQ; + /* copy instruction */ p->opcode = *p->addr; -- 2.36.1