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 |
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 --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 */