x86/HVM: don't leak PFEC_implict to guests Doing so may not only confuse them, but will - on VMX - lead to VMRESUME failures. Add respective ASSERT()s where the fields get set to guard against future similar issues (or - in the restore case - fail the operation). In that latter code at once convert the mis-used gdprintk() to dprintk(), as the vCPU of interest is not "current". Signed-off-by: Jan Beulich --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -3111,7 +3111,7 @@ static enum hvm_copy_result __hvm_copy( if ( pfinfo ) { pfinfo->linear = addr; - pfinfo->ec = pfec; + pfinfo->ec = pfec & ~PFEC_implicit; } return HVMCOPY_bad_gva_to_gfn; } --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -269,13 +269,23 @@ static int svm_vmcb_restore(struct vcpu struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; struct p2m_domain *p2m = p2m_get_hostp2m(v->domain); - if ( c->pending_valid && - ((c->pending_type == 1) || (c->pending_type > 6) || - (c->pending_reserved != 0)) ) + if ( c->pending_valid ) { - gdprintk(XENLOG_ERR, "Invalid pending event %#"PRIx32".\n", - c->pending_event); - return -EINVAL; + if ( (c->pending_type == 1) || (c->pending_type > 6) || + (c->pending_reserved != 0) ) + { + dprintk(XENLOG_ERR, "%pv: Invalid pending event %#"PRIx32".\n", + v, c->pending_event); + return -EINVAL; + } + + if ( c->pending_error_valid && + c->error_code != (uint16_t)c->error_code ) + { + dprintk(XENLOG_ERR, "%pv: Invalid error code %#"PRIx32".\n", + v, c->error_code); + return -EINVAL; + } } if ( !paging_mode_hap(v->domain) ) @@ -1288,6 +1298,8 @@ static void svm_inject_event(const struc vmcb->nextrip = (uint32_t)vmcb->nextrip; } + ASSERT(!eventinj.fields.ev || + eventinj.fields.errorcode == (uint16_t)eventinj.fields.errorcode); vmcb->eventinj = eventinj; if ( _event.vector == TRAP_page_fault ) --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -731,13 +731,23 @@ static int vmx_vmcs_restore(struct vcpu { int rc; - if ( c->pending_valid && - ((c->pending_type == 1) || (c->pending_type > 6) || - (c->pending_reserved != 0)) ) + if ( c->pending_valid ) { - gdprintk(XENLOG_ERR, "Invalid pending event %#"PRIx32".\n", - c->pending_event); - return -EINVAL; + if ( (c->pending_type == 1) || (c->pending_type > 6) || + (c->pending_reserved != 0) ) + { + dprintk(XENLOG_ERR, "%pv: Invalid pending event %#"PRIx32".\n", + v, c->pending_event); + return -EINVAL; + } + + if ( c->pending_error_valid && + c->error_code != (uint16_t)c->error_code ) + { + dprintk(XENLOG_ERR, "%pv: Invalid error code %#"PRIx32".\n", + v, c->error_code); + return -EINVAL; + } } rc = vmx_restore_cr0_cr3(v, c->cr0, c->cr3); @@ -1660,6 +1670,7 @@ static void __vmx_inject_exception(int t MASK_INSR(trap, INTR_INFO_VECTOR_MASK); if ( error_code != X86_EVENT_NO_EC ) { + ASSERT(error_code == (uint16_t)error_code); __vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code); intr_fields |= INTR_INFO_DELIVER_CODE_MASK; }