summaryrefslogtreecommitdiff
path: root/mm/vmalloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/vmalloc.c')
-rw-r--r--mm/vmalloc.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index f2481cb..195de42 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -244,11 +244,21 @@ struct page *vmalloc_to_page(const void *vmalloc_addr)
*/
VIRTUAL_BUG_ON(!is_vmalloc_or_module_addr(vmalloc_addr));
+ /*
+ * Don't dereference bad PUD or PMD (below) entries. This will also
+ * identify huge mappings, which we may encounter on architectures
+ * that define CONFIG_HAVE_ARCH_HUGE_VMAP=y. Such regions will be
+ * identified as vmalloc addresses by is_vmalloc_addr(), but are
+ * not [unambiguously] associated with a struct page, so there is
+ * no correct value to return for them.
+ */
if (!pgd_none(*pgd)) {
pud_t *pud = pud_offset(pgd, addr);
- if (!pud_none(*pud)) {
+ WARN_ON_ONCE(pud_bad(*pud));
+ if (!pud_none(*pud) && !pud_bad(*pud)) {
pmd_t *pmd = pmd_offset(pud, addr);
- if (!pmd_none(*pmd)) {
+ WARN_ON_ONCE(pmd_bad(*pmd));
+ if (!pmd_none(*pmd) && !pmd_bad(*pmd)) {
pte_t *ptep, pte;
ptep = pte_offset_map(pmd, addr);