Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

x86: pgtable: move pagetable_dtor() to __tlb_remove_table()

Move pagetable_dtor() to __tlb_remove_table(), so that ptlock and page
table pages can be freed together (regardless of whether RCU is used).
This prevents the use-after-free problem where the ptlock is freed
immediately but the page table pages is freed later via RCU.

Link: https://lkml.kernel.org/r/27b3cdc8786bebd4f748380bf82f796482718504.1736317725.git.zhengqi.arch@bytedance.com
Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
Suggested-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Kevin Brodsky <kevin.brodsky@arm.com>
Cc: Alexander Gordeev <agordeev@linux.ibm.com>
Cc: Alexandre Ghiti <alex@ghiti.fr>
Cc: Alexandre Ghiti <alexghiti@rivosinc.com>
Cc: Andreas Larsson <andreas@gaisler.com>
Cc: Aneesh Kumar K.V (Arm) <aneesh.kumar@kernel.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: David Hildenbrand <david@redhat.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: Jann Horn <jannh@google.com>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Mike Rapoport (Microsoft) <rppt@kernel.org>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Palmer Dabbelt <palmer@dabbelt.com>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vishal Moola (Oracle) <vishal.moola@gmail.com>
Cc: Will Deacon <will@kernel.org>
Cc: Yu Zhao <yuzhao@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Qi Zheng and committed by
Andrew Morton
ee0934b0 0b6476f9

+6 -12
+1
arch/x86/include/asm/tlb.h
··· 33 33 { 34 34 struct ptdesc *ptdesc = (struct ptdesc *)table; 35 35 36 + pagetable_dtor(ptdesc); 36 37 pagetable_free(ptdesc); 37 38 } 38 39
+1
arch/x86/kernel/paravirt.c
··· 64 64 { 65 65 struct ptdesc *ptdesc = (struct ptdesc *)table; 66 66 67 + pagetable_dtor(ptdesc); 67 68 tlb_remove_page(tlb, ptdesc_page(ptdesc)); 68 69 } 69 70 #else
+4 -12
arch/x86/mm/pgtable.c
··· 25 25 { 26 26 struct ptdesc *ptdesc = (struct ptdesc *)table; 27 27 28 + pagetable_dtor(ptdesc); 28 29 tlb_remove_page(tlb, ptdesc_page(ptdesc)); 29 30 } 30 31 #else ··· 63 62 64 63 void ___pte_free_tlb(struct mmu_gather *tlb, struct page *pte) 65 64 { 66 - pagetable_dtor(page_ptdesc(pte)); 67 65 paravirt_release_pte(page_to_pfn(pte)); 68 66 paravirt_tlb_remove_table(tlb, page_ptdesc(pte)); 69 67 } ··· 70 70 #if CONFIG_PGTABLE_LEVELS > 2 71 71 void ___pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd) 72 72 { 73 - struct ptdesc *ptdesc = virt_to_ptdesc(pmd); 74 73 paravirt_release_pmd(__pa(pmd) >> PAGE_SHIFT); 75 74 /* 76 75 * NOTE! For PAE, any changes to the top page-directory-pointer-table ··· 78 79 #ifdef CONFIG_X86_PAE 79 80 tlb->need_flush_all = 1; 80 81 #endif 81 - pagetable_dtor(ptdesc); 82 - paravirt_tlb_remove_table(tlb, ptdesc); 82 + paravirt_tlb_remove_table(tlb, virt_to_ptdesc(pmd)); 83 83 } 84 84 85 85 #if CONFIG_PGTABLE_LEVELS > 3 86 86 void ___pud_free_tlb(struct mmu_gather *tlb, pud_t *pud) 87 87 { 88 - struct ptdesc *ptdesc = virt_to_ptdesc(pud); 89 - 90 - pagetable_dtor(ptdesc); 91 88 paravirt_release_pud(__pa(pud) >> PAGE_SHIFT); 92 - paravirt_tlb_remove_table(tlb, ptdesc); 89 + paravirt_tlb_remove_table(tlb, virt_to_ptdesc(pud)); 93 90 } 94 91 95 92 #if CONFIG_PGTABLE_LEVELS > 4 96 93 void ___p4d_free_tlb(struct mmu_gather *tlb, p4d_t *p4d) 97 94 { 98 - struct ptdesc *ptdesc = virt_to_ptdesc(p4d); 99 - 100 - pagetable_dtor(ptdesc); 101 95 paravirt_release_p4d(__pa(p4d) >> PAGE_SHIFT); 102 - paravirt_tlb_remove_table(tlb, ptdesc); 96 + paravirt_tlb_remove_table(tlb, virt_to_ptdesc(p4d)); 103 97 } 104 98 #endif /* CONFIG_PGTABLE_LEVELS > 4 */ 105 99 #endif /* CONFIG_PGTABLE_LEVELS > 3 */