From patchwork Thu Jun 4 13:33:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Zyngier X-Patchwork-Id: 11587961 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id BC276739 for ; Thu, 4 Jun 2020 13:34:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A0E9220772 for ; Thu, 4 Jun 2020 13:34:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1591277648; bh=oTpdh0V2Z95uY3LBT8s4QiNnX2wWztmbveBiUjivoGs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=X0mGr0U9aURgMUJBkqpRckti2Wa3MeHfvdCKtNnGfN9OHW8rC89UmvK4fA06x7Wu3 TCbZP6OsI5inMN2gLwk6W8qTjYlIN+aklNmHbe/f1/CSsV+srD29FPFKuSPEu6018z Szw9yUw63nvgK1fmUSaZLCBhy//dBesLX3Z0x0jA= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728639AbgFDNeH (ORCPT ); Thu, 4 Jun 2020 09:34:07 -0400 Received: from mail.kernel.org ([198.145.29.99]:36190 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728617AbgFDNeG (ORCPT ); Thu, 4 Jun 2020 09:34:06 -0400 Received: from disco-boy.misterjones.org (disco-boy.misterjones.org [51.254.78.96]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id B0BDC207F5; Thu, 4 Jun 2020 13:34:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1591277645; bh=oTpdh0V2Z95uY3LBT8s4QiNnX2wWztmbveBiUjivoGs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YR6CZ4InhWsUIB0fnTVAgtFWHZM0Q9V817LIfrnpJkEIN3cbTWbaHSqpkaGScFNAF dKit3INlFzUfog/sqPThe1V17GKxiCOkAU+HJ0Mj9RSzznP/Zn8zAOQKvR/mHDmhIa 6qEZ+dO3rA3gYktLJj6oAvywWHIrYTn7S/Cnk4OM= Received: from 78.163-31-62.static.virginmediabusiness.co.uk ([62.31.163.78] helo=why.lan) by disco-boy.misterjones.org with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jgq0S-000G3O-6u; Thu, 04 Jun 2020 14:34:04 +0100 From: Marc Zyngier To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org Cc: James Morse , Julien Thierry , Suzuki K Poulose , Will Deacon , Catalin Marinas , Mark Rutland , kernel-team@android.com, stable@vger.kernel.org Subject: [PATCH 1/3] KVM: arm64: Save the host's PtrAuth keys in non-preemptible context Date: Thu, 4 Jun 2020 14:33:52 +0100 Message-Id: <20200604133354.1279412-2-maz@kernel.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200604133354.1279412-1-maz@kernel.org> References: <20200604133354.1279412-1-maz@kernel.org> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 62.31.163.78 X-SA-Exim-Rcpt-To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, james.morse@arm.com, julien.thierry.kdev@gmail.com, suzuki.poulose@arm.com, will@kernel.org, catalin.marinas@arm.com, mark.rutland@arm.com, kernel-team@android.com, stable@vger.kernel.org X-SA-Exim-Mail-From: maz@kernel.org X-SA-Exim-Scanned: No (on disco-boy.misterjones.org); SAEximRunCond expanded to false Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org When using the PtrAuth feature in a guest, we need to save the host's keys before allowing the guest to program them. For that, we dump them in a per-CPU data structure (the so called host context). But both call sites that do this are in preemptible context, which may end up in disaster should the vcpu thread get preempted before reentering the guest. Instead, save the keys eagerly on each vcpu_load(). This has an increased overhead, but is at least safe. Cc: stable@vger.kernel.org Signed-off-by: Marc Zyngier Reviewed-by: Mark Rutland --- arch/arm64/include/asm/kvm_emulate.h | 6 ------ arch/arm64/kvm/arm.c | 18 +++++++++++++++++- arch/arm64/kvm/handle_exit.c | 19 ++----------------- 3 files changed, 19 insertions(+), 24 deletions(-) diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index a30b4eec7cb4..977843e4d5fb 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -112,12 +112,6 @@ static inline void vcpu_ptrauth_disable(struct kvm_vcpu *vcpu) vcpu->arch.hcr_el2 &= ~(HCR_API | HCR_APK); } -static inline void vcpu_ptrauth_setup_lazy(struct kvm_vcpu *vcpu) -{ - if (vcpu_has_ptrauth(vcpu)) - vcpu_ptrauth_disable(vcpu); -} - static inline unsigned long vcpu_get_vsesr(struct kvm_vcpu *vcpu) { return vcpu->arch.vsesr_el2; diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index d6988401c22a..152049c5055d 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -337,6 +337,12 @@ void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu) preempt_enable(); } +#define __ptrauth_save_key(regs, key) \ +({ \ + regs[key ## KEYLO_EL1] = read_sysreg_s(SYS_ ## key ## KEYLO_EL1); \ + regs[key ## KEYHI_EL1] = read_sysreg_s(SYS_ ## key ## KEYHI_EL1); \ +}) + void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) { int *last_ran; @@ -370,7 +376,17 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) else vcpu_set_wfx_traps(vcpu); - vcpu_ptrauth_setup_lazy(vcpu); + if (vcpu_has_ptrauth(vcpu)) { + struct kvm_cpu_context *ctxt = vcpu->arch.host_cpu_context; + + __ptrauth_save_key(ctxt->sys_regs, APIA); + __ptrauth_save_key(ctxt->sys_regs, APIB); + __ptrauth_save_key(ctxt->sys_regs, APDA); + __ptrauth_save_key(ctxt->sys_regs, APDB); + __ptrauth_save_key(ctxt->sys_regs, APGA); + + vcpu_ptrauth_disable(vcpu); + } } void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c index eb194696ef62..065251efa2e6 100644 --- a/arch/arm64/kvm/handle_exit.c +++ b/arch/arm64/kvm/handle_exit.c @@ -162,31 +162,16 @@ static int handle_sve(struct kvm_vcpu *vcpu, struct kvm_run *run) return 1; } -#define __ptrauth_save_key(regs, key) \ -({ \ - regs[key ## KEYLO_EL1] = read_sysreg_s(SYS_ ## key ## KEYLO_EL1); \ - regs[key ## KEYHI_EL1] = read_sysreg_s(SYS_ ## key ## KEYHI_EL1); \ -}) - /* * Handle the guest trying to use a ptrauth instruction, or trying to access a * ptrauth register. */ void kvm_arm_vcpu_ptrauth_trap(struct kvm_vcpu *vcpu) { - struct kvm_cpu_context *ctxt; - - if (vcpu_has_ptrauth(vcpu)) { + if (vcpu_has_ptrauth(vcpu)) vcpu_ptrauth_enable(vcpu); - ctxt = vcpu->arch.host_cpu_context; - __ptrauth_save_key(ctxt->sys_regs, APIA); - __ptrauth_save_key(ctxt->sys_regs, APIB); - __ptrauth_save_key(ctxt->sys_regs, APDA); - __ptrauth_save_key(ctxt->sys_regs, APDB); - __ptrauth_save_key(ctxt->sys_regs, APGA); - } else { + else kvm_inject_undefined(vcpu); - } } /* From patchwork Thu Jun 4 13:33:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Zyngier X-Patchwork-Id: 11587965 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 649B2159A for ; Thu, 4 Jun 2020 13:34:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 489112086A for ; Thu, 4 Jun 2020 13:34:10 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1591277650; bh=+JJdpvErLuCFaTF3oWAo65vqniAHR2Y2NhleefKGwlg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=A5xAV2ey2zKIDP/xqpKid8Tansz12GUB4277nFPedke8ADHV3nU9ujLzlqXBvQFn0 xkiRmHyEYY5L0xYaqJdHx0+4mtwG9+G4v3Zy1g9n1FUBXsqh0AurxZ/BcZFNyAETMm fhOGTOs9Ga2p1zA+ON7ZI4sF2OMJLUhgQGO9/bNY= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728641AbgFDNeI (ORCPT ); Thu, 4 Jun 2020 09:34:08 -0400 Received: from mail.kernel.org ([198.145.29.99]:36222 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728550AbgFDNeH (ORCPT ); Thu, 4 Jun 2020 09:34:07 -0400 Received: from disco-boy.misterjones.org (disco-boy.misterjones.org [51.254.78.96]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 50046207F7; Thu, 4 Jun 2020 13:34:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1591277646; bh=+JJdpvErLuCFaTF3oWAo65vqniAHR2Y2NhleefKGwlg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=D2uRxr4VvsE1XYjqmMGJkaeIrFJIVc+7vzDhv6o8kVTo/9/hxflS/PDotccGOULDK D+zTuc2Y/SvdrGJ645ej+ygX6FcxrT64XjrWB4hu/WEHFRwXcnUfU31cNyi1l8EU93 PkRpu2KaehZwQGKtV1QtXXjxAJzetu0PBXk1ocFo= Received: from 78.163-31-62.static.virginmediabusiness.co.uk ([62.31.163.78] helo=why.lan) by disco-boy.misterjones.org with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jgq0S-000G3O-SU; Thu, 04 Jun 2020 14:34:05 +0100 From: Marc Zyngier To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org Cc: James Morse , Julien Thierry , Suzuki K Poulose , Will Deacon , Catalin Marinas , Mark Rutland , kernel-team@android.com Subject: [PATCH 2/3] KVM: arm64: Handle PtrAuth traps early Date: Thu, 4 Jun 2020 14:33:53 +0100 Message-Id: <20200604133354.1279412-3-maz@kernel.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200604133354.1279412-1-maz@kernel.org> References: <20200604133354.1279412-1-maz@kernel.org> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 62.31.163.78 X-SA-Exim-Rcpt-To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, james.morse@arm.com, julien.thierry.kdev@gmail.com, suzuki.poulose@arm.com, will@kernel.org, catalin.marinas@arm.com, mark.rutland@arm.com, kernel-team@android.com X-SA-Exim-Mail-From: maz@kernel.org X-SA-Exim-Scanned: No (on disco-boy.misterjones.org); SAEximRunCond expanded to false Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org The current way we deal with PtrAuth is a bit heavy handed: - We forcefully save the host's keys on each vcpu_load() - Handling the PtrAuth trap forces us to go all the way back to the exit handling code to just set the HCR bits Overall, this is pretty heavy handed. A better approach would be to handle it the same way we deal with the FPSIMD registers: - On vcpu_load() disable PtrAuth for the guest - On first use, save the host's keys, enable PtrAuth in the guest Crutially, this can happen as a fixup, which is done very early on exit. We can then reenter the guest immediately without leaving the hypervisor role. Another thing is that it simplify the rest of the host handling: exiting all the way to the host means that the only possible outcome for this trap is to inject an UNDEF. Signed-off-by: Marc Zyngier Reviewed-by: Mark Rutland --- arch/arm64/kvm/arm.c | 17 +---------- arch/arm64/kvm/handle_exit.c | 17 ++--------- arch/arm64/kvm/hyp/switch.c | 59 ++++++++++++++++++++++++++++++++++++ arch/arm64/kvm/sys_regs.c | 13 +++----- 4 files changed, 68 insertions(+), 38 deletions(-) diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c index 152049c5055d..14b747266607 100644 --- a/arch/arm64/kvm/arm.c +++ b/arch/arm64/kvm/arm.c @@ -337,12 +337,6 @@ void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu) preempt_enable(); } -#define __ptrauth_save_key(regs, key) \ -({ \ - regs[key ## KEYLO_EL1] = read_sysreg_s(SYS_ ## key ## KEYLO_EL1); \ - regs[key ## KEYHI_EL1] = read_sysreg_s(SYS_ ## key ## KEYHI_EL1); \ -}) - void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) { int *last_ran; @@ -376,17 +370,8 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) else vcpu_set_wfx_traps(vcpu); - if (vcpu_has_ptrauth(vcpu)) { - struct kvm_cpu_context *ctxt = vcpu->arch.host_cpu_context; - - __ptrauth_save_key(ctxt->sys_regs, APIA); - __ptrauth_save_key(ctxt->sys_regs, APIB); - __ptrauth_save_key(ctxt->sys_regs, APDA); - __ptrauth_save_key(ctxt->sys_regs, APDB); - __ptrauth_save_key(ctxt->sys_regs, APGA); - + if (vcpu_has_ptrauth(vcpu)) vcpu_ptrauth_disable(vcpu); - } } void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c index 065251efa2e6..5a02d4c90559 100644 --- a/arch/arm64/kvm/handle_exit.c +++ b/arch/arm64/kvm/handle_exit.c @@ -162,25 +162,14 @@ static int handle_sve(struct kvm_vcpu *vcpu, struct kvm_run *run) return 1; } -/* - * Handle the guest trying to use a ptrauth instruction, or trying to access a - * ptrauth register. - */ -void kvm_arm_vcpu_ptrauth_trap(struct kvm_vcpu *vcpu) -{ - if (vcpu_has_ptrauth(vcpu)) - vcpu_ptrauth_enable(vcpu); - else - kvm_inject_undefined(vcpu); -} - /* * Guest usage of a ptrauth instruction (which the guest EL1 did not turn into - * a NOP). + * a NOP). If we get here, it is that we didn't fixup ptrauth on exit, and all + * that we can do is give the guest an UNDEF. */ static int kvm_handle_ptrauth(struct kvm_vcpu *vcpu, struct kvm_run *run) { - kvm_arm_vcpu_ptrauth_trap(vcpu); + kvm_inject_undefined(vcpu); return 1; } diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c index c07a45643cd4..2a50b3771c3b 100644 --- a/arch/arm64/kvm/hyp/switch.c +++ b/arch/arm64/kvm/hyp/switch.c @@ -490,6 +490,62 @@ static bool __hyp_text handle_tx2_tvm(struct kvm_vcpu *vcpu) return true; } +#define __ptrauth_save_key(regs, key) \ +({ \ + regs[key ## KEYLO_EL1] = read_sysreg_s(SYS_ ## key ## KEYLO_EL1); \ + regs[key ## KEYHI_EL1] = read_sysreg_s(SYS_ ## key ## KEYHI_EL1); \ +}) + +static bool __hyp_text __hyp_handle_ptrauth(struct kvm_vcpu *vcpu) +{ + u32 sysreg = esr_sys64_to_sysreg(kvm_vcpu_get_hsr(vcpu)); + u32 ec = kvm_vcpu_trap_get_class(vcpu); + struct kvm_cpu_context *ctxt; + u64 val; + + if (!vcpu_has_ptrauth(vcpu)) + return false; + + switch (ec) { + case ESR_ELx_EC_PAC: + break; + case ESR_ELx_EC_SYS64: + switch (sysreg) { + case SYS_APIAKEYLO_EL1: + case SYS_APIAKEYHI_EL1: + case SYS_APIBKEYLO_EL1: + case SYS_APIBKEYHI_EL1: + case SYS_APDAKEYLO_EL1: + case SYS_APDAKEYHI_EL1: + case SYS_APDBKEYLO_EL1: + case SYS_APDBKEYHI_EL1: + case SYS_APGAKEYLO_EL1: + case SYS_APGAKEYHI_EL1: + break; + default: + return false; + } + break; + default: + return false; + } + + ctxt = kern_hyp_va(vcpu->arch.host_cpu_context); + __ptrauth_save_key(ctxt->sys_regs, APIA); + __ptrauth_save_key(ctxt->sys_regs, APIB); + __ptrauth_save_key(ctxt->sys_regs, APDA); + __ptrauth_save_key(ctxt->sys_regs, APDB); + __ptrauth_save_key(ctxt->sys_regs, APGA); + + vcpu_ptrauth_enable(vcpu); + + val = read_sysreg(hcr_el2); + val |= (HCR_API | HCR_APK); + write_sysreg(val, hcr_el2); + + return true; +} + /* * Return true when we were able to fixup the guest exit and should return to * the guest, false when we should restore the host state and return to the @@ -524,6 +580,9 @@ static bool __hyp_text fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code) if (__hyp_handle_fpsimd(vcpu)) return true; + if (__hyp_handle_ptrauth(vcpu)) + return true; + if (!__populate_fault_info(vcpu)) return true; diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index ad1d57501d6d..564995084cf8 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -1034,16 +1034,13 @@ static bool trap_ptrauth(struct kvm_vcpu *vcpu, struct sys_reg_params *p, const struct sys_reg_desc *rd) { - kvm_arm_vcpu_ptrauth_trap(vcpu); - /* - * Return false for both cases as we never skip the trapped - * instruction: - * - * - Either we re-execute the same key register access instruction - * after enabling ptrauth. - * - Or an UNDEF is injected as ptrauth is not supported/enabled. + * If we land here, that is because we didn't fixup the access on exit + * by allowing the PtrAuth sysregs. The only way this happens is when + * the guest does not have PtrAuth support enabled. */ + kvm_inject_undefined(vcpu); + return false; } From patchwork Thu Jun 4 13:33:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Zyngier X-Patchwork-Id: 11587963 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 01A19739 for ; Thu, 4 Jun 2020 13:34:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id DA481207F5 for ; Thu, 4 Jun 2020 13:34:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1591277649; bh=rotJuRrjsUR85tXo2BdW5+A/L5Ugu4nDYunoj5XseZ4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=RIEFfeSMRa8syTaLqyf72Yc9qNC2CtgX0Uy9kzv6M/NCe9Z3lXxdx8ZxDTpTMKzw/ X1+CSW7K/D9EUJmzCMVv3QcNiJ1cE8rIU12uTE2LpElLAv1PZRkF9Nkm7qGa4SGUd7 bNO8PRcF664BXRWOD/w+cLyY8otj/a4QbuYWlLcU= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728646AbgFDNeJ (ORCPT ); Thu, 4 Jun 2020 09:34:09 -0400 Received: from mail.kernel.org ([198.145.29.99]:36256 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728629AbgFDNeH (ORCPT ); Thu, 4 Jun 2020 09:34:07 -0400 Received: from disco-boy.misterjones.org (disco-boy.misterjones.org [51.254.78.96]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id DAD8F20829; Thu, 4 Jun 2020 13:34:06 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1591277647; bh=rotJuRrjsUR85tXo2BdW5+A/L5Ugu4nDYunoj5XseZ4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UCGPpRD9IJ9+GPQ3TWSKTU05OHcM/VphXHokwWzbhrdpLFx/eDNRYwqji0n/HGzVV cMjCXN35g+TBwjZkQS/5sIya4Vp88R2C6w6htT97ukxGsKKmGjhQTipyHOHCIqkaQh pKPoUb5LNgL6imf5v3AJpUNMyapbYKQ0Erphzs/o= Received: from 78.163-31-62.static.virginmediabusiness.co.uk ([62.31.163.78] helo=why.lan) by disco-boy.misterjones.org with esmtpsa (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jgq0T-000G3O-Er; Thu, 04 Jun 2020 14:34:05 +0100 From: Marc Zyngier To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org Cc: James Morse , Julien Thierry , Suzuki K Poulose , Will Deacon , Catalin Marinas , Mark Rutland , kernel-team@android.com Subject: [PATCH 3/3] KVM: arm64: Enforce PtrAuth being disabled if not advertized Date: Thu, 4 Jun 2020 14:33:54 +0100 Message-Id: <20200604133354.1279412-4-maz@kernel.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200604133354.1279412-1-maz@kernel.org> References: <20200604133354.1279412-1-maz@kernel.org> MIME-Version: 1.0 X-SA-Exim-Connect-IP: 62.31.163.78 X-SA-Exim-Rcpt-To: kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, james.morse@arm.com, julien.thierry.kdev@gmail.com, suzuki.poulose@arm.com, will@kernel.org, catalin.marinas@arm.com, mark.rutland@arm.com, kernel-team@android.com X-SA-Exim-Mail-From: maz@kernel.org X-SA-Exim-Scanned: No (on disco-boy.misterjones.org); SAEximRunCond expanded to false Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Even if we don't expose PtrAuth to a guest, the guest can still write to its SCTIRLE_1 register and set the En{I,D}{A,B} bits and execute PtrAuth instructions from the NOP space. This has the effect of trapping to EL2, and we currently inject an UNDEF. This is definitely the wrong thing to do, as the architecture says that these instructions should behave as NOPs. Instead, we can simply reset the offending SCTLR_EL1 bits to zero, and resume the guest. It can still observe the SCTLR bits being set and then being cleared by magic, but that's much better than delivering an unexpected extension. Signed-off-by: Marc Zyngier --- arch/arm64/kvm/handle_exit.c | 12 ------------ arch/arm64/kvm/hyp/switch.c | 18 ++++++++++++++++-- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c index 5a02d4c90559..98d8adf6f865 100644 --- a/arch/arm64/kvm/handle_exit.c +++ b/arch/arm64/kvm/handle_exit.c @@ -162,17 +162,6 @@ static int handle_sve(struct kvm_vcpu *vcpu, struct kvm_run *run) return 1; } -/* - * Guest usage of a ptrauth instruction (which the guest EL1 did not turn into - * a NOP). If we get here, it is that we didn't fixup ptrauth on exit, and all - * that we can do is give the guest an UNDEF. - */ -static int kvm_handle_ptrauth(struct kvm_vcpu *vcpu, struct kvm_run *run) -{ - kvm_inject_undefined(vcpu); - return 1; -} - static exit_handle_fn arm_exit_handlers[] = { [0 ... ESR_ELx_EC_MAX] = kvm_handle_unknown_ec, [ESR_ELx_EC_WFx] = kvm_handle_wfx, @@ -195,7 +184,6 @@ static exit_handle_fn arm_exit_handlers[] = { [ESR_ELx_EC_BKPT32] = kvm_handle_guest_debug, [ESR_ELx_EC_BRK64] = kvm_handle_guest_debug, [ESR_ELx_EC_FP_ASIMD] = handle_no_fpsimd, - [ESR_ELx_EC_PAC] = kvm_handle_ptrauth, }; static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu) diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c index 2a50b3771c3b..fc09c3dfa466 100644 --- a/arch/arm64/kvm/hyp/switch.c +++ b/arch/arm64/kvm/hyp/switch.c @@ -503,8 +503,22 @@ static bool __hyp_text __hyp_handle_ptrauth(struct kvm_vcpu *vcpu) struct kvm_cpu_context *ctxt; u64 val; - if (!vcpu_has_ptrauth(vcpu)) - return false; + if (!vcpu_has_ptrauth(vcpu)) { + if (ec != ESR_ELx_EC_PAC) + return false; + + /* + * Interesting situation: the guest has enabled PtrAuth, + * despite KVM not advertising it. Fix SCTLR_El1 on behalf + * of the guest (the bits should behave as RES0 anyway). + */ + val = read_sysreg_el1(SYS_SCTLR); + val &= ~(SCTLR_ELx_ENIA | SCTLR_ELx_ENIB | + SCTLR_ELx_ENDA | SCTLR_ELx_ENDB); + write_sysreg_el1(val, SYS_SCTLR); + + return true; + } switch (ec) { case ESR_ELx_EC_PAC: