Skip to content

Commit 2f37f74

Browse files
committed
KVM: guest_memfd: let kvm_gmem_populate() operate only on private gfns
JIRA: https://issues.redhat.com/browse/RHEL-32435 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 <michael.roth@amd.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> (cherry picked from commit e4ee544) Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent 8f2d1be commit 2f37f74

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
@@ -2202,13 +2202,6 @@ static int sev_gmem_post_populate(struct kvm *kvm, gfn_t gfn_start, kvm_pfn_t pf
22022202
bool assigned;
22032203
int level;
22042204

2205-
if (!kvm_mem_is_private(kvm, gfn)) {
2206-
pr_debug("%s: Failed to ensure GFN 0x%llx has private memory attribute set\n",
2207-
__func__, gfn);
2208-
ret = -EINVAL;
2209-
goto err;
2210-
}
2211-
22122205
ret = snp_lookup_rmpentry((u64)pfn + i, &assigned, &level);
22132206
if (ret || assigned) {
22142207
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
@@ -2447,6 +2447,7 @@ static inline int kvm_gmem_get_pfn(struct kvm *kvm,
24472447
int kvm_arch_gmem_prepare(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn, int max_order);
24482448
#endif
24492449

2450+
#ifdef CONFIG_KVM_GENERIC_PRIVATE_MEM
24502451
/**
24512452
* kvm_gmem_populate() - Populate/prepare a GPA range with guest data
24522453
*
@@ -2473,6 +2474,7 @@ typedef int (*kvm_gmem_populate_cb)(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,
24732474

24742475
long kvm_gmem_populate(struct kvm *kvm, gfn_t gfn, void __user *src, long npages,
24752476
kvm_gmem_populate_cb post_populate, void *opaque);
2477+
#endif
24762478

24772479
#ifdef CONFIG_HAVE_KVM_ARCH_GMEM_INVALIDATE
24782480
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
@@ -616,6 +616,7 @@ int kvm_gmem_get_pfn(struct kvm *kvm, struct kvm_memory_slot *slot,
616616
}
617617
EXPORT_SYMBOL_GPL(kvm_gmem_get_pfn);
618618

619+
#ifdef CONFIG_KVM_GENERIC_PRIVATE_MEM
619620
long kvm_gmem_populate(struct kvm *kvm, gfn_t start_gfn, void __user *src, long npages,
620621
kvm_gmem_populate_cb post_populate, void *opaque)
621622
{
@@ -669,11 +670,21 @@ long kvm_gmem_populate(struct kvm *kvm, gfn_t start_gfn, void __user *src, long
669670
(npages - i) < (1 << max_order))
670671
max_order = 0;
671672

673+
ret = -EINVAL;
674+
while (!kvm_range_has_memory_attributes(kvm, gfn, gfn + (1 << max_order),
675+
KVM_MEMORY_ATTRIBUTE_PRIVATE,
676+
KVM_MEMORY_ATTRIBUTE_PRIVATE)) {
677+
if (!max_order)
678+
goto put_folio_and_exit;
679+
max_order--;
680+
}
681+
672682
p = src ? src + i * PAGE_SIZE : NULL;
673683
ret = post_populate(kvm, gfn, pfn, p, max_order, opaque);
674684
if (!ret)
675685
folio_mark_uptodate(folio);
676686

687+
put_folio_and_exit:
677688
folio_put(folio);
678689
if (ret)
679690
break;
@@ -685,3 +696,4 @@ long kvm_gmem_populate(struct kvm *kvm, gfn_t start_gfn, void __user *src, long
685696
return ret && !i ? ret : i;
686697
}
687698
EXPORT_SYMBOL_GPL(kvm_gmem_populate);
699+
#endif

0 commit comments

Comments
 (0)