Commit 7b868e81 authored by Aneesh Kumar K.V's avatar Aneesh Kumar K.V Committed by Michael Ellerman

powerpc/mm: Return NULL for not present hugetlb page

We need to check whether pte is present in follow_huge_addr() and
properly return NULL if mapping is not present. Also use READ_ONCE
when dereferencing pte_t address.

Without this patch, we may wrongly return a zero pfn page in
follow_huge_addr().
Reviewed-by: default avatarDavid Gibson <david@gibson.dropbear.id.au>
Signed-off-by: default avatarAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 13bd817b
...@@ -689,27 +689,34 @@ void hugetlb_free_pgd_range(struct mmu_gather *tlb, ...@@ -689,27 +689,34 @@ void hugetlb_free_pgd_range(struct mmu_gather *tlb,
struct page * struct page *
follow_huge_addr(struct mm_struct *mm, unsigned long address, int write) follow_huge_addr(struct mm_struct *mm, unsigned long address, int write)
{ {
pte_t *ptep; pte_t *ptep, pte;
struct page *page;
unsigned shift; unsigned shift;
unsigned long mask, flags; unsigned long mask, flags;
struct page *page = ERR_PTR(-EINVAL);
local_irq_save(flags);
ptep = find_linux_pte_or_hugepte(mm->pgd, address, &shift);
if (!ptep)
goto no_page;
pte = READ_ONCE(*ptep);
/* /*
* Verify it is a huge page else bail.
* Transparent hugepages are handled by generic code. We can skip them * Transparent hugepages are handled by generic code. We can skip them
* here. * here.
*/ */
local_irq_save(flags); if (!shift || pmd_trans_huge(__pmd(pte_val(pte))))
ptep = find_linux_pte_or_hugepte(mm->pgd, address, &shift); goto no_page;
/* Verify it is a huge page else bail. */ if (!pte_present(pte)) {
if (!ptep || !shift || pmd_trans_huge(*(pmd_t *)ptep)) { page = NULL;
local_irq_restore(flags); goto no_page;
return ERR_PTR(-EINVAL);
} }
mask = (1UL << shift) - 1; mask = (1UL << shift) - 1;
page = pte_page(*ptep); page = pte_page(pte);
if (page) if (page)
page += (address & mask) / PAGE_SIZE; page += (address & mask) / PAGE_SIZE;
no_page:
local_irq_restore(flags); local_irq_restore(flags);
return page; return page;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment