[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