Userspace should not be able to inject an invalid exception into a kvm guest via KVM_SET_VCPU_EVENTS, nor should it be able to convert a valid pending exception to an invalid one via KVM_SET_SREGS. In particular, only certain exceptions deliver an error code in protected mode, and no exception delivers an error code in real-address mode. Reported-by: syzbot <syzkaller@xxxxxxxxxxxxxxxx> Signed-off-by: Jim Mattson <jmattson@xxxxxxxxxx> --- arch/x86/kvm/x86.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 66d66d77caee..47b4d1099467 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3528,9 +3528,18 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu, events->exception_has_payload = 0; } - if ((events->exception.injected || events->exception.pending) && - (events->exception.nr > 31 || events->exception.nr == NMI_VECTOR)) - return -EINVAL; + if (events->exception.injected || events->exception.pending) { + bool needs_error_code; + + if (events->exception.nr > 31 || + events->exception.nr == NMI_VECTOR) + return -EINVAL; + + needs_error_code = is_protmode(vcpu) && + x86_exception_has_error_code(events->exception.nr); + if (!!events->exception.has_error_code != needs_error_code) + return -EINVAL; + } /* INITs are latched while in SMM */ if (events->flags & KVM_VCPUEVENT_VALID_SMM && @@ -8312,6 +8321,18 @@ static int kvm_valid_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) return -EINVAL; } + /* + * Switching between real-address mode and protected mode can + * potentially invalidate a pending exception. + */ + if (vcpu->arch.exception.injected || vcpu->arch.exception.pending) { + bool needs_error_code = (sregs->cr0 & X86_CR0_PE) && + x86_exception_has_error_code(vcpu->arch.exception.nr); + + if (vcpu->arch.exception.has_error_code != needs_error_code) + return -EINVAL; + } + return 0; } -- 2.19.1.568.g152ad8e336-goog