Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: x86: fix overlap between SPTE_MMIO_MASK and generation

The SPTE_MMIO_MASK overlaps with the bits used to track MMIO
generation number. A high enough generation number would overwrite the
SPTE_SPECIAL_MASK region and cause the MMIO SPTE to be misinterpreted.

Likewise, setting bits 52 and 53 would also cause an incorrect generation
number to be read from the PTE, though this was partially mitigated by the
(useless if it weren't for the bug) removal of SPTE_SPECIAL_MASK from
the spte in get_mmio_spte_generation. Drop that removal, and replace
it with a compile-time assertion.

Fixes: 6eeb4ef049e7 ("KVM: x86: assign two bits to track SPTE kinds")
Reported-by: Ben Gardon <bgardon@google.com>
Cc: stable@vger.kernel.org
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

+5 -5
+5 -5
arch/x86/kvm/mmu/mmu.c
··· 418 418 * requires a full MMU zap). The flag is instead explicitly queried when 419 419 * checking for MMIO spte cache hits. 420 420 */ 421 - #define MMIO_SPTE_GEN_MASK GENMASK_ULL(18, 0) 421 + #define MMIO_SPTE_GEN_MASK GENMASK_ULL(17, 0) 422 422 423 423 #define MMIO_SPTE_GEN_LOW_START 3 424 424 #define MMIO_SPTE_GEN_LOW_END 11 425 425 #define MMIO_SPTE_GEN_LOW_MASK GENMASK_ULL(MMIO_SPTE_GEN_LOW_END, \ 426 426 MMIO_SPTE_GEN_LOW_START) 427 427 428 - #define MMIO_SPTE_GEN_HIGH_START 52 429 - #define MMIO_SPTE_GEN_HIGH_END 61 428 + #define MMIO_SPTE_GEN_HIGH_START PT64_SECOND_AVAIL_BITS_SHIFT 429 + #define MMIO_SPTE_GEN_HIGH_END 62 430 430 #define MMIO_SPTE_GEN_HIGH_MASK GENMASK_ULL(MMIO_SPTE_GEN_HIGH_END, \ 431 431 MMIO_SPTE_GEN_HIGH_START) 432 + 432 433 static u64 generation_mmio_spte_mask(u64 gen) 433 434 { 434 435 u64 mask; 435 436 436 437 WARN_ON(gen & ~MMIO_SPTE_GEN_MASK); 438 + BUILD_BUG_ON((MMIO_SPTE_GEN_HIGH_MASK | MMIO_SPTE_GEN_LOW_MASK) & SPTE_SPECIAL_MASK); 437 439 438 440 mask = (gen << MMIO_SPTE_GEN_LOW_START) & MMIO_SPTE_GEN_LOW_MASK; 439 441 mask |= (gen << MMIO_SPTE_GEN_HIGH_START) & MMIO_SPTE_GEN_HIGH_MASK; ··· 445 443 static u64 get_mmio_spte_generation(u64 spte) 446 444 { 447 445 u64 gen; 448 - 449 - spte &= ~shadow_mmio_mask; 450 446 451 447 gen = (spte & MMIO_SPTE_GEN_LOW_MASK) >> MMIO_SPTE_GEN_LOW_START; 452 448 gen |= (spte & MMIO_SPTE_GEN_HIGH_MASK) >> MMIO_SPTE_GEN_HIGH_START;