diff mbox

[v2] kvm: nVMX: Check memory operand to INVVPID

Message ID 20170628163737.111865-1-jmattson@google.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jim Mattson June 28, 2017, 4:37 p.m. UTC
The memory operand fetched for INVVPID is 128 bits. Bits 63:16 are
reserved and must be zero.  Otherwise, the instruction fails with
VMfail(Invalid operand to INVEPT/INVVPID).  If the INVVPID_TYPE is 0
(individual address invalidation), then bits 127:64 must be in
canonical form, or the instruction fails with VMfail(Invalid operand
to INVEPT/INVVPID).

Signed-off-by: Jim Mattson <jmattson@google.com>
---
 arch/x86/kvm/vmx.c | 22 ++++++++++++++++++----
 1 file changed, 18 insertions(+), 4 deletions(-)

Comments

Paolo Bonzini June 28, 2017, 4:43 p.m. UTC | #1
On 28/06/2017 18:37, Jim Mattson wrote:
> The memory operand fetched for INVVPID is 128 bits. Bits 63:16 are
> reserved and must be zero.  Otherwise, the instruction fails with
> VMfail(Invalid operand to INVEPT/INVVPID).  If the INVVPID_TYPE is 0
> (individual address invalidation), then bits 127:64 must be in
> canonical form, or the instruction fails with VMfail(Invalid operand
> to INVEPT/INVVPID).
> 
> Signed-off-by: Jim Mattson <jmattson@google.com>
> ---
>  arch/x86/kvm/vmx.c | 22 ++++++++++++++++++----
>  1 file changed, 18 insertions(+), 4 deletions(-)

Thanks, looks good.  Will apply, kvm-unit-tests patches are always
welcome. :)

Paolo

> diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
> index 42db3eb2d13b..3c80a2fec5c6 100644
> --- a/arch/x86/kvm/vmx.c
> +++ b/arch/x86/kvm/vmx.c
> @@ -7651,7 +7651,10 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)
>  	unsigned long type, types;
>  	gva_t gva;
>  	struct x86_exception e;
> -	int vpid;
> +	struct {
> +		u64 vpid;
> +		u64 gla;
> +	} operand;
>  
>  	if (!(vmx->nested.nested_vmx_secondary_ctls_high &
>  	      SECONDARY_EXEC_ENABLE_VPID) ||
> @@ -7681,17 +7684,28 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)
>  	if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
>  			vmx_instruction_info, false, &gva))
>  		return 1;
> -	if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, &vpid,
> -				sizeof(u32), &e)) {
> +	if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, &operand,
> +				sizeof(operand), &e)) {
>  		kvm_inject_page_fault(vcpu, &e);
>  		return 1;
>  	}
> +	if (operand.vpid >> 16) {
> +		nested_vmx_failValid(vcpu,
> +			VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
> +		return kvm_skip_emulated_instruction(vcpu);
> +	}
>  
>  	switch (type) {
>  	case VMX_VPID_EXTENT_INDIVIDUAL_ADDR:
> +		if (is_noncanonical_address(operand.gla)) {
> +			nested_vmx_failValid(vcpu,
> +				VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
> +			return kvm_skip_emulated_instruction(vcpu);
> +		}
> +		/* fall through */
>  	case VMX_VPID_EXTENT_SINGLE_CONTEXT:
>  	case VMX_VPID_EXTENT_SINGLE_NON_GLOBAL:
> -		if (!vpid) {
> +		if (!operand.vpid) {
>  			nested_vmx_failValid(vcpu,
>  				VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
>  			return kvm_skip_emulated_instruction(vcpu);
>
David Hildenbrand June 28, 2017, 5 p.m. UTC | #2
On 28.06.2017 18:37, Jim Mattson wrote:
> The memory operand fetched for INVVPID is 128 bits. Bits 63:16 are
> reserved and must be zero.  Otherwise, the instruction fails with
> VMfail(Invalid operand to INVEPT/INVVPID).  If the INVVPID_TYPE is 0
> (individual address invalidation), then bits 127:64 must be in
> canonical form, or the instruction fails with VMfail(Invalid operand
> to INVEPT/INVVPID).
> 
> Signed-off-by: Jim Mattson <jmattson@google.com>
> ---

My r-b still holds :)
Paolo Bonzini June 29, 2017, 8:22 a.m. UTC | #3
On 29/06/2017 00:41, Jim Mattson wrote:
>     Will apply, kvm-unit-tests patches are always
>     welcome. :)
> 
> Working on a crossport of the test. Bear with me.

No problem.

David, any news on the EPT without A/D bugfix, too?

Paolo
David Matlack June 29, 2017, 6:14 p.m. UTC | #4
On Thu, Jun 29, 2017 at 1:22 AM, Paolo Bonzini <pbonzini@redhat.com> wrote:
> On 29/06/2017 00:41, Jim Mattson wrote:
>>     Will apply, kvm-unit-tests patches are always
>>     welcome. :)
>>
>> Working on a crossport of the test. Bear with me.
>
> No problem.
>
> David, any news on the EPT without A/D bugfix, too?

Thanks for the reminder. Peter's aiming to get it out today or
tomorrow. Sorry for the delay!

>
> Paolo
Peter Feiner June 30, 2017, 9:55 p.m. UTC | #5
On Thu, Jun 29, 2017 at 11:14 AM, David Matlack <dmatlack@google.com> wrote:
> On Thu, Jun 29, 2017 at 1:22 AM, Paolo Bonzini <pbonzini@redhat.com> wrote:
>> On 29/06/2017 00:41, Jim Mattson wrote:
>>>     Will apply, kvm-unit-tests patches are always
>>>     welcome. :)
>>>
>>> Working on a crossport of the test. Bear with me.
>>
>> No problem.
>>
>> David, any news on the EPT without A/D bugfix, too?
>
> Thanks for the reminder. Peter's aiming to get it out today or
> tomorrow. Sorry for the delay!

I could send the patches out but they aren't working yet :-) Debugging
the bitrot between Google's kernel & upstream is taking longer than I
had hoped.

Since I'm on vacation next week, I won't have it working until
sometime during the week of July 10.

Again, sorry for the delay getting started on this.

Peter
diff mbox

Patch

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 42db3eb2d13b..3c80a2fec5c6 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -7651,7 +7651,10 @@  static int handle_invvpid(struct kvm_vcpu *vcpu)
 	unsigned long type, types;
 	gva_t gva;
 	struct x86_exception e;
-	int vpid;
+	struct {
+		u64 vpid;
+		u64 gla;
+	} operand;
 
 	if (!(vmx->nested.nested_vmx_secondary_ctls_high &
 	      SECONDARY_EXEC_ENABLE_VPID) ||
@@ -7681,17 +7684,28 @@  static int handle_invvpid(struct kvm_vcpu *vcpu)
 	if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
 			vmx_instruction_info, false, &gva))
 		return 1;
-	if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, &vpid,
-				sizeof(u32), &e)) {
+	if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, &operand,
+				sizeof(operand), &e)) {
 		kvm_inject_page_fault(vcpu, &e);
 		return 1;
 	}
+	if (operand.vpid >> 16) {
+		nested_vmx_failValid(vcpu,
+			VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
+		return kvm_skip_emulated_instruction(vcpu);
+	}
 
 	switch (type) {
 	case VMX_VPID_EXTENT_INDIVIDUAL_ADDR:
+		if (is_noncanonical_address(operand.gla)) {
+			nested_vmx_failValid(vcpu,
+				VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
+			return kvm_skip_emulated_instruction(vcpu);
+		}
+		/* fall through */
 	case VMX_VPID_EXTENT_SINGLE_CONTEXT:
 	case VMX_VPID_EXTENT_SINGLE_NON_GLOBAL:
-		if (!vpid) {
+		if (!operand.vpid) {
 			nested_vmx_failValid(vcpu,
 				VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
 			return kvm_skip_emulated_instruction(vcpu);