Re: [PATCH v2] gfs2: reject journal extents with gaps

From: Deepanshu Kartikey

Date: Mon Mar 30 2026 - 05:49:41 EST


On Thu, Mar 26, 2026 at 5:22 AM Deepanshu Kartikey
<kartikey406@xxxxxxxxx> wrote:
>
> A malicious or corrupted GFS2 filesystem image can have a journal
> extent list with gaps between extents. gfs2_find_jhead() advances
> blocks_read sequentially through all page indices, but only grabs
> pages for blocks it actually visits via filemap_grab_folio(). Pages
> falling in the gaps between extents are never grabbed. When the
> cleanup loop at out: calls gfs2_jhead_process_page() for these
> pages, filemap_get_folio() returns ERR_PTR(-ENOENT) which is passed
> directly to folio_wait_locked() without checking for errors, hanging
> the kernel task in uninterruptible sleep (state D) forever,
> triggering the hung task watchdog.
>
> Fix this by rejecting journal extents with gaps at mapping time
> in gfs2_add_jextent(). If the new extent does not start exactly
> where the previous one ended, return -EINVAL to reject the
> corrupted journal early, before any I/O is submitted.
>
> Fixes: f4686c26ecc3 ("gfs2: read journal in large chunks")
> Reported-by: syzbot+9013411dc43f3582823a@xxxxxxxxxxxxxxxxxxxxxxxxx
> Closes: https://syzkaller.appspot.com/bug?extid=9013411dc43f3582823a
> Link: https://lore.kernel.org/all/20260324033959.1456418-1-kartikey406@xxxxxxxxx/T/ [v1]
> Suggested-by: Andreas Gruenbacher <agruenba@xxxxxxxxxx>
> Signed-off-by: Deepanshu Kartikey <kartikey406@xxxxxxxxx>
>
> ---
> Changes in v2:
> - Instead of checking ERR_PTR in gfs2_jhead_process_page(), reject
> the gap at extent mapping time in gfs2_add_jextent() as suggested
> by Andreas Gruenbacher.
> ---
> fs/gfs2/bmap.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
> index 1cd8ec0bce83..d3ba37291e4c 100644
> --- a/fs/gfs2/bmap.c
> +++ b/fs/gfs2/bmap.c
> @@ -2219,6 +2219,8 @@ static int gfs2_add_jextent(struct gfs2_jdesc *jd, u64 lblock, u64 dblock, u64 b
>
> if (!list_empty(&jd->extent_list)) {
> jext = list_last_entry(&jd->extent_list, struct gfs2_journal_extent, list);
> + if (jext->lblock + jext->blocks != lblock)
> + return -EINVAL;
> if ((jext->dblock + jext->blocks) == dblock) {
> jext->blocks += blocks;
> return 0;
> --
> 2.43.0
>
Hi Andreas,

gentle ping on this patch . Let me know if anything else required from my side

Thanks
Deepanshu