From mboxrd@z Thu Jan 1 00:00:00 1970 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 0D70EC636CD for ; Tue, 7 Feb 2023 13:14:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232463AbjBGNOJ (ORCPT ); Tue, 7 Feb 2023 08:14:09 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59910 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232291AbjBGNNy (ORCPT ); Tue, 7 Feb 2023 08:13:54 -0500 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2389A15CAD for ; Tue, 7 Feb 2023 05:13:27 -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 2887561426 for ; Tue, 7 Feb 2023 13:12:36 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 18E34C433D2; Tue, 7 Feb 2023 13:12:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1675775555; bh=jF588OS06EZ7OVCKPKqSccccj8by1biw3niYMnBPBlg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=K8GxE+YbxqZXRtUVHS0MdiH6sp6u5i8aAy+7+kD85AJn2eKBJllwj215CXvyc/DBa oU0iFu90hixR5Y9IFufET7J/uFSoEoquKRWEh140XfA7J/UhnTNj88e9C2RLw1ocvG LnO2IaFDqnhxlZhVw+LT+kC2RblUD3B3+rEaTVlI= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Guo Ren , Guo Ren , =?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= , Palmer Dabbelt , Sasha Levin Subject: [PATCH 5.15 040/120] riscv: kprobe: Fixup kernel panic when probing an illegal position Date: Tue, 7 Feb 2023 13:56:51 +0100 Message-Id: <20230207125620.481819449@linuxfoundation.org> X-Mailer: git-send-email 2.39.1 In-Reply-To: <20230207125618.699726054@linuxfoundation.org> References: <20230207125618.699726054@linuxfoundation.org> User-Agent: quilt/0.67 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Guo Ren [ Upstream commit 87f48c7ccc73afc78630530d9af51f458f58cab8 ] 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 Reviewed-by: Björn Töpel Link: https://lore.kernel.org/r/20230201040604.3390509-1-guoren@kernel.org Signed-off-by: Palmer Dabbelt Signed-off-by: Sasha Levin --- 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 00088dc6da4b..125241ce82d6 100644 --- a/arch/riscv/kernel/probes/kprobes.c +++ b/arch/riscv/kernel/probes/kprobes.c @@ -46,6 +46,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(*(u16 *)tmp); + } + + return false; +} + int __kprobes arch_prepare_kprobe(struct kprobe *p) { unsigned long probe_addr = (unsigned long)p->addr; @@ -56,6 +71,9 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p) return -EINVAL; } + if (!arch_check_kprobe(p)) + return -EILSEQ; + /* copy instruction */ p->opcode = *p->addr; -- 2.39.0