[PATCH v2] mm/kasan: Fix double free for kasan pXds
Aboorva Devarajan
aboorvad at linux.ibm.com
Wed Mar 11 06:50:15 AEDT 2026
On Tue, 2026-02-24 at 18:53 +0530, Ritesh Harjani (IBM) wrote:
> kasan_free_pxd() assumes the page table is always struct page aligned.
> But that's not always the case for all architectures. E.g. In case of
> powerpc with 64K pagesize, PUD table (of size 4096) comes from slab
> cache named pgtable-2^9. Hence instead of page_to_virt(pxd_page()) let's
> just directly pass the start of the pxd table which is passed as the 1st
> argument.
>
> This fixes the below double free kasan issue seen with PMEM:
>
> radix-mmu: Mapped 0x0000047d10000000-0x0000047f90000000 with 2.00 MiB pages
> ==================================================================
> BUG: KASAN: double-free in kasan_remove_zero_shadow+0x9c4/0xa20
> Free of addr c0000003c38e0000 by task ndctl/2164
>
> CPU: 34 UID: 0 PID: 2164 Comm: ndctl Not tainted 6.19.0-rc1-00048-gea1013c15392 #157 VOLUNTARY
> Hardware name: IBM,9080-HEX POWER10 (architected) 0x800200 0xf000006 of:IBM,FW1060.00 (NH1060_012) hv:phyp pSeries
> Call Trace:
> dump_stack_lvl+0x88/0xc4 (unreliable)
> print_report+0x214/0x63c
> kasan_report_invalid_free+0xe4/0x110
> check_slab_allocation+0x100/0x150
> kmem_cache_free+0x128/0x6e0
> kasan_remove_zero_shadow+0x9c4/0xa20
> memunmap_pages+0x2b8/0x5c0
> devm_action_release+0x54/0x70
> release_nodes+0xc8/0x1a0
> devres_release_all+0xe0/0x140
> device_unbind_cleanup+0x30/0x120
> device_release_driver_internal+0x3e4/0x450
> unbind_store+0xfc/0x110
> drv_attr_store+0x78/0xb0
> sysfs_kf_write+0x114/0x140
> kernfs_fop_write_iter+0x264/0x3f0
> vfs_write+0x3bc/0x7d0
> ksys_write+0xa4/0x190
> system_call_exception+0x190/0x480
> system_call_vectored_common+0x15c/0x2ec
> ---- interrupt: 3000 at 0x7fff93b3d3f4
> NIP: 00007fff93b3d3f4 LR: 00007fff93b3d3f4 CTR: 0000000000000000
> REGS: c0000003f1b07e80 TRAP: 3000 Not tainted (6.19.0-rc1-00048-gea1013c15392)
> MSR: 800000000280f033 <SF,VEC,VSX,EE,PR,FP,ME,IR,DR,RI,LE> CR: 48888208 XER: 00000000
> <...>
> NIP [00007fff93b3d3f4] 0x7fff93b3d3f4
> LR [00007fff93b3d3f4] 0x7fff93b3d3f4
> ---- interrupt: 3000
>
> The buggy address belongs to the object at c0000003c38e0000
> which belongs to the cache pgtable-2^9 of size 4096
> The buggy address is located 0 bytes inside of
> 4096-byte region [c0000003c38e0000, c0000003c38e1000)
>
> The buggy address belongs to the physical page:
> page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x3c38c
> head: order:2 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
> memcg:c0000003bfd63e01
> flags: 0x63ffff800000040(head|node=6|zone=0|lastcpupid=0x7ffff)
> page_type: f5(slab)
> raw: 063ffff800000040 c000000140058980 5deadbeef0000122 0000000000000000
> raw: 0000000000000000 0000000080200020 00000000f5000000 c0000003bfd63e01
> head: 063ffff800000040 c000000140058980 5deadbeef0000122 0000000000000000
> head: 0000000000000000 0000000080200020 00000000f5000000 c0000003bfd63e01
> head: 063ffff800000002 c00c000000f0e301 00000000ffffffff 00000000ffffffff
> head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000004
> page dumped because: kasan: bad access detected
>
> [ 138.953636] [ T2164] Memory state around the buggy address:
> [ 138.953643] [ T2164] c0000003c38dff00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
> [ 138.953652] [ T2164] c0000003c38dff80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
> [ 138.953661] [ T2164] >c0000003c38e0000: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
> [ 138.953669] [ T2164] ^
> [ 138.953675] [ T2164] c0000003c38e0080: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
> [ 138.953684] [ T2164] c0000003c38e0100: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
> [ 138.953692] [ T2164] ==================================================================
> [ 138.953701] [ T2164] Disabling lock debugging due to kernel taint
>
> Fixes: 0207df4fa1a8 ("kernel/memremap, kasan: make ZONE_DEVICE with work with KASAN")
> Cc: stable at vger.kernel.org
> Reported-by: Venkat Rao Bagalkote <venkat88 at linux.ibm.com>
> Signed-off-by: Ritesh Harjani (IBM) <ritesh.list at gmail.com>
> ---
>
> v1 -> v2:
> 1. cc'd linux-mm
> 2. Added tags (Fixes, CC, Reported).
>
> mm/kasan/init.c | 8 ++++----
> 1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/mm/kasan/init.c b/mm/kasan/init.c
> index f084e7a5df1e..9c880f607c6a 100644
> --- a/mm/kasan/init.c
> +++ b/mm/kasan/init.c
> @@ -292,7 +292,7 @@ static void kasan_free_pte(pte_t *pte_start, pmd_t *pmd)
> return;
> }
>
> - pte_free_kernel(&init_mm, (pte_t *)page_to_virt(pmd_page(*pmd)));
> + pte_free_kernel(&init_mm, pte_start);
> pmd_clear(pmd);
> }
>
> @@ -307,7 +307,7 @@ static void kasan_free_pmd(pmd_t *pmd_start, pud_t *pud)
> return;
> }
>
> - pmd_free(&init_mm, (pmd_t *)page_to_virt(pud_page(*pud)));
> + pmd_free(&init_mm, pmd_start);
> pud_clear(pud);
> }
>
> @@ -322,7 +322,7 @@ static void kasan_free_pud(pud_t *pud_start, p4d_t *p4d)
> return;
> }
>
> - pud_free(&init_mm, (pud_t *)page_to_virt(p4d_page(*p4d)));
> + pud_free(&init_mm, pud_start);
> p4d_clear(p4d);
> }
>
> @@ -337,7 +337,7 @@ static void kasan_free_p4d(p4d_t *p4d_start, pgd_t *pgd)
> return;
> }
>
> - p4d_free(&init_mm, (p4d_t *)page_to_virt(pgd_page(*pgd)));
> + p4d_free(&init_mm, p4d_start);
> pgd_clear(pgd);
> }
>
> --
> 2.53.0
I observed this issue in the almost recent mainline kernel.
# ndctl create-namespace -t pmem -m fsdax -M dev -r region1 -s 10737418240
{
"dev":"namespace1.0",
"mode":"fsdax",
"map":"dev",
"size":"9.99 GiB (10.72 GB)",
"uuid":"..",
"sector_size":512,
"align":2097152,
"blockdev":"pmem1"
}
# ndctl destroy-namespace namespace1.0 --force
destroyed 1 namespace
# dmesg
...
[ 940.927567] [ T3360] radix-mmu: Mapped 0x0000047d10000000-0x0000047f90000000 with 64.0 KiB pages
[ 948.389280] [ T3382] ==================================================================
[ 948.389333] [ T3382] BUG: KASAN: double-free in kasan_remove_zero_shadow+0x9c4/0xa20
[ 948.389356] [ T3382] Free of addr c00000016f240000 by task ndctl/3382
[ 948.389379] [ T3382] CPU: 17 UID: 0 PID: 3382 Comm: ndctl Not tainted 7.0.0-rc2-00534-g014441d1e4b2 #3 PREEMPT(full)
[ 948.389385] [ T3382] Hardware name: IBM,9080-HEX POWER10 (architected) 0x800200 0xf000006 of:IBM,FW1060.00 (NH1060_012) hv:phyp pSeries
[ 948.389391] [ T3382] Call Trace:
[ 948.389394] [ T3382] [c00000017900f4e0] [c000000001cc0f64] dump_stack_lvl+0x88/0xc4 (unreliable)
[ 948.389408] [ T3382] [c00000017900f510] [c000000000886470] print_report+0x228/0x658
[ 948.389415] [ T3382] [c00000017900f600] [c000000000885e74] kasan_report_invalid_free+0xe4/0x110
[ 948.389422] [ T3382] [c00000017900f6f0] [c0000000008844e0] check_slab_allocation+0x100/0x150
[ 948.389428] [ T3382] [c00000017900f720] [c00000000081e980] kmem_cache_free+0xd0/0x650
[ 948.389435] [ T3382] [c00000017900f7a0] [c000000000887264] kasan_remove_zero_shadow+0x9c4/0xa20
[ 948.389442] [ T3382] [c00000017900f8c0] [c0000000008fb408] memunmap_pages+0x2c8/0x5d0
[ 948.389450] [ T3382] [c00000017900f9b0] [c000000001378614] devm_action_release+0x54/0x70
[ 948.389459] [ T3382] [c00000017900f9e0] [c000000001378bd8] release_nodes+0xd8/0x260
[ 948.389465] [ T3382] [c00000017900fa60] [c00000000137c0b0] devres_release_all+0xe0/0x140
[ 948.389471] [ T3382] [c00000017900fad0] [c00000000136d824] device_unbind_cleanup+0x34/0x160
[ 948.389479] [ T3382] [c00000017900fb10] [c0000000013701c4] device_release_driver_internal+0x3e4/0x450
[ 948.389485] [ T3382] [c00000017900fb70] [c00000000136b94c] unbind_store+0xfc/0x110
[ 948.389491] [ T3382] [c00000017900fbb0] [c0000000013699a8] drv_attr_store+0x78/0xb0
[ 948.389498] [ T3382] [c00000017900fbf0] [c000000000a70054] sysfs_kf_write+0x134/0x160
[ 948.389504] [ T3382] [c00000017900fc40] [c000000000a6bb94] kernfs_fop_write_iter+0x264/0x3f0
[ 948.389512] [ T3382] [c00000017900fca0] [c00000000090e56c] vfs_write+0x3bc/0x870
[ 948.389517] [ T3382] [c00000017900fd90] [c00000000090ecd4] ksys_write+0xa4/0x190
[ 948.389523] [ T3382] [c00000017900fdf0] [c00000000003ae40] system_call_exception+0x190/0x500
[ 948.389530] [ T3382] [c00000017900fe50] [c00000000000d05c] system_call_vectored_common+0x15c/0x2ec
[ 948.389538] [ T3382] ---- interrupt: 3000 at 0x7fffb0d3d3f4
[ 948.389547] [ T3382] NIP: 00007fffb0d3d3f4 LR: 00007fffb0d3d3f4 CTR: 0000000000000000
[ 948.389550] [ T3382] REGS: c00000017900fe80 TRAP: 3000 Not tainted (7.0.0-rc2-00534-g014441d1e4b2)
[ 948.389553] [ T3382] MSR: 800000000280f033 <SF,VEC,VSX,EE,PR,FP,ME,IR,DR,RI,LE> CR: 48888208 XER: 00000000
[ 948.389571] [ T3382] IRQMASK: 0
GPR00: 0000000000000004 00007fffd47ce6f0 0000000000100000 0000000000000004
GPR04: 0000000145394bec 0000000000000007 0000000000000000 0000000000000000
GPR08: 0000000000000030 0000000000000000 0000000000000000 0000000000000000
GPR12: 0000000000000000 00007fffb12508a0 0000000040000000 0000000000000003
GPR16: 0000000040000000 00000001453948b0 00000001352f6060 00000001352f0810
GPR20: 00000001352f0818 00000001453953ac 00007fffd47ced18 000000000000000c
GPR24: 0000000145394400 00007fffd47ce840 00000001453953ac 0000000145394400
GPR28: 0000000000000007 0000000000000000 0000000145394bec 0000000000000004
[ 948.389618] [ T3382] NIP [00007fffb0d3d3f4] 0x7fffb0d3d3f4
[ 948.389621] [ T3382] LR [00007fffb0d3d3f4] 0x7fffb0d3d3f4
[ 948.389624] [ T3382] ---- interrupt: 3000
[ 948.389813] [ T3382] Allocated by task 3360:
[ 948.389822] [ T3382] kasan_save_stack+0x48/0x80
[ 948.389831] [ T3382] kasan_save_track+0x2c/0x50
[ 948.389841] [ T3382] kasan_save_alloc_info+0x44/0x60
[ 948.389851] [ T3382] __kasan_slab_alloc+0x90/0xe0
[ 948.389860] [ T3382] kmem_cache_alloc_noprof+0x1b4/0x620
[ 948.389869] [ T3382] __pud_alloc+0x90/0x260
[ 948.389877] [ T3382] __map_kernel_page+0x45c/0x5c0
[ 948.389887] [ T3382] create_physical_mapping.constprop.0+0x218/0x500
[ 948.389898] [ T3382] create_section_mapping+0x20/0x60
[ 948.389908] [ T3382] arch_create_linear_mapping+0x7c/0xf0
[ 948.389917] [ T3382] arch_add_memory+0x4c/0xf0
[ 948.389926] [ T3382] memremap_pages+0x434/0xd10
[ 948.389935] [ T3382] devm_memremap_pages+0x44/0xb0
[ 948.389945] [ T3382] pmem_attach_disk+0x73c/0x990
[ 948.389955] [ T3382] nvdimm_bus_probe+0x11c/0x350
[ 948.389963] [ T3382] really_probe+0x178/0x520
[ 948.389971] [ T3382] __driver_probe_device+0x10c/0x250
[ 948.389980] [ T3382] device_driver_attach+0x94/0x160
[ 948.389988] [ T3382] bind_store+0xd8/0x160
[ 948.389997] [ T3382] drv_attr_store+0x78/0xb0
[ 948.390006] [ T3382] sysfs_kf_write+0x134/0x160
[ 948.390015] [ T3382] kernfs_fop_write_iter+0x264/0x3f0
[ 948.390024] [ T3382] vfs_write+0x3bc/0x870
[ 948.390032] [ T3382] ksys_write+0xa4/0x190
[ 948.390041] [ T3382] system_call_exception+0x190/0x500
[ 948.390049] [ T3382] system_call_vectored_common+0x15c/0x2ec
[ 948.390065] [ T3382] Freed by task 3382:
[ 948.390071] [ T3382] kasan_save_stack+0x48/0x80
[ 948.390080] [ T3382] kasan_save_track+0x2c/0x50
[ 948.390089] [ T3382] kasan_save_free_info+0x60/0xd0
[ 948.390100] [ T3382] __kasan_slab_free+0x78/0xc0
[ 948.390110] [ T3382] kmem_cache_free+0x104/0x650
[ 948.390118] [ T3382] remove_pagetable+0xe14/0xf90
[ 948.390127] [ T3382] radix__remove_section_mapping+0x24/0x40
[ 948.390136] [ T3382] remove_section_mapping+0x20/0x60
[ 948.390147] [ T3382] arch_remove_linear_mapping+0x5c/0xc0
[ 948.390156] [ T3382] memunmap_pages+0x28c/0x5d0
[ 948.390166] [ T3382] devm_action_release+0x54/0x70
[ 948.390175] [ T3382] release_nodes+0xd8/0x260
[ 948.390183] [ T3382] devres_release_all+0xe0/0x140
[ 948.390193] [ T3382] device_unbind_cleanup+0x34/0x160
[ 948.390203] [ T3382] device_release_driver_internal+0x3e4/0x450
[ 948.390213] [ T3382] unbind_store+0xfc/0x110
[ 948.390222] [ T3382] drv_attr_store+0x78/0xb0
[ 948.390231] [ T3382] sysfs_kf_write+0x134/0x160
[ 948.390239] [ T3382] kernfs_fop_write_iter+0x264/0x3f0
[ 948.390249] [ T3382] vfs_write+0x3bc/0x870
[ 948.390257] [ T3382] ksys_write+0xa4/0x190
[ 948.390265] [ T3382] system_call_exception+0x190/0x500
[ 948.390274] [ T3382] system_call_vectored_common+0x15c/0x2ec
[ 948.390289] [ T3382] The buggy address belongs to the object at c00000016f240000
which belongs to the cache pgtable-2^9 of size 4096
[ 948.390302] [ T3382] The buggy address is located 0 bytes inside of
4096-byte region [c00000016f240000, c00000016f241000)
[ 948.390320] [ T3382] The buggy address belongs to the physical page:
[ 948.390330] [ T3382] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x16f20
[ 948.390341] [ T3382] head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
[ 948.390351] [ T3382] memcg:c00000017383e601
[ 948.390357] [ T3382] flags: 0x13ffff800000040(head|node=1|zone=0|lastcpupid=0x7ffff)
[ 948.390371] [ T3382] page_type: f5(slab)
[ 948.390381] [ T3382] raw: 013ffff800000040 c00000000601a580 c00c000000646a10 c00c000000648210
[ 948.390392] [ T3382] raw: 0000000000000000 00000008002a002a 00000000f5000000 c00000017383e601
[ 948.390402] [ T3382] head: 013ffff800000040 c00000000601a580 c00c000000646a10 c00c000000648210
[ 948.390413] [ T3382] head: 0000000000000000 00000008002a002a 00000000f5000000 c00000017383e601
[ 948.390423] [ T3382] head: 013ffff800000003 c00c0000005bc801 00000000ffffffff 00000000ffffffff
[ 948.390432] [ T3382] head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000008
[ 948.390441] [ T3382] page dumped because: kasan: bad access detected
[ 948.390453] [ T3382] Memory state around the buggy address:
[ 948.390461] [ T3382] c00000016f23ff00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 948.390470] [ T3382] c00000016f23ff80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[ 948.390479] [ T3382] >c00000016f240000: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 948.390486] [ T3382] ^
[ 948.390493] [ T3382] c00000016f240080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 948.390501] [ T3382] c00000016f240100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 948.390510] [ T3382] ==================================================================
[ 948.390544] [ T3382] Disabling lock debugging due to kernel taint
...
With this patch I do not see the issue:
# ndctl create-namespace -t pmem -m fsdax -M dev -r region1 -s 10737418240
{
"dev":"namespace1.0",
"mode":"fsdax",
"map":"dev",
"size":"9.99 GiB (10.72 GB)",
"uuid":"bd796a2a-f998-4e38-b399-7d414b60add3",
"sector_size":512,
"align":2097152,
"blockdev":"pmem1"
}
# ndctl destroy-namespace namespace1.0 --force
destroyed 1 namespace
# dmesg | grep "double-free"
..
...
So,
Tested-by: Aboorva Devarajan <aboorvad at linux.ibm.com>
Thanks,
Aboorva
More information about the Linuxppc-dev
mailing list