From patchwork Mon Aug 10 13:25:53 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhichao Huang X-Patchwork-Id: 52245 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-lb0-f198.google.com (mail-lb0-f198.google.com [209.85.217.198]) by patches.linaro.org (Postfix) with ESMTPS id 0E1D522919 for ; Mon, 10 Aug 2015 13:26:31 +0000 (UTC) Received: by lbcli1 with SMTP id li1sf5430000lbc.2 for ; Mon, 10 Aug 2015 06:26:29 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe; bh=hyd9tNoxKZ9iaAp4LckfSTzJPrtB6w8rGYyBWExNfiw=; b=nDEofus7FSQ8vBhugIsh1ZxkIZro3D+LCTKGoHzNIy1YrWNsuaUcaBl9GKAXKgOY8Q wfq3h5+pfqbCc4AESAiBRpKYwua52NhfjObq/t/JzYcYj2H1Ef5UJ7mUcCAd7Zg0CMGr p/i4g2NbN69JLv94oeJpzPQA7xT6OZ1bd2wdZiMl0Hgi4IMrEkZFXbe1N3wiwcW6v209 IieBCjylTviHdU+rkcq81c9yfa/pez1ycEb8VDjiWlUQi9altONDfHitDenbanPFqtY7 oglhDD7VXibOXuq6qUmw2p4tBG5w5NN9CWc2+taDZYxQ8DIfyxsrHXlzNuzpI2rAndPi mabQ== X-Gm-Message-State: ALoCoQkA4SptFlWLv/rSLiQBNlGPz9rJ6n0g5HZT5eTPrF0+AlX3esHX7BWoXyTnk7tyZC2TTgoi X-Received: by 10.180.89.104 with SMTP id bn8mr339884wib.4.1439213189906; Mon, 10 Aug 2015 06:26:29 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.5.67 with SMTP id q3ls647805laq.78.gmail; Mon, 10 Aug 2015 06:26:29 -0700 (PDT) X-Received: by 10.112.159.226 with SMTP id xf2mr19669469lbb.74.1439213189739; Mon, 10 Aug 2015 06:26:29 -0700 (PDT) Received: from mail-la0-f50.google.com (mail-la0-f50.google.com. [209.85.215.50]) by mx.google.com with ESMTPS id uh3si11932985lac.125.2015.08.10.06.26.29 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 10 Aug 2015 06:26:29 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.50 as permitted sender) client-ip=209.85.215.50; Received: by lahi9 with SMTP id i9so23125895lah.2 for ; Mon, 10 Aug 2015 06:26:29 -0700 (PDT) X-Received: by 10.152.44.196 with SMTP id g4mr1626328lam.56.1439213189600; Mon, 10 Aug 2015 06:26:29 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.7.198 with SMTP id l6csp1934028lba; Mon, 10 Aug 2015 06:26:28 -0700 (PDT) X-Received: by 10.68.241.230 with SMTP id wl6mr44329471pbc.32.1439213187985; Mon, 10 Aug 2015 06:26:27 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id mn2si16568197pbc.95.2015.08.10.06.26.27; Mon, 10 Aug 2015 06:26:27 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753820AbbHJN0Y (ORCPT + 1 other); Mon, 10 Aug 2015 09:26:24 -0400 Received: from mail-pa0-f46.google.com ([209.85.220.46]:33856 "EHLO mail-pa0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752598AbbHJN0X (ORCPT ); Mon, 10 Aug 2015 09:26:23 -0400 Received: by pawu10 with SMTP id u10so140661656paw.1 for ; Mon, 10 Aug 2015 06:26:22 -0700 (PDT) X-Received: by 10.68.195.74 with SMTP id ic10mr43795960pbc.68.1439213182667; Mon, 10 Aug 2015 06:26:22 -0700 (PDT) Received: from localhost ([199.168.112.128]) by smtp.gmail.com with ESMTPSA id fv2sm19960165pbd.54.2015.08.10.06.26.19 (version=TLSv1 cipher=RC4-SHA bits=128/128); Mon, 10 Aug 2015 06:26:21 -0700 (PDT) From: Zhichao Huang To: kvm@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu, christoffer.dall@linaro.org, marc.zyngier@arm.com, alex.bennee@linaro.org, will.deacon@arm.com Cc: huangzhichao@huawei.com, Zhichao Huang , Subject: [PATCH v4 01/15] KVM: arm: plug guest debug exploit Date: Mon, 10 Aug 2015 21:25:53 +0800 Message-Id: <1439213167-8988-2-git-send-email-zhichao.huang@linaro.org> X-Mailer: git-send-email 1.9.5.msysgit.1 In-Reply-To: <1439213167-8988-1-git-send-email-zhichao.huang@linaro.org> References: <1439213167-8988-1-git-send-email-zhichao.huang@linaro.org> Sender: stable-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: stable@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: zhichao.huang@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.50 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Hardware debugging in guests is not intercepted currently, it means that a malicious guest can bring down the entire machine by writing to the debug registers. This patch enable trapping of all debug registers, preventing the guests to access the debug registers. This patch also disable the debug mode(DBGDSCR) in the guest world all the time, preventing the guests to mess with the host state. However, it is a precursor for later patches which will need to do more to world switch debug states while necessary. Cc: Signed-off-by: Zhichao Huang --- arch/arm/include/asm/kvm_coproc.h | 3 +- arch/arm/kvm/coproc.c | 82 +++++++++++++++++++++++++++++---------- arch/arm/kvm/handle_exit.c | 4 +- arch/arm/kvm/interrupts.S | 12 +++--- arch/arm/kvm/interrupts_head.S | 21 ++++++++-- 5 files changed, 89 insertions(+), 33 deletions(-) diff --git a/arch/arm/include/asm/kvm_coproc.h b/arch/arm/include/asm/kvm_coproc.h index 4917c2f..e74ab0f 100644 --- a/arch/arm/include/asm/kvm_coproc.h +++ b/arch/arm/include/asm/kvm_coproc.h @@ -31,7 +31,8 @@ void kvm_register_target_coproc_table(struct kvm_coproc_target_table *table); int kvm_handle_cp10_id(struct kvm_vcpu *vcpu, struct kvm_run *run); int kvm_handle_cp_0_13_access(struct kvm_vcpu *vcpu, struct kvm_run *run); int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run); -int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run); +int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run); +int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run); int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run); int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run); diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c index f3d88dc..a885cfe 100644 --- a/arch/arm/kvm/coproc.c +++ b/arch/arm/kvm/coproc.c @@ -91,12 +91,6 @@ int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run) return 1; } -int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run) -{ - kvm_inject_undefined(vcpu); - return 1; -} - static void reset_mpidr(struct kvm_vcpu *vcpu, const struct coproc_reg *r) { /* @@ -465,12 +459,8 @@ static int emulate_cp15(struct kvm_vcpu *vcpu, return 1; } -/** - * kvm_handle_cp15_64 -- handles a mrrc/mcrr trap on a guest CP15 access - * @vcpu: The VCPU pointer - * @run: The kvm_run struct - */ -int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run) +static int kvm_handle_cp_64(struct kvm_vcpu *vcpu, struct kvm_run *run, + bool cp15) { struct coproc_params params; @@ -484,7 +474,35 @@ int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run) params.Rt2 = (kvm_vcpu_get_hsr(vcpu) >> 10) & 0xf; params.CRm = 0; - return emulate_cp15(vcpu, ¶ms); + if (cp15) + return emulate_cp15(vcpu, ¶ms); + + /* raz_wi cp14 */ + (void)pm_fake(vcpu, ¶ms, NULL); + + /* handled */ + kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu)); + return 1; +} + +/** + * kvm_handle_cp15_64 -- handles a mrrc/mcrr trap on a guest CP15 access + * @vcpu: The VCPU pointer + * @run: The kvm_run struct + */ +int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run) +{ + return kvm_handle_cp_64(vcpu, run, 1); +} + +/** + * kvm_handle_cp14_64 -- handles a mrrc/mcrr trap on a guest CP14 access + * @vcpu: The VCPU pointer + * @run: The kvm_run struct + */ +int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run) +{ + return kvm_handle_cp_64(vcpu, run, 0); } static void reset_coproc_regs(struct kvm_vcpu *vcpu, @@ -497,12 +515,8 @@ static void reset_coproc_regs(struct kvm_vcpu *vcpu, table[i].reset(vcpu, &table[i]); } -/** - * kvm_handle_cp15_32 -- handles a mrc/mcr trap on a guest CP15 access - * @vcpu: The VCPU pointer - * @run: The kvm_run struct - */ -int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run) +static int kvm_handle_cp_32(struct kvm_vcpu *vcpu, struct kvm_run *run, + bool cp15) { struct coproc_params params; @@ -516,7 +530,35 @@ int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run) params.Op2 = (kvm_vcpu_get_hsr(vcpu) >> 17) & 0x7; params.Rt2 = 0; - return emulate_cp15(vcpu, ¶ms); + if (cp15) + return emulate_cp15(vcpu, ¶ms); + + /* raz_wi cp14 */ + (void)pm_fake(vcpu, ¶ms, NULL); + + /* handled */ + kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu)); + return 1; +} + +/** + * kvm_handle_cp15_32 -- handles a mrc/mcr trap on a guest CP15 access + * @vcpu: The VCPU pointer + * @run: The kvm_run struct + */ +int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run) +{ + return kvm_handle_cp_32(vcpu, run, 1); +} + +/** + * kvm_handle_cp14_32 -- handles a mrc/mcr trap on a guest CP14 access + * @vcpu: The VCPU pointer + * @run: The kvm_run struct + */ +int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run) +{ + return kvm_handle_cp_32(vcpu, run, 0); } /****************************************************************************** diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c index 95f12b2..357ad1b 100644 --- a/arch/arm/kvm/handle_exit.c +++ b/arch/arm/kvm/handle_exit.c @@ -104,9 +104,9 @@ static exit_handle_fn arm_exit_handlers[] = { [HSR_EC_WFI] = kvm_handle_wfx, [HSR_EC_CP15_32] = kvm_handle_cp15_32, [HSR_EC_CP15_64] = kvm_handle_cp15_64, - [HSR_EC_CP14_MR] = kvm_handle_cp14_access, + [HSR_EC_CP14_MR] = kvm_handle_cp14_32, [HSR_EC_CP14_LS] = kvm_handle_cp14_load_store, - [HSR_EC_CP14_64] = kvm_handle_cp14_access, + [HSR_EC_CP14_64] = kvm_handle_cp14_64, [HSR_EC_CP_0_13] = kvm_handle_cp_0_13_access, [HSR_EC_CP10_ID] = kvm_handle_cp10_id, [HSR_EC_SVC_HYP] = handle_svc_hyp, diff --git a/arch/arm/kvm/interrupts.S b/arch/arm/kvm/interrupts.S index 568494d..48333ff 100644 --- a/arch/arm/kvm/interrupts.S +++ b/arch/arm/kvm/interrupts.S @@ -112,9 +112,9 @@ ENTRY(__kvm_vcpu_run) restore_vgic_state restore_timer_state - @ Store hardware CP15 state and load guest state - read_cp15_state store_to_vcpu = 0 - write_cp15_state read_from_vcpu = 1 + @ Store hardware CP14/CP15 state and load guest state + read_coproc_state store_to_vcpu = 0 + write_coproc_state read_from_vcpu = 1 @ If the host kernel has not been configured with VFPv3 support, @ then it is safer if we deny guests from using it as well. @@ -199,9 +199,9 @@ after_vfp_restore: mrc p15, 0, r2, c0, c0, 5 mcr p15, 4, r2, c0, c0, 5 - @ Store guest CP15 state and restore host state - read_cp15_state store_to_vcpu = 1 - write_cp15_state read_from_vcpu = 0 + @ Store guest CP14/CP15 state and restore host state + read_coproc_state store_to_vcpu = 1 + write_coproc_state read_from_vcpu = 0 save_timer_state save_vgic_state diff --git a/arch/arm/kvm/interrupts_head.S b/arch/arm/kvm/interrupts_head.S index 702740d..7c4075c 100644 --- a/arch/arm/kvm/interrupts_head.S +++ b/arch/arm/kvm/interrupts_head.S @@ -239,7 +239,7 @@ vcpu .req r0 @ vcpu pointer always in r0 save_guest_regs_mode irq, #VCPU_IRQ_REGS .endm -/* Reads cp15 registers from hardware and stores them in memory +/* Reads cp14/cp15 registers from hardware and stores them in memory * @store_to_vcpu: If 0, registers are written in-order to the stack, * otherwise to the VCPU struct pointed to by vcpup * @@ -247,7 +247,12 @@ vcpu .req r0 @ vcpu pointer always in r0 * * Clobbers r2 - r12 */ -.macro read_cp15_state store_to_vcpu +.macro read_coproc_state store_to_vcpu + .if \store_to_vcpu == 0 + mrc p14, 0, r2, c0, c1, 0 @ DBGDSCR + push {r2} + .endif + mrc p15, 0, r2, c1, c0, 0 @ SCTLR mrc p15, 0, r3, c1, c0, 2 @ CPACR mrc p15, 0, r4, c2, c0, 2 @ TTBCR @@ -325,7 +330,7 @@ vcpu .req r0 @ vcpu pointer always in r0 * * Assumes vcpu pointer in vcpu reg */ -.macro write_cp15_state read_from_vcpu +.macro write_coproc_state read_from_vcpu .if \read_from_vcpu == 0 pop {r2,r4-r7} .else @@ -394,6 +399,14 @@ vcpu .req r0 @ vcpu pointer always in r0 mcr p15, 0, r10, c10, c2, 0 @ PRRR mcr p15, 0, r11, c10, c2, 1 @ NMRR mcr p15, 2, r12, c0, c0, 0 @ CSSELR + + .if \read_from_vcpu == 0 + pop {r2} + .else + mov r2, #0 + .endif + + mcr p14, 0, r2, c0, c2, 2 @ DBGDSCR .endm /* @@ -620,7 +633,7 @@ ARM_BE8(rev r6, r6 ) * (hardware reset value is 0) */ .macro set_hdcr operation mrc p15, 4, r2, c1, c1, 1 - ldr r3, =(HDCR_TPM|HDCR_TPMCR) + ldr r3, =(HDCR_TPM|HDCR_TPMCR|HDCR_TDRA|HDCR_TDOSA|HDCR_TDA) .if \operation == vmentry orr r2, r2, r3 @ Trap some perfmon accesses .else