• David Matlack's avatar
    kvm: x86: do not leak guest xcr0 into host interrupt handlers · fc5b7f3b
    David Matlack authored
    An interrupt handler that uses the fpu can kill a KVM VM, if it runs
    under the following conditions:
     - the guest's xcr0 register is loaded on the cpu
     - the guest's fpu context is not loaded
     - the host is using eagerfpu
    
    Note that the guest's xcr0 register and fpu context are not loaded as
    part of the atomic world switch into "guest mode". They are loaded by
    KVM while the cpu is still in "host mode".
    
    Usage of the fpu in interrupt context is gated by irq_fpu_usable(). The
    interrupt handler will look something like this:
    
    if (irq_fpu_usable()) {
            kernel_fpu_begin();
    
            [... code that uses the fpu ...]
    
            kernel_fpu_end();
    }
    
    As long as the guest's fpu is not loaded and the host is using eager
    fpu, irq_fpu_usable() returns true (interrupted_kernel_fpu_idle()
    returns true). The interrupt handler proceeds to use the fpu with
    the guest's xcr0 live.
    
    kernel_fpu_begin() saves the current fpu context. If this uses
    XSAVE[OPT], it may leave the xsave area in an undesirable state.
    According to the SDM, during XSAVE bit i of XSTATE_BV is not modified
    if bit i is 0 in xcr0. So it's possible that XSTATE_BV[i] == 1 and
    xcr0[i] == 0 following an XSAVE.
    
    kernel_fpu_end() restores the fpu context. Now if any bit i in
    XSTATE_BV == 1 while xcr0[i] == 0, XRSTOR generates a #GP. The
    fault is trapped and SIGSEGV is delivered to the current process.
    
    Only pre-4.2 kernels appear to be vulnerable to this sequence of
    events. Commit 653f52c3 ("kvm,x86: load guest FPU context more eagerly")
    from 4.2 forces the guest's fpu to always be loaded on eagerfpu hosts.
    
    This patch fixes the bug by keeping the host's xcr0 loaded outside
    of the interrupts-disabled region where KVM switches into guest mode.
    
    Cc: stable@vger.kernel.org
    Suggested-by: default avatarAndy Lutomirski <luto@amacapital.net>
    Signed-off-by: default avatarDavid Matlack <dmatlack@google.com>
    [Move load after goto cancel_injection. - Paolo]
    Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
    fc5b7f3b
x86.c 214 KB