Skip to content
This repository was archived by the owner on Nov 7, 2025. It is now read-only.

Commit ee017ee

Browse files
jongwuwilldeacon
authored andcommitted
arm64/mm: avoid fixmap race condition when create pud mapping
The 'fixmap' is a global resource and is used recursively by create pud mapping(), leading to a potential race condition in the presence of a concurrent call to alloc_init_pud(): kernel_init thread virtio-mem workqueue thread ================== =========================== alloc_init_pud(...) alloc_init_pud(...) pudp = pud_set_fixmap_offset(...) pudp = pud_set_fixmap_offset(...) READ_ONCE(*pudp) pud_clear_fixmap(...) READ_ONCE(*pudp) // CRASH! As kernel may sleep during creating pud mapping, introduce a mutex lock to serialise use of the fixmap entries by alloc_init_pud(). However, there is no need for locking in early boot stage and it doesn't work well with KASLR enabled when early boot. So, enable lock when system_state doesn't equal to "SYSTEM_BOOTING". Signed-off-by: Jianyong Wu <[email protected]> Reviewed-by: Catalin Marinas <[email protected]> Fixes: f471044 ("arm64: mm: use fixmap when creating page tables") Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Will Deacon <[email protected]>
1 parent e921da6 commit ee017ee

File tree

1 file changed

+9
-0
lines changed

1 file changed

+9
-0
lines changed

arch/arm64/mm/mmu.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ static pmd_t bm_pmd[PTRS_PER_PMD] __page_aligned_bss __maybe_unused;
6363
static pud_t bm_pud[PTRS_PER_PUD] __page_aligned_bss __maybe_unused;
6464

6565
static DEFINE_SPINLOCK(swapper_pgdir_lock);
66+
static DEFINE_MUTEX(fixmap_lock);
6667

6768
void set_swapper_pgd(pgd_t *pgdp, pgd_t pgd)
6869
{
@@ -329,6 +330,12 @@ static void alloc_init_pud(pgd_t *pgdp, unsigned long addr, unsigned long end,
329330
}
330331
BUG_ON(p4d_bad(p4d));
331332

333+
/*
334+
* No need for locking during early boot. And it doesn't work as
335+
* expected with KASLR enabled.
336+
*/
337+
if (system_state != SYSTEM_BOOTING)
338+
mutex_lock(&fixmap_lock);
332339
pudp = pud_set_fixmap_offset(p4dp, addr);
333340
do {
334341
pud_t old_pud = READ_ONCE(*pudp);
@@ -359,6 +366,8 @@ static void alloc_init_pud(pgd_t *pgdp, unsigned long addr, unsigned long end,
359366
} while (pudp++, addr = next, addr != end);
360367

361368
pud_clear_fixmap();
369+
if (system_state != SYSTEM_BOOTING)
370+
mutex_unlock(&fixmap_lock);
362371
}
363372

364373
static void __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys,

0 commit comments

Comments
 (0)