Skip to content

Commit f8be156

Browse files
npigginbonzini
authored andcommitted
KVM: do not allow mapping valid but non-reference-counted pages
It's possible to create a region which maps valid but non-refcounted pages (e.g., tail pages of non-compound higher order allocations). These host pages can then be returned by gfn_to_page, gfn_to_pfn, etc., family of APIs, which take a reference to the page, which takes it from 0 to 1. When the reference is dropped, this will free the page incorrectly. Fix this by only taking a reference on valid pages if it was non-zero, which indicates it is participating in normal refcounting (and can be released with put_page). This addresses CVE-2021-22543. Signed-off-by: Nicholas Piggin <[email protected]> Tested-by: Paolo Bonzini <[email protected]> Cc: [email protected] Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 309505d commit f8be156

File tree

1 file changed

+17
-2
lines changed

1 file changed

+17
-2
lines changed

virt/kvm/kvm_main.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2055,6 +2055,13 @@ static bool vma_is_valid(struct vm_area_struct *vma, bool write_fault)
20552055
return true;
20562056
}
20572057

2058+
static int kvm_try_get_pfn(kvm_pfn_t pfn)
2059+
{
2060+
if (kvm_is_reserved_pfn(pfn))
2061+
return 1;
2062+
return get_page_unless_zero(pfn_to_page(pfn));
2063+
}
2064+
20582065
static int hva_to_pfn_remapped(struct vm_area_struct *vma,
20592066
unsigned long addr, bool *async,
20602067
bool write_fault, bool *writable,
@@ -2104,13 +2111,21 @@ static int hva_to_pfn_remapped(struct vm_area_struct *vma,
21042111
* Whoever called remap_pfn_range is also going to call e.g.
21052112
* unmap_mapping_range before the underlying pages are freed,
21062113
* causing a call to our MMU notifier.
2114+
*
2115+
* Certain IO or PFNMAP mappings can be backed with valid
2116+
* struct pages, but be allocated without refcounting e.g.,
2117+
* tail pages of non-compound higher order allocations, which
2118+
* would then underflow the refcount when the caller does the
2119+
* required put_page. Don't allow those pages here.
21072120
*/
2108-
kvm_get_pfn(pfn);
2121+
if (!kvm_try_get_pfn(pfn))
2122+
r = -EFAULT;
21092123

21102124
out:
21112125
pte_unmap_unlock(ptep, ptl);
21122126
*p_pfn = pfn;
2113-
return 0;
2127+
2128+
return r;
21142129
}
21152130

21162131
/*

0 commit comments

Comments
 (0)