rmap_next() expects the "spte" argument to be NULL whenever there's only
one remaining entry in the descriptor. That is, it was not designed to
handle changes in the chain while iterating.

This bug cripples rmap_write_protect() so that it won't nuke all
writable large mappings to a particular gfn.

Signed-off-by: Marcelo Tosatti <[EMAIL PROTECTED]>

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index aaccc40..e11ff17 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -632,17 +632,19 @@ static void rmap_write_protect(struct kvm *kvm, u64 gfn)
        rmapp = gfn_to_rmap(kvm, gfn, 1);
        spte = rmap_next(kvm, rmapp, NULL);
        while (spte) {
+               u64 *next_spte;
                BUG_ON(!spte);
                BUG_ON(!(*spte & PT_PRESENT_MASK));
                BUG_ON((*spte & (PT_PAGE_SIZE_MASK|PT_PRESENT_MASK)) != 
(PT_PAGE_SIZE_MASK|PT_PRESENT_MASK));
                pgprintk("rmap_write_protect(large): spte %p %llx %lld\n", 
spte, *spte, gfn);
+               next_spte = rmap_next(kvm, rmapp, spte);
                if (is_writeble_pte(*spte)) {
                        rmap_remove(kvm, spte);
                        --kvm->stat.lpages;
                        set_shadow_pte(spte, shadow_trap_nonpresent_pte);
                        write_protected = 1;
                }
-               spte = rmap_next(kvm, rmapp, spte);
+               spte = next_spte;
        }
 
        if (write_protected)
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to