From patchwork Fri Apr 16 08:27:31 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Liao, Chang" X-Patchwork-Id: 12207181 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER, INCLUDES_PATCH,MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7683CC433ED for ; Fri, 16 Apr 2021 08:59:30 +0000 (UTC) Received: from desiato.infradead.org (desiato.infradead.org [90.155.92.199]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D704261153 for ; Fri, 16 Apr 2021 08:59:29 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D704261153 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=huawei.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-riscv-bounces+linux-riscv=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=desiato.20200630; h=Sender:Content-Transfer-Encoding :Content-Type:List-Subscribe:List-Help:List-Post:List-Archive: List-Unsubscribe:List-Id:MIME-Version:Message-ID:Date:Subject:CC:To:From: Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender :Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References:List-Owner; bh=FFiUWZY+gM/Hs9dIXvEMTPa4cs2JJ0mDl9zG4Tk6cvU=; b=Dn8xJl65ZNiUlZl1aAAHkHPedT rcsStsWuXbnA53uIZS2s18Y/6o2nSr+cArWk2KvXw+WmS6fwPlJcWiXszMGFdlqmYOSITE8EkNCtQ HgYED0ML8SPbzYdVEnZyAcsHEbeGYRI3+36YrLjqHUgy0FhsXMi//vXZwjgs5qT7ow8n4IKbM8C2D EbO/8Lq5TPMf771G5SgQpqBEsy7zZ3/AuhMNO8Iwh8buHfX3fH70XR4RB3t9A/mGXVjx8VHGBoAz6 D//yo1L3WEosnoyyIRwQDTy7Zo28jFSUTd1pDrGpr+nfdYpi3gnw+ECn+lVNSk3s2o0BAzHw1WF5V kHSQpEPg==; Received: from localhost ([::1] helo=desiato.infradead.org) by desiato.infradead.org with esmtp (Exim 4.94 #2 (Red Hat Linux)) id 1lXKJl-001Se3-HF; Fri, 16 Apr 2021 08:59:13 +0000 Received: from bombadil.infradead.org ([2607:7c80:54:e::133]) by desiato.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1lXJpG-001LMU-AP for linux-riscv@desiato.infradead.org; Fri, 16 Apr 2021 08:27:45 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20210309; h=Content-Type:MIME-Version:Message-ID: Date:Subject:CC:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID: Content-Description:In-Reply-To:References; bh=G+k0LvztAmWD/ih1Ia3fz1p9KlB1lgMKQT/GFIdmSR8=; b=o2Op9K0cHJcQ8quWzizpkaQP3E 7RneLXc8d0piCaVaaST6UZ/mB3rBKJ8GKiEC4HaqLkqTC9PVyqPV+I/6Ry+q2aAgUGaDbpiNLSACw NZVlYcnIU9wF4El0skrJOdvLL0dbKm7EjVkdyovgX46HGle2kWvQ5xjUeQOrsbJYb+oYrVLs752ol KWNl1k6KZaMsCYuk0+FXbb2XDAWGlCfZImqU8aeW4ZRwC6ubZUXOYQ/cvUsqmNb08bg2j9HLenYdZ aROw0wBt3KkLDy0SsSdIPPPqeziAaiojUMUWrYOPITcJYTitYbROhx9HZ1zHMwqxSJ8tqjDn1QEwL xthX29BQ==; Received: from szxga06-in.huawei.com ([45.249.212.32]) by bombadil.infradead.org with esmtps (Exim 4.94 #2 (Red Hat Linux)) id 1lXJpC-009Bwx-TU for linux-riscv@lists.infradead.org; Fri, 16 Apr 2021 08:27:40 +0000 Received: from DGGEMS411-HUB.china.huawei.com (unknown [172.30.72.59]) by szxga06-in.huawei.com (SkyGuard) with ESMTP id 4FM8RM2QhBzlYDD; Fri, 16 Apr 2021 16:25:35 +0800 (CST) Received: from huawei.com (10.67.174.53) by DGGEMS411-HUB.china.huawei.com (10.3.19.211) with Microsoft SMTP Server id 14.3.498.0; Fri, 16 Apr 2021 16:27:21 +0800 From: Liao Chang To: , , , , , , , , , CC: , , Subject: [PATCH v2] riscv/kprobe: Restore local irqflag if kprobe is cancelled Date: Fri, 16 Apr 2021 16:27:31 +0800 Message-ID: <20210416082731.121494-1-liaochang1@huawei.com> X-Mailer: git-send-email 2.17.1 MIME-Version: 1.0 X-Originating-IP: [10.67.174.53] X-CFilter-Loop: Reflected X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20210416_012739_287670_FF47EB6D X-CRM114-Status: GOOD ( 11.95 ) X-BeenThere: linux-riscv@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-riscv" Errors-To: linux-riscv-bounces+linux-riscv=archiver.kernel.org@lists.infradead.org The execution of sys_read end up hitting a BUG_ON() in __find_get_block after installing probe at sys_read via kprobe, the BUG message like the following: [ 65.708663] ------------[ cut here ]------------ [ 65.709987] kernel BUG at fs/buffer.c:1251! [ 65.711283] Kernel BUG [#1] [ 65.712032] Modules linked in: [ 65.712925] CPU: 0 PID: 51 Comm: sh Not tainted 5.12.0-rc4 #1 [ 65.714407] Hardware name: riscv-virtio,qemu (DT) [ 65.715696] epc : __find_get_block+0x218/0x2c8 [ 65.716835] ra : __getblk_gfp+0x1c/0x4a [ 65.717831] epc : ffffffe00019f11e ra : ffffffe00019f56a sp : ffffffe002437930 [ 65.719553] gp : ffffffe000f06030 tp : ffffffe0015abc00 t0 : ffffffe00191e038 [ 65.721290] t1 : ffffffe00191e038 t2 : 000000000000000a s0 : ffffffe002437960 [ 65.723051] s1 : ffffffe00160ad00 a0 : ffffffe00160ad00 a1 : 000000000000012a [ 65.724772] a2 : 0000000000000400 a3 : 0000000000000008 a4 : 0000000000000040 [ 65.726545] a5 : 0000000000000000 a6 : ffffffe00191e000 a7 : 0000000000000000 [ 65.728308] s2 : 000000000000012a s3 : 0000000000000400 s4 : 0000000000000008 [ 65.730049] s5 : 000000000000006c s6 : ffffffe00240f800 s7 : ffffffe000f080a8 [ 65.731802] s8 : 0000000000000001 s9 : 000000000000012a s10: 0000000000000008 [ 65.733516] s11: 0000000000000008 t3 : 00000000000003ff t4 : 000000000000000f [ 65.734434] t5 : 00000000000003ff t6 : 0000000000040000 [ 65.734613] status: 0000000000000100 badaddr: 0000000000000000 cause: 0000000000000003 [ 65.734901] Call Trace: [ 65.735076] [] __find_get_block+0x218/0x2c8 [ 65.735417] [] __ext4_get_inode_loc+0xb2/0x2f6 [ 65.735618] [] ext4_get_inode_loc+0x3a/0x8a [ 65.735802] [] ext4_reserve_inode_write+0x2e/0x8c [ 65.735999] [] __ext4_mark_inode_dirty+0x4c/0x18e [ 65.736208] [] ext4_dirty_inode+0x46/0x66 [ 65.736387] [] __mark_inode_dirty+0x12c/0x3da [ 65.736576] [] touch_atime+0x146/0x150 [ 65.736748] [] filemap_read+0x234/0x246 [ 65.736920] [] generic_file_read_iter+0xc0/0x114 [ 65.737114] [] ext4_file_read_iter+0x42/0xea [ 65.737310] [] new_sync_read+0xe2/0x15a [ 65.737483] [] vfs_read+0xca/0xf2 [ 65.737641] [] ksys_read+0x5e/0xc8 [ 65.737816] [] sys_read+0xe/0x16 [ 65.737973] [] ret_from_syscall+0x0/0x2 [ 65.738858] ---[ end trace fe93f985456c935d ]--- A simple reproducer looks like: echo 'p:myprobe sys_read fd=%a0 buf=%a1 count=%a2' > /sys/kernel/debug/tracing/kprobe_events echo 1 > /sys/kernel/debug/tracing/events/kprobes/myprobe/enable cat trace Here's what happens to hit that BUG_ON(): If instruction being single stepped caused page fault, the kprobe is cancelled to let the page fault handler continues as normal page fault. But the local irqflags are disabled, so CPU will restore 'sstatus' with 'SIE' masked. After page fault is serviced, the kprobe is triggered again, we overwrite the saved irqflag by calling kprobe_save_local_irqflag(). Note, 'SIE' is masked in this new saved irqflag. After kprobe is serviced, the CPU 'sstatus' is restored with 'SIE' masked. This overwritten 'sstatus' cause BUG_ON() in __find_get_block. This bug is already fixed on arm64 by Jisheng Zhang. Fixes: c22b0bcb1dd02 ("riscv: Add kprobes supported") Signed-off-by: Liao Chang Reviewed-by: Masami Hiramatsu --- Changes in v2: - Reorganize commit message. 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 7e2c78e2ca6b..d71f7c49a721 100644 --- a/arch/riscv/kernel/probes/kprobes.c +++ b/arch/riscv/kernel/probes/kprobes.c @@ -260,8 +260,10 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int trapnr) if (kcb->kprobe_status == KPROBE_REENTER) restore_previous_kprobe(kcb); - else + else { + kprobes_restore_local_irqflag(kcb, regs); reset_current_kprobe(); + } break; case KPROBE_HIT_ACTIVE: