• W
    KVM: x86: fix escape of guest dr6 to the host · efdab992
    Wanpeng Li 提交于
    syzkaller reported:
    
       WARNING: CPU: 0 PID: 12927 at arch/x86/kernel/traps.c:780 do_debug+0x222/0x250
       CPU: 0 PID: 12927 Comm: syz-executor Tainted: G           OE    4.15.0-rc2+ #16
       RIP: 0010:do_debug+0x222/0x250
       Call Trace:
        <#DB>
        debug+0x3e/0x70
       RIP: 0010:copy_user_enhanced_fast_string+0x10/0x20
        </#DB>
        _copy_from_user+0x5b/0x90
        SyS_timer_create+0x33/0x80
        entry_SYSCALL_64_fastpath+0x23/0x9a
    
    The testcase sets a watchpoint (with perf_event_open) on a buffer that is
    passed to timer_create() as the struct sigevent argument.  In timer_create(),
    copy_from_user()'s rep movsb triggers the BP.  The testcase also sets
    the debug registers for the guest.
    
    However, KVM only restores host debug registers when the host has active
    watchpoints, which triggers a race condition when running the testcase with
    multiple threads.  The guest's DR6.BS bit can escape to the host before
    another thread invokes timer_create(), and do_debug() complains.
    
    The fix is to respect do_debug()'s dr6 invariant when leaving KVM.
    Reported-by: NDmitry Vyukov <dvyukov@google.com>
    Cc: Paolo Bonzini <pbonzini@redhat.com>
    Cc: Radim Krčmář <rkrcmar@redhat.com>
    Cc: David Hildenbrand <david@redhat.com>
    Cc: Dmitry Vyukov <dvyukov@google.com>
    Reviewed-by: NDavid Hildenbrand <david@redhat.com>
    Signed-off-by: NWanpeng Li <wanpeng.li@hotmail.com>
    Signed-off-by: NPaolo Bonzini <pbonzini@redhat.com>
    Signed-off-by: NRadim Krčmář <rkrcmar@redhat.com>
    efdab992
x86.c 229.2 KB