Messages in this thread Patch in this message |  | | Date | Sun, 10 May 2026 17:45:40 +0300 | | From | Mike Rapoport <> | | Subject | Re: [PATCH] sched/isolation: Don't free memblock allocated cpumasks |
| |
Hi Breno,
On Fri, May 08, 2026 at 07:19:06AM -0700, Breno Leitao wrote: > On Tue, May 05, 2026 at 01:18:21AM -0400, Waiman Long wrote: > > One workaround for now to avoid these warning/bug > > messages is to keep the memblock allocated cpumasks even if they are > > no longer needed until the memblock subsystem is properly updated to > > handle memblock_free(). > > We just hit the same KASAN UAF from a different caller on a v7.1-rc3 boot, > which I think reinforces that the fix really needs to be in memblock rather > than in each subsystem. > > In our case the offender is the IMA kexec buffer release path: > > [ 113.498542] BUG: KASAN: use-after-free in memblock_isolate_range+0x208/0x8f0 > [ 113.514206] Read of size 8 at addr ff11001824ba4000 by task swapper/0/1 > ... > [ 113.532258] memblock_isolate_range+0x208/0x8f0 > [ 113.532267] memblock_phys_free+0x5f/0x300 > [ 113.532274] ima_free_kexec_buffer+0x1d/0x40 > [ 113.532280] ima_load_kexec_buffer+0xbf/0xf0 > [ 113.532285] ima_init+0x42/0xa0 > [ 113.532287] init_ima+0x5e/0x190 > [ 113.532290] security_initcall_late+0xad/0x210 > [ 113.532301] do_one_initcall+0x138/0x540 > > Same shape as your second trace: memblock_phys_free() reads > memblock.reserved.regions, which memblock_discard() has already returned > to the buddy allocator (the KASAN shadow shows the page as fully poisoned, > and pfn 0x1824ba4 has been reallocated). It then page-faults a moment later > on the same address. > > ima_init runs as a security_initcall_late, so by the time > ima_free_kexec_buffer() calls memblock_phys_free() on the previous > kernel's measurement buffer, memblock has long been torn down on > configurations without CONFIG_ARCH_KEEP_MEMBLOCK > > This regression seems to come from commit 87ce9e83ab8b ("memblock, treewide: make > memblock_free() handle late freeing"), which dropped memblock_free_late() > and made memblock_phys_free() unconditionally call > memblock_remove_range(&memblock.reserved, ...) followed by an optional > __free_reserved_area().
Oops, somehow I overlooked that late freeing can't access memblock arrays :(
Can you please test this fix:
diff --git a/mm/memblock.c b/mm/memblock.c index a6a1c91e276d..ccd43f3abb82 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -989,13 +989,15 @@ void __init_memblock memblock_free(void *ptr, size_t size) int __init_memblock memblock_phys_free(phys_addr_t base, phys_addr_t size) { phys_addr_t end = base + size - 1; - int ret; + int ret = 0; memblock_dbg("%s: [%pa-%pa] %pS\n", __func__, &base, &end, (void *)_RET_IP_); kmemleak_free_part_phys(base, size); - ret = memblock_remove_range(&memblock.reserved, base, size); + + if (!slab_is_available() || IS_ENABLED(CONFIG_ARCH_KEEP_MEMBLOCK)) + ret = memblock_remove_range(&memblock.reserved, base, size); if (slab_is_available()) __free_reserved_area(base, base + size, -1);
-- Sincerely yours, Mike.
|  |