lkml.org 
[lkml]   [2016]   [Aug]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.10 093/180] KVM: x86: fix OOPS after invalid KVM_SET_DEBUGREGS
    Date
    From: Paolo Bonzini <pbonzini@redhat.com>

    commit d14bdb553f9196169f003058ae1cdabe514470e6 upstream.

    MOV to DR6 or DR7 causes a #GP if an attempt is made to write a 1 to
    any of bits 63:32. However, this is not detected at KVM_SET_DEBUGREGS
    time, and the next KVM_RUN oopses:

    general protection fault: 0000 [#1] SMP
    CPU: 2 PID: 14987 Comm: a.out Not tainted 4.4.9-300.fc23.x86_64 #1
    Hardware name: LENOVO 2325F51/2325F51, BIOS G2ET32WW (1.12 ) 05/30/2012
    [...]
    Call Trace:
    [<ffffffffa072c93d>] kvm_arch_vcpu_ioctl_run+0x141d/0x14e0 [kvm]
    [<ffffffffa071405d>] kvm_vcpu_ioctl+0x33d/0x620 [kvm]
    [<ffffffff81241648>] do_vfs_ioctl+0x298/0x480
    [<ffffffff812418a9>] SyS_ioctl+0x79/0x90
    [<ffffffff817a0f2e>] entry_SYSCALL_64_fastpath+0x12/0x71
    Code: 55 83 ff 07 48 89 e5 77 27 89 ff ff 24 fd 90 87 80 81 0f 23 fe 5d c3 0f 23 c6 5d c3 0f 23 ce 5d c3 0f 23 d6 5d c3 0f 23 de 5d c3 <0f> 23 f6 5d c3 0f 0b 66 66 66 66 66 2e 0f 1f 84 00 00 00 00 00
    RIP [<ffffffff810639eb>] native_set_debugreg+0x2b/0x40
    RSP <ffff88005836bd50>

    Testcase (beautified/reduced from syzkaller output):

    #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[8];

    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);

    memcpy(&dr,
    "\x5d\x6a\x6b\xe8\x57\x3b\x4b\x7e\xcf\x0d\xa1\x72"
    "\xa3\x4a\x29\x0c\xfc\x6d\x44\x00\xa7\x52\xc7\xd8"
    "\x00\xdb\x89\x9d\x78\xb5\x54\x6b\x6b\x13\x1c\xe9"
    "\x5e\xd3\x0e\x40\x6f\xb4\x66\xf7\x5b\xe3\x36\xcb",
    48);
    r[7] = ioctl(r[4], KVM_SET_DEBUGREGS, &dr);
    r[6] = ioctl(r[4], KVM_RUN, 0);
    }

    Reported-by: Dmitry Vyukov <dvyukov@google.com>
    Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
    Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    Signed-off-by: Willy Tarreau <w@1wt.eu>
    ---
    arch/x86/kvm/x86.c | 5 +++++
    1 file changed, 5 insertions(+)

    diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
    index 3c0b085..8e57771 100644
    --- a/arch/x86/kvm/x86.c
    +++ b/arch/x86/kvm/x86.c
    @@ -2966,6 +2966,11 @@ static int kvm_vcpu_ioctl_x86_set_debugregs(struct kvm_vcpu *vcpu,
    if (dbgregs->flags)
    return -EINVAL;

    + if (dbgregs->dr6 & ~0xffffffffull)
    + return -EINVAL;
    + if (dbgregs->dr7 & ~0xffffffffull)
    + return -EINVAL;
    +
    memcpy(vcpu->arch.db, dbgregs->db, sizeof(vcpu->arch.db));
    vcpu->arch.dr6 = dbgregs->dr6;
    vcpu->arch.dr7 = dbgregs->dr7;
    --
    2.8.0.rc2.1.gbe9624a
    \
     
     \ /
      Last update: 2016-09-17 09:57    [W:2.151 / U:0.132 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site