Skip to content

Commit b10a1e5

Browse files
committed
erofs: fix rare pcluster memory leak after unmounting
There may still exist some pcluster with valid reference counts during unmounting. Instead of introducing another synchronization primitive, just try again as unmounting is relatively rare. This approach is similar to z_erofs_cache_invalidate_folio(). It was also reported by syzbot as a UAF due to commit f5ad9f9 ("erofs: free pclusters if no cached folio is attached"): BUG: KASAN: slab-use-after-free in do_raw_spin_trylock+0x72/0x1f0 kernel/locking/spinlock_debug.c:123 .. queued_spin_trylock include/asm-generic/qspinlock.h:92 [inline] do_raw_spin_trylock+0x72/0x1f0 kernel/locking/spinlock_debug.c:123 __raw_spin_trylock include/linux/spinlock_api_smp.h:89 [inline] _raw_spin_trylock+0x20/0x80 kernel/locking/spinlock.c:138 spin_trylock include/linux/spinlock.h:361 [inline] z_erofs_put_pcluster fs/erofs/zdata.c:959 [inline] z_erofs_decompress_pcluster fs/erofs/zdata.c:1403 [inline] z_erofs_decompress_queue+0x3798/0x3ef0 fs/erofs/zdata.c:1425 z_erofs_decompressqueue_work+0x99/0xe0 fs/erofs/zdata.c:1437 process_one_work kernel/workqueue.c:3229 [inline] process_scheduled_works+0xa68/0x1840 kernel/workqueue.c:3310 worker_thread+0x870/0xd30 kernel/workqueue.c:3391 kthread+0x2f2/0x390 kernel/kthread.c:389 ret_from_fork+0x4d/0x80 arch/x86/kernel/process.c:147 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244 </TASK> However, it seems a long outstanding memory leak. Fix it now. Fixes: f5ad9f9 ("erofs: free pclusters if no cached folio is attached") Reported-by: [email protected] Closes: https://lore.kernel.org/r/[email protected] Reviewed-by: Chao Yu <[email protected]> Signed-off-by: Gao Xiang <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 40384c8 commit b10a1e5

File tree

1 file changed

+4
-3
lines changed

1 file changed

+4
-3
lines changed

fs/erofs/zutil.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -230,9 +230,10 @@ void erofs_shrinker_unregister(struct super_block *sb)
230230
struct erofs_sb_info *const sbi = EROFS_SB(sb);
231231

232232
mutex_lock(&sbi->umount_mutex);
233-
/* clean up all remaining pclusters in memory */
234-
z_erofs_shrink_scan(sbi, ~0UL);
235-
233+
while (!xa_empty(&sbi->managed_pslots)) {
234+
z_erofs_shrink_scan(sbi, ~0UL);
235+
cond_resched();
236+
}
236237
spin_lock(&erofs_sb_list_lock);
237238
list_del(&sbi->list);
238239
spin_unlock(&erofs_sb_list_lock);

0 commit comments

Comments
 (0)