From: Marcelo Tosatti <mtosatti@redhat.com>
To: Avi Kivity <avi@redhat.com>
Cc: Xiao Guangrong <xiaoguangrong@cn.fujitsu.com>, kvm@vger.kernel.org
Subject: Re: [PATCH v3 7/8] KVM: MMU: Validate all gptes during fetch, not just those used for new pages
Date: Mon, 12 Jul 2010 16:16:44 -0300 [thread overview]
Message-ID: <20100712191644.GD8262@amt.cnet> (raw)
In-Reply-To: <1278951351-6300-8-git-send-email-avi@redhat.com>
On Mon, Jul 12, 2010 at 07:15:50PM +0300, Avi Kivity wrote:
> Currently, when we fetch an spte, we only verify that gptes match those that
> the walker saw if we build new shadow pages for them.
>
> However, this misses the following race:
>
> vcpu1 vcpu2
>
> walk
> change gpte
> walk
> instantiate sp
>
> fetch existing sp
>
> Fix by validating every gpte, regardless of whether it is used for building
> a new sp or not.
>
> Signed-off-by: Avi Kivity <avi@redhat.com>
> ---
> arch/x86/kvm/paging_tmpl.h | 44 +++++++++++++++++++++++++++++++-------------
> 1 files changed, 31 insertions(+), 13 deletions(-)
>
> diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
> index 441f51c..89b2dab 100644
> --- a/arch/x86/kvm/paging_tmpl.h
> +++ b/arch/x86/kvm/paging_tmpl.h
> @@ -310,7 +310,8 @@ static bool FNAME(validate_indirect_spte)(struct kvm_vcpu *vcpu,
> gw->pte_gpa[level - 1],
> &curr_pte, sizeof(curr_pte));
> if (r || curr_pte != gw->ptes[level - 1]) {
> - kvm_mmu_put_page(sp, sptep);
> + if (sp)
> + kvm_mmu_put_page(sp, sptep);
> return false;
> }
> return true;
> @@ -325,10 +326,11 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
> int *ptwrite, pfn_t pfn)
> {
> unsigned access = gw->pt_access;
> - struct kvm_mmu_page *sp;
> + struct kvm_mmu_page *uninitialized_var(sp);
> u64 *sptep = NULL;
> int uninitialized_var(level);
> bool dirty = is_dirty_gpte(gw->ptes[gw->level - 1]);
> + int top_level;
> unsigned direct_access;
> struct kvm_shadow_walk_iterator iterator;
>
> @@ -339,34 +341,46 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr,
> if (!dirty)
> direct_access &= ~ACC_WRITE_MASK;
>
> + top_level = vcpu->arch.mmu.root_level;
> + if (top_level == PT32E_ROOT_LEVEL)
> + top_level = PT32_ROOT_LEVEL;
> + /*
> + * Verify that the top-level gpte is still there. Since the page
> + * is a root page, it is either write protected (and cannot be
> + * changed from now on) or it is invalid (in which case, we don't
> + * really care if it changes underneath us after this point).
> + */
> + if (!FNAME(validate_indirect_spte)(vcpu, NULL, NULL, gw, top_level))
> + goto out_error;
> +
> for (shadow_walk_init(&iterator, vcpu, addr);
> shadow_walk_okay(&iterator) && iterator.level > gw->level;
> shadow_walk_next(&iterator)) {
> gfn_t table_gfn;
> + bool new_page = false;
>
> level = iterator.level;
> sptep = iterator.sptep;
>
> drop_large_spte(vcpu, sptep);
>
> - if (is_shadow_present_pte(*sptep))
> - continue;
> -
> - table_gfn = gw->table_gfn[level - 2];
> - sp = kvm_mmu_get_page(vcpu, table_gfn, addr, level-1,
> - false, access, sptep);
> + if (!is_shadow_present_pte(*sptep)) {
> + table_gfn = gw->table_gfn[level - 2];
> + sp = kvm_mmu_get_page(vcpu, table_gfn, addr, level-1,
> + false, access, sptep);
> + new_page = true;
> + }
>
> /*
> * Verify that the gpte in the page we've just write
> * protected is still there.
> */
> if (!FNAME(validate_indirect_spte)(vcpu, sptep, sp,
> - gw, level - 1)) {
> - kvm_release_pfn_clean(pfn);
> - return NULL;
> - }
> + gw, level - 1))
> + goto out_error;
If its not a new page, and validation fails, can't "sp" point to
a shadow page previously instantiated in the loop?
next prev parent reply other threads:[~2010-07-12 19:17 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-07-12 16:15 [PATCH v3 0/8] Simplify and fix fetch() Avi Kivity
2010-07-12 16:15 ` [PATCH v3 1/8] KVM: MMU: Add link_shadow_page() helper Avi Kivity
2010-07-12 16:15 ` [PATCH v3 2/8] KVM: MMU: Use __set_spte to link shadow pages Avi Kivity
2010-07-12 16:15 ` [PATCH v3 3/8] KVM: MMU: Add drop_large_spte() helper Avi Kivity
2010-07-12 16:15 ` [PATCH v3 4/8] KVM: MMU: Add validate_direct_spte() helper Avi Kivity
2010-07-12 16:15 ` [PATCH v3 5/8] KVM: MMU: Add validate_indirect_spte() helper Avi Kivity
2010-07-12 16:15 ` [PATCH v3 6/8] KVM: MMU: Simplify spte fetch() function Avi Kivity
2010-07-12 16:15 ` [PATCH v3 7/8] KVM: MMU: Validate all gptes during fetch, not just those used for new pages Avi Kivity
2010-07-12 19:16 ` Marcelo Tosatti [this message]
2010-07-13 4:20 ` Avi Kivity
2010-07-13 1:51 ` Xiao Guangrong
2010-07-13 4:18 ` Avi Kivity
2010-07-13 4:27 ` Xiao Guangrong
2010-07-12 16:15 ` [PATCH v3 8/8] KVM: MMU: Eliminate redundant temporaries in FNAME(fetch) Avi Kivity
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20100712191644.GD8262@amt.cnet \
--to=mtosatti@redhat.com \
--cc=avi@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=xiaoguangrong@cn.fujitsu.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.