[PATCH v2] gfs2: reject journal extents with gaps

Deepanshu Kartikey posted 1 patch 1 week ago
fs/gfs2/bmap.c | 2 ++
1 file changed, 2 insertions(+)
[PATCH v2] gfs2: reject journal extents with gaps
Posted by Deepanshu Kartikey 1 week ago
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@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=9013411dc43f3582823a
Link: https://lore.kernel.org/all/20260324033959.1456418-1-kartikey406@gmail.com/T/ [v1]
Suggested-by: Andreas Gruenbacher <agruenba@redhat.com>
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>

---
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
Re: [PATCH v2] gfs2: reject journal extents with gaps
Posted by Deepanshu Kartikey 3 days, 12 hours ago
On Thu, Mar 26, 2026 at 5:22 AM Deepanshu Kartikey
<kartikey406@gmail.com> 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@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=9013411dc43f3582823a
> Link: https://lore.kernel.org/all/20260324033959.1456418-1-kartikey406@gmail.com/T/ [v1]
> Suggested-by: Andreas Gruenbacher <agruenba@redhat.com>
> Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
>
> ---
> 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