mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 09:36:22 +02:00
KVM: SEV: Pin source page for write when adding CPUID data for SNP guest
When populating a guest_memfd instance with the initial CPUID data for an
SNP guest, acquire a writable pin on the source page as KVM will write back
the "correct" CPUID information if the userspace provided data is rejected
by trusted firmware. Because KVM writes to the source page using a kernel
mapping, pinning for read could result in KVM clobbering read-only memory.
Note, well-behaved VMMs are unlikely to be affected, as CPUID information
is almost always dynamically generated by userspace, i.e. it's unlikely for
the CPUID information to be backed by a read-only mapping.
Fixes: 2a62345b30 ("KVM: guest_memfd: GUP source pages prior to populating guest memory")
Cc: stable@vger.kernel.org
Signed-off-by: Ackerley Tng <ackerleytng@google.com>
Link: https://patch.msgid.link/20260522-fix-sev-gmem-post-populate-v2-1-3f196bfad5a1@google.com
[sean: rewrite shortlog and changelog, tag for stable@]
Signed-off-by: Sean Christopherson <seanjc@google.com>
This commit is contained in:
parent
4c735bf1bc
commit
f13e900599
|
|
@ -2456,6 +2456,7 @@ static int snp_launch_update(struct kvm *kvm, struct kvm_sev_cmd *argp)
|
|||
sev_populate_args.type = params.type;
|
||||
|
||||
count = kvm_gmem_populate(kvm, params.gfn_start, src, npages,
|
||||
params.type == KVM_SEV_SNP_PAGE_TYPE_CPUID,
|
||||
sev_gmem_post_populate, &sev_populate_args);
|
||||
if (count < 0) {
|
||||
argp->error = sev_populate_args.fw_error;
|
||||
|
|
|
|||
|
|
@ -3185,7 +3185,7 @@ static int tdx_vcpu_init_mem_region(struct kvm_vcpu *vcpu, struct kvm_tdx_cmd *c
|
|||
};
|
||||
gmem_ret = kvm_gmem_populate(kvm, gpa_to_gfn(region.gpa),
|
||||
u64_to_user_ptr(region.source_addr),
|
||||
1, tdx_gmem_post_populate, &arg);
|
||||
1, false, tdx_gmem_post_populate, &arg);
|
||||
if (gmem_ret < 0) {
|
||||
ret = gmem_ret;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -2596,7 +2596,8 @@ int kvm_arch_gmem_prepare(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn, int max_ord
|
|||
typedef int (*kvm_gmem_populate_cb)(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,
|
||||
struct page *page, void *opaque);
|
||||
|
||||
long kvm_gmem_populate(struct kvm *kvm, gfn_t gfn, void __user *src, long npages,
|
||||
long kvm_gmem_populate(struct kvm *kvm, gfn_t start_gfn, void __user *src,
|
||||
long npages, bool may_writeback_src,
|
||||
kvm_gmem_populate_cb post_populate, void *opaque);
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -858,7 +858,8 @@ static long __kvm_gmem_populate(struct kvm *kvm, struct kvm_memory_slot *slot,
|
|||
return ret;
|
||||
}
|
||||
|
||||
long kvm_gmem_populate(struct kvm *kvm, gfn_t start_gfn, void __user *src, long npages,
|
||||
long kvm_gmem_populate(struct kvm *kvm, gfn_t start_gfn, void __user *src,
|
||||
long npages, bool may_writeback_src,
|
||||
kvm_gmem_populate_cb post_populate, void *opaque)
|
||||
{
|
||||
struct kvm_memory_slot *slot;
|
||||
|
|
@ -892,8 +893,9 @@ long kvm_gmem_populate(struct kvm *kvm, gfn_t start_gfn, void __user *src, long
|
|||
|
||||
if (src) {
|
||||
unsigned long uaddr = (unsigned long)src + i * PAGE_SIZE;
|
||||
unsigned int flags = may_writeback_src ? FOLL_WRITE : 0;
|
||||
|
||||
ret = get_user_pages_fast(uaddr, 1, 0, &src_page);
|
||||
ret = get_user_pages_fast(uaddr, 1, flags, &src_page);
|
||||
if (ret < 0)
|
||||
break;
|
||||
if (ret != 1) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user