Description: Fix stack out-of-bounds write in savemeta (CVE-2026-71221)
 In savemeta, save_inode_data() in gfs2/edit/savemeta.c reads the on-disk
 di_height field (an unbounded uint16_t from untrusted filesystem
 metadata) and uses it, after an optional adjustment for exhash
 directories, as the bound of a loop and as an index into the stack array
 indq[GFS2_MAX_META_HEIGHT] without any bounds checking.  A crafted GFS2
 filesystem image with a large di_height value therefore causes a stack
 buffer overflow that may lead to arbitrary code execution when processed
 by savemeta.
 .
 Validate that the derived height does not exceed GFS2_MAX_META_HEIGHT
 before using it as a loop bound or array index, skipping such inodes.
 The height is widened from uint16_t to unsigned so the exhash increment
 (di_height + 1) cannot wrap around and bypass the bounds check.
Author: Valentin Vidic <vvidic@debian.org>
Last-Update: 2026-10-06
---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
--- a/gfs2/edit/savemeta.c
+++ b/gfs2/edit/savemeta.c
@@ -844,7 +844,7 @@ static void save_inode_data(struct metafd *mfd, char *ibuf, uint64_t iblk)
 {
 	struct block_range_queue indq[GFS2_MAX_META_HEIGHT] = {{NULL}};
 	struct gfs2_dinode *dip = (struct gfs2_dinode *)ibuf;
-	uint16_t height;
+	unsigned height;
 	int is_exhash;
 
 	for (unsigned i = 0; i < GFS2_MAX_META_HEIGHT; i++)
@@ -866,6 +866,13 @@ static void save_inode_data(struct metafd *mfd, char *ibuf, uint64_t iblk)
 		 !block_is_systemfile(iblk) && !S_ISDIR(be32_to_cpu(dip->di_mode)))
 		height--;
 
+	if (height > GFS2_MAX_META_HEIGHT) {
+		fprintf(stderr, "Inode 0x%"PRIx64" has an invalid height of %u "
+			"(maximum is %u); skipping it.\n",
+			iblk, height, (unsigned)GFS2_MAX_META_HEIGHT);
+		return;
+	}
+
 	if (height == 1)
 		save_indirect_blocks(mfd, ibuf, iblk, NULL, sizeof(*dip));
 	else if (height > 1)
