Skip to content

Commit

Permalink
KVM: MMU: fix direct sp's access corrupted
Browse files Browse the repository at this point in the history
If the mapping is writable but the dirty flag is not set, we will find
the read-only direct sp and setup the mapping, then if the write #PF
occur, we will mark this mapping writable in the read-only direct sp,
now, other real read-only mapping will happily write it without #PF.

It may hurt guest's COW

Fixed by re-install the mapping when write #PF occur.

Signed-off-by: Xiao Guangrong <[email protected]>
Signed-off-by: Marcelo Tosatti <[email protected]>
  • Loading branch information
Xiao Guangrong authored and avikivity committed Aug 1, 2010
1 parent 5fd5387 commit 9e7b0e7
Showing 1 changed file with 26 additions and 2 deletions.
28 changes: 26 additions & 2 deletions arch/x86/kvm/paging_tmpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -325,8 +325,32 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
break;
}

if (is_shadow_present_pte(*sptep) && !is_large_pte(*sptep))
continue;
if (is_shadow_present_pte(*sptep) && !is_large_pte(*sptep)) {
struct kvm_mmu_page *child;
unsigned direct_access;

if (level != gw->level)
continue;

/*
* For the direct sp, if the guest pte's dirty bit
* changed form clean to dirty, it will corrupt the
* sp's access: allow writable in the read-only sp,
* so we should update the spte at this point to get
* a new sp with the correct access.
*/
direct_access = gw->pt_access & gw->pte_access;
if (!is_dirty_gpte(gw->ptes[gw->level - 1]))
direct_access &= ~ACC_WRITE_MASK;

child = page_header(*sptep & PT64_BASE_ADDR_MASK);
if (child->role.access == direct_access)
continue;

mmu_page_remove_parent_pte(child, sptep);
__set_spte(sptep, shadow_trap_nonpresent_pte);
kvm_flush_remote_tlbs(vcpu->kvm);
}

if (is_large_pte(*sptep)) {
rmap_remove(vcpu->kvm, sptep);
Expand Down

0 comments on commit 9e7b0e7

Please sign in to comment.