KVM: MMU: fix wrong not write protected sp report
Xiao Guangrong [Sat, 28 Aug 2010 11:22:46 +0000 (19:22 +0800)]
The audit code reports some sp not write protected in current code, it's just the
bug in audit_write_protection(), since:

- the invalid sp not need write protected
- using uninitialize local variable('gfn')
- call kvm_mmu_audit() out of mmu_lock's protection

Signed-off-by: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com>
Signed-off-by: Avi Kivity <avi@redhat.com>

arch/x86/kvm/mmu.c
arch/x86/kvm/paging_tmpl.h

index 1c784b9..68575dc 100644 (file)
@@ -3708,16 +3708,17 @@ static void audit_write_protection(struct kvm_vcpu *vcpu)
        struct kvm_memory_slot *slot;
        unsigned long *rmapp;
        u64 *spte;
-       gfn_t gfn;
 
        list_for_each_entry(sp, &vcpu->kvm->arch.active_mmu_pages, link) {
                if (sp->role.direct)
                        continue;
                if (sp->unsync)
                        continue;
+               if (sp->role.invalid)
+                       continue;
 
                slot = gfn_to_memslot(vcpu->kvm, sp->gfn);
-               rmapp = &slot->rmap[gfn - slot->base_gfn];
+               rmapp = &slot->rmap[sp->gfn - slot->base_gfn];
 
                spte = rmap_next(vcpu->kvm, rmapp, NULL);
                while (spte) {
index a4e8389..a0f2feb 100644 (file)
@@ -504,7 +504,6 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
        unsigned long mmu_seq;
 
        pgprintk("%s: addr %lx err %x\n", __func__, addr, error_code);
-       kvm_mmu_audit(vcpu, "pre page fault");
 
        r = mmu_topup_memory_caches(vcpu);
        if (r)
@@ -542,6 +541,8 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
        spin_lock(&vcpu->kvm->mmu_lock);
        if (mmu_notifier_retry(vcpu, mmu_seq))
                goto out_unlock;
+
+       kvm_mmu_audit(vcpu, "pre page fault");
        kvm_mmu_free_some_pages(vcpu);
        sptep = FNAME(fetch)(vcpu, addr, &walker, user_fault, write_fault,
                             level, &write_pt, pfn);