Re: KMSAN: use-after-free in sw842_decompress (zswap writeback)

dane phillips <[email protected]>
Newsgroups gmane.linux.kernel.cryptoapi,gmane.linux.kernel,gmane.linux.kernel.mm
Message-ID <CAAzp_c4_4tVB68P_2EoXP4nLVa7npiHobmTHnjP-aCh0RRKHRA@mail.gmail.com>
 Retracting both of my earlier mails in this thread. There is no bug
here,
 in zswap or in lib/842's input handling, and nobody should spend time
on it.

I could not reproduce the report; that trace should not have gone out
and
I'm sorry for the noise.

On Fri, Jul 31, 2026 at 8:50 AM dane phillips <[email protected]> wrote:
>
> I got the mechanism wrong in my first mail, correcting before anyone
> wastes time on it.
>
> I read the "Uninit was created at" chain as causal. It isn't. That
> chain just says where the page had been before the allocator handed
> it back out. exit_mmap has nothing to do with it and there's no race
> with process exit.
>
> The poison is in the compressed input, not in a swapped-out page:
>
>   next_bits+0xac2         lib/842/842_decompress.c:118
>   sw842_decompress+0x1a6  lib/842/842_decompress.c:297
>   sw842_decompress+0x11c8 lib/842/842_decompress.c:303
>
> 297 is the opcode fetch, 303 uses it.
>
> What I think is happening: zpool_obj_read_begin() copies exactly
> entry->length bytes into acomp_ctx->buffer, which is kmalloc'd and
> never zeroed, and sw842_decompress reads past entry->length into
> whatever was there before. next_bits() does full 8-byte loads while
> p->ilen >= 8, so entry->length not being a multiple of 8 looks like
> the trigger.
>
> So the subject should be something like "KMSAN: uninit-value in
> sw842_decompress, over-read of compressed input past entry->length"
> rather than use-after-free.
>
> Testing that now with kzalloc_node() for the buffer, plus a sweep of
> compressed lengths across residues mod 8. Also rerunning with lzo,
> zstd and deflate to see whether this is lib/842 or zswap's bounce
> buffer.
>
> Two things I should have mentioned the first time: the kernel was
> already tainted W from an unrelated get_xsave_addr warning earlier in
> that boot, and the tree was 503 commits past 7.2.0-rc4. I'll redo it
> clean on mainline.
>
> More once I have something.
>
> Dane
>
> On Thu, Jul 30, 2026 at 11:20 AM dane phillips <[email protected]> wrote:
> >
> > Hi,
> >
> > I am running syzkaller on commit 3dab139d4795 and it
> > reported the use-after-free below. The issue occurs when zswap
> > writeback decompresses a page that has already been freed by
> > process exit.
> >
> > Kernel version: 7.2.0-rc4-00503-g3dab139d4795
> > Config: CONFIG_KMSAN=y, CONFIG_ZSWAP=y, CONFIG_CRYPTO_842=y
> >
> > The bug manifests in sw842_decompress accessing memory that was
> > freed in exit_mmap, while the shrinker is still walking the zswap
> > pool.
> >
> > BUG: KMSAN: use-after-free in sw842_decompress+0x11c8/0x1750
> > lib/842/842_decompress.c:303
> >  sw842_decompress+0x11c8/0x1750 lib/842/842_decompress.c:303
> >  crypto842_sdecompress+0x46/0x60 crypto/842.c:53
> >  scomp_acomp_comp_decomp+0xa49/0x1120 include/crypto/internal/scompress.h:-1
> >  scomp_acomp_decompress+0x30/0x40 crypto/scompress.c:283
> >  crypto_acomp_decompress+0x5c4/0xe50 crypto/acompress.c:297
> >  zswap_decompress+0x4ba/0xcc0 mm/zswap.c:952
> >  zswap_writeback_entry mm/zswap.c:1032 [inline]
> >  shrink_memcg_cb+0x78f/0xda0 mm/zswap.c:1147
> >  __list_lru_walk_one+0x49a/0xde0 mm/list_lru.c:362
> >  list_lru_walk_one+0x5c/0x70 mm/list_lru.c:399
> >  list_lru_shrink_walk include/linux/list_lru.h:332 [inline]
> >  zswap_shrinker_scan+0x11f/0x290 mm/zswap.c:1181
> >  do_shrink_slab+0x736/0x1460 mm/shrinker.c:443
> >  shrink_slab_memcg mm/shrinker.c:560 [inline]
> >  shrink_slab+0xb70/0x14c0 mm/shrinker.c:638
> >  shrink_one+0x560/0xc10 mm/vmscan.c:5026
> >  shrink_many mm/vmscan.c:5087 [inline]
> >  lru_gen_shrink_node mm/vmscan.c:5165 [inline]
> >  shrink_node+0x47a5/0x5b70 mm/vmscan.c:6154
> >  kswapd_shrink_node mm/vmscan.c:7008 [inline]
> >  balance_pgdat mm/vmscan.c:7186 [inline]
> >  kswapd+0x3029/0x5a50 mm/vmscan.c:7462
> >  kthread+0x53f/0x600 kernel/kthread.c:436
> >  ret_from_fork+0x20f/0x8d0 arch/x86/kernel/process.c:158
> >  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
> >
> > Uninit was stored to memory at:
> >  sw842_decompress+0x11c1/0x1750 lib/842/842_decompress.c:303
> >  crypto842_sdecompress+0x46/0x60 crypto/842.c:53
> >  scomp_acomp_comp_decomp+0xa49/0x1120 include/crypto/internal/scompress.h:-1
> >  scomp_acomp_decompress+0x30/0x40 crypto/scompress.c:283
> >  crypto_acomp_decompress+0x5c4/0xe50 crypto/acompress.c:297
> >  zswap_decompress+0x4ba/0xcc0 mm/zswap.c:952
> >  zswap_writeback_entry mm/zswap.c:1032 [inline]
> >  shrink_memcg_cb+0x78f/0xda0 mm/zswap.c:1147
> >  __list_lru_walk_one+0x49a/0xde0 mm/list_lru.c:362
> >  list_lru_walk_one+0x5c/0x70 mm/list_lru.c:399
> >  list_lru_shrink_walk include/linux/list_lru.h:332 [inline]
> >  zswap_shrinker_scan+0x11f/0x290 mm/zswap.c:1181
> >  do_shrink_slab+0x736/0x1460 mm/shrinker.c:443
> >  shrink_slab_memcg mm/shrinker.c:560 [inline]
> >  shrink_slab+0xb70/0x14c0 mm/shrinker.c:638
> >  shrink_one+0x560/0xc10 mm/vmscan.c:5026
> >  shrink_many mm/vmscan.c:5087 [inline]
> >  lru_gen_shrink_node mm/vmscan.c:5165 [inline]
> >  shrink_node+0x47a5/0x5b70 mm/vmscan.c:6154
> >  kswapd_shrink_node mm/vmscan.c:7008 [inline]
> >  balance_pgdat mm/vmscan.c:7186 [inline]
> >  kswapd+0x3029/0x5a50 mm/vmscan.c:7462
> >  kthread+0x53f/0x600 kernel/kthread.c:436
> >  ret_from_fork+0x20f/0x8d0 arch/x86/kernel/process.c:158
> >  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
> >
> > Uninit was stored to memory at:
> >  next_bits+0xac2/0xda0 lib/842/842_decompress.c:118
> >  sw842_decompress+0x1a6/0x1750 lib/842/842_decompress.c:297
> >  crypto842_sdecompress+0x46/0x60 crypto/842.c:53
> >  scomp_acomp_comp_decomp+0xa49/0x1120 include/crypto/internal/scompress.h:-1
> >  scomp_acomp_decompress+0x30/0x40 crypto/scompress.c:283
> >  crypto_acomp_decompress+0x5c4/0xe50 crypto/acompress.c:297
> >  zswap_decompress+0x4ba/0xcc0 mm/zswap.c:952
> >  zswap_writeback_entry mm/zswap.c:1032 [inline]
> >  shrink_memcg_cb+0x78f/0xda0 mm/zswap.c:1147
> >  __list_lru_walk_one+0x49a/0xde0 mm/list_lru.c:362
> >  list_lru_walk_one+0x5c/0x70 mm/list_lru.c:399
> >  list_lru_shrink_walk include/linux/list_lru.h:332 [inline]
> >  zswap_shrinker_scan+0x11f/0x290 mm/zswap.c:1181
> >  do_shrink_slab+0x736/0x1460 mm/shrinker.c:443
> >  shrink_slab_memcg mm/shrinker.c:560 [inline]
> >  shrink_slab+0xb70/0x14c0 mm/shrinker.c:638
> >  shrink_one+0x560/0xc10 mm/vmscan.c:5026
> >  shrink_many mm/vmscan.c:5087 [inline]
> >  lru_gen_shrink_node mm/vmscan.c:5165 [inline]
> >  shrink_node+0x47a5/0x5b70 mm/vmscan.c:6154
> >  kswapd_shrink_node mm/vmscan.c:7008 [inline]
> >  balance_pgdat mm/vmscan.c:7186 [inline]
> >  kswapd+0x3029/0x5a50 mm/vmscan.c:7462
> >  kthread+0x53f/0x600 kernel/kthread.c:436
> >  ret_from_fork+0x20f/0x8d0 arch/x86/kernel/process.c:158
> >  ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
> >
> > Uninit was created at:
> >  __free_pages_prepare mm/page_alloc.c:1327 [inline]
> >  free_unref_folios+0x280/0x2880 mm/page_alloc.c:3011
> >  folios_put_refs+0xb2e/0xba0 mm/swap.c:1057
> >  free_pages_and_swap_cache+0x804/0x840 mm/swap_state.c:589
> >  __tlb_batch_free_encoded_pages mm/mmu_gather.c:138 [inline]
> >  tlb_batch_pages_flush mm/mmu_gather.c:151 [inline]
> >  tlb_flush_mmu_free mm/mmu_gather.c:417 [inline]
> >  tlb_flush_mmu+0x92b/0xe90 mm/mmu_gather.c:424
> >  zap_pte_range mm/memory.c:1973 [inline]
> >  zap_pmd_range mm/memory.c:2020 [inline]
> >  zap_pud_range mm/memory.c:2048 [inline]
> >  zap_p4d_range mm/memory.c:2069 [inline]
> >  __zap_vma_range+0x763f/0x9340 mm/memory.c:2109
> >  unmap_vmas+0x440/0x800 mm/memory.c:2178
> >  exit_mmap+0x27c/0xac0 mm/mmap.c:1300
> >  __mmput+0x134/0x650 kernel/fork.c:1187
> >  mmput+0x74/0x90 kernel/fork.c:1210
> >  exit_mm+0x2b1/0x4b0 kernel/exit.c:615
> >  do_exit+0x9a9/0x3c30 kernel/exit.c:997
> >  do_group_exit+0x258/0x390 kernel/exit.c:1152
> >  __do_sys_exit_group kernel/exit.c:1163 [inline]
> >  __se_sys_exit_group kernel/exit.c:1161 [inline]
> >  __x64_sys_exit_group+0x35/0x40 kernel/exit.c:1161
> >  x64_sys_call+0x3e6d/0x3ea0 arch/x86/include/generated/asm/syscalls_64.h:232
> >  do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
> >  do_syscall_64+0x15d/0x3c0 arch/x86/entry/syscall_64.c:94
> >  entry_SYSCALL_64_after_hwframe+0x77/0x7f
> >
> > CPU: 0 UID: 0 PID: 81 Comm: kswapd0 Tainted: G        W
> > 7.2.0-rc4-00503-g3dab139d4795 #9 PREEMPT(lazy)
> > Tainted: [W]=WARN
> > Hardware name: QEMU Ubuntu 26.04 PC (i440FX + PIIX, 1996), BIOS
> > 1.17.0-debian-1.17.0-1ubuntu1 04/01/2014
> > =====================================================
> >
> >
> >
> > The full syzkaller log is available if needed.  I do not yet have a
> > reliable reproducer.
> >
> > Thanks,
> >
> > Dane Phillips
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.