Whamcloud - gitweb
e2fsck: don't try backup superblocks beyond the size of the device
authorTheodore Ts'o <tytso@mit.edu>
Wed, 17 Apr 2024 20:52:00 +0000 (16:52 -0400)
committerTheodore Ts'o <tytso@mit.edu>
Wed, 17 Apr 2024 20:58:26 +0000 (16:58 -0400)
Commit f7ef5f3e356d ("e2fsck: check all sparse_super backups") tries
to limit the number of block groups to search for backup superblocks
based on ctx->num_blocks.  Unfortunately, get_backup_sb() gets called
before ctx->num_blocks is set, so we try all block groups up to 2**32
- 1.  Not only does this waste time trying to read from blocks that
don't exist, it triggers the UBSAN checker when multiplying a very
large number by the block size.

Fix this by using ext2fs_get_Device_size(), and if that isn't
available, arbitrarily cap things so that we search block groups up to
128.

Fixes: f7ef5f3e356d ("e2fsck: check all sparse_super backups")
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
e2fsck/util.c

index 6982966..734e45c 100644 (file)
@@ -588,16 +588,26 @@ blk64_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
 
        for (; blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
                dgrp_t grp, three = 1, five = 5, seven = 7;
-               dgrp_t limit = (dgrp_t)-1;
+               dgrp_t limit;
                blk_t this_bpg = bpg ? bpg : blocksize * 8;
-
-               if (ctx->num_blocks && limit > ctx->num_blocks / this_bpg)
-                       limit = ctx->num_blocks / this_bpg;
+               blk64_t num_blocks;
+
+               if (ext2fs_get_device_size2(ctx->filesystem_name,
+                                           blocksize,
+                                           &num_blocks) == 0) {
+                       limit = num_blocks / this_bpg;
+               } else {
+                       /* If we can't figure out the device size,
+                        * arbitrarily set a limit which is enough for
+                        * 8 block groups or so...
+                        */
+                       limit = 128;
+               }
 
                io_channel_set_blksize(io, blocksize);
 
                while ((grp = ext2fs_list_backups(NULL, &three,
-                                                 &five, &seven)) < limit) {
+                                                 &five, &seven)) <= limit) {
                        blk64_t superblock = (blk64_t)grp * this_bpg;
 
                        if (blocksize == 1024)