[PATCH] gfs2: valid the length of rgrp header

Edward Adam Davis posted 1 patch 1 month, 1 week ago
fs/gfs2/rgrp.c | 8 ++++++++
1 file changed, 8 insertions(+)
[PATCH] gfs2: valid the length of rgrp header
Posted by Edward Adam Davis 1 month, 1 week ago
When mounting a deliberately corrupted filesystem image, an excessively
large rgrp header length is used in a call to kzalloc_objs() within
compute_bitstructs(), and the memory allocator cannot handle such a large
allocation request. This triggers [1].

Add a check for the rgrp header length to avoid [1].

[1]
WARNING: mm/page_alloc.c:5280 at __alloc_frozen_pages_noprof+0x2427/0x2dc0 mm/page_alloc.c:5280, CPU#1: syz-executor256/5629
Call Trace:
 alloc_pages_mpol+0x1fb/0x540 mm/mempolicy.c:2490
 ___kmalloc_large_node+0xe5/0x120 mm/slub.c:5274
 __kmalloc_large_node_noprof+0x1c/0x70 mm/slub.c:5305
 __do_kmalloc_node mm/slub.c:5322 [inline]
 __kmalloc_noprof+0x5a1/0x820 mm/slub.c:5359
 _kmalloc_noprof include/linux/slab.h:992 [inline]
 _kzalloc_noprof include/linux/slab.h:1309 [inline]
 compute_bitstructs fs/gfs2/rgrp.c:766 [inline]
 read_rindex_entry+0x4a1/0x1250 fs/gfs2/rgrp.c:931
 gfs2_ri_update+0x6f/0x3b0 fs/gfs2/rgrp.c:1001
 gfs2_rindex_update+0x40b/0x480 fs/gfs2/rgrp.c:1051
 init_inodes+0x1f78/0x2790 fs/gfs2/ops_fstype.c:872
 gfs2_fill_super+0x1d3d/0x2cf0 fs/gfs2/ops_fstype.c:1250
 get_tree_bdev_flags+0x38c/0x620 fs/super.c:1640
 gfs2_get_tree+0x4e/0x280 fs/gfs2/ops_fstype.c:1332
 vfs_get_tree+0x92/0x320 fs/super.c:1700
 fc_mount fs/namespace.c:1198 [inline]

Fixes: bb8d8a6f54c1 ("[GFS2] Fix sign problem in quota/statfs and cleanup _host structures")
Reported-by: syzbot+9d20c3ad7d29227de28d@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=9d20c3ad7d29227de28d
Tested-by: syzbot+9d20c3ad7d29227de28d@syzkaller.appspotmail.com
Signed-off-by: Edward Adam Davis <eadavis@qq.com>
---
 fs/gfs2/rgrp.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 5988a165a830..53d097ce668e 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -899,6 +899,7 @@ static int read_rindex_entry(struct gfs2_inode *ip)
 	struct gfs2_rindex buf;
 	int error;
 	struct gfs2_rgrpd *rgd;
+	size_t size;
 
 	if (pos >= i_size_read(&ip->i_inode))
 		return 1;
@@ -917,6 +918,13 @@ static int read_rindex_entry(struct gfs2_inode *ip)
 	rgd->rd_sbd = sdp;
 	rgd->rd_addr = be64_to_cpu(buf.ri_addr);
 	rgd->rd_length = be32_to_cpu(buf.ri_length);
+
+	size = rgd->rd_length * sizeof(struct gfs2_bitmap);
+	if (get_order(size) > MAX_PAGE_ORDER) {
+		error = -EINVAL;
+		goto fail;
+	}
+
 	rgd->rd_data0 = be64_to_cpu(buf.ri_data0);
 	rgd->rd_data = be32_to_cpu(buf.ri_data);
 	rgd->rd_bitbytes = be32_to_cpu(buf.ri_bitbytes);
-- 
2.43.0
Re: [PATCH] gfs2: valid the length of rgrp header
Posted by Andreas Gruenbacher 1 month, 1 week ago
On Thu, Aug 20, 2026 at 6:37 AM Edward Adam Davis <eadavis@qq.com> wrote:
> When mounting a deliberately corrupted filesystem image, an excessively
> large rgrp header length is used in a call to kzalloc_objs() within
> compute_bitstructs(), and the memory allocator cannot handle such a large
> allocation request. This triggers [1].
>
> Add a check for the rgrp header length to avoid [1].
>
> [1]
> WARNING: mm/page_alloc.c:5280 at __alloc_frozen_pages_noprof+0x2427/0x2dc0 mm/page_alloc.c:5280, CPU#1: syz-executor256/5629
> Call Trace:
>  alloc_pages_mpol+0x1fb/0x540 mm/mempolicy.c:2490
>  ___kmalloc_large_node+0xe5/0x120 mm/slub.c:5274
>  __kmalloc_large_node_noprof+0x1c/0x70 mm/slub.c:5305
>  __do_kmalloc_node mm/slub.c:5322 [inline]
>  __kmalloc_noprof+0x5a1/0x820 mm/slub.c:5359
>  _kmalloc_noprof include/linux/slab.h:992 [inline]
>  _kzalloc_noprof include/linux/slab.h:1309 [inline]
>  compute_bitstructs fs/gfs2/rgrp.c:766 [inline]
>  read_rindex_entry+0x4a1/0x1250 fs/gfs2/rgrp.c:931
>  gfs2_ri_update+0x6f/0x3b0 fs/gfs2/rgrp.c:1001
>  gfs2_rindex_update+0x40b/0x480 fs/gfs2/rgrp.c:1051
>  init_inodes+0x1f78/0x2790 fs/gfs2/ops_fstype.c:872
>  gfs2_fill_super+0x1d3d/0x2cf0 fs/gfs2/ops_fstype.c:1250
>  get_tree_bdev_flags+0x38c/0x620 fs/super.c:1640
>  gfs2_get_tree+0x4e/0x280 fs/gfs2/ops_fstype.c:1332
>  vfs_get_tree+0x92/0x320 fs/super.c:1700
>  fc_mount fs/namespace.c:1198 [inline]
>
> Fixes: bb8d8a6f54c1 ("[GFS2] Fix sign problem in quota/statfs and cleanup _host structures")
> Reported-by: syzbot+9d20c3ad7d29227de28d@syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=9d20c3ad7d29227de28d
> Tested-by: syzbot+9d20c3ad7d29227de28d@syzkaller.appspotmail.com
> Signed-off-by: Edward Adam Davis <eadavis@qq.com>
> ---
>  fs/gfs2/rgrp.c | 8 ++++++++
>  1 file changed, 8 insertions(+)
>
> diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
> index 5988a165a830..53d097ce668e 100644
> --- a/fs/gfs2/rgrp.c
> +++ b/fs/gfs2/rgrp.c
> @@ -899,6 +899,7 @@ static int read_rindex_entry(struct gfs2_inode *ip)
>         struct gfs2_rindex buf;
>         int error;
>         struct gfs2_rgrpd *rgd;
> +       size_t size;
>
>         if (pos >= i_size_read(&ip->i_inode))
>                 return 1;
> @@ -917,6 +918,13 @@ static int read_rindex_entry(struct gfs2_inode *ip)
>         rgd->rd_sbd = sdp;
>         rgd->rd_addr = be64_to_cpu(buf.ri_addr);
>         rgd->rd_length = be32_to_cpu(buf.ri_length);
> +
> +       size = rgd->rd_length * sizeof(struct gfs2_bitmap);
> +       if (get_order(size) > MAX_PAGE_ORDER) {
> +               error = -EINVAL;
> +               goto fail;
> +       }
> +
>         rgd->rd_data0 = be64_to_cpu(buf.ri_data0);
>         rgd->rd_data = be32_to_cpu(buf.ri_data);
>         rgd->rd_bitbytes = be32_to_cpu(buf.ri_bitbytes);
> --
> 2.43.0

Thanks. The patch I've pushed to 'for-later' for validating the
resource group geometry [*] should prevent this from happening in the
first place.

[*] https://lore.kernel.org/gfs2/20260821124944.1648686-1-agruenba@redhat.com/

Andreas