diff mbox series

[linux-5.4.y] KVM: x86: determine if an exception has an error code only when injecting it.

Message ID 20210728230745.1762245-1-zsm@chromium.org
State New
Headers show
Series [linux-5.4.y] KVM: x86: determine if an exception has an error code only when injecting it. | expand

Commit Message

Zubin Mithra July 28, 2021, 11:07 p.m. UTC
From: Maxim Levitsky <mlevitsk@redhat.com>

commit b97f074583736c42fb36f2da1164e28c73758912 upstream.

A page fault can be queued while vCPU is in real paged mode on AMD, and
AMD manual asks the user to always intercept it
(otherwise result is undefined).
The resulting VM exit, does have an error code.

Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>
Message-Id: <20210225154135.405125-2-mlevitsk@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Zubin Mithra <zsm@chromium.org>
---
Backport Note:
* Syzkaller triggered a WARNING with the following stacktrace:
 WARNING: CPU: 0 PID: 3594 at arch/x86/kvm/x86.c:8635 kvm_arch_vcpu_ioctl_run+0x338/0x2421
 Kernel panic - not syncing: panic_on_warn set ...
 CPU: 0 PID: 3594 Comm: poc Not tainted 5.4.136-00181-g253dccefb5cb #3
 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-2 04/01/2014
 Call Trace:
  dump_stack+0x97/0xd3
  panic+0x198/0x388
  ? __warn_printk+0xee/0xee
  ? printk+0xad/0xde
  ? rcu_read_unlock_sched_notrace+0xf/0xf
  ? kvm_arch_vcpu_ioctl_run+0x338/0x2421
  __warn+0xd3/0x113
  ? kvm_arch_vcpu_ioctl_run+0x338/0x2421
  report_bug+0xbf/0x100
  fixup_bug+0x28/0x4b
  do_error_trap+0xe7/0xf7
  ? kvm_arch_vcpu_ioctl_run+0x338/0x2421
  do_invalid_op+0x3a/0x3f
  ? kvm_arch_vcpu_ioctl_run+0x338/0x2421
  invalid_op+0x23/0x30
 RIP: 0010:kvm_arch_vcpu_ioctl_run+0x338/0x2421

* This commit is present in linux-5.13.y.

* Conflict arises as the following commit is is not present in
linux-5.10.y and older.
- b3646477d458 ("KVM: x86: use static calls to reduce kvm_x86_ops overhead")

* Tests run: syzkaller reproducer, Chrome OS tryjobs

 arch/x86/kvm/x86.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

Comments

Paolo Bonzini July 29, 2021, 8:37 a.m. UTC | #1
On 29/07/21 01:07, Zubin Mithra wrote:
> From: Maxim Levitsky <mlevitsk@redhat.com>

> 

> commit b97f074583736c42fb36f2da1164e28c73758912 upstream.

> 

> A page fault can be queued while vCPU is in real paged mode on AMD, and

> AMD manual asks the user to always intercept it

> (otherwise result is undefined).

> The resulting VM exit, does have an error code.

> 

> Signed-off-by: Maxim Levitsky <mlevitsk@redhat.com>

> Message-Id: <20210225154135.405125-2-mlevitsk@redhat.com>

> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

> Signed-off-by: Zubin Mithra <zsm@chromium.org>

> ---

> Backport Note:

> * Syzkaller triggered a WARNING with the following stacktrace:

>   WARNING: CPU: 0 PID: 3594 at arch/x86/kvm/x86.c:8635 kvm_arch_vcpu_ioctl_run+0x338/0x2421

>   Kernel panic - not syncing: panic_on_warn set ...

>   CPU: 0 PID: 3594 Comm: poc Not tainted 5.4.136-00181-g253dccefb5cb #3

>   Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-2 04/01/2014

>   Call Trace:

>    dump_stack+0x97/0xd3

>    panic+0x198/0x388

>    ? __warn_printk+0xee/0xee

>    ? printk+0xad/0xde

>    ? rcu_read_unlock_sched_notrace+0xf/0xf

>    ? kvm_arch_vcpu_ioctl_run+0x338/0x2421

>    __warn+0xd3/0x113

>    ? kvm_arch_vcpu_ioctl_run+0x338/0x2421

>    report_bug+0xbf/0x100

>    fixup_bug+0x28/0x4b

>    do_error_trap+0xe7/0xf7

>    ? kvm_arch_vcpu_ioctl_run+0x338/0x2421

>    do_invalid_op+0x3a/0x3f

>    ? kvm_arch_vcpu_ioctl_run+0x338/0x2421

>    invalid_op+0x23/0x30

>   RIP: 0010:kvm_arch_vcpu_ioctl_run+0x338/0x2421

> 

> * This commit is present in linux-5.13.y.

> 

> * Conflict arises as the following commit is is not present in

> linux-5.10.y and older.

> - b3646477d458 ("KVM: x86: use static calls to reduce kvm_x86_ops overhead")

> 

> * Tests run: syzkaller reproducer, Chrome OS tryjobs

> 

>   arch/x86/kvm/x86.c | 13 +++++++++----

>   1 file changed, 9 insertions(+), 4 deletions(-)

> 

> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c

> index 377157656a8b..5d35b9656b67 100644

> --- a/arch/x86/kvm/x86.c

> +++ b/arch/x86/kvm/x86.c

> @@ -475,8 +475,6 @@ static void kvm_multiple_exception(struct kvm_vcpu *vcpu,

>   

>   	if (!vcpu->arch.exception.pending && !vcpu->arch.exception.injected) {

>   	queue:

> -		if (has_error && !is_protmode(vcpu))

> -			has_error = false;

>   		if (reinject) {

>   			/*

>   			 * On vmentry, vcpu->arch.exception.pending is only

> @@ -7592,6 +7590,13 @@ static void update_cr8_intercept(struct kvm_vcpu *vcpu)

>   	kvm_x86_ops->update_cr8_intercept(vcpu, tpr, max_irr);

>   }

>   

> +static void kvm_inject_exception(struct kvm_vcpu *vcpu)

> +{

> +       if (vcpu->arch.exception.error_code && !is_protmode(vcpu))

> +               vcpu->arch.exception.error_code = false;

> +       kvm_x86_ops->queue_exception(vcpu);

> +}

> +

>   static int inject_pending_event(struct kvm_vcpu *vcpu)

>   {

>   	int r;

> @@ -7599,7 +7604,7 @@ static int inject_pending_event(struct kvm_vcpu *vcpu)

>   	/* try to reinject previous events if any */

>   

>   	if (vcpu->arch.exception.injected)

> -		kvm_x86_ops->queue_exception(vcpu);

> +		kvm_inject_exception(vcpu);

>   	/*

>   	 * Do not inject an NMI or interrupt if there is a pending

>   	 * exception.  Exceptions and interrupts are recognized at

> @@ -7665,7 +7670,7 @@ static int inject_pending_event(struct kvm_vcpu *vcpu)

>   			}

>   		}

>   

> -		kvm_x86_ops->queue_exception(vcpu);

> +		kvm_inject_exception(vcpu);

>   	}

>   

>   	/* Don't consider new event if we re-injected an event */

> 



Acked-by: Paolo Bonzini <pbonzini@redhat.com>
diff mbox series

Patch

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 377157656a8b..5d35b9656b67 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -475,8 +475,6 @@  static void kvm_multiple_exception(struct kvm_vcpu *vcpu,
 
 	if (!vcpu->arch.exception.pending && !vcpu->arch.exception.injected) {
 	queue:
-		if (has_error && !is_protmode(vcpu))
-			has_error = false;
 		if (reinject) {
 			/*
 			 * On vmentry, vcpu->arch.exception.pending is only
@@ -7592,6 +7590,13 @@  static void update_cr8_intercept(struct kvm_vcpu *vcpu)
 	kvm_x86_ops->update_cr8_intercept(vcpu, tpr, max_irr);
 }
 
+static void kvm_inject_exception(struct kvm_vcpu *vcpu)
+{
+       if (vcpu->arch.exception.error_code && !is_protmode(vcpu))
+               vcpu->arch.exception.error_code = false;
+       kvm_x86_ops->queue_exception(vcpu);
+}
+
 static int inject_pending_event(struct kvm_vcpu *vcpu)
 {
 	int r;
@@ -7599,7 +7604,7 @@  static int inject_pending_event(struct kvm_vcpu *vcpu)
 	/* try to reinject previous events if any */
 
 	if (vcpu->arch.exception.injected)
-		kvm_x86_ops->queue_exception(vcpu);
+		kvm_inject_exception(vcpu);
 	/*
 	 * Do not inject an NMI or interrupt if there is a pending
 	 * exception.  Exceptions and interrupts are recognized at
@@ -7665,7 +7670,7 @@  static int inject_pending_event(struct kvm_vcpu *vcpu)
 			}
 		}
 
-		kvm_x86_ops->queue_exception(vcpu);
+		kvm_inject_exception(vcpu);
 	}
 
 	/* Don't consider new event if we re-injected an event */