Skip to content

Commit 521f3bc

Browse files
author
Charan Teja Kalla
committed
ANDROID: mm: fix UAF in SPF
The below race is observed on the SPF path: pthread1 pthread2 -------- -------- Speculatively enter __pte_map_lock: irq_disable() ............ All seq lock checks are succeeded. ............ ptl = (pmd_page(*pmd))->ptl __vm_munmap(): mmap_write_lock_killable(); (update the seq count) __do_munmap()--> unmap_region()--> free_pgtables()--> .......... free_pte_range(): ptl = pmd_lock() unlock(ptl) pte_free_tlb()--> ......... pgtable_pte_page_dtor(): (Free the pmd_page(page)->ptl to the slab, on which pthread1 still operating on) spin_trylock(ptl) Seq count check fails spin_unlock(): SPIN_BUG() checks are passed kmem_cache_free()--> do_slab_free(): (a) *(ptl + offset) = c->freelist (b) c->freelist = ptl update ptl->owner, owner->cpu (This is use-after-free of the ptl slab object which is corrupting the next pointer,(a), filled by the pthread2 in the cuuren->freelist) Note that when DEBUG_SPINLOCK is not enabled, race won't exist as ALLOC_SPLIT_PTLOCKS is not defined i.e. ptl is stored directly in the page structure. Note that this change as uses smp sync doesn't have any perf impact in the production builds as the intended code is under ALLOC_SPLIT_PTLOCKS which will be absent. Bug: 265837312 Change-Id: I05b11c80a45c285ab8d293cca925aa4388f62d05 Signed-off-by: Charan Teja Kalla <quic_charante@quicinc.com>
1 parent e09118b commit 521f3bc

File tree

1 file changed

+13
-0
lines changed

1 file changed

+13
-0
lines changed

mm/memory.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,11 @@ void put_vma(struct vm_area_struct *vma)
253253
vm_area_free_no_check(vma);
254254
}
255255

256+
#if ALLOC_SPLIT_PTLOCKS
257+
static void wait_for_smp_sync(void *arg)
258+
{
259+
}
260+
#endif
256261
#endif /* CONFIG_SPECULATIVE_PAGE_FAULT */
257262

258263
/*
@@ -272,6 +277,14 @@ static void free_pte_range(struct mmu_gather *tlb, pmd_t *pmd,
272277
*/
273278
spinlock_t *ptl = pmd_lock(tlb->mm, pmd);
274279
spin_unlock(ptl);
280+
#if ALLOC_SPLIT_PTLOCKS
281+
/*
282+
* The __pte_map_lock can still be working on the ->ptl in the read side
283+
* critical section while ->ptl is freed which results into the use-after
284+
* -free. Sync it using the smp_call_().
285+
*/
286+
smp_call_function(wait_for_smp_sync, NULL, 1);
287+
#endif
275288
#endif
276289
pmd_clear(pmd);
277290
pte_free_tlb(tlb, token, addr);

0 commit comments

Comments
 (0)