@@ -654,6 +654,49 @@ xfs_set_low_space_thresholds(
mp->m_low_space[i] = dblocks * (i + 1);
}
+/*
+ * libxfs_initialize_rtgroup will allocate a rtgroup structure for each
+ * rtgroup. If rgcount is corrupted and insanely high, this will OOM the box.
+ * Try to read what would be the last rtgroup superblock. If that fails, read
+ * the first one and let the user know to check the geometry.
+ */
+static inline bool
+check_many_rtgroups(
+ struct xfs_mount *mp,
+ struct xfs_sb *sbp)
+{
+ struct xfs_buf *bp;
+ xfs_daddr_t d;
+ int error;
+
+ if (!mp->m_rtdev->bt_bdev) {
+ fprintf(stderr, _("%s: no rt device, ignoring rgcount %u\n"),
+ progname, sbp->sb_rgcount);
+ if (!xfs_is_debugger(mp))
+ return false;
+
+ sbp->sb_rgcount = 0;
+ return true;
+ }
+
+ d = (xfs_daddr_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_rblocks);
+ error = libxfs_buf_read(mp->m_rtdev, d - XFS_FSB_TO_BB(mp, 1), 1, 0,
+ &bp, NULL);
+ if (!error) {
+ libxfs_buf_relse(bp);
+ return true;
+ }
+
+ fprintf(stderr, _("%s: read of rtgroup %u failed\n"), progname,
+ sbp->sb_rgcount - 1);
+ if (!xfs_is_debugger(mp))
+ return false;
+
+ fprintf(stderr, _("%s: limiting reads to rtgroup 0\n"), progname);
+ sbp->sb_rgcount = 1;
+ return true;
+}
+
/*
* Mount structure initialization, provides a filled-in xfs_mount_t
* such that the numerous XFS_* macros can be used. If dev is zero,
@@ -810,6 +853,9 @@ libxfs_mount(
libxfs_buf_relse(bp);
}
+ if (sbp->sb_rgcount > 1000000 && !check_many_rtgroups(mp, sbp))
+ goto out_da;
+
error = libxfs_initialize_perag(mp, 0, sbp->sb_agcount,
sbp->sb_dblocks, &mp->m_maxagi);
if (error) {