From b8ac208a87e26b8d38990bd14f3eafffdc3664fb Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Thu, 12 Dec 2013 16:15:05 -0500 Subject: [PATCH] CVE-2013-6368 kvm: cross page vapic_addr access (rhbz 1032210 1042090) --- ...synchronization-to-_cached-functions.patch | 247 ++++++++++++++++++ kernel.spec | 7 + 2 files changed, 254 insertions(+) create mode 100644 KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch diff --git a/KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch b/KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch new file mode 100644 index 000000000..a37d4cf29 --- /dev/null +++ b/KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch @@ -0,0 +1,247 @@ +Bugzilla: 1042090 +Upstream-status: 3.13 and sent for stable +Delivered-To: jwboyer@gmail.com +Received: by 10.76.104.107 with SMTP id gd11csp361293oab; + Thu, 12 Dec 2013 12:41:12 -0800 (PST) +X-Received: by 10.68.244.2 with SMTP id xc2mr15600217pbc.58.1386880872483; + Thu, 12 Dec 2013 12:41:12 -0800 (PST) +Return-Path: +Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) + by mx.google.com with ESMTP id 5si8126292pbj.245.2013.12.12.12.40.49 + for ; + Thu, 12 Dec 2013 12:41:12 -0800 (PST) +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; +Authentication-Results: mx.google.com; + spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mail=stable-owner@vger.kernel.org; + dkim=neutral (bad format) header.i=@gmail.com +Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand + id S1751901Ab3LLUiK (ORCPT + 64 others); + Thu, 12 Dec 2013 15:38:10 -0500 +Received: from mail-ea0-f169.google.com ([209.85.215.169]:43997 "EHLO + mail-ea0-f169.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org + with ESMTP id S1751940Ab3LLUhR (ORCPT + ); Thu, 12 Dec 2013 15:37:17 -0500 +Received: by mail-ea0-f169.google.com with SMTP id l9so411843eaj.0 + for ; Thu, 12 Dec 2013 12:37:15 -0800 (PST) +DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; + d=gmail.com; s=20120113; + h=sender:from:to:cc:subject:date:message-id; + bh=2MLmYgVGbv9FpnyP90yrPKk21SJoXFj93yQcaRn4G8Y=; + b=ouBadI22VTf1UuezbySC80FWJYdpF/8Ks6I8f5rq1/7SDQPTpScjOYjZX0UtIf1ihj + aeQ7IHqpmIYGKWadUbH2l88ZP1+rP7T+f2dZQeCb3HLNsPum0Ix8dzm/koeDnuS3dx75 + 50E9ZcFXO13Hx24tM8p0SAuYZ1DvbCNnPRK0yxHOmCtCWe+mQLBIgig1rg8TzSAazWm7 + 8LhpztDlIzNyZcfzKQvtdqTOBdnhadx5x39fxOe54Yw4JbppDa7R+BY5Jz6GOd3U0Op1 + Nf97rU0pe/jeyOtjF0LVs/d9iyPPeRoSE+VAr91iT8qj9S2PFEN1QxxWL8sdvsDPZK6B + ZCmw== +X-Received: by 10.14.182.199 with SMTP id o47mr10030582eem.7.1386880635352; + Thu, 12 Dec 2013 12:37:15 -0800 (PST) +Received: from playground.com (net-2-35-202-54.cust.dsl.vodafone.it. [2.35.202.54]) + by mx.google.com with ESMTPSA id o47sm70323739eem.21.2013.12.12.12.37.13 + for + (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); + Thu, 12 Dec 2013 12:37:14 -0800 (PST) +From: Paolo Bonzini +To: linux-kernel@vger.kernel.org +Cc: gleb@redhat.com, kvm@vger.kernel.org, pmatouse@redhat.com, + Andy Honig , stable@vger.kernel.org +Subject: [PATCH] KVM: x86: Convert vapic synchronization to _cached functions (CVE-2013-6368) +Date: Thu, 12 Dec 2013 21:36:53 +0100 +Message-Id: <1386880614-23300-3-git-send-email-pbonzini@redhat.com> +X-Mailer: git-send-email 1.8.3.1 +Sender: stable-owner@vger.kernel.org +Precedence: bulk +List-ID: +X-Mailing-List: stable@vger.kernel.org + +From: Andy Honig + +In kvm_lapic_sync_from_vapic and kvm_lapic_sync_to_vapic there is the +potential to corrupt kernel memory if userspace provides an address that +is at the end of a page. This patches concerts those functions to use +kvm_write_guest_cached and kvm_read_guest_cached. It also checks the +vapic_address specified by userspace during ioctl processing and returns +an error to userspace if the address is not a valid GPA. + +This is generally not guest triggerable, because the required write is +done by firmware that runs before the guest. Also, it only affects AMD +processors and oldish Intel that do not have the FlexPriority feature +(unless you disable FlexPriority, of course; then newer processors are +also affected). + +Fixes: b93463aa59d6 ('KVM: Accelerated apic support') + +Reported-by: Andrew Honig +Cc: stable@vger.kernel.org +Signed-off-by: Andrew Honig +Signed-off-by: Paolo Bonzini +--- + arch/x86/kvm/lapic.c | 27 +++++++++++++++------------ + arch/x86/kvm/lapic.h | 4 ++-- + arch/x86/kvm/x86.c | 40 +--------------------------------------- + 3 files changed, 18 insertions(+), 53 deletions(-) + +diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c +index 89b52ec7d09c..b8bec45c1610 100644 +--- a/arch/x86/kvm/lapic.c ++++ b/arch/x86/kvm/lapic.c +@@ -1692,7 +1692,6 @@ static void apic_sync_pv_eoi_from_guest(struct kvm_vcpu *vcpu, + void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu) + { + u32 data; +- void *vapic; + + if (test_bit(KVM_APIC_PV_EOI_PENDING, &vcpu->arch.apic_attention)) + apic_sync_pv_eoi_from_guest(vcpu, vcpu->arch.apic); +@@ -1700,9 +1699,8 @@ void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu) + if (!test_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention)) + return; + +- vapic = kmap_atomic(vcpu->arch.apic->vapic_page); +- data = *(u32 *)(vapic + offset_in_page(vcpu->arch.apic->vapic_addr)); +- kunmap_atomic(vapic); ++ kvm_read_guest_cached(vcpu->kvm, &vcpu->arch.apic->vapic_cache, &data, ++ sizeof(u32)); + + apic_set_tpr(vcpu->arch.apic, data & 0xff); + } +@@ -1738,7 +1736,6 @@ void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu) + u32 data, tpr; + int max_irr, max_isr; + struct kvm_lapic *apic = vcpu->arch.apic; +- void *vapic; + + apic_sync_pv_eoi_to_guest(vcpu, apic); + +@@ -1754,18 +1751,24 @@ void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu) + max_isr = 0; + data = (tpr & 0xff) | ((max_isr & 0xf0) << 8) | (max_irr << 24); + +- vapic = kmap_atomic(vcpu->arch.apic->vapic_page); +- *(u32 *)(vapic + offset_in_page(vcpu->arch.apic->vapic_addr)) = data; +- kunmap_atomic(vapic); ++ kvm_write_guest_cached(vcpu->kvm, &vcpu->arch.apic->vapic_cache, &data, ++ sizeof(u32)); + } + +-void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr) ++int kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr) + { +- vcpu->arch.apic->vapic_addr = vapic_addr; +- if (vapic_addr) ++ if (vapic_addr) { ++ if (kvm_gfn_to_hva_cache_init(vcpu->kvm, ++ &vcpu->arch.apic->vapic_cache, ++ vapic_addr, sizeof(u32))) ++ return -EINVAL; + __set_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention); +- else ++ } else { + __clear_bit(KVM_APIC_CHECK_VAPIC, &vcpu->arch.apic_attention); ++ } ++ ++ vcpu->arch.apic->vapic_addr = vapic_addr; ++ return 0; + } + + int kvm_x2apic_msr_write(struct kvm_vcpu *vcpu, u32 msr, u64 data) +diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h +index c730ac9fe801..c8b0d0d2da5c 100644 +--- a/arch/x86/kvm/lapic.h ++++ b/arch/x86/kvm/lapic.h +@@ -34,7 +34,7 @@ struct kvm_lapic { + */ + void *regs; + gpa_t vapic_addr; +- struct page *vapic_page; ++ struct gfn_to_hva_cache vapic_cache; + unsigned long pending_events; + unsigned int sipi_vector; + }; +@@ -76,7 +76,7 @@ void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data); + void kvm_apic_write_nodecode(struct kvm_vcpu *vcpu, u32 offset); + void kvm_apic_set_eoi_accelerated(struct kvm_vcpu *vcpu, int vector); + +-void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr); ++int kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr); + void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu); + void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu); + +diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c +index 21ef1ba184ae..5d004da1e35d 100644 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -3214,8 +3214,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp, + r = -EFAULT; + if (copy_from_user(&va, argp, sizeof va)) + goto out; +- r = 0; +- kvm_lapic_set_vapic_addr(vcpu, va.vapic_addr); ++ r = kvm_lapic_set_vapic_addr(vcpu, va.vapic_addr); + break; + } + case KVM_X86_SETUP_MCE: { +@@ -5739,36 +5738,6 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu) + !kvm_event_needs_reinjection(vcpu); + } + +-static int vapic_enter(struct kvm_vcpu *vcpu) +-{ +- struct kvm_lapic *apic = vcpu->arch.apic; +- struct page *page; +- +- if (!apic || !apic->vapic_addr) +- return 0; +- +- page = gfn_to_page(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT); +- if (is_error_page(page)) +- return -EFAULT; +- +- vcpu->arch.apic->vapic_page = page; +- return 0; +-} +- +-static void vapic_exit(struct kvm_vcpu *vcpu) +-{ +- struct kvm_lapic *apic = vcpu->arch.apic; +- int idx; +- +- if (!apic || !apic->vapic_addr) +- return; +- +- idx = srcu_read_lock(&vcpu->kvm->srcu); +- kvm_release_page_dirty(apic->vapic_page); +- mark_page_dirty(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT); +- srcu_read_unlock(&vcpu->kvm->srcu, idx); +-} +- + static void update_cr8_intercept(struct kvm_vcpu *vcpu) + { + int max_irr, tpr; +@@ -6069,11 +6038,6 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) + struct kvm *kvm = vcpu->kvm; + + vcpu->srcu_idx = srcu_read_lock(&kvm->srcu); +- r = vapic_enter(vcpu); +- if (r) { +- srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx); +- return r; +- } + + r = 1; + while (r > 0) { +@@ -6132,8 +6096,6 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) + + srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx); + +- vapic_exit(vcpu); +- + return r; + } + +-- +1.8.3.1 + +-- +To unsubscribe from this list: send the line "unsubscribe stable" 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/kernel.spec b/kernel.spec index 609238567..1914f41d2 100644 --- a/kernel.spec +++ b/kernel.spec @@ -717,6 +717,9 @@ Patch25171: elantech-Properly-differentiate-between-clickpads-an.patch #CVE-2013-6367 rhbz 1032207 1042081 Patch25172: KVM-x86-Fix-potential-divide-by-0-in-lapic.patch +#CVE-2013-6368 rhbz 1032210 1042090 +Patch25173: KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch + # END OF PATCH DEFINITIONS %endif @@ -1400,6 +1403,9 @@ ApplyPatch elantech-Properly-differentiate-between-clickpads-an.patch #CVE-2013-6367 rhbz 1032207 1042081 ApplyPatch KVM-x86-Fix-potential-divide-by-0-in-lapic.patch +#CVE-2013-6368 rhbz 1032210 1042090 +ApplyPatch KVM-x86-Convert-vapic-synchronization-to-_cached-functions.patch + # END OF PATCH APPLICATIONS %endif @@ -2213,6 +2219,7 @@ fi # || || %changelog * Thu Dec 12 2013 Josh Boyer +- CVE-2013-6368 kvm: cross page vapic_addr access (rhbz 1032210 1042090) - CVE-2013-6367 kvm: division by 0 in apic_get_tmcct (rhbz 1032207 1042081) * Wed Dec 11 2013 Josh Boyer - 3.13.0-0.rc3.git2.1