| From mtosatti@redhat.com Thu Sep 3 14:22:22 2009 |
| From: mtosatti@redhat.com |
| Date: Mon, 3 Aug 2009 14:57:49 -0300 |
| Subject: KVM: x86: check for cr3 validity in mmu_alloc_roots |
| To: stable@kernel.org |
| Cc: Marcelo Tosatti <mtosatti@redhat.com>, avi@redhat.com |
| Message-ID: <1249322277-5824-2-git-send-email-mtosatti@redhat.com> |
| |
| |
| From: Marcelo Tosatti <mtosatti@redhat.com> |
| |
| (cherry picked from commit 8986ecc0ef58c96eec48d8502c048f3ab67fd8e2) |
| |
| Verify the cr3 address stored in vcpu->arch.cr3 points to an existant |
| memslot. If not, inject a triple fault. |
| |
| Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> |
| Signed-off-by: Avi Kivity <avi@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| --- |
| arch/x86/kvm/mmu.c | 27 +++++++++++++++++++++++---- |
| arch/x86/kvm/x86.c | 1 + |
| 2 files changed, 24 insertions(+), 4 deletions(-) |
| |
| --- a/arch/x86/kvm/mmu.c |
| +++ b/arch/x86/kvm/mmu.c |
| @@ -1942,7 +1942,19 @@ static void mmu_free_roots(struct kvm_vc |
| vcpu->arch.mmu.root_hpa = INVALID_PAGE; |
| } |
| |
| -static void mmu_alloc_roots(struct kvm_vcpu *vcpu) |
| +static int mmu_check_root(struct kvm_vcpu *vcpu, gfn_t root_gfn) |
| +{ |
| + int ret = 0; |
| + |
| + if (!kvm_is_visible_gfn(vcpu->kvm, root_gfn)) { |
| + set_bit(KVM_REQ_TRIPLE_FAULT, &vcpu->requests); |
| + ret = 1; |
| + } |
| + |
| + return ret; |
| +} |
| + |
| +static int mmu_alloc_roots(struct kvm_vcpu *vcpu) |
| { |
| int i; |
| gfn_t root_gfn; |
| @@ -1957,13 +1969,15 @@ static void mmu_alloc_roots(struct kvm_v |
| ASSERT(!VALID_PAGE(root)); |
| if (tdp_enabled) |
| direct = 1; |
| + if (mmu_check_root(vcpu, root_gfn)) |
| + return 1; |
| sp = kvm_mmu_get_page(vcpu, root_gfn, 0, |
| PT64_ROOT_LEVEL, direct, |
| ACC_ALL, NULL); |
| root = __pa(sp->spt); |
| ++sp->root_count; |
| vcpu->arch.mmu.root_hpa = root; |
| - return; |
| + return 0; |
| } |
| direct = !is_paging(vcpu); |
| if (tdp_enabled) |
| @@ -1980,6 +1994,8 @@ static void mmu_alloc_roots(struct kvm_v |
| root_gfn = vcpu->arch.pdptrs[i] >> PAGE_SHIFT; |
| } else if (vcpu->arch.mmu.root_level == 0) |
| root_gfn = 0; |
| + if (mmu_check_root(vcpu, root_gfn)) |
| + return 1; |
| sp = kvm_mmu_get_page(vcpu, root_gfn, i << 30, |
| PT32_ROOT_LEVEL, direct, |
| ACC_ALL, NULL); |
| @@ -1988,6 +2004,7 @@ static void mmu_alloc_roots(struct kvm_v |
| vcpu->arch.mmu.pae_root[i] = root | PT_PRESENT_MASK; |
| } |
| vcpu->arch.mmu.root_hpa = __pa(vcpu->arch.mmu.pae_root); |
| + return 0; |
| } |
| |
| static void mmu_sync_roots(struct kvm_vcpu *vcpu) |
| @@ -2006,7 +2023,7 @@ static void mmu_sync_roots(struct kvm_vc |
| for (i = 0; i < 4; ++i) { |
| hpa_t root = vcpu->arch.mmu.pae_root[i]; |
| |
| - if (root) { |
| + if (root && VALID_PAGE(root)) { |
| root &= PT64_BASE_ADDR_MASK; |
| sp = page_header(root); |
| mmu_sync_children(vcpu, sp); |
| @@ -2290,9 +2307,11 @@ int kvm_mmu_load(struct kvm_vcpu *vcpu) |
| goto out; |
| spin_lock(&vcpu->kvm->mmu_lock); |
| kvm_mmu_free_some_pages(vcpu); |
| - mmu_alloc_roots(vcpu); |
| + r = mmu_alloc_roots(vcpu); |
| mmu_sync_roots(vcpu); |
| spin_unlock(&vcpu->kvm->mmu_lock); |
| + if (r) |
| + goto out; |
| kvm_x86_ops->set_cr3(vcpu, vcpu->arch.mmu.root_hpa); |
| kvm_mmu_flush_tlb(vcpu); |
| out: |
| --- a/arch/x86/kvm/x86.c |
| +++ b/arch/x86/kvm/x86.c |
| @@ -4433,6 +4433,7 @@ int kvm_arch_set_memory_region(struct kv |
| void kvm_arch_flush_shadow(struct kvm *kvm) |
| { |
| kvm_mmu_zap_all(kvm); |
| + kvm_reload_remote_mmus(kvm); |
| } |
| |
| int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu) |