All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] KVM: X86: Fix load RFLAGS w/o the fixed bit
@ 2017-12-06 11:59 Wanpeng Li
  2017-12-06 14:40 ` David Hildenbrand
  0 siblings, 1 reply; 6+ messages in thread
From: Wanpeng Li @ 2017-12-06 11:59 UTC (permalink / raw)
  To: linux-kernel, kvm
  Cc: Paolo Bonzini, Radim Krčmář, Wanpeng Li, Jim Mattson

From: Wanpeng Li <wanpeng.li@hotmail.com>

 *** Guest State ***
 CR0: actual=0x0000000000000030, shadow=0x0000000060000010, gh_mask=fffffffffffffff7
 CR4: actual=0x0000000000002050, shadow=0x0000000000000000, gh_mask=ffffffffffffe871
 CR3 = 0x00000000fffbc000
 RSP = 0x0000000000000000  RIP = 0x0000000000000000
 RFLAGS=0x00000000         DR7 = 0x0000000000000400
        ^^^^^^^^^^

The failed vmentry is triggered by the following testcase when ept=Y:

    #include <unistd.h>
    #include <sys/syscall.h>
    #include <string.h>
    #include <stdint.h>
    #include <linux/kvm.h>
    #include <fcntl.h>
    #include <sys/ioctl.h>
    
    long r[5];
    int main()
    {
    	r[2] = open("/dev/kvm", O_RDONLY);
    	r[3] = ioctl(r[2], KVM_CREATE_VM, 0);
    	r[4] = ioctl(r[3], KVM_CREATE_VCPU, 7);
    	struct kvm_regs regs = {
    		.rflags = 0,
    	};
    	ioctl(r[4], KVM_SET_REGS, &regs);
    	ioctl(r[4], KVM_RUN, 0);
    }

X86 RFLAGS bit 1 is fixed set, userspace can simply clearing bit 1 
of RFLAGS with KVM_SET_REGS ioctl which results in vmentry fails.
This patch fixes it by oring X86_EFLAGS_FIXED during ioctl.

Suggested-by: Jim Mattson <jmattson@google.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Radim Krčmář <rkrcmar@redhat.com>
Cc: Jim Mattson <jmattson@google.com>
Signed-off-by: Wanpeng Li <wanpeng.li@hotmail.com>
---
v1 -> v2:
 * Oring X86_EFLAGS_FIXED

 virt/kvm/kvm_main.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index b55bad3..0f3f283 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2602,6 +2602,7 @@ static long kvm_vcpu_ioctl(struct file *filp,
 			r = PTR_ERR(kvm_regs);
 			goto out;
 		}
+		kvm_regs->rflags |= X86_EFLAGS_FIXED;
 		r = kvm_arch_vcpu_ioctl_set_regs(vcpu, kvm_regs);
 		kfree(kvm_regs);
 		break;
-- 
2.7.4

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] KVM: X86: Fix load RFLAGS w/o the fixed bit
  2017-12-06 11:59 [PATCH v2] KVM: X86: Fix load RFLAGS w/o the fixed bit Wanpeng Li
@ 2017-12-06 14:40 ` David Hildenbrand
  2017-12-06 17:14   ` Jim Mattson
  2017-12-06 17:28   ` David Hildenbrand
  0 siblings, 2 replies; 6+ messages in thread
From: David Hildenbrand @ 2017-12-06 14:40 UTC (permalink / raw)
  To: Wanpeng Li, linux-kernel, kvm
  Cc: Paolo Bonzini, Radim Krčmář, Wanpeng Li, Jim Mattson

On 06.12.2017 12:59, Wanpeng Li wrote:
> From: Wanpeng Li <wanpeng.li@hotmail.com>
> 
>  *** Guest State ***
>  CR0: actual=0x0000000000000030, shadow=0x0000000060000010, gh_mask=fffffffffffffff7
>  CR4: actual=0x0000000000002050, shadow=0x0000000000000000, gh_mask=ffffffffffffe871
>  CR3 = 0x00000000fffbc000
>  RSP = 0x0000000000000000  RIP = 0x0000000000000000
>  RFLAGS=0x00000000         DR7 = 0x0000000000000400
>         ^^^^^^^^^^
> 
> The failed vmentry is triggered by the following testcase when ept=Y:
> 
>     #include <unistd.h>
>     #include <sys/syscall.h>
>     #include <string.h>
>     #include <stdint.h>
>     #include <linux/kvm.h>
>     #include <fcntl.h>
>     #include <sys/ioctl.h>
>     
>     long r[5];
>     int main()
>     {
>     	r[2] = open("/dev/kvm", O_RDONLY);
>     	r[3] = ioctl(r[2], KVM_CREATE_VM, 0);
>     	r[4] = ioctl(r[3], KVM_CREATE_VCPU, 7);
>     	struct kvm_regs regs = {
>     		.rflags = 0,
>     	};
>     	ioctl(r[4], KVM_SET_REGS, &regs);
>     	ioctl(r[4], KVM_RUN, 0);
>     }
> 
> X86 RFLAGS bit 1 is fixed set, userspace can simply clearing bit 1 
> of RFLAGS with KVM_SET_REGS ioctl which results in vmentry fails.
> This patch fixes it by oring X86_EFLAGS_FIXED during ioctl.
> 
> Suggested-by: Jim Mattson <jmattson@google.com>
> Cc: Paolo Bonzini <pbonzini@redhat.com>
> Cc: Radim Krčmář <rkrcmar@redhat.com>
> Cc: Jim Mattson <jmattson@google.com>
> Signed-off-by: Wanpeng Li <wanpeng.li@hotmail.com>
> ---
> v1 -> v2:
>  * Oring X86_EFLAGS_FIXED
> 
>  virt/kvm/kvm_main.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index b55bad3..0f3f283 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -2602,6 +2602,7 @@ static long kvm_vcpu_ioctl(struct file *filp,
>  			r = PTR_ERR(kvm_regs);
>  			goto out;
>  		}
> +		kvm_regs->rflags |= X86_EFLAGS_FIXED;
>  		r = kvm_arch_vcpu_ioctl_set_regs(vcpu, kvm_regs);
>  		kfree(kvm_regs);
>  		break;
> 

Not sure if failing KVM_SET_REGS would be nicer, but maybe this has
already been discussed. So this should be fine.

Reviewed-by: David Hildenbrand <david@redhat.com>

-- 

Thanks,

David / dhildenb

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] KVM: X86: Fix load RFLAGS w/o the fixed bit
  2017-12-06 14:40 ` David Hildenbrand
@ 2017-12-06 17:14   ` Jim Mattson
  2017-12-07  3:21     ` Wanpeng Li
  2017-12-06 17:28   ` David Hildenbrand
  1 sibling, 1 reply; 6+ messages in thread
From: Jim Mattson @ 2017-12-06 17:14 UTC (permalink / raw)
  To: David Hildenbrand
  Cc: Wanpeng Li, LKML, kvm list, Paolo Bonzini,
	Radim Krčmář,
	Wanpeng Li

What if I change the testcase so that regs.rflags is initialized to (1 << 3)?

On Wed, Dec 6, 2017 at 6:40 AM, David Hildenbrand <david@redhat.com> wrote:
> On 06.12.2017 12:59, Wanpeng Li wrote:
>> From: Wanpeng Li <wanpeng.li@hotmail.com>
>>
>>  *** Guest State ***
>>  CR0: actual=0x0000000000000030, shadow=0x0000000060000010, gh_mask=fffffffffffffff7
>>  CR4: actual=0x0000000000002050, shadow=0x0000000000000000, gh_mask=ffffffffffffe871
>>  CR3 = 0x00000000fffbc000
>>  RSP = 0x0000000000000000  RIP = 0x0000000000000000
>>  RFLAGS=0x00000000         DR7 = 0x0000000000000400
>>         ^^^^^^^^^^
>>
>> The failed vmentry is triggered by the following testcase when ept=Y:
>>
>>     #include <unistd.h>
>>     #include <sys/syscall.h>
>>     #include <string.h>
>>     #include <stdint.h>
>>     #include <linux/kvm.h>
>>     #include <fcntl.h>
>>     #include <sys/ioctl.h>
>>
>>     long r[5];
>>     int main()
>>     {
>>       r[2] = open("/dev/kvm", O_RDONLY);
>>       r[3] = ioctl(r[2], KVM_CREATE_VM, 0);
>>       r[4] = ioctl(r[3], KVM_CREATE_VCPU, 7);
>>       struct kvm_regs regs = {
>>               .rflags = 0,
>>       };
>>       ioctl(r[4], KVM_SET_REGS, &regs);
>>       ioctl(r[4], KVM_RUN, 0);
>>     }
>>
>> X86 RFLAGS bit 1 is fixed set, userspace can simply clearing bit 1
>> of RFLAGS with KVM_SET_REGS ioctl which results in vmentry fails.
>> This patch fixes it by oring X86_EFLAGS_FIXED during ioctl.
>>
>> Suggested-by: Jim Mattson <jmattson@google.com>
>> Cc: Paolo Bonzini <pbonzini@redhat.com>
>> Cc: Radim Krčmář <rkrcmar@redhat.com>
>> Cc: Jim Mattson <jmattson@google.com>
>> Signed-off-by: Wanpeng Li <wanpeng.li@hotmail.com>
>> ---
>> v1 -> v2:
>>  * Oring X86_EFLAGS_FIXED
>>
>>  virt/kvm/kvm_main.c | 1 +
>>  1 file changed, 1 insertion(+)
>>
>> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
>> index b55bad3..0f3f283 100644
>> --- a/virt/kvm/kvm_main.c
>> +++ b/virt/kvm/kvm_main.c
>> @@ -2602,6 +2602,7 @@ static long kvm_vcpu_ioctl(struct file *filp,
>>                       r = PTR_ERR(kvm_regs);
>>                       goto out;
>>               }
>> +             kvm_regs->rflags |= X86_EFLAGS_FIXED;
>>               r = kvm_arch_vcpu_ioctl_set_regs(vcpu, kvm_regs);
>>               kfree(kvm_regs);
>>               break;
>>
>
> Not sure if failing KVM_SET_REGS would be nicer, but maybe this has
> already been discussed. So this should be fine.
>
> Reviewed-by: David Hildenbrand <david@redhat.com>
>
> --
>
> Thanks,
>
> David / dhildenb

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] KVM: X86: Fix load RFLAGS w/o the fixed bit
  2017-12-06 14:40 ` David Hildenbrand
  2017-12-06 17:14   ` Jim Mattson
@ 2017-12-06 17:28   ` David Hildenbrand
  2017-12-07  8:32     ` Wanpeng Li
  1 sibling, 1 reply; 6+ messages in thread
From: David Hildenbrand @ 2017-12-06 17:28 UTC (permalink / raw)
  To: Wanpeng Li, linux-kernel, kvm
  Cc: Paolo Bonzini, Radim Krčmář, Wanpeng Li, Jim Mattson

On 06.12.2017 15:40, David Hildenbrand wrote:
> On 06.12.2017 12:59, Wanpeng Li wrote:
>> From: Wanpeng Li <wanpeng.li@hotmail.com>
>>
>>  *** Guest State ***
>>  CR0: actual=0x0000000000000030, shadow=0x0000000060000010, gh_mask=fffffffffffffff7
>>  CR4: actual=0x0000000000002050, shadow=0x0000000000000000, gh_mask=ffffffffffffe871
>>  CR3 = 0x00000000fffbc000
>>  RSP = 0x0000000000000000  RIP = 0x0000000000000000
>>  RFLAGS=0x00000000         DR7 = 0x0000000000000400
>>         ^^^^^^^^^^
>>
>> The failed vmentry is triggered by the following testcase when ept=Y:
>>
>>     #include <unistd.h>
>>     #include <sys/syscall.h>
>>     #include <string.h>
>>     #include <stdint.h>
>>     #include <linux/kvm.h>
>>     #include <fcntl.h>
>>     #include <sys/ioctl.h>
>>     
>>     long r[5];
>>     int main()
>>     {
>>     	r[2] = open("/dev/kvm", O_RDONLY);
>>     	r[3] = ioctl(r[2], KVM_CREATE_VM, 0);
>>     	r[4] = ioctl(r[3], KVM_CREATE_VCPU, 7);
>>     	struct kvm_regs regs = {
>>     		.rflags = 0,
>>     	};
>>     	ioctl(r[4], KVM_SET_REGS, &regs);
>>     	ioctl(r[4], KVM_RUN, 0);
>>     }
>>
>> X86 RFLAGS bit 1 is fixed set, userspace can simply clearing bit 1 
>> of RFLAGS with KVM_SET_REGS ioctl which results in vmentry fails.
>> This patch fixes it by oring X86_EFLAGS_FIXED during ioctl.
>>
>> Suggested-by: Jim Mattson <jmattson@google.com>
>> Cc: Paolo Bonzini <pbonzini@redhat.com>
>> Cc: Radim Krčmář <rkrcmar@redhat.com>
>> Cc: Jim Mattson <jmattson@google.com>
>> Signed-off-by: Wanpeng Li <wanpeng.li@hotmail.com>
>> ---
>> v1 -> v2:
>>  * Oring X86_EFLAGS_FIXED
>>
>>  virt/kvm/kvm_main.c | 1 +
>>  1 file changed, 1 insertion(+)
>>
>> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
>> index b55bad3..0f3f283 100644
>> --- a/virt/kvm/kvm_main.c
>> +++ b/virt/kvm/kvm_main.c
>> @@ -2602,6 +2602,7 @@ static long kvm_vcpu_ioctl(struct file *filp,
>>  			r = PTR_ERR(kvm_regs);
>>  			goto out;
>>  		}
>> +		kvm_regs->rflags |= X86_EFLAGS_FIXED;

Just realized that this should go into kvm_arch_vcpu_ioctl_set_regs().


>>  		r = kvm_arch_vcpu_ioctl_set_regs(vcpu, kvm_regs);
>>  		kfree(kvm_regs);
>>  		break;
>>
> 
> Not sure if failing KVM_SET_REGS would be nicer, but maybe this has
> already been discussed. So this should be fine.
> 
> Reviewed-by: David Hildenbrand <david@redhat.com>
> 
-- 

Thanks,

David / dhildenb

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] KVM: X86: Fix load RFLAGS w/o the fixed bit
  2017-12-06 17:14   ` Jim Mattson
@ 2017-12-07  3:21     ` Wanpeng Li
  0 siblings, 0 replies; 6+ messages in thread
From: Wanpeng Li @ 2017-12-07  3:21 UTC (permalink / raw)
  To: Jim Mattson
  Cc: David Hildenbrand, LKML, kvm list, Paolo Bonzini,
	Radim Krčmář,
	Wanpeng Li

2017-12-07 1:14 GMT+08:00 Jim Mattson <jmattson@google.com>:
> What if I change the testcase so that regs.rflags is initialized to (1 << 3)?

>From Paolo's pointing:

> I suspect somebody might be passing an all-zero regs struct to
> KVM_SET_REGS, so ORing X86_EFLAGS_FIXED is better.

I think the patch tries to fix a case when the userspace forgets to
set the fixed bit of rflags instead of set invalidate guest state
deliberately.

Regards,
Wanpeng Li

>
> On Wed, Dec 6, 2017 at 6:40 AM, David Hildenbrand <david@redhat.com> wrote:
>> On 06.12.2017 12:59, Wanpeng Li wrote:
>>> From: Wanpeng Li <wanpeng.li@hotmail.com>
>>>
>>>  *** Guest State ***
>>>  CR0: actual=0x0000000000000030, shadow=0x0000000060000010, gh_mask=fffffffffffffff7
>>>  CR4: actual=0x0000000000002050, shadow=0x0000000000000000, gh_mask=ffffffffffffe871
>>>  CR3 = 0x00000000fffbc000
>>>  RSP = 0x0000000000000000  RIP = 0x0000000000000000
>>>  RFLAGS=0x00000000         DR7 = 0x0000000000000400
>>>         ^^^^^^^^^^
>>>
>>> The failed vmentry is triggered by the following testcase when ept=Y:
>>>
>>>     #include <unistd.h>
>>>     #include <sys/syscall.h>
>>>     #include <string.h>
>>>     #include <stdint.h>
>>>     #include <linux/kvm.h>
>>>     #include <fcntl.h>
>>>     #include <sys/ioctl.h>
>>>
>>>     long r[5];
>>>     int main()
>>>     {
>>>       r[2] = open("/dev/kvm", O_RDONLY);
>>>       r[3] = ioctl(r[2], KVM_CREATE_VM, 0);
>>>       r[4] = ioctl(r[3], KVM_CREATE_VCPU, 7);
>>>       struct kvm_regs regs = {
>>>               .rflags = 0,
>>>       };
>>>       ioctl(r[4], KVM_SET_REGS, &regs);
>>>       ioctl(r[4], KVM_RUN, 0);
>>>     }
>>>
>>> X86 RFLAGS bit 1 is fixed set, userspace can simply clearing bit 1
>>> of RFLAGS with KVM_SET_REGS ioctl which results in vmentry fails.
>>> This patch fixes it by oring X86_EFLAGS_FIXED during ioctl.
>>>
>>> Suggested-by: Jim Mattson <jmattson@google.com>
>>> Cc: Paolo Bonzini <pbonzini@redhat.com>
>>> Cc: Radim Krčmář <rkrcmar@redhat.com>
>>> Cc: Jim Mattson <jmattson@google.com>
>>> Signed-off-by: Wanpeng Li <wanpeng.li@hotmail.com>
>>> ---
>>> v1 -> v2:
>>>  * Oring X86_EFLAGS_FIXED
>>>
>>>  virt/kvm/kvm_main.c | 1 +
>>>  1 file changed, 1 insertion(+)
>>>
>>> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
>>> index b55bad3..0f3f283 100644
>>> --- a/virt/kvm/kvm_main.c
>>> +++ b/virt/kvm/kvm_main.c
>>> @@ -2602,6 +2602,7 @@ static long kvm_vcpu_ioctl(struct file *filp,
>>>                       r = PTR_ERR(kvm_regs);
>>>                       goto out;
>>>               }
>>> +             kvm_regs->rflags |= X86_EFLAGS_FIXED;
>>>               r = kvm_arch_vcpu_ioctl_set_regs(vcpu, kvm_regs);
>>>               kfree(kvm_regs);
>>>               break;
>>>
>>
>> Not sure if failing KVM_SET_REGS would be nicer, but maybe this has
>> already been discussed. So this should be fine.
>>
>> Reviewed-by: David Hildenbrand <david@redhat.com>
>>
>> --
>>
>> Thanks,
>>
>> David / dhildenb

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] KVM: X86: Fix load RFLAGS w/o the fixed bit
  2017-12-06 17:28   ` David Hildenbrand
@ 2017-12-07  8:32     ` Wanpeng Li
  0 siblings, 0 replies; 6+ messages in thread
From: Wanpeng Li @ 2017-12-07  8:32 UTC (permalink / raw)
  To: David Hildenbrand
  Cc: linux-kernel, kvm, Paolo Bonzini, Radim Krčmář,
	Wanpeng Li, Jim Mattson

2017-12-07 1:28 GMT+08:00 David Hildenbrand <david@redhat.com>:
> On 06.12.2017 15:40, David Hildenbrand wrote:
>> On 06.12.2017 12:59, Wanpeng Li wrote:
>>> From: Wanpeng Li <wanpeng.li@hotmail.com>
>>>
>>>  *** Guest State ***
>>>  CR0: actual=0x0000000000000030, shadow=0x0000000060000010, gh_mask=fffffffffffffff7
>>>  CR4: actual=0x0000000000002050, shadow=0x0000000000000000, gh_mask=ffffffffffffe871
>>>  CR3 = 0x00000000fffbc000
>>>  RSP = 0x0000000000000000  RIP = 0x0000000000000000
>>>  RFLAGS=0x00000000         DR7 = 0x0000000000000400
>>>         ^^^^^^^^^^
>>>
>>> The failed vmentry is triggered by the following testcase when ept=Y:
>>>
>>>     #include <unistd.h>
>>>     #include <sys/syscall.h>
>>>     #include <string.h>
>>>     #include <stdint.h>
>>>     #include <linux/kvm.h>
>>>     #include <fcntl.h>
>>>     #include <sys/ioctl.h>
>>>
>>>     long r[5];
>>>     int main()
>>>     {
>>>      r[2] = open("/dev/kvm", O_RDONLY);
>>>      r[3] = ioctl(r[2], KVM_CREATE_VM, 0);
>>>      r[4] = ioctl(r[3], KVM_CREATE_VCPU, 7);
>>>      struct kvm_regs regs = {
>>>              .rflags = 0,
>>>      };
>>>      ioctl(r[4], KVM_SET_REGS, &regs);
>>>      ioctl(r[4], KVM_RUN, 0);
>>>     }
>>>
>>> X86 RFLAGS bit 1 is fixed set, userspace can simply clearing bit 1
>>> of RFLAGS with KVM_SET_REGS ioctl which results in vmentry fails.
>>> This patch fixes it by oring X86_EFLAGS_FIXED during ioctl.
>>>
>>> Suggested-by: Jim Mattson <jmattson@google.com>
>>> Cc: Paolo Bonzini <pbonzini@redhat.com>
>>> Cc: Radim Krčmář <rkrcmar@redhat.com>
>>> Cc: Jim Mattson <jmattson@google.com>
>>> Signed-off-by: Wanpeng Li <wanpeng.li@hotmail.com>
>>> ---
>>> v1 -> v2:
>>>  * Oring X86_EFLAGS_FIXED
>>>
>>>  virt/kvm/kvm_main.c | 1 +
>>>  1 file changed, 1 insertion(+)
>>>
>>> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
>>> index b55bad3..0f3f283 100644
>>> --- a/virt/kvm/kvm_main.c
>>> +++ b/virt/kvm/kvm_main.c
>>> @@ -2602,6 +2602,7 @@ static long kvm_vcpu_ioctl(struct file *filp,
>>>                      r = PTR_ERR(kvm_regs);
>>>                      goto out;
>>>              }
>>> +            kvm_regs->rflags |= X86_EFLAGS_FIXED;
>
> Just realized that this should go into kvm_arch_vcpu_ioctl_set_regs().

Do it in v3, thanks for your review. :)

Regards,
Wanpeng Li

>
>
>>>              r = kvm_arch_vcpu_ioctl_set_regs(vcpu, kvm_regs);
>>>              kfree(kvm_regs);
>>>              break;
>>>
>>
>> Not sure if failing KVM_SET_REGS would be nicer, but maybe this has
>> already been discussed. So this should be fine.
>>
>> Reviewed-by: David Hildenbrand <david@redhat.com>
>>
> --
>
> Thanks,
>
> David / dhildenb

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2017-12-07  8:32 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-12-06 11:59 [PATCH v2] KVM: X86: Fix load RFLAGS w/o the fixed bit Wanpeng Li
2017-12-06 14:40 ` David Hildenbrand
2017-12-06 17:14   ` Jim Mattson
2017-12-07  3:21     ` Wanpeng Li
2017-12-06 17:28   ` David Hildenbrand
2017-12-07  8:32     ` Wanpeng Li

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.