From: Yongpeng Yang <[email protected]>

When formatting a device that is too small , the error handling in
f2fs_prepare_super_block() is flawed, leading to a division-by-zero
exception.

Reproducer:
root@vm:~/f2fs-tools# dd if=/dev/zero of=data.6M bs=1M count=6
root@vm:~/f2fs-tools# losetup -f data.6M
root@vm:~/f2fs-tools# mkfs.f2fs /dev/loop0

This patch adds a check to verify if the device has enough capacity to
store the metadata area. If not, it immediately returns an error to
prevent the subsequent division-by-zero exception from being triggered.

Signed-off-by: Yongpeng Yang <[email protected]>
---
 mkfs/f2fs_format.c | 32 +++++++++++++++++++++++---------
 1 file changed, 23 insertions(+), 9 deletions(-)

diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c
index b3dccd0..df68b23 100644
--- a/mkfs/f2fs_format.c
+++ b/mkfs/f2fs_format.c
@@ -268,6 +268,7 @@ static int f2fs_prepare_super_block(void)
        uint32_t segment_size_bytes, zone_size_bytes;
        uint32_t alignment_bytes;
        uint32_t sit_segments, nat_segments;
+       uint32_t segment_count_meta;
        uint32_t blocks_for_sit, blocks_for_nat, blocks_for_ssa;
        uint32_t total_valid_blks_available;
        uint64_t zone_align_start_offset, diff;
@@ -423,9 +424,14 @@ static int f2fs_prepare_super_block(void)
        set_sb(nat_blkaddr, get_sb(sit_blkaddr) + get_sb(segment_count_sit) *
                        c.blks_per_seg);
 
+       segment_count_meta = get_sb(segment_count_ckpt) + 
get_sb(segment_count_sit);
+       if (get_sb(segment_count) <= segment_count_meta) {
+               MSG(0, "\tError: segment_count: %u too small, 
segment_count_meta: %u\n",
+                               get_sb(segment_count), segment_count_meta);
+               goto too_small;
+       }
        total_valid_blks_available = (get_sb(segment_count) -
-                       (get_sb(segment_count_ckpt) +
-                       get_sb(segment_count_sit))) * c.blks_per_seg;
+                       segment_count_meta) * c.blks_per_seg;
 
        blocks_for_nat = SIZE_ALIGN(total_valid_blks_available,
                        NAT_ENTRY_PER_BLOCK);
@@ -491,11 +497,16 @@ static int f2fs_prepare_super_block(void)
        set_sb(ssa_blkaddr, get_sb(nat_blkaddr) + get_sb(segment_count_nat) *
                        c.blks_per_seg);
 
-       total_valid_blks_available = (get_sb(segment_count) -
-                       (get_sb(segment_count_ckpt) +
+       segment_count_meta = get_sb(segment_count_ckpt) +
                        get_sb(segment_count_sit) +
-                       get_sb(segment_count_nat))) *
-                       c.blks_per_seg;
+                       get_sb(segment_count_nat);
+       if (get_sb(segment_count) <= segment_count_meta) {
+               MSG(0, "\tError: segment_count: %u too small, 
segment_count_meta(with nat): %u\n",
+                               get_sb(segment_count), segment_count_meta);
+               goto too_small;
+       }
+       total_valid_blks_available = (get_sb(segment_count) -
+                       segment_count_meta) * c.blks_per_seg;
 
        if (c.feature & F2FS_FEATURE_RO) {
                blocks_for_ssa = 0;
@@ -560,10 +571,13 @@ static int f2fs_prepare_super_block(void)
                }
        }
 
-       total_zones = get_sb(segment_count) / (c.segs_per_zone) -
-                                                       total_meta_zones;
-       if (total_zones == 0)
+       total_zones = get_sb(segment_count) / (c.segs_per_zone);
+       if (total_zones <= total_meta_zones) {
+               MSG(0, "\tError: total_zones:%u too small, total_meta_zones: 
%lu\n",
+                               total_zones, total_meta_zones);
                goto too_small;
+       }
+       total_zones -= total_meta_zones;
        set_sb(section_count, total_zones * c.secs_per_zone);
 
        set_sb(segment_count_main, get_sb(section_count) * c.segs_per_sec);
-- 
2.47.1



_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to