Received: by 2002:a05:6a10:17d3:0:0:0:0 with SMTP id hz19csp2546265pxb; Mon, 19 Apr 2021 08:09:21 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyfcHLfOSKdB4NsMsTCtbzdUCicbPoRU8Rsc7u27x9lFkALKq608lLxV6wj6EQ72RUX7a+N X-Received: by 2002:a17:902:bb94:b029:eb:7a3e:1fe with SMTP id m20-20020a170902bb94b02900eb7a3e01femr22263247pls.25.1618844961579; Mon, 19 Apr 2021 08:09:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1618844961; cv=none; d=google.com; s=arc-20160816; b=uegk/jYWcwiHcyfqEEkufctRqTk/7onuVB6X++iq9YOaEM+wC+51eLrWgkskZU8KNR +Iz3IXQHommDNPUuwKwe3xiAO35z6WaSqFanfWC+lcuKIZWLCeD4Zt+4jD0xURwmn1NY /w+lZDlIC5DXaAacQ73WJNGMr1rCyCHzLM2l8YmGazeY79Hi+zXOvmqA7gt7G7yE6cvi M38zV5x2isD/1CZOKxMQs9ObWbnHROVsocPqE3ers0iMsXijU8b5R4pWTAfNW2xhLzuj qmGXPuNTCY/ZAPL6zzQW9dHbsb2C6btYqrhPwJnqfZsdhvTBhbTUs/cIuE7ph2g1hATl cmbg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=MZug95AxlDlBZKeQLMaqJvPetYETXmgLr77AeeKVkkw=; b=UJoRJNOUDM1UbdBO6qaIM/w6BQY44xXt0nBEQzvZ1NdACh906jAUijUergtZ2I9Dyg n12GULg3FmJDTHH+fj8UnPThJ83MtHRY+PeRUEvw7UdtYyjKFonwOHs8SsSpCJnHWV8u FA7teyQhffO5DtmBgIunGMnbAD+N6IB3mp/Vy5goDGZtUFeBJtJM0Rim75P+mB8jMLqS BIya8hKmRFvjRRhxHxws+OY9HieUo7gEcY1ePdiSBECOi0NA4O9SkB+0hTaMf0SyQhTc A/NzdkBvTH4l/mQnMORJgPSQPNaHMbAj3Z3Ll9vh6xGxPO9nbCnD3291ERVXjEfF1uwt TSwg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=tHdYh+kw; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id 144si18343387pfc.264.2021.04.19.08.09.09; Mon, 19 Apr 2021 08:09:21 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=tHdYh+kw; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240090AbhDSNMd (ORCPT + 99 others); Mon, 19 Apr 2021 09:12:33 -0400 Received: from mail.kernel.org ([198.145.29.99]:46552 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239588AbhDSNKt (ORCPT ); Mon, 19 Apr 2021 09:10:49 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id EAC9C61279; Mon, 19 Apr 2021 13:10:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1618837819; bh=rkm6X9OKesAxMZd4NC2/70SbIw1V88Qvylcs74rdNc0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=tHdYh+kwhCDSxu3TzZDx8qV332ylT+C+GusPKWMkhRGg+l/PYYdheL0AyCClT//aU fgOXRNDSI49SEgoMTZ5/ZAnNMFXlQqFxrRMBS8IXYxqj2kE7Hd991ouKWEarLCcFIn ZL4XoEXcPiVWiaU/EbT0XpGUOeLODYqVqBe9uzmg= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Christophe Leroy , Michael Ellerman , Sasha Levin Subject: [PATCH 5.11 030/122] powerpc/signal32: Fix Oops on sigreturn with unmapped VDSO Date: Mon, 19 Apr 2021 15:05:10 +0200 Message-Id: <20210419130531.186925937@linuxfoundation.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210419130530.166331793@linuxfoundation.org> References: <20210419130530.166331793@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Christophe Leroy [ Upstream commit acca57217c688c5bbbd5140974533d81e8757cc9 ] PPC32 encounters a KUAP fault when trying to handle a signal with VDSO unmapped. Kernel attempted to read user page (7fc07ec0) - exploit attempt? (uid: 0) BUG: Unable to handle kernel data access on read at 0x7fc07ec0 Faulting instruction address: 0xc00111d4 Oops: Kernel access of bad area, sig: 11 [#1] BE PAGE_SIZE=16K PREEMPT CMPC885 CPU: 0 PID: 353 Comm: sigreturn_vdso Not tainted 5.12.0-rc4-s3k-dev-01553-gb30c310ea220 #4814 NIP: c00111d4 LR: c0005a28 CTR: 00000000 REGS: cadb3dd0 TRAP: 0300 Not tainted (5.12.0-rc4-s3k-dev-01553-gb30c310ea220) MSR: 00009032 CR: 48000884 XER: 20000000 DAR: 7fc07ec0 DSISR: 88000000 GPR00: c0007788 cadb3e90 c28d4a40 7fc07ec0 7fc07ed0 000004e0 7fc07ce0 00000000 GPR08: 00000001 00000001 7fc07ec0 00000000 28000282 1001b828 100a0920 00000000 GPR16: 100cac0c 100b0000 105c43a4 105c5685 100d0000 100d0000 100d0000 100b2e9e GPR24: ffffffff 105c43c8 00000000 7fc07ec8 cadb3f40 cadb3ec8 c28d4a40 00000000 NIP [c00111d4] flush_icache_range+0x90/0xb4 LR [c0005a28] handle_signal32+0x1bc/0x1c4 Call Trace: [cadb3e90] [100d0000] 0x100d0000 (unreliable) [cadb3ec0] [c0007788] do_notify_resume+0x260/0x314 [cadb3f20] [c000c764] syscall_exit_prepare+0x120/0x184 [cadb3f30] [c00100b4] ret_from_syscall+0xc/0x28 --- interrupt: c00 at 0xfe807f8 NIP: 0fe807f8 LR: 10001060 CTR: c0139378 REGS: cadb3f40 TRAP: 0c00 Not tainted (5.12.0-rc4-s3k-dev-01553-gb30c310ea220) MSR: 0000d032 CR: 28000482 XER: 20000000 GPR00: 00000025 7fc081c0 77bb1690 00000000 0000000a 28000482 00000001 0ff03a38 GPR08: 0000d032 00006de5 c28d4a40 00000009 88000482 1001b828 100a0920 00000000 GPR16: 100cac0c 100b0000 105c43a4 105c5685 100d0000 100d0000 100d0000 100b2e9e GPR24: ffffffff 105c43c8 00000000 77ba7628 10002398 10010000 10002124 00024000 NIP [0fe807f8] 0xfe807f8 LR [10001060] 0x10001060 --- interrupt: c00 Instruction dump: 38630010 7c001fac 38630010 4200fff0 7c0004ac 4c00012c 4e800020 7c001fac 2c0a0000 38630010 4082ffcc 4bffffe4 <7c00186c> 2c070000 39430010 4082ff8c ---[ end trace 3973fb72b049cb06 ]--- This is because flush_icache_range() is called on user addresses. The same problem was detected some time ago on PPC64. It was fixed by enabling KUAP in commit 59bee45b9712 ("powerpc/mm: Fix missing KUAP disable in flush_coherent_icache()"). PPC32 doesn't use flush_coherent_icache() and fallbacks on clean_dcache_range() and invalidate_icache_range(). We could fix it similarly by enabling user access in those functions, but this is overkill for just flushing two instructions. The two instructions are 8 bytes aligned, so a single dcbst/icbi is enough to flush them. Do like __patch_instruction() and inline a dcbst followed by an icbi just after the write of the instructions, while user access is still allowed. The isync is not required because rfi will be used to return to user. icbi() is handled as a read so read-write user access is needed. Signed-off-by: Christophe Leroy Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/bde9154e5351a5ac7bca3d59cdb5a5e8edacbb79.1617199569.git.christophe.leroy@csgroup.eu Signed-off-by: Sasha Levin --- arch/powerpc/kernel/signal_32.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 934cbdf6dd10..30eddc69c9cf 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -775,7 +775,7 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset, else prepare_save_user_regs(1); - if (!user_write_access_begin(frame, sizeof(*frame))) + if (!user_access_begin(frame, sizeof(*frame))) goto badframe; /* Put the siginfo & fill in most of the ucontext */ @@ -809,17 +809,15 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset, unsafe_put_user(PPC_INST_ADDI + __NR_rt_sigreturn, &mctx->mc_pad[0], failed); unsafe_put_user(PPC_INST_SC, &mctx->mc_pad[1], failed); + asm("dcbst %y0; sync; icbi %y0; sync" :: "Z" (mctx->mc_pad[0])); } unsafe_put_sigset_t(&frame->uc.uc_sigmask, oldset, failed); - user_write_access_end(); + user_access_end(); if (copy_siginfo_to_user(&frame->info, &ksig->info)) goto badframe; - if (tramp == (unsigned long)mctx->mc_pad) - flush_icache_range(tramp, tramp + 2 * sizeof(unsigned long)); - regs->link = tramp; #ifdef CONFIG_PPC_FPU_REGS @@ -844,7 +842,7 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset, return 0; failed: - user_write_access_end(); + user_access_end(); badframe: signal_fault(tsk, regs, "handle_rt_signal32", frame); @@ -879,7 +877,7 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset, else prepare_save_user_regs(1); - if (!user_write_access_begin(frame, sizeof(*frame))) + if (!user_access_begin(frame, sizeof(*frame))) goto badframe; sc = (struct sigcontext __user *) &frame->sctx; @@ -908,11 +906,9 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset, /* Set up the sigreturn trampoline: li r0,sigret; sc */ unsafe_put_user(PPC_INST_ADDI + __NR_sigreturn, &mctx->mc_pad[0], failed); unsafe_put_user(PPC_INST_SC, &mctx->mc_pad[1], failed); + asm("dcbst %y0; sync; icbi %y0; sync" :: "Z" (mctx->mc_pad[0])); } - user_write_access_end(); - - if (tramp == (unsigned long)mctx->mc_pad) - flush_icache_range(tramp, tramp + 2 * sizeof(unsigned long)); + user_access_end(); regs->link = tramp; @@ -934,7 +930,7 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset, return 0; failed: - user_write_access_end(); + user_access_end(); badframe: signal_fault(tsk, regs, "handle_signal32", frame); -- 2.30.2