• Paolo Bonzini's avatar
    KVM: x86/mmu: do compare-and-exchange of gPTE via the user address · 2a8859f3
    Paolo Bonzini authored
    FNAME(cmpxchg_gpte) is an inefficient mess.  It is at least decent if it
    can go through get_user_pages_fast(), but if it cannot then it tries to
    use memremap(); that is not just terribly slow, it is also wrong because
    it assumes that the VM_PFNMAP VMA is contiguous.
    
    The right way to do it would be to do the same thing as
    hva_to_pfn_remapped() does since commit add6a0cd ("KVM: MMU: try to
    fix up page faults before giving up", 2016-07-05), using follow_pte()
    and fixup_user_fault() to determine the correct address to use for
    memremap().  To do this, one could for example extract hva_to_pfn()
    for use outside virt/kvm/kvm_main.c.  But really there is no reason to
    do that either, because there is already a perfectly valid address to
    do the cmpxchg() on, only it is a userspace address.  That means doing
    user_access_begin()/user_access_end() and writing the code in assembly
    to handle exceptions correctly.  Worse, the guest PTE can be 8-byte
    even on i686 so there is the extra complication of using cmpxchg8b to
    account for.  But at least it is an efficient mess.
    
    (Thanks to Linus for suggesting improvement on the inline assembly).
    Reported-by: default avatarQiuhao Li <qiuhao@sysec.org>
    Reported-by: default avatarGaoning Pan <pgn@zju.edu.cn>
    Reported-by: default avatarYongkang Jia <kangel@zju.edu.cn>
    Reported-by: syzbot+6cde2282daa792c49ab8@syzkaller.appspotmail.com
    Debugged-by: default avatarTadeusz Struk <tadeusz.struk@linaro.org>
    Tested-by: default avatarMaxim Levitsky <mlevitsk@redhat.com>
    Cc: stable@vger.kernel.org
    Fixes: bd53cb35 ("X86/KVM: Handle PFNs outside of kernel reach when touching GPTEs")
    Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
    2a8859f3
paging_tmpl.h 31.6 KB