[PATCH] Fix hugepage crash on failing mmap()

This patch fixes a crash in the hugepage code. unmap_hugepage_area() was
assuming that (due to prefault) PTEs must exist for all the area in
question. However, this may not be the case, if mmap() encounters an error
before the prefault and calls unmap_region() to clean up any partial
mapping.

Depending on the hugepage configuration, this crash can be triggered by an
unpriveleged user.

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Cc: William Lee Irwin III <wli@holomorphy.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by David Gibson and committed by Linus Torvalds c7546f8f e6cb9941

+10 -1
+10 -1
mm/hugetlb.c
··· 301 { 302 struct mm_struct *mm = vma->vm_mm; 303 unsigned long address; 304 pte_t pte; 305 struct page *page; 306 ··· 310 BUG_ON(end & ~HPAGE_MASK); 311 312 for (address = start; address < end; address += HPAGE_SIZE) { 313 - pte = huge_ptep_get_and_clear(mm, address, huge_pte_offset(mm, address)); 314 if (pte_none(pte)) 315 continue; 316 page = pte_page(pte); 317 put_page(page); 318 }
··· 301 { 302 struct mm_struct *mm = vma->vm_mm; 303 unsigned long address; 304 + pte_t *ptep; 305 pte_t pte; 306 struct page *page; 307 ··· 309 BUG_ON(end & ~HPAGE_MASK); 310 311 for (address = start; address < end; address += HPAGE_SIZE) { 312 + ptep = huge_pte_offset(mm, address); 313 + if (! ptep) 314 + /* This can happen on truncate, or if an 315 + * mmap() is aborted due to an error before 316 + * the prefault */ 317 + continue; 318 + 319 + pte = huge_ptep_get_and_clear(mm, address, ptep); 320 if (pte_none(pte)) 321 continue; 322 + 323 page = pte_page(pte); 324 put_page(page); 325 }