All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] fsck.f2fs: add more sanity check for superblock
@ 2019-06-13  8:10 ` Chao Yu
  0 siblings, 0 replies; 2+ messages in thread
From: Chao Yu @ 2019-06-13  8:10 UTC (permalink / raw)
  To: linux-f2fs-devel; +Cc: jaegeuk, seulbae

Add more sanity check logic for superblock like we did in kernel side.

This fixes bug reported by Seulbae Kim from bugzilla.

https://bugzilla.kernel.org/show_bug.cgi?id=203861

Reproted-by: Seulbae Kim <seulbae@gatech.edu>
Signed-off-by: Chao Yu <yuchao0@huawei.com>
---
 fsck/mount.c      | 96 ++++++++++++++++++++++++++++++++++++++++++-----
 include/f2fs_fs.h |  2 +
 2 files changed, 88 insertions(+), 10 deletions(-)

diff --git a/fsck/mount.c b/fsck/mount.c
index 8d5d5cf..f295642 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -601,38 +601,117 @@ static int verify_sb_chksum(struct f2fs_super_block *sb)
 int sanity_check_raw_super(struct f2fs_super_block *sb, enum SB_ADDR sb_addr)
 {
 	unsigned int blocksize;
+	unsigned int segment_count, segs_per_sec, secs_per_zone;
+	unsigned int total_sections, blocks_per_seg;
 
 	if ((get_sb(feature) & F2FS_FEATURE_SB_CHKSUM) &&
 					verify_sb_chksum(sb))
 		return -1;
 
-	if (F2FS_SUPER_MAGIC != get_sb(magic))
+	if (F2FS_SUPER_MAGIC != get_sb(magic)) {
+		MSG(0, "Magic Mismatch, valid(0x%x) - read(0x%x)\n",
+			F2FS_SUPER_MAGIC, get_sb(magic));
 		return -1;
+	}
 
-	if (F2FS_BLKSIZE != PAGE_CACHE_SIZE)
+	if (F2FS_BLKSIZE != PAGE_CACHE_SIZE) {
+		MSG(0, "Invalid page_cache_size (%d), supports only 4KB\n",
+			PAGE_CACHE_SIZE);
 		return -1;
+	}
 
 	blocksize = 1 << get_sb(log_blocksize);
-	if (F2FS_BLKSIZE != blocksize)
+	if (F2FS_BLKSIZE != blocksize) {
+		MSG(0, "Invalid blocksize (%u), supports only 4KB\n",
+			blocksize);
 		return -1;
+	}
 
 	/* check log blocks per segment */
-	if (get_sb(log_blocks_per_seg) != 9)
+	if (get_sb(log_blocks_per_seg) != 9) {
+		MSG(0, "Invalid log blocks per segment (%u)\n",
+			get_sb(log_blocks_per_seg));
 		return -1;
+	}
 
 	/* Currently, support 512/1024/2048/4096 bytes sector size */
 	if (get_sb(log_sectorsize) > F2FS_MAX_LOG_SECTOR_SIZE ||
-			get_sb(log_sectorsize) < F2FS_MIN_LOG_SECTOR_SIZE)
+			get_sb(log_sectorsize) < F2FS_MIN_LOG_SECTOR_SIZE) {
+		MSG(0, "Invalid log sectorsize (%u)\n", get_sb(log_sectorsize));
 		return -1;
+	}
 
 	if (get_sb(log_sectors_per_block) + get_sb(log_sectorsize) !=
-						F2FS_MAX_LOG_SECTOR_SIZE)
+						F2FS_MAX_LOG_SECTOR_SIZE) {
+		MSG(0, "Invalid log sectors per block(%u) log sectorsize(%u)\n",
+			get_sb(log_sectors_per_block),
+			get_sb(log_sectorsize));
+		return -1;
+	}
+
+	segment_count = get_sb(segment_count);
+	segs_per_sec = get_sb(segs_per_sec);
+	secs_per_zone = get_sb(secs_per_zone);
+	total_sections = get_sb(section_count);
+
+	/* blocks_per_seg should be 512, given the above check */
+	blocks_per_seg = 1 << get_sb(log_blocks_per_seg);
+
+	if (segment_count > F2FS_MAX_SEGMENT ||
+			segment_count < F2FS_MIN_SEGMENTS) {
+		MSG(0, "\tInvalid segment count (%u)\n", segment_count);
 		return -1;
+	}
+
+	if (total_sections > segment_count ||
+			total_sections < F2FS_MIN_SEGMENTS ||
+			segs_per_sec > segment_count || !segs_per_sec) {
+		MSG(0, "\tInvalid segment/section count (%u, %u x %u)\n",
+			segment_count, total_sections, segs_per_sec);
+		return 1;
+	}
+
+	if ((segment_count / segs_per_sec) < total_sections) {
+		MSG(0, "Small segment_count (%u < %u * %u)\n",
+			segment_count, segs_per_sec, total_sections);
+		return 1;
+	}
+
+	if (segment_count > (get_sb(block_count) >> 9)) {
+		MSG(0, "Wrong segment_count / block_count (%u > %llu)\n",
+			segment_count, get_sb(block_count));
+		return 1;
+	}
+
+	if (secs_per_zone > total_sections || !secs_per_zone) {
+		MSG(0, "Wrong secs_per_zone / total_sections (%u, %u)\n",
+			secs_per_zone, total_sections);
+		return 1;
+	}
+	if (get_sb(extension_count) > F2FS_MAX_EXTENSION ||
+			sb->hot_ext_count > F2FS_MAX_EXTENSION ||
+			get_sb(extension_count) +
+			sb->hot_ext_count > F2FS_MAX_EXTENSION) {
+		MSG(0, "Corrupted extension count (%u + %u > %u)\n",
+			get_sb(extension_count),
+			sb->hot_ext_count,
+			F2FS_MAX_EXTENSION);
+		return 1;
+	}
+
+	if (get_sb(cp_payload) > (blocks_per_seg - F2FS_CP_PACKS)) {
+		MSG(0, "Insane cp_payload (%u > %u)\n",
+			get_sb(cp_payload), blocks_per_seg - F2FS_CP_PACKS);
+		return 1;
+	}
 
 	/* check reserved ino info */
 	if (get_sb(node_ino) != 1 || get_sb(meta_ino) != 2 ||
-					get_sb(root_ino) != 3)
+						get_sb(root_ino) != 3) {
+		MSG(0, "Invalid Fs Meta Ino: node(%u) meta(%u) root(%u)\n",
+			get_sb(node_ino), get_sb(meta_ino), get_sb(root_ino));
 		return -1;
+	}
 
 	/* Check zoned block device feature */
 	if (c.devices[0].zoned_model == F2FS_ZONED_HM &&
@@ -641,9 +720,6 @@ int sanity_check_raw_super(struct f2fs_super_block *sb, enum SB_ADDR sb_addr)
 		return -1;
 	}
 
-	if (get_sb(segment_count) > F2FS_MAX_SEGMENT)
-		return -1;
-
 	if (sanity_check_area_boundary(sb, sb_addr))
 		return -1;
 	return 0;
diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h
index 1890975..9f1e86c 100644
--- a/include/f2fs_fs.h
+++ b/include/f2fs_fs.h
@@ -662,6 +662,8 @@ struct f2fs_super_block {
 #define CP_ORPHAN_PRESENT_FLAG	0x00000002
 #define CP_UMOUNT_FLAG		0x00000001
 
+#define F2FS_CP_PACKS		2	/* # of checkpoint packs */
+
 struct f2fs_checkpoint {
 	__le64 checkpoint_ver;		/* checkpoint block version number */
 	__le64 user_block_count;	/* # of user blocks */
-- 
2.18.0.rc1

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* [f2fs-dev] [PATCH] fsck.f2fs: add more sanity check for superblock
@ 2019-06-13  8:10 ` Chao Yu
  0 siblings, 0 replies; 2+ messages in thread
From: Chao Yu @ 2019-06-13  8:10 UTC (permalink / raw)
  To: linux-f2fs-devel; +Cc: jaegeuk, seulbae

Add more sanity check logic for superblock like we did in kernel side.

This fixes bug reported by Seulbae Kim from bugzilla.

https://bugzilla.kernel.org/show_bug.cgi?id=203861

Reproted-by: Seulbae Kim <seulbae@gatech.edu>
Signed-off-by: Chao Yu <yuchao0@huawei.com>
---
 fsck/mount.c      | 96 ++++++++++++++++++++++++++++++++++++++++++-----
 include/f2fs_fs.h |  2 +
 2 files changed, 88 insertions(+), 10 deletions(-)

diff --git a/fsck/mount.c b/fsck/mount.c
index 8d5d5cf..f295642 100644
--- a/fsck/mount.c
+++ b/fsck/mount.c
@@ -601,38 +601,117 @@ static int verify_sb_chksum(struct f2fs_super_block *sb)
 int sanity_check_raw_super(struct f2fs_super_block *sb, enum SB_ADDR sb_addr)
 {
 	unsigned int blocksize;
+	unsigned int segment_count, segs_per_sec, secs_per_zone;
+	unsigned int total_sections, blocks_per_seg;
 
 	if ((get_sb(feature) & F2FS_FEATURE_SB_CHKSUM) &&
 					verify_sb_chksum(sb))
 		return -1;
 
-	if (F2FS_SUPER_MAGIC != get_sb(magic))
+	if (F2FS_SUPER_MAGIC != get_sb(magic)) {
+		MSG(0, "Magic Mismatch, valid(0x%x) - read(0x%x)\n",
+			F2FS_SUPER_MAGIC, get_sb(magic));
 		return -1;
+	}
 
-	if (F2FS_BLKSIZE != PAGE_CACHE_SIZE)
+	if (F2FS_BLKSIZE != PAGE_CACHE_SIZE) {
+		MSG(0, "Invalid page_cache_size (%d), supports only 4KB\n",
+			PAGE_CACHE_SIZE);
 		return -1;
+	}
 
 	blocksize = 1 << get_sb(log_blocksize);
-	if (F2FS_BLKSIZE != blocksize)
+	if (F2FS_BLKSIZE != blocksize) {
+		MSG(0, "Invalid blocksize (%u), supports only 4KB\n",
+			blocksize);
 		return -1;
+	}
 
 	/* check log blocks per segment */
-	if (get_sb(log_blocks_per_seg) != 9)
+	if (get_sb(log_blocks_per_seg) != 9) {
+		MSG(0, "Invalid log blocks per segment (%u)\n",
+			get_sb(log_blocks_per_seg));
 		return -1;
+	}
 
 	/* Currently, support 512/1024/2048/4096 bytes sector size */
 	if (get_sb(log_sectorsize) > F2FS_MAX_LOG_SECTOR_SIZE ||
-			get_sb(log_sectorsize) < F2FS_MIN_LOG_SECTOR_SIZE)
+			get_sb(log_sectorsize) < F2FS_MIN_LOG_SECTOR_SIZE) {
+		MSG(0, "Invalid log sectorsize (%u)\n", get_sb(log_sectorsize));
 		return -1;
+	}
 
 	if (get_sb(log_sectors_per_block) + get_sb(log_sectorsize) !=
-						F2FS_MAX_LOG_SECTOR_SIZE)
+						F2FS_MAX_LOG_SECTOR_SIZE) {
+		MSG(0, "Invalid log sectors per block(%u) log sectorsize(%u)\n",
+			get_sb(log_sectors_per_block),
+			get_sb(log_sectorsize));
+		return -1;
+	}
+
+	segment_count = get_sb(segment_count);
+	segs_per_sec = get_sb(segs_per_sec);
+	secs_per_zone = get_sb(secs_per_zone);
+	total_sections = get_sb(section_count);
+
+	/* blocks_per_seg should be 512, given the above check */
+	blocks_per_seg = 1 << get_sb(log_blocks_per_seg);
+
+	if (segment_count > F2FS_MAX_SEGMENT ||
+			segment_count < F2FS_MIN_SEGMENTS) {
+		MSG(0, "\tInvalid segment count (%u)\n", segment_count);
 		return -1;
+	}
+
+	if (total_sections > segment_count ||
+			total_sections < F2FS_MIN_SEGMENTS ||
+			segs_per_sec > segment_count || !segs_per_sec) {
+		MSG(0, "\tInvalid segment/section count (%u, %u x %u)\n",
+			segment_count, total_sections, segs_per_sec);
+		return 1;
+	}
+
+	if ((segment_count / segs_per_sec) < total_sections) {
+		MSG(0, "Small segment_count (%u < %u * %u)\n",
+			segment_count, segs_per_sec, total_sections);
+		return 1;
+	}
+
+	if (segment_count > (get_sb(block_count) >> 9)) {
+		MSG(0, "Wrong segment_count / block_count (%u > %llu)\n",
+			segment_count, get_sb(block_count));
+		return 1;
+	}
+
+	if (secs_per_zone > total_sections || !secs_per_zone) {
+		MSG(0, "Wrong secs_per_zone / total_sections (%u, %u)\n",
+			secs_per_zone, total_sections);
+		return 1;
+	}
+	if (get_sb(extension_count) > F2FS_MAX_EXTENSION ||
+			sb->hot_ext_count > F2FS_MAX_EXTENSION ||
+			get_sb(extension_count) +
+			sb->hot_ext_count > F2FS_MAX_EXTENSION) {
+		MSG(0, "Corrupted extension count (%u + %u > %u)\n",
+			get_sb(extension_count),
+			sb->hot_ext_count,
+			F2FS_MAX_EXTENSION);
+		return 1;
+	}
+
+	if (get_sb(cp_payload) > (blocks_per_seg - F2FS_CP_PACKS)) {
+		MSG(0, "Insane cp_payload (%u > %u)\n",
+			get_sb(cp_payload), blocks_per_seg - F2FS_CP_PACKS);
+		return 1;
+	}
 
 	/* check reserved ino info */
 	if (get_sb(node_ino) != 1 || get_sb(meta_ino) != 2 ||
-					get_sb(root_ino) != 3)
+						get_sb(root_ino) != 3) {
+		MSG(0, "Invalid Fs Meta Ino: node(%u) meta(%u) root(%u)\n",
+			get_sb(node_ino), get_sb(meta_ino), get_sb(root_ino));
 		return -1;
+	}
 
 	/* Check zoned block device feature */
 	if (c.devices[0].zoned_model == F2FS_ZONED_HM &&
@@ -641,9 +720,6 @@ int sanity_check_raw_super(struct f2fs_super_block *sb, enum SB_ADDR sb_addr)
 		return -1;
 	}
 
-	if (get_sb(segment_count) > F2FS_MAX_SEGMENT)
-		return -1;
-
 	if (sanity_check_area_boundary(sb, sb_addr))
 		return -1;
 	return 0;
diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h
index 1890975..9f1e86c 100644
--- a/include/f2fs_fs.h
+++ b/include/f2fs_fs.h
@@ -662,6 +662,8 @@ struct f2fs_super_block {
 #define CP_ORPHAN_PRESENT_FLAG	0x00000002
 #define CP_UMOUNT_FLAG		0x00000001
 
+#define F2FS_CP_PACKS		2	/* # of checkpoint packs */
+
 struct f2fs_checkpoint {
 	__le64 checkpoint_ver;		/* checkpoint block version number */
 	__le64 user_block_count;	/* # of user blocks */
-- 
2.18.0.rc1



_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2019-06-13  8:11 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-13  8:10 [PATCH] fsck.f2fs: add more sanity check for superblock Chao Yu
2019-06-13  8:10 ` [f2fs-dev] " Chao Yu

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.