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> Reviewed-by: Marc Orr <marcorr@xxxxxxxxxx> --- arch/x86/kvm/x86.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 4ab569171ad1..b67a664b1d7b 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3423,6 +3423,14 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu, vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) return -EINVAL; + if (events->exception.injected) { + bool has_error_code = is_protmode(vcpu) && + x86_exception_has_error_code(events->exception.nr); + + if (!!events->exception.has_error_code != has_error_code) + return -EINVAL; + } + process_nmi(vcpu); vcpu->arch.exception.injected = false; vcpu->arch.exception.pending = events->exception.injected; @@ -8170,6 +8178,14 @@ static int kvm_valid_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) return -EINVAL; } + if (vcpu->arch.exception.injected || vcpu->arch.exception.pending) { + bool has_error_code = (sregs->cr0 & X86_CR0_PE) && + x86_exception_has_error_code(vcpu->arch.exception.nr); + + if (vcpu->arch.exception.has_error_code != has_error_code) + return -EINVAL; + } + return 0; } -- 2.19.1.331.ge82ca0e54c-goog