]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_repair: validate some of the log space information
authorDarrick J. Wong <darrick.wong@oracle.com>
Wed, 23 May 2018 21:30:48 +0000 (16:30 -0500)
committerEric Sandeen <sandeen@redhat.com>
Wed, 23 May 2018 21:30:48 +0000 (16:30 -0500)
Validate the log space information in a similar manner to the kernel so
that repair will stumble over (and fix) broken log info that prevents
mounting.  Fixes logsunit fuzz-and-fix failures in xfs/350.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Allison Henderson <allison.henderson@oracle.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
repair/globals.h
repair/sb.c
repair/xfs_repair.c

index e777ba275a179831493dc83d8c301714e3194f15..164619b0e0d084edef7f509837056ac626c498cb 100644 (file)
@@ -51,7 +51,8 @@
 #define XR_BAD_SVN             19      /* bad shared version number */
 #define XR_BAD_CRC             20      /* Bad CRC */
 #define XR_BAD_DIR_SIZE_DATA   21      /* Bad directory geometry */
-#define XR_BAD_ERR_CODE                22      /* Bad error code */
+#define XR_BAD_LOG_GEOMETRY    22      /* Bad log geometry */
+#define XR_BAD_ERR_CODE                23      /* Bad error code */
 
 /* XFS filesystem (il)legal values */
 
index 3dc6538bb4ffc64578e29076364ac0ab10bf9739..ef44e39c77463dd5829ac08fe877bd0c5b38fd7c 100644 (file)
@@ -298,6 +298,30 @@ sb_validate_ino_align(struct xfs_sb *sb)
        return false;
 }
 
+/*
+ * Validate the given log space.  Derived from xfs_log_mount, though we
+ * can't validate the minimum log size until later.  We only do this
+ * validation on V5 filesystems because the kernel doesn't reject malformed
+ * log geometry on older revision filesystems.
+ *
+ * Returns false if the log is garbage.
+ */
+static bool
+verify_sb_loginfo(
+       struct xfs_sb   *sb)
+{
+       if (xfs_sb_version_hascrc(sb) &&
+           (sb->sb_logblocks == 0 ||
+            sb->sb_logblocks > XFS_MAX_LOG_BLOCKS ||
+            (sb->sb_logblocks << sb->sb_blocklog) > XFS_MAX_LOG_BYTES))
+               return false;
+
+       if (sb->sb_logsunit > 1 && sb->sb_logsunit % sb->sb_blocksize)
+               return false;
+
+       return true;
+}
+
 /*
  * verify a superblock -- does not verify root inode #
  *     can only check that geometry info is internally
@@ -412,6 +436,9 @@ verify_sb(char *sb_buf, xfs_sb_t *sb, int is_primary_sb)
            (sb->sb_blocklog - sb->sb_inodelog != sb->sb_inopblog))
                return XR_BAD_INO_SIZE_DATA;
 
+       if (!verify_sb_loginfo(sb))
+               return XR_BAD_LOG_GEOMETRY;
+
        if (xfs_sb_version_hassector(sb))  {
 
                /* check to make sure log sector is legal 2^N, 9 <= N <= 15 */
index ff6a7384250a10a88e77611f892774ba123b9682..b7c2d267141c7e09b6c000a41f04e5caf9e732b3 100644 (file)
@@ -155,6 +155,8 @@ err_string(int err_code)
                        _("bad CRC in superblock");
                err_message[XR_BAD_DIR_SIZE_DATA] =
                        _("inconsistent directory geometry information");
+               err_message[XR_BAD_LOG_GEOMETRY] =
+                       _("inconsistent log geometry information");
                done = 1;
        }