git: 6149261d549b - stable/14 - ffs_reallocblks(): ensure that pref cg is valid

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Mon, 20 Jan 2025 02:40:37 UTC
The branch stable/14 has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=6149261d549b3b5072fe69b498f26e8172de1623

commit 6149261d549b3b5072fe69b498f26e8172de1623
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2025-01-05 22:51:23 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2025-01-20 02:40:09 +0000

    ffs_reallocblks(): ensure that pref cg is valid
    
    (cherry picked from commit dc37121d3210d08c96a883ebfed780660e7e2b39)
---
 sys/ufs/ffs/ffs_alloc.c | 27 +++++++++++++++++++++++----
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c
index d08a51264fdb..b586ab8e126a 100644
--- a/sys/ufs/ffs/ffs_alloc.c
+++ b/sys/ufs/ffs/ffs_alloc.c
@@ -683,6 +683,7 @@ ffs_reallocblks_ufs1(
 	 * groups that we will search.
 	 */
 	cg = dtog(fs, pref);
+	MPASS(cg < fs->fs_ncg);
 	for (i = min(maxclustersearch, fs->fs_ncg); i > 0; i--) {
 		if ((newblk = ffs_clusteralloc(ip, cg, pref, len)) != 0)
 			break;
@@ -949,6 +950,7 @@ ffs_reallocblks_ufs2(
 	 * groups that we will search.
 	 */
 	cg = dtog(fs, pref);
+	MPASS(cg < fs->fs_ncg);
 	for (i = min(maxclustersearch, fs->fs_ncg); i > 0; i--) {
 		if ((newblk = ffs_clusteralloc(ip, cg, pref, len)) != 0)
 			break;
@@ -1440,8 +1442,11 @@ ffs_blkpref_ufs1(struct inode *ip,
 		 * place it immediately following the last direct block.
 		 */
 		if (indx == -1 && lbn < UFS_NDADDR + NINDIR(fs) &&
-		    ip->i_din1->di_db[UFS_NDADDR - 1] != 0)
+		    ip->i_din1->di_db[UFS_NDADDR - 1] != 0) {
 			pref = ip->i_din1->di_db[UFS_NDADDR - 1] + fs->fs_frag;
+			if (dtog(fs, pref) >= fs->fs_ncg)
+				pref = 0;
+		}
 		return (pref);
 	}
 	/*
@@ -1452,8 +1457,11 @@ ffs_blkpref_ufs1(struct inode *ip,
 	if (lbn == UFS_NDADDR) {
 		pref = ip->i_din1->di_ib[0];
 		if (pref != 0 && pref >= cgdata(fs, inocg) &&
-		    pref < cgbase(fs, inocg + 1))
+		    pref < cgbase(fs, inocg + 1)) {
+			if (dtog(fs, pref + fs->fs_frag) >= fs->fs_ncg)
+				return (0);
 			return (pref + fs->fs_frag);
+		}
 	}
 	/*
 	 * If we are at the beginning of a file, or we have already allocated
@@ -1508,6 +1516,8 @@ ffs_blkpref_ufs1(struct inode *ip,
 	/*
 	 * Otherwise, we just always try to lay things out contiguously.
 	 */
+	if (dtog(fs, prevbn + fs->fs_frag) >= fs->fs_ncg)
+		return (0);
 	return (prevbn + fs->fs_frag);
 }
 
@@ -1552,8 +1562,11 @@ ffs_blkpref_ufs2(struct inode *ip,
 		 * place it immediately following the last direct block.
 		 */
 		if (indx == -1 && lbn < UFS_NDADDR + NINDIR(fs) &&
-		    ip->i_din2->di_db[UFS_NDADDR - 1] != 0)
+		    ip->i_din2->di_db[UFS_NDADDR - 1] != 0) {
 			pref = ip->i_din2->di_db[UFS_NDADDR - 1] + fs->fs_frag;
+			if (dtog(fs, pref) >= fs->fs_ncg)
+				pref = 0;
+		}
 		return (pref);
 	}
 	/*
@@ -1564,8 +1577,11 @@ ffs_blkpref_ufs2(struct inode *ip,
 	if (lbn == UFS_NDADDR) {
 		pref = ip->i_din2->di_ib[0];
 		if (pref != 0 && pref >= cgdata(fs, inocg) &&
-		    pref < cgbase(fs, inocg + 1))
+		    pref < cgbase(fs, inocg + 1)) {
+			if (dtog(fs, pref + fs->fs_frag) >= fs->fs_ncg)
+				return (0);
 			return (pref + fs->fs_frag);
+		}
 	}
 	/*
 	 * If we are at the beginning of a file, or we have already allocated
@@ -1620,6 +1636,8 @@ ffs_blkpref_ufs2(struct inode *ip,
 	/*
 	 * Otherwise, we just always try to lay things out contiguously.
 	 */
+	if (dtog(fs, prevbn + fs->fs_frag) >= fs->fs_ncg)
+		return (0);
 	return (prevbn + fs->fs_frag);
 }
 
@@ -1970,6 +1988,7 @@ ffs_clusteralloc(struct inode *ip,
 
 	ump = ITOUMP(ip);
 	fs = ump->um_fs;
+	MPASS(cg < fs->fs_ncg);
 	if (fs->fs_maxcluster[cg] < len)
 		return (0);
 	UFS_UNLOCK(ump);