Skip to content

Commit e4ee544

Browse files
committed
KVM: guest_memfd: let kvm_gmem_populate() operate only on private gfns
This check is currently performed by sev_gmem_post_populate(), but it applies to all callers of kvm_gmem_populate(): the point of the function is that the memory is being encrypted and some work has to be done on all the gfns in order to encrypt them. Therefore, check the KVM_MEMORY_ATTRIBUTE_PRIVATE attribute prior to invoking the callback, and stop the operation if a shared page is encountered. Because CONFIG_KVM_PRIVATE_MEM in principle does not require attributes, this makes kvm_gmem_populate() depend on CONFIG_KVM_GENERIC_PRIVATE_MEM (which does require them). Reviewed-by: Michael Roth <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 4b5f671 commit e4ee544

File tree

3 files changed

+14
-7
lines changed

3 files changed

+14
-7
lines changed

arch/x86/kvm/svm/sev.c

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2279,13 +2279,6 @@ static int sev_gmem_post_populate(struct kvm *kvm, gfn_t gfn_start, kvm_pfn_t pf
22792279
bool assigned;
22802280
int level;
22812281

2282-
if (!kvm_mem_is_private(kvm, gfn)) {
2283-
pr_debug("%s: Failed to ensure GFN 0x%llx has private memory attribute set\n",
2284-
__func__, gfn);
2285-
ret = -EINVAL;
2286-
goto err;
2287-
}
2288-
22892282
ret = snp_lookup_rmpentry((u64)pfn + i, &assigned, &level);
22902283
if (ret || assigned) {
22912284
pr_debug("%s: Failed to ensure GFN 0x%llx RMP entry is initial shared state, ret: %d assigned: %d\n",

include/linux/kvm_host.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2449,6 +2449,7 @@ static inline int kvm_gmem_get_pfn(struct kvm *kvm,
24492449
int kvm_arch_gmem_prepare(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn, int max_order);
24502450
#endif
24512451

2452+
#ifdef CONFIG_KVM_GENERIC_PRIVATE_MEM
24522453
/**
24532454
* kvm_gmem_populate() - Populate/prepare a GPA range with guest data
24542455
*
@@ -2475,6 +2476,7 @@ typedef int (*kvm_gmem_populate_cb)(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,
24752476

24762477
long kvm_gmem_populate(struct kvm *kvm, gfn_t gfn, void __user *src, long npages,
24772478
kvm_gmem_populate_cb post_populate, void *opaque);
2479+
#endif
24782480

24792481
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE
24802482
void kvm_arch_gmem_invalidate(kvm_pfn_t start, kvm_pfn_t end);

virt/kvm/guest_memfd.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,7 @@ int kvm_gmem_get_pfn(struct kvm *kvm, struct kvm_memory_slot *slot,
612612
}
613613
EXPORT_SYMBOL_GPL(kvm_gmem_get_pfn);
614614

615+
#ifdef CONFIG_KVM_GENERIC_PRIVATE_MEM
615616
long kvm_gmem_populate(struct kvm *kvm, gfn_t start_gfn, void __user *src, long npages,
616617
kvm_gmem_populate_cb post_populate, void *opaque)
617618
{
@@ -665,11 +666,21 @@ long kvm_gmem_populate(struct kvm *kvm, gfn_t start_gfn, void __user *src, long
665666
(npages - i) < (1 << max_order))
666667
max_order = 0;
667668

669+
ret = -EINVAL;
670+
while (!kvm_range_has_memory_attributes(kvm, gfn, gfn + (1 << max_order),
671+
KVM_MEMORY_ATTRIBUTE_PRIVATE,
672+
KVM_MEMORY_ATTRIBUTE_PRIVATE)) {
673+
if (!max_order)
674+
goto put_folio_and_exit;
675+
max_order--;
676+
}
677+
668678
p = src ? src + i * PAGE_SIZE : NULL;
669679
ret = post_populate(kvm, gfn, pfn, p, max_order, opaque);
670680
if (!ret)
671681
folio_mark_uptodate(folio);
672682

683+
put_folio_and_exit:
673684
folio_put(folio);
674685
if (ret)
675686
break;
@@ -681,3 +692,4 @@ long kvm_gmem_populate(struct kvm *kvm, gfn_t start_gfn, void __user *src, long
681692
return ret && !i ? ret : i;
682693
}
683694
EXPORT_SYMBOL_GPL(kvm_gmem_populate);
695+
#endif

0 commit comments

Comments
 (0)