[PATCH v2] mm/kasan: Fix double free for kasan pXds

0 views
Skip to first unread message

Ritesh Harjani (IBM)

unread,
Feb 24, 2026, 8:23:43 AMFeb 24
to kasa...@googlegroups.com, linu...@kvack.org, Andrey Ryabinin, Alexander Potapenko, Andrey Konovalov, Dmitry Vyukov, Vincenzo Frascino, linuxp...@lists.ozlabs.org, Ritesh Harjani (IBM), sta...@vger.kernel.org, Venkat Rao Bagalkote
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: sta...@vger.kernel.org
Reported-by: Venkat Rao Bagalkote <venk...@linux.ibm.com>
Signed-off-by: Ritesh Harjani (IBM) <rites...@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

Alexander Potapenko

unread,
Mar 2, 2026, 5:29:39 AMMar 2
to Ritesh Harjani (IBM), kasa...@googlegroups.com, linu...@kvack.org, Andrey Ryabinin, Andrey Konovalov, Dmitry Vyukov, Vincenzo Frascino, linuxp...@lists.ozlabs.org, sta...@vger.kernel.org, Venkat Rao Bagalkote
Reviewed-by: Alexander Potapenko <gli...@google.com>

Andrey Ryabinin

unread,
Mar 5, 2026, 1:31:10 PMMar 5
to Ritesh Harjani (IBM), kasa...@googlegroups.com, linu...@kvack.org, Alexander Potapenko, Andrey Konovalov, Dmitry Vyukov, Vincenzo Frascino, linuxp...@lists.ozlabs.org, sta...@vger.kernel.org, Venkat Rao Bagalkote
"Ritesh Harjani (IBM)" <rites...@gmail.com> writes:

> 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
...
>
> Fixes: 0207df4fa1a8 ("kernel/memremap, kasan: make ZONE_DEVICE with work with KASAN")
> Cc: sta...@vger.kernel.org
> Reported-by: Venkat Rao Bagalkote <venk...@linux.ibm.com>
> Signed-off-by: Ritesh Harjani (IBM) <rites...@gmail.com>
>

Reviewed-by: Andrey Ryabinin <ryabin...@gmail.com>

Aboorva Devarajan

unread,
Mar 10, 2026, 3:50:31 PM (10 days ago) Mar 10
to Ritesh Harjani (IBM), kasa...@googlegroups.com, linu...@kvack.org, Andrey Ryabinin, Alexander Potapenko, Andrey Konovalov, Dmitry Vyukov, Vincenzo Frascino, linuxp...@lists.ozlabs.org, sta...@vger.kernel.org, Venkat Rao Bagalkote
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 <aboo...@linux.ibm.com>


Thanks,
Aboorva
Reply all
Reply to author
Forward
0 new messages