On Thu, Jul 11, 2024 at 06:27:52PM -0400, Paolo Bonzini wrote: > Do not allow populating the same page twice with startup data. In the > case of SEV-SNP, for example, the firmware does not allow it anyway, > since the launch-update operation is only possible on pages that are > still shared in the RMP. > > Even if it worked, kvm_gmem_populate()'s callback is meant to have side > effects such as updating launch measurements, and updating the same > page twice is unlikely to have the desired results. > > Races between calls to the ioctl are not possible because kvm_gmem_populate() > holds slots_lock and the VM should not be running. But again, even if > this worked on other confidential computing technology, it doesn't matter > to guest_memfd.c whether this is an intentional attempt to do something > fishy, or missing synchronization in userspace, or even something > intentional. One of the racers wins, and the page is initialized by I think one of those "intentional"s was meant to be an "unintentional". > either kvm_gmem_prepare_folio() or kvm_gmem_populate(). > > Anyway, out of paranoia, adjust sev_gmem_post_populate() anyway to use > the same errno that kvm_gmem_populate() is using. > > Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx> Assuming based on the discussion here that there will be some logic added to enforce that KVM_PRE_FAULT_MEMORY can only happen after finalization, I think the new checks make sense. Reviewed-by: Michael Roth <michael.roth@xxxxxxx> > --- > arch/x86/kvm/svm/sev.c | 2 +- > virt/kvm/guest_memfd.c | 7 +++++++ > 2 files changed, 8 insertions(+), 1 deletion(-) > > diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c > index df8818759698..397ef9e70182 100644 > --- a/arch/x86/kvm/svm/sev.c > +++ b/arch/x86/kvm/svm/sev.c > @@ -2213,7 +2213,7 @@ static int sev_gmem_post_populate(struct kvm *kvm, gfn_t gfn_start, kvm_pfn_t pf > if (ret || assigned) { > pr_debug("%s: Failed to ensure GFN 0x%llx RMP entry is initial shared state, ret: %d assigned: %d\n", > __func__, gfn, ret, assigned); > - ret = -EINVAL; > + ret = ret ? -EINVAL : -EEXIST; > goto err; > } > > diff --git a/virt/kvm/guest_memfd.c b/virt/kvm/guest_memfd.c > index 509360eefea5..266810bb91c9 100644 > --- a/virt/kvm/guest_memfd.c > +++ b/virt/kvm/guest_memfd.c > @@ -650,6 +650,13 @@ long kvm_gmem_populate(struct kvm *kvm, gfn_t start_gfn, void __user *src, long > break; > } > > + if (folio_test_uptodate(folio)) { > + folio_unlock(folio); > + folio_put(folio); > + ret = -EEXIST; > + break; > + } > + > folio_unlock(folio); > if (!IS_ALIGNED(gfn, (1 << max_order)) || > (npages - i) < (1 << max_order)) > -- > 2.43.0 > > >