Skip to content

Commit e4c8f85

Browse files
committed
mm/khugepaged: fix GUP-fast interaction by sending IPI
jira VULN-71586 cve-pre CVE-2025-38085 commit-author Jann Horn <[email protected]> commit 2ba99c5 upstream-diff Resolved contextual conflicts due to lack of backported 8d3c106 Since commit 70cbc3c ("mm: gup: fix the fast GUP race against THP collapse"), the lockless_pages_from_mm() fastpath rechecks the pmd_t to ensure that the page table was not removed by khugepaged in between. However, lockless_pages_from_mm() still requires that the page table is not concurrently freed. Fix it by sending IPIs (if the architecture uses semi-RCU-style page table freeing) before freeing/reusing page tables. Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Fixes: ba76149 ("thp: khugepaged") Signed-off-by: Jann Horn <[email protected]> Reviewed-by: Yang Shi <[email protected]> Acked-by: David Hildenbrand <[email protected]> Cc: John Hubbard <[email protected]> Cc: Peter Xu <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]> (cherry picked from commit 2ba99c5) Signed-off-by: Marcin Wcisło <[email protected]>
1 parent 408b318 commit e4c8f85

File tree

3 files changed

+7
-3
lines changed

3 files changed

+7
-3
lines changed

include/asm-generic/tlb.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,12 +222,16 @@ extern void tlb_remove_table(struct mmu_gather *tlb, void *table);
222222
#define tlb_needs_table_invalidate() (true)
223223
#endif
224224

225+
void tlb_remove_table_sync_one(void);
226+
225227
#else
226228

227229
#ifdef tlb_needs_table_invalidate
228230
#error tlb_needs_table_invalidate() requires MMU_GATHER_RCU_TABLE_FREE
229231
#endif
230232

233+
static inline void tlb_remove_table_sync_one(void) { }
234+
231235
#endif /* CONFIG_MMU_GATHER_RCU_TABLE_FREE */
232236

233237

mm/khugepaged.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,6 +1138,7 @@ static void collapse_huge_page(struct mm_struct *mm,
11381138
_pmd = pmdp_collapse_flush(vma, address, pmd);
11391139
spin_unlock(pmd_ptl);
11401140
mmu_notifier_invalidate_range_end(&range);
1141+
tlb_remove_table_sync_one();
11411142

11421143
spin_lock(pte_ptl);
11431144
isolated = __collapse_huge_page_isolate(vma, address, pte,
@@ -1413,6 +1414,7 @@ static void collapse_and_free_pmd(struct mm_struct *mm, struct vm_area_struct *v
14131414
ptl = pmd_lock(vma->vm_mm, pmdp);
14141415
pmd = pmdp_collapse_flush(vma, addr, pmdp);
14151416
spin_unlock(ptl);
1417+
tlb_remove_table_sync_one();
14161418
mm_dec_nr_ptes(mm);
14171419
page_table_check_pte_clear_range(mm, addr, pmd);
14181420
pte_free(mm, pmd_pgtable(pmd));

mm/mmu_gather.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ static void tlb_remove_table_smp_sync(void *arg)
140140
/* Simply deliver the interrupt */
141141
}
142142

143-
static void tlb_remove_table_sync_one(void)
143+
void tlb_remove_table_sync_one(void)
144144
{
145145
/*
146146
* This isn't an RCU grace period and hence the page-tables cannot be
@@ -164,8 +164,6 @@ static void tlb_remove_table_free(struct mmu_table_batch *batch)
164164

165165
#else /* !CONFIG_MMU_GATHER_RCU_TABLE_FREE */
166166

167-
static void tlb_remove_table_sync_one(void) { }
168-
169167
static void tlb_remove_table_free(struct mmu_table_batch *batch)
170168
{
171169
__tlb_remove_table_free(batch);

0 commit comments

Comments
 (0)