Skip to content

Commit cd389f5

Browse files
committed
KVM: x86/mmu: check for invalid async page faults involving private memory
Right now the error code is not used when an async page fault is completed. This is not a problem in the current code, but it is untidy. For protected VMs, we will also need to check that the page attributes match the current state of the page, because asynchronous page faults can only occur on shared pages (private pages go through kvm_faultin_pfn_private() instead of __gfn_to_pfn_memslot()). Start by piping the error code from kvm_arch_setup_async_pf() to kvm_arch_async_page_ready() via the architecture-specific async page fault data. For now, it can be used to assert that there are no async page faults on private memory. Extracted from a patch by Isaku Yamahata. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent b3d5dc6 commit cd389f5

2 files changed

Lines changed: 12 additions & 7 deletions

File tree

arch/x86/include/asm/kvm_host.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1849,6 +1849,7 @@ struct kvm_arch_async_pf {
18491849
gfn_t gfn;
18501850
unsigned long cr3;
18511851
bool direct_map;
1852+
u64 error_code;
18521853
};
18531854

18541855
extern u32 __read_mostly kvm_nr_uret_msrs;

arch/x86/kvm/mmu/mmu.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4206,24 +4206,28 @@ static u32 alloc_apf_token(struct kvm_vcpu *vcpu)
42064206
return (vcpu->arch.apf.id++ << 12) | vcpu->vcpu_id;
42074207
}
42084208

4209-
static bool kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
4210-
gfn_t gfn)
4209+
static bool kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu,
4210+
struct kvm_page_fault *fault)
42114211
{
42124212
struct kvm_arch_async_pf arch;
42134213

42144214
arch.token = alloc_apf_token(vcpu);
4215-
arch.gfn = gfn;
4215+
arch.gfn = fault->gfn;
4216+
arch.error_code = fault->error_code;
42164217
arch.direct_map = vcpu->arch.mmu->root_role.direct;
42174218
arch.cr3 = kvm_mmu_get_guest_pgd(vcpu, vcpu->arch.mmu);
42184219

4219-
return kvm_setup_async_pf(vcpu, cr2_or_gpa,
4220-
kvm_vcpu_gfn_to_hva(vcpu, gfn), &arch);
4220+
return kvm_setup_async_pf(vcpu, fault->addr,
4221+
kvm_vcpu_gfn_to_hva(vcpu, fault->gfn), &arch);
42214222
}
42224223

42234224
void kvm_arch_async_page_ready(struct kvm_vcpu *vcpu, struct kvm_async_pf *work)
42244225
{
42254226
int r;
42264227

4228+
if (WARN_ON_ONCE(work->arch.error_code & PFERR_PRIVATE_ACCESS))
4229+
return;
4230+
42274231
if ((vcpu->arch.mmu->root_role.direct != work->arch.direct_map) ||
42284232
work->wakeup_all)
42294233
return;
@@ -4236,7 +4240,7 @@ void kvm_arch_async_page_ready(struct kvm_vcpu *vcpu, struct kvm_async_pf *work)
42364240
work->arch.cr3 != kvm_mmu_get_guest_pgd(vcpu, vcpu->arch.mmu))
42374241
return;
42384242

4239-
kvm_mmu_do_page_fault(vcpu, work->cr2_or_gpa, 0, true, NULL);
4243+
kvm_mmu_do_page_fault(vcpu, work->cr2_or_gpa, work->arch.error_code, true, NULL);
42404244
}
42414245

42424246
static inline u8 kvm_max_level_for_order(int order)
@@ -4333,7 +4337,7 @@ static int __kvm_faultin_pfn(struct kvm_vcpu *vcpu, struct kvm_page_fault *fault
43334337
trace_kvm_async_pf_repeated_fault(fault->addr, fault->gfn);
43344338
kvm_make_request(KVM_REQ_APF_HALT, vcpu);
43354339
return RET_PF_RETRY;
4336-
} else if (kvm_arch_setup_async_pf(vcpu, fault->addr, fault->gfn)) {
4340+
} else if (kvm_arch_setup_async_pf(vcpu, fault)) {
43374341
return RET_PF_RETRY;
43384342
}
43394343
}

0 commit comments

Comments
 (0)