• Kazuki Takiguchi's avatar
    KVM: x86/mmu: Fix race condition in direct_page_fault · 47b0c2e4
    Kazuki Takiguchi authored
    make_mmu_pages_available() must be called with mmu_lock held for write.
    However, if the TDP MMU is used, it will be called with mmu_lock held for
    read.
    This function does nothing unless shadow pages are used, so there is no
    race unless nested TDP is used.
    Since nested TDP uses shadow pages, old shadow pages may be zapped by this
    function even when the TDP MMU is enabled.
    Since shadow pages are never allocated by kvm_tdp_mmu_map(), a race
    condition can be avoided by not calling make_mmu_pages_available() if the
    TDP MMU is currently in use.
    
    I encountered this when repeatedly starting and stopping nested VM.
    It can be artificially caused by allocating a large number of nested TDP
    SPTEs.
    
    For example, the following BUG and general protection fault are caused in
    the host kernel.
    
    pte_list_remove: 00000000cd54fc10 many->many
    ------------[ cut here ]------------
    kernel BUG at arch/x86/kvm/mmu/mmu.c:963!
    invalid opcode: 0000 [#1] PREEMPT SMP NOPTI
    RIP: 0010:pte_list_remove.cold+0x16/0x48 [kvm]
    Call Trace:
     <TASK>
     drop_spte+0xe0/0x180 [kvm]
     mmu_page_zap_pte+0x4f/0x140 [kvm]
     __kvm_mmu_prepare_zap_page+0x62/0x3e0 [kvm]
     kvm_mmu_zap_oldest_mmu_pages+0x7d/0xf0 [kvm]
     direct_page_fault+0x3cb/0x9b0 [kvm]
     kvm_tdp_page_fault+0x2c/0xa0 [kvm]
     kvm_mmu_page_fault+0x207/0x930 [kvm]
     npf_interception+0x47/0xb0 [kvm_amd]
     svm_invoke_exit_handler+0x13c/0x1a0 [kvm_amd]
     svm_handle_exit+0xfc/0x2c0 [kvm_amd]
     kvm_arch_vcpu_ioctl_run+0xa79/0x1780 [kvm]
     kvm_vcpu_ioctl+0x29b/0x6f0 [kvm]
     __x64_sys_ioctl+0x95/0xd0
     do_syscall_64+0x5c/0x90
    
    general protection fault, probably for non-canonical address
    0xdead000000000122: 0000 [#1] PREEMPT SMP NOPTI
    RIP: 0010:kvm_mmu_commit_zap_page.part.0+0x4b/0xe0 [kvm]
    Call Trace:
     <TASK>
     kvm_mmu_zap_oldest_mmu_pages+0xae/0xf0 [kvm]
     direct_page_fault+0x3cb/0x9b0 [kvm]
     kvm_tdp_page_fault+0x2c/0xa0 [kvm]
     kvm_mmu_page_fault+0x207/0x930 [kvm]
     npf_interception+0x47/0xb0 [kvm_amd]
    
    CVE: CVE-2022-45869
    Fixes: a2855afc ("KVM: x86/mmu: Allow parallel page faults for the TDP MMU")
    Signed-off-by: default avatarKazuki Takiguchi <takiguchi.kazuki171@gmail.com>
    Cc: stable@vger.kernel.org
    Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
    47b0c2e4
mmu.c 189 KB