[PATCH 0/2] f2fs: fix use-after-free of sbi in the compressed read path
From: Fan Wu
Date: Fri Sep 04 2026 - 21:36:15 EST
This series fixes two windows in which the completion of a compressed
read drops the last reference of a decompress_io_ctx after the pages
of the cluster were unlocked, so that f2fs_free_dic() dereferences sbi
after a concurrent unmount may already have destroyed
sbi->page_array_slab and freed sbi:
1/2 reorders the direct completions (the fsverity worker tail and
the in-task decompression completion) so that their put of the
decompress_io_ctx happens before the last page unlock of the
cluster, closing the window when that put releases the final
reference. It mirrors the ordering rule the write path already
has in f2fs_compress_write_end_io(), and needs no new state.
2/2 makes f2fs_put_super() wait for in-flight decompress_io_ctx
before the post-read workqueue and the page-array slab are
destroyed. It covers the remaining completion, where a mixed
bio of a verity file releases the compressed-page references on
the global fsverity workqueue, which unmount does not drain.
This is the design proposed in Cen Zhang's report of this bug.
Both windows were reproduced with KASAN in QEMU on the f2fs dev tree
baseline with a deterministic 10 s park inside the respective window
(the instrumentation is disclosed in the note of patch 1/2; the
use-after-free itself is the unmodified put_dic -> free_dic path):
readahead() on a compressed fsverity file, close(), umount():
28 reports, 0 with patch 1/2
readahead() spanning an incompressible and a compressible cluster
of a verity file, close(), umount():
14 reports with patch 1/2 alone, 0 with patch 2/2
Cen Zhang reported this bug with a KASAN reproduction and proposed the
counter design adopted in 2/2.
Patch 1/2 is not a substitute for patch 2/2: the counter in 2/2 is
the complete lifetime fix and closes every final-put completion
measured here, including the worker tail that 1/2 reorders, while
1/2 alone leaves the mixed-bio completion above still reporting.
Apply the series together: with the reorder, the decompress_io_ctx is
usually gone before the last page unlock, avoiding an unmount delay
in the common case.
Fan Wu (2):
f2fs: compress: fix use-after-free of sbi in read path
f2fs: compress: drain decompress contexts at unmount
fs/f2fs/compress.c | 38 +++++++++++++++++++++++++++++++++++---
fs/f2fs/f2fs.h | 6 ++++++
fs/f2fs/super.c | 3 +++
3 files changed, 44 insertions(+), 3 deletions(-)
--
2.34.1