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

dane phillips <[email protected]>
Newsgroups org.kvack.linux-mm,org.kernel.vger.linux-crypto,org.kernel.vger.linux-kernel
Message-ID <CAAzp_c7vP1om1eHrwhXLZdqURo6vhu9S0J0b3HM8z7hFzmaRpQ@mail.gmail.com>
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.