From 935f60b120f86f254abea81a2323d080ea920657 Mon Sep 17 00:00:00 2001 From: Quentin Perret Date: Fri, 25 Mar 2022 17:58:43 +0000 Subject: [PATCH] ANDROID: KVM: arm64: Check pin_user_pages() return value Let's check the return value of pin_user_pages() before blindly dereferencing the struct page pointer as it may very well be NULL. Bug: 223678931 Reported-by: Keir Fraser Signed-off-by: Quentin Perret Change-Id: I49eb0eb14b88429cfeed3e7cc8a2a72404cfea97 --- arch/arm64/kvm/mmu.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index 14b822a187d0..30d2a349786f 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -1189,28 +1189,28 @@ static int pkvm_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, ret = pin_user_pages(hva, 1, flags, &page, NULL); mmap_read_unlock(mm); - /* - * We really can't deal with page-cache pages returned by GUP - * because (a) we may trigger writeback of a page for which we - * no longer have access and (b) page_mkclean() won't find the - * stage-2 mapping in the rmap so we can get out-of-whack with - * the filesystem when marking the page dirty during unpinning. - * - * Ideally we'd just restrict ourselves to anonymous pages, but - * we also want to allow memfd (i.e. shmem) pages, so check for - * pages backed by swap in the knowledge that the GUP pin will - * prevent try_to_unmap() from succeeding. - */ - if (!PageSwapBacked(page)) { - ret = -EIO; - goto dec_account; - } else if (ret == -EHWPOISON) { + if (ret == -EHWPOISON) { kvm_send_hwpoison_signal(hva, PAGE_SHIFT); ret = 0; goto dec_account; } else if (ret != 1) { ret = -EFAULT; goto dec_account; + } else if (!PageSwapBacked(page)) { + /* + * We really can't deal with page-cache pages returned by GUP + * because (a) we may trigger writeback of a page for which we + * no longer have access and (b) page_mkclean() won't find the + * stage-2 mapping in the rmap so we can get out-of-whack with + * the filesystem when marking the page dirty during unpinning. + * + * Ideally we'd just restrict ourselves to anonymous pages, but + * we also want to allow memfd (i.e. shmem) pages, so check for + * pages backed by swap in the knowledge that the GUP pin will + * prevent try_to_unmap() from succeeding. + */ + ret = -EIO; + goto dec_account; } spin_lock(&kvm->mmu_lock);