[PATCH] squashfs: fix leaked page locks when page actor allocation fails

From: Nguyen Ngoc Thang

Date: Sun Sep 27 2026 - 02:06:00 EST


Hi Phillip,

syzbot reports a hang in evict() during umount of a squashfs mount
(INFO: task hung in evict (2)):

https://syzkaller.appspot.com/bug?extid=65b1e2d8f2d618a93e96

Root cause: squashfs_readpage_block() grabs and locks the sibling pages
of the block with grab_cache_page_nowait(), and only afterwards allocates
the page actor. If squashfs_page_actor_init_special() fails, the code
does "goto out", which only kfree()s the page array. The locked, referenced
sibling pages are never unlocked or put. A later truncate_inode_pages_range()
from evict() blocks on the leaked folio lock forever.

The ordering was introduced by f268eedddf35 ("squashfs: extend "page actor"
to handle missing pages"); before it the actor was allocated first.

Fix: use "goto mark_errored", which already unlocks and puts every page
except the target page (owned by the caller, which unlocks it via
folio_end_read()). res is still -ENOMEM at that point.

Testing: QEMU (KVM, KASAN, lockdep, IMA tcb policy) running the syzbot C
reproducer, with fail-nth swept over 1..400 in openat(). The failslab
hit lands in squashfs_page_actor_init_special() from
squashfs_readpage_block() via ima_calc_file_hash().
- before: hung task in evict()/truncate_inode_pages_range() after ~12s,
same trace as the syzbot report
- after: 170s of runs, 174 injected failures at that site, no hang

The patch is below / attached.

----- patch -----