mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] squashfs: fix leaked page locks when page actor allocation fails
@ 2026-09-27  6:05 Nguyen Ngoc Thang
  2026-11-06 21:51 ` Phillip Lougher
  0 siblings, 1 reply; 2+ messages in thread
From: Nguyen Ngoc Thang @ 2026-09-27  6:05 UTC (permalink / raw)
  To: Phillip Lougher
  Cc: Andrew Morton, linux-kernel, stable, syzbot+65b1e2d8f2d618a93e96,
	Nguyen Ngoc Thang

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 -----
From f686b39f997dc20222f455c5ac6421f6a5d6c8d8 Mon Sep 17 00:00:00 2001
From: Nguyen Ngoc Thang <ngocthang2710.1999@gmail.com>
Date: Sun, 27 Sep 2026 12:40:12 +0700
Subject: [PATCH] squashfs: fix leaked page locks when page actor allocation
 fails

squashfs_readpage_block() grabs and locks the sibling pages of the
target block before it allocates the page actor.  If that allocation
fails it jumps to "out", which only frees the page array, so the locked
pages are never unlocked or released.

A later truncate_inode_pages_range() on the inode, e.g. from evict() at
umount, then waits forever on the leaked folio lock and the task hangs.

Go through mark_errored instead, which unlocks and puts every page
except the target, which the caller handles.

Fixes: f268eedddf35 ("squashfs: extend "page actor" to handle missing pages")
Reported-by: syzbot+65b1e2d8f2d618a93e96@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=65b1e2d8f2d618a93e96
Cc: stable@vger.kernel.org
Signed-off-by: Nguyen Ngoc Thang <ngocthang2710.1999@gmail.com>
---
 fs/squashfs/file_direct.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/squashfs/file_direct.c b/fs/squashfs/file_direct.c
index 2c3e809d6891..177357443543 100644
--- a/fs/squashfs/file_direct.c
+++ b/fs/squashfs/file_direct.c
@@ -70,7 +70,7 @@ int squashfs_readpage_block(struct folio *folio, u64 block, int bsize,
 	actor = squashfs_page_actor_init_special(msblk, page, pages, expected,
 						start_index << PAGE_SHIFT);
 	if (actor == NULL)
-		goto out;
+		goto mark_errored;
 
 	/* Decompress directly into the page cache buffers */
 	res = squashfs_read_data(inode->i_sb, block, bsize, NULL, actor);
-- 
2.43.0


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] squashfs: fix leaked page locks when page actor allocation fails
  2026-09-27  6:05 [PATCH] squashfs: fix leaked page locks when page actor allocation fails Nguyen Ngoc Thang
@ 2026-11-06 21:51 ` Phillip Lougher
  0 siblings, 0 replies; 2+ messages in thread
From: Phillip Lougher @ 2026-11-06 21:51 UTC (permalink / raw)
  To: Nguyen Ngoc Thang
  Cc: Andrew Morton, linux-kernel, stable, syzbot+65b1e2d8f2d618a93e96

On 27/09/2026 07:05, Nguyen Ngoc Thang wrote:

> 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 -----
>  From f686b39f997dc20222f455c5ac6421f6a5d6c8d8 Mon Sep 17 00:00:00 2001
> From: Nguyen Ngoc Thang <ngocthang2710.1999@gmail.com>
> Date: Sun, 27 Sep 2026 12:40:12 +0700
> Subject: [PATCH] squashfs: fix leaked page locks when page actor allocation
>   fails
>
> squashfs_readpage_block() grabs and locks the sibling pages of the
> target block before it allocates the page actor.  If that allocation
> fails it jumps to "out", which only frees the page array, so the locked
> pages are never unlocked or released.
>
> A later truncate_inode_pages_range() on the inode, e.g. from evict() at
> umount, then waits forever on the leaked folio lock and the task hangs.
>
> Go through mark_errored instead, which unlocks and puts every page
> except the target, which the caller handles.
>
> Fixes: f268eedddf35 ("squashfs: extend "page actor" to handle missing pages")
> Reported-by: syzbot+65b1e2d8f2d618a93e96@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=65b1e2d8f2d618a93e96
> Cc: stable@vger.kernel.org
> Signed-off-by: Nguyen Ngoc Thang <ngocthang2710.1999@gmail.com>
> ---
>   fs/squashfs/file_direct.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/fs/squashfs/file_direct.c b/fs/squashfs/file_direct.c
> index 2c3e809d6891..177357443543 100644
> --- a/fs/squashfs/file_direct.c
> +++ b/fs/squashfs/file_direct.c
> @@ -70,7 +70,7 @@ int squashfs_readpage_block(struct folio *folio, u64 block, int bsize,
>   	actor = squashfs_page_actor_init_special(msblk, page, pages, expected,
>   						start_index << PAGE_SHIFT);
>   	if (actor == NULL)
> -		goto out;
> +		goto mark_errored;
>   
>   	/* Decompress directly into the page cache buffers */
>   	res = squashfs_read_data(inode->i_sb, block, bsize, NULL, actor);

Sorry for the delay, I'm currently snowed under with AI reports and bugs;

But, it looks good.

Reviewed-by: Phillip Lougher <phillip@squashfs.org.uk 
<https://squashfs.org.uk>>

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-11-06 21:51 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-27  6:05 [PATCH] squashfs: fix leaked page locks when page actor allocation fails Nguyen Ngoc Thang
2026-11-06 21:51 ` Phillip Lougher

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®