This is a note to let you know that I've just added the patch titled KVM: do not allow mapping valid but non-reference-counted pages to the 4.9-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: kvm-do-not-allow-mapping-valid-but-non-reference-counted-pages.patch and it can be found in the queue-4.9 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. >From foo@baz Mon Jan 24 07:28:36 PM CET 2022 From: Ben Hutchings <ben@xxxxxxxxxxxxxxx> Date: Mon, 24 Jan 2022 17:45:00 +0100 Subject: KVM: do not allow mapping valid but non-reference-counted pages To: stable@xxxxxxxxxxxxxxx Cc: Paolo Bonzini <pbonzini@xxxxxxxxxx>, Nicholas Piggin <npiggin@xxxxxxxxx> Message-ID: <Ye7XjLxf61gjp8w2@xxxxxxxxxxxxxxx> Content-Disposition: inline From: Nicholas Piggin <npiggin@xxxxxxxxx> commit f8be156be163a052a067306417cd0ff679068c97 upstream. 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 <npiggin@xxxxxxxxx> Tested-by: Paolo Bonzini <pbonzini@xxxxxxxxxx> Cc: stable@xxxxxxxxxxxxxxx Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx> Signed-off-by: Ben Hutchings <ben@xxxxxxxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- virt/kvm/kvm_main.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -1513,6 +1513,13 @@ static bool vma_is_valid(struct vm_area_ return true; } +static int kvm_try_get_pfn(kvm_pfn_t pfn) +{ + if (kvm_is_reserved_pfn(pfn)) + return 1; + return get_page_unless_zero(pfn_to_page(pfn)); +} + static int hva_to_pfn_remapped(struct vm_area_struct *vma, unsigned long addr, bool *async, bool write_fault, bool *writable, @@ -1562,13 +1569,21 @@ static int hva_to_pfn_remapped(struct vm * Whoever called remap_pfn_range is also going to call e.g. * unmap_mapping_range before the underlying pages are freed, * causing a call to our MMU notifier. + * + * Certain IO or PFNMAP mappings can be backed with valid + * struct pages, but be allocated without refcounting e.g., + * tail pages of non-compound higher order allocations, which + * would then underflow the refcount when the caller does the + * required put_page. Don't allow those pages here. */ - kvm_get_pfn(pfn); + if (!kvm_try_get_pfn(pfn)) + r = -EFAULT; out: pte_unmap_unlock(ptep, ptl); *p_pfn = pfn; - return 0; + + return r; } /* Patches currently in stable-queue which might be from ben@xxxxxxxxxxxxxxx are queue-4.9/lib-timerqueue-rely-on-rbtree-semantics-for-next-timer.patch queue-4.9/gup-document-and-work-around-cow-can-break-either-way-issue.patch queue-4.9/fuse-fix-live-lock-in-fuse_iget.patch queue-4.9/kvm-do-not-assume-pte-is-writable-after-follow_pfn.patch queue-4.9/drm-ttm-nouveau-don-t-call-tt-destroy-callback-on-alloc-failure.patch queue-4.9/gianfar-simplify-fcs-handling-and-fix-memory-leak.patch queue-4.9/mm-add-follow_pte_pmd.patch queue-4.9/revert-gup-document-and-work-around-cow-can-break-either-way-issue.patch queue-4.9/gianfar-fix-jumbo-packets-napi-rx-overrun-crash.patch queue-4.9/cipso-calipso-resolve-a-number-of-problems-with-the-doi-refcounts.patch queue-4.9/rbtree-cache-leftmost-node-internally.patch queue-4.9/kvm-use-kvm_pfn_t-for-local-pfn-variable-in-hva_to_pfn_remapped.patch queue-4.9/kvm-do-not-allow-mapping-valid-but-non-reference-counted-pages.patch queue-4.9/fuse-fix-bad-inode.patch