mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-08 22:23:18 +00:00
x86, mm: do not leak page->ptl for pmd page tables
There are two code paths how page with pmd page table can be freed: pmd_free() and pmd_free_tlb(). I've missed the second one and didn't add page table destructor call there. It leads to leak of page->ptl for pmd page tables, if dynamically allocated page->ptl is in use. The patch adds the missed destructor and modifies documentation accordingly. Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Reported-by: Andrey Vagin <avagin@openvz.org> Tested-by: Andrey Vagin <avagin@openvz.org> Cc: Ingo Molnar <mingo@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
3a72660b07
commit
c283610e44
@ -63,9 +63,9 @@ levels.
|
|||||||
PMD split lock enabling requires pgtable_pmd_page_ctor() call on PMD table
|
PMD split lock enabling requires pgtable_pmd_page_ctor() call on PMD table
|
||||||
allocation and pgtable_pmd_page_dtor() on freeing.
|
allocation and pgtable_pmd_page_dtor() on freeing.
|
||||||
|
|
||||||
Allocation usually happens in pmd_alloc_one(), freeing in pmd_free(), but
|
Allocation usually happens in pmd_alloc_one(), freeing in pmd_free() and
|
||||||
make sure you cover all PMD table allocation / freeing paths: i.e X86_PAE
|
pmd_free_tlb(), but make sure you cover all PMD table allocation / freeing
|
||||||
preallocate few PMDs on pgd_alloc().
|
paths: i.e X86_PAE preallocate few PMDs on pgd_alloc().
|
||||||
|
|
||||||
With everything in place you can set CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK.
|
With everything in place you can set CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK.
|
||||||
|
|
||||||
|
@ -61,6 +61,7 @@ void ___pte_free_tlb(struct mmu_gather *tlb, struct page *pte)
|
|||||||
#if PAGETABLE_LEVELS > 2
|
#if PAGETABLE_LEVELS > 2
|
||||||
void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
|
void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
|
||||||
{
|
{
|
||||||
|
struct page *page = virt_to_page(pmd);
|
||||||
paravirt_release_pmd(__pa(pmd) >> PAGE_SHIFT);
|
paravirt_release_pmd(__pa(pmd) >> PAGE_SHIFT);
|
||||||
/*
|
/*
|
||||||
* NOTE! For PAE, any changes to the top page-directory-pointer-table
|
* NOTE! For PAE, any changes to the top page-directory-pointer-table
|
||||||
@ -69,7 +70,8 @@ void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd)
|
|||||||
#ifdef CONFIG_X86_PAE
|
#ifdef CONFIG_X86_PAE
|
||||||
tlb->need_flush_all = 1;
|
tlb->need_flush_all = 1;
|
||||||
#endif
|
#endif
|
||||||
tlb_remove_page(tlb, virt_to_page(pmd));
|
pgtable_pmd_page_dtor(page);
|
||||||
|
tlb_remove_page(tlb, page);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PAGETABLE_LEVELS > 3
|
#if PAGETABLE_LEVELS > 3
|
||||||
|
Loading…
Reference in New Issue
Block a user