Blame SOURCES/bz1622050-1-fsck_gfs2_Don_t_check_fs_formats_we_don_t_recognise.patch

c48b4d
commit 47261faa39aca05d6feb486fdeec26f8ffc3ef15
c48b4d
Author: Andrew Price <anprice@redhat.com>
c48b4d
Date:   Fri Aug 17 12:49:24 2018 +0100
c48b4d
c48b4d
    fsck.gfs2: Don't check fs formats we don't recognise
c48b4d
    
c48b4d
    Currently fsck.gfs2 will ignore sb_fs_format but in order to support
c48b4d
    future formats we need to make sure it doesn't try to check filesystems
c48b4d
    with formats we don't recognise yet. Better late than never.
c48b4d
    
c48b4d
    Tests included.
c48b4d
    
c48b4d
    rhbz#1616389
c48b4d
    rhbz#1622050
c48b4d
    
c48b4d
    Signed-off-by: Andrew Price <anprice@redhat.com>
c48b4d
c48b4d
diff --git a/gfs2/fsck/fsck.h b/gfs2/fsck/fsck.h
c48b4d
index d3f76352..877448c3 100644
c48b4d
--- a/gfs2/fsck/fsck.h
c48b4d
+++ b/gfs2/fsck/fsck.h
c48b4d
@@ -4,6 +4,8 @@
c48b4d
 #include "libgfs2.h"
c48b4d
 #include "osi_tree.h"
c48b4d
 
c48b4d
+#define FSCK_MAX_FORMAT (1801)
c48b4d
+
c48b4d
 #define FSCK_HASH_SHIFT         (13)
c48b4d
 #define FSCK_HASH_SIZE          (1 << FSCK_HASH_SHIFT)
c48b4d
 #define FSCK_HASH_MASK          (FSCK_HASH_SIZE - 1)
c48b4d
diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c
c48b4d
index ebe62b9f..d1c620af 100644
c48b4d
--- a/gfs2/fsck/initialize.c
c48b4d
+++ b/gfs2/fsck/initialize.c
c48b4d
@@ -1334,12 +1334,12 @@ static int fill_super_block(struct gfs2_sbd *sdp)
c48b4d
 	if (sizeof(struct gfs2_sb) > sdp->sd_sb.sb_bsize){
c48b4d
 		log_crit( _("GFS superblock is larger than the blocksize!\n"));
c48b4d
 		log_debug("sizeof(struct gfs2_sb) > sdp->sd_sb.sb_bsize\n");
c48b4d
-		return -1;
c48b4d
+		return FSCK_ERROR;
c48b4d
 	}
c48b4d
 
c48b4d
 	if (compute_constants(sdp)) {
c48b4d
 		log_crit("%s\n", _("Failed to compute file system constants"));
c48b4d
-		exit(FSCK_ERROR);
c48b4d
+		return FSCK_ERROR;
c48b4d
 	}
c48b4d
 	ret = read_sb(sdp);
c48b4d
 	if (ret < 0) {
c48b4d
@@ -1348,10 +1348,15 @@ static int fill_super_block(struct gfs2_sbd *sdp)
c48b4d
 		/* Now that we've tried to repair it, re-read it. */
c48b4d
 		ret = read_sb(sdp);
c48b4d
 		if (ret < 0)
c48b4d
-			return -1;
c48b4d
+			return FSCK_ERROR;
c48b4d
 	}
c48b4d
 	if (sdp->gfs1)
c48b4d
 		sbd1 = (struct gfs_sb *)&sdp->sd_sb;
c48b4d
+	else if (sdp->sd_sb.sb_fs_format > FSCK_MAX_FORMAT) {
c48b4d
+		log_crit(_("Unsupported gfs2 format found: %"PRIu32"\n"), sdp->sd_sb.sb_fs_format);
c48b4d
+		log_crit(_("A newer fsck.gfs2 is required to check this file system.\n"));
c48b4d
+		return FSCK_USAGE;
c48b4d
+	}
c48b4d
 	return 0;
c48b4d
 }
c48b4d
 
c48b4d
@@ -1556,6 +1561,7 @@ int initialize(struct gfs2_sbd *sdp, int force_check, int preen,
c48b4d
 	       int *all_clean)
c48b4d
 {
c48b4d
 	int clean_journals = 0, open_flag;
c48b4d
+	int err;
c48b4d
 
c48b4d
 	*all_clean = 0;
c48b4d
 
c48b4d
@@ -1601,8 +1607,9 @@ int initialize(struct gfs2_sbd *sdp, int force_check, int preen,
c48b4d
 	}
c48b4d
 
c48b4d
 	/* read in sb from disk */
c48b4d
-	if (fill_super_block(sdp))
c48b4d
-		return FSCK_ERROR;
c48b4d
+	err = fill_super_block(sdp);
c48b4d
+	if (err != FSCK_OK)
c48b4d
+		return err;
c48b4d
 
c48b4d
 	/* Change lock protocol to be fsck_* instead of lock_* */
c48b4d
 	if (!opts.no && preen_is_safe(sdp, preen, force_check)) {
c48b4d
diff --git a/gfs2/libgfs2/super.c b/gfs2/libgfs2/super.c
c48b4d
index 6e7d8c23..75925643 100644
c48b4d
--- a/gfs2/libgfs2/super.c
c48b4d
+++ b/gfs2/libgfs2/super.c
c48b4d
@@ -29,11 +29,18 @@ int check_sb(struct gfs2_sb *sb)
c48b4d
 		errno = EIO;
c48b4d
 		return -1;
c48b4d
 	}
c48b4d
+	/* Check for gfs1 */
c48b4d
 	if (sb->sb_fs_format == GFS_FORMAT_FS &&
c48b4d
 	    sb->sb_header.mh_format == GFS_FORMAT_SB &&
c48b4d
 	    sb->sb_multihost_format == GFS_FORMAT_MULTI) {
c48b4d
 		return 1;
c48b4d
 	}
c48b4d
+	/* It's gfs2. Check format number is in a sensible range. */
c48b4d
+	if (sb->sb_fs_format < GFS2_FORMAT_FS ||
c48b4d
+	    sb->sb_fs_format > 1899) {
c48b4d
+		errno = EINVAL;
c48b4d
+		return -1;
c48b4d
+	}
c48b4d
 	return 2;
c48b4d
 }
c48b4d
 
c48b4d
diff --git a/tests/fsck.at b/tests/fsck.at
c48b4d
index 39a04d04..97a00a90 100644
c48b4d
--- a/tests/fsck.at
c48b4d
+++ b/tests/fsck.at
c48b4d
@@ -54,3 +54,16 @@ AT_CHECK([gfs2_edit -p journal0 field di_header.mh_magic 0 $GFS_TGT], 0, [ignore
c48b4d
 AT_CHECK([fsck.gfs2 -y $GFS_TGT], 1, [ignore], [ignore])
c48b4d
 AT_CHECK([fsck.gfs2 -n $GFS_TGT], 0, [ignore], [ignore])
c48b4d
 AT_CLEANUP
c48b4d
+
c48b4d
+AT_SETUP([gfs2 format versions])
c48b4d
+AT_KEYWORDS(fsck.gfs2 fsck)
c48b4d
+GFS_TGT_REGEN
c48b4d
+AT_CHECK([mkfs.gfs2 -O -p lock_nolock ${GFS_TGT}], 0, [ignore], [ignore])
c48b4d
+AT_CHECK([echo "set sb { sb_fs_format: 1802 }" | gfs2l ${GFS_TGT}], 0, [ignore], [ignore])
c48b4d
+# Unsupported format, FSCK_USAGE == 16
c48b4d
+AT_CHECK([fsck.gfs2 -y $GFS_TGT], 16, [ignore], [ignore])
c48b4d
+# Format out of range
c48b4d
+AT_CHECK([echo "set sb { sb_fs_format: 4242 }" | gfs2l ${GFS_TGT}], 0, [ignore], [ignore])
c48b4d
+AT_CHECK([fsck.gfs2 -y $GFS_TGT], 1, [ignore], [ignore])
c48b4d
+AT_CHECK([fsck.gfs2 -n $GFS_TGT], 0, [ignore], [ignore])
c48b4d
+AT_CLEANUP