From patchwork Fri Jul 8 22:36:06 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jim Mattson X-Patchwork-Id: 9221851 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 93E486089D for ; Fri, 8 Jul 2016 22:36:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 78EF7285E0 for ; Fri, 8 Jul 2016 22:36:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6D5FB285E7; Fri, 8 Jul 2016 22:36:15 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0A87B285E0 for ; Fri, 8 Jul 2016 22:36:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756415AbcGHWgM (ORCPT ); Fri, 8 Jul 2016 18:36:12 -0400 Received: from mail-pa0-f43.google.com ([209.85.220.43]:34883 "EHLO mail-pa0-f43.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756356AbcGHWgJ (ORCPT ); Fri, 8 Jul 2016 18:36:09 -0400 Received: by mail-pa0-f43.google.com with SMTP id dx3so16014175pab.2 for ; Fri, 08 Jul 2016 15:36:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=date:from:to:cc:subject:message-id:mime-version:content-disposition :in-reply-to:user-agent; bh=Rs0oBbZbuue6HSNVh/4nQbNyf+Cm5EfBKwwi5uYtCHo=; b=NSp6vD01rOjjyA8PAeQHtTvKMvZROj97oWvdQaaVTC9Kbn2sNZa9SRV1BuXzJggMkO Y7vN6u3LvnoRKY1CgNrM5DbWIk9FtMTdYzDJrjId9Q5JxRiEBFiDnxm6BsEfeGwM7jBX 4ruRQH6/7m8HQvYdXEjX1VmB9MaM4DQyYO1jtRSCaxgJ6VQl73KQjqGbiPsBw3EUENfM qsUo9SfFjwVMyudk7aRn5f0Wu1xDKYqcdjiuR3czJWH3EdC9vooiWD0S3oUo1Wy13nS0 kCDfOpq9DFFoabjMBmi545KTpP3KPzXaPGaOrN/+sPrRb3MTJylgkkp93pPlruffs4sr IlQg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:date:from:to:cc:subject:message-id:mime-version :content-disposition:in-reply-to:user-agent; bh=Rs0oBbZbuue6HSNVh/4nQbNyf+Cm5EfBKwwi5uYtCHo=; b=BEGwrvfA5yYYe4qt2C84NsyAgJhoQZwWodKKm2RdyihBMmHeL9LPw2FWrT4ZjHMYR3 pUNT4PRnhsifCJvxdnQqIe+pcvtDUHRrUQGYL4CWzhosEhIl+Vnd0wsltQ6rD/v+b2rm L+ddvxN6g8N3X+lI+p1Iag6uZxJA7XiaUvh5lWTiGz31Zfpbk3p0pU1Hk+I0a7ZftVVy NHicpL6AQzu7/eaj6I1agIIZROSQpNZrp6hiVcwb61y34Skf+ITxJx/BPRwhQWvmBK0M QAw1K7VirXUy5DoDcWQXgnZHBi/Cq26OQQpjbJPRn2rIPJfLy1TcQIWmapf0A9qouYxi dUXw== X-Gm-Message-State: ALyK8tITdZkYMXR7bYyoCUjUMYSMJiuExBO8wWjVXb5z1OvuwK9XLrKUUAkoMS+AhahD8vZw X-Received: by 10.66.76.10 with SMTP id g10mr13764530paw.110.1468017368341; Fri, 08 Jul 2016 15:36:08 -0700 (PDT) Received: from jmattson.sea.corp.google.com ([2620:0:1009:11:c840:dd61:8c6f:b387]) by smtp.gmail.com with ESMTPSA id v62sm6938589pfv.50.2016.07.08.15.36.07 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Fri, 08 Jul 2016 15:36:07 -0700 (PDT) Date: Fri, 8 Jul 2016 15:36:06 -0700 From: Jim Mattson To: Paolo Bonzini Cc: kvm@vger.kernel.org Subject: [PATCH v2] KVM: nVMX: Fix memory corruption when using VMCS shadowing Message-ID: <20160708223606.GA17035@jmattson.sea.corp.google.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When freeing the nested resources of a vcpu, there is an assumption that the vcpu's vmcs01 is the current VMCS on the CPU that executes nested_release_vmcs12(). If this assumption is violated, the vcpu's vmcs01 may be made active on multiple CPUs at the same time, in violation of Intel's specification. Moreover, since the vcpu's vmcs01 is not VMCLEARed on every CPU on which it is active, it can linger in a CPU's VMCS cache after it has been freed and potentially repurposed. Subsequent eviction from the CPU's VMCS cache on a capacity miss can result in memory corruption. It is not sufficient for vmx_free_vcpu() to call vmx_load_vmcs01(). If the vcpu in question was last loaded on a different CPU, it must be migrated to the current CPU before calling vmx_load_vmcs01(). Signed-off-by: Jim Mattson --- arch/x86/kvm/vmx.c | 19 +++++++++++++++++-- virt/kvm/kvm_main.c | 2 ++ 2 files changed, 19 insertions(+), 2 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 003618e..afb1ab3 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -8855,6 +8855,22 @@ static void vmx_load_vmcs01(struct kvm_vcpu *vcpu) put_cpu(); } +/* + * Ensure that the current vmcs of the logical processor is the + * vmcs01 of the vcpu before calling free_nested(). + */ +static void vmx_free_vcpu_nested(struct kvm_vcpu *vcpu) +{ + struct vcpu_vmx *vmx = to_vmx(vcpu); + int r; + + r = vcpu_load(vcpu); + BUG_ON(r); + vmx_load_vmcs01(vcpu); + free_nested(vmx); + vcpu_put(vcpu); +} + static void vmx_free_vcpu(struct kvm_vcpu *vcpu) { struct vcpu_vmx *vmx = to_vmx(vcpu); @@ -8863,8 +8879,7 @@ static void vmx_free_vcpu(struct kvm_vcpu *vcpu) vmx_destroy_pml_buffer(vmx); free_vpid(vmx->vpid); leave_guest_mode(vcpu); - vmx_load_vmcs01(vcpu); - free_nested(vmx); + vmx_free_vcpu_nested(vcpu); free_loaded_vmcs(vmx->loaded_vmcs); kfree(vmx->guest_msrs); kvm_vcpu_uninit(vcpu); diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 48bd520..dd25346 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -148,6 +148,7 @@ int vcpu_load(struct kvm_vcpu *vcpu) put_cpu(); return 0; } +EXPORT_SYMBOL_GPL(vcpu_load); void vcpu_put(struct kvm_vcpu *vcpu) { @@ -157,6 +158,7 @@ void vcpu_put(struct kvm_vcpu *vcpu) preempt_enable(); mutex_unlock(&vcpu->mutex); } +EXPORT_SYMBOL_GPL(vcpu_put); static void ack_flush(void *_completed) {