diff options
-rw-r--r-- | arch/x86/kvm/paging_tmpl.h | 9 |
1 files changed, 8 insertions, 1 deletions
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h index 9d03ad4dd5ec..1caeb4d22e01 100644 --- a/arch/x86/kvm/paging_tmpl.h +++ b/arch/x86/kvm/paging_tmpl.h | |||
@@ -246,6 +246,12 @@ walk: | |||
246 | gfn_t gfn; | 246 | gfn_t gfn; |
247 | u32 ac; | 247 | u32 ac; |
248 | 248 | ||
249 | /* check if the kernel is fetching from user page */ | ||
250 | if (unlikely(pte_access & PT_USER_MASK) && | ||
251 | kvm_read_cr4_bits(vcpu, X86_CR4_SMEP)) | ||
252 | if (fetch_fault && !user_fault) | ||
253 | eperm = true; | ||
254 | |||
249 | gfn = gpte_to_gfn_lvl(pte, lvl); | 255 | gfn = gpte_to_gfn_lvl(pte, lvl); |
250 | gfn += (addr & PT_LVL_OFFSET_MASK(lvl)) >> PAGE_SHIFT; | 256 | gfn += (addr & PT_LVL_OFFSET_MASK(lvl)) >> PAGE_SHIFT; |
251 | 257 | ||
@@ -305,7 +311,8 @@ error: | |||
305 | 311 | ||
306 | walker->fault.error_code |= write_fault | user_fault; | 312 | walker->fault.error_code |= write_fault | user_fault; |
307 | 313 | ||
308 | if (fetch_fault && mmu->nx) | 314 | if (fetch_fault && (mmu->nx || |
315 | kvm_read_cr4_bits(vcpu, X86_CR4_SMEP))) | ||
309 | walker->fault.error_code |= PFERR_FETCH_MASK; | 316 | walker->fault.error_code |= PFERR_FETCH_MASK; |
310 | if (rsvd_fault) | 317 | if (rsvd_fault) |
311 | walker->fault.error_code |= PFERR_RSVD_MASK; | 318 | walker->fault.error_code |= PFERR_RSVD_MASK; |