KVM: x86/mmu: fix potential races when walking host page table
authorMingwei Zhang <mizhang@google.com>
Fri, 29 Apr 2022 03:17:57 +0000 (03:17 +0000)
committerPaolo Bonzini <pbonzini@redhat.com>
Fri, 29 Apr 2022 16:38:22 +0000 (12:38 -0400)
commit44187235cbcc7c1129ea7c004bc12f8757d29415
tree8e4b6707f92fedcf09dd277eed826c0a2d34b3fd
parentd495f942f40aa412f8d4d65951152648cfa09903
KVM: x86/mmu: fix potential races when walking host page table

KVM uses lookup_address_in_mm() to detect the hugepage size that the host
uses to map a pfn.  The function suffers from several issues:

 - no usage of READ_ONCE(*). This allows multiple dereference of the same
   page table entry. The TOCTOU problem because of that may cause KVM to
   incorrectly treat a newly generated leaf entry as a nonleaf one, and
   dereference the content by using its pfn value.

 - the information returned does not match what KVM needs; for non-present
   entries it returns the level at which the walk was terminated, as long
   as the entry is not 'none'.  KVM needs level information of only 'present'
   entries, otherwise it may regard a non-present PXE entry as a present
   large page mapping.

 - the function is not safe for mappings that can be torn down, because it
   does not disable IRQs and because it returns a PTE pointer which is never
   safe to dereference after the function returns.

So implement the logic for walking host page tables directly in KVM, and
stop using lookup_address_in_mm().

Cc: Sean Christopherson <seanjc@google.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Mingwei Zhang <mizhang@google.com>
Message-Id: <20220429031757.2042406-1-mizhang@google.com>
[Inline in host_pfn_mapping_level, ensure no semantic change for its
 callers. - Paolo]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/mmu/mmu.c