Skip to content
  • Wanpeng Li's avatar
    KVM: VMX: Fix rflags cache during vCPU reset · fe7832ff
    Wanpeng Li authored
    
    [ Upstream commit c37c2873
    
     ]
    
    Reported by syzkaller:
    
       *** Guest State ***
       CR0: actual=0x0000000080010031, shadow=0x0000000060000010, gh_mask=fffffffffffffff7
       CR4: actual=0x0000000000002061, shadow=0x0000000000000000, gh_mask=ffffffffffffe8f1
       CR3 = 0x000000002081e000
       RSP = 0x000000000000fffa  RIP = 0x0000000000000000
       RFLAGS=0x00023000         DR7 = 0x00000000000000
              ^^^^^^^^^^
       ------------[ cut here ]------------
       WARNING: CPU: 6 PID: 24431 at /home/kernel/linux/arch/x86/kvm//x86.c:7302 kvm_arch_vcpu_ioctl_run+0x651/0x2ea0 [kvm]
       CPU: 6 PID: 24431 Comm: reprotest Tainted: G        W  OE   4.14.0+ #26
       RIP: 0010:kvm_arch_vcpu_ioctl_run+0x651/0x2ea0 [kvm]
       RSP: 0018:ffff880291d179e0 EFLAGS: 00010202
       Call Trace:
        kvm_vcpu_ioctl+0x479/0x880 [kvm]
        do_vfs_ioctl+0x142/0x9a0
        SyS_ioctl+0x74/0x80
        entry_SYSCALL_64_fastpath+0x23/0x9a
    
    The failed vmentry is triggered by the following beautified testcase:
    
        #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()
        {
            struct kvm_debugregs dr = { 0 };
    
            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_guest_debug debug = {
                    .control = 0xf0403,
                    .arch = {
                            .debugreg[6] = 0x2,
                            .debugreg[7] = 0x2
                    }
            };
            ioctl(r[4], KVM_SET_GUEST_DEBUG, &debug);
            ioctl(r[4], KVM_RUN, 0);
        }
    
    which testcase tries to setup the processor specific debug
    registers and configure vCPU for handling guest debug events through
    KVM_SET_GUEST_DEBUG.  The KVM_SET_GUEST_DEBUG ioctl will get and set
    rflags in order to set TF bit if single step is needed. All regs' caches
    are reset to avail and GUEST_RFLAGS vmcs field is reset to 0x2 during vCPU
    reset. However, the cache of rflags is not reset during vCPU reset. The
    function vmx_get_rflags() returns an unreset rflags cache value since
    the cache is marked avail, it is 0 after boot. Vmentry fails if the
    rflags reserved bit 1 is 0.
    
    This patch fixes it by resetting both the GUEST_RFLAGS vmcs field and
    its cache to 0x2 during vCPU reset.
    
    Reported-by: default avatarDmitry Vyukov <dvyukov@google.com>
    Tested-by: default avatarDmitry Vyukov <dvyukov@google.com>
    Reviewed-by: default avatarDavid Hildenbrand <david@redhat.com>
    Cc: Paolo Bonzini <pbonzini@redhat.com>
    Cc: Radim Krčmář <rkrcmar@redhat.com>
    Cc: Nadav Amit <nadav.amit@gmail.com>
    Cc: Dmitry Vyukov <dvyukov@google.com>
    Signed-off-by: default avatarWanpeng Li <wanpeng.li@hotmail.com>
    Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
    Signed-off-by: default avatarSasha Levin <alexander.levin@microsoft.com>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    fe7832ff