]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
libext2fs: fix potential OOB read check_for_inode_bad_blocks()
authorTheodore Ts'o <tytso@mit.edu>
Thu, 16 Jan 2020 23:14:37 +0000 (18:14 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Wed, 12 Feb 2020 16:28:29 +0000 (11:28 -0500)
If the bad block list has been reset in the middle of an inode scan,
it's possible for bb->list[scan->bad_blocks_ptr] to result in an
out-of-bounds read access.

This is highly unlikely to happen under normal circumstances; in
particular, we generally don't use bad block inodes any more.  In
addition, this would only happen if the bad block inode itself is
corrupt so e2fsck needs to wipe it out.  This might cause e2fsck to
crash, but it will more likely cause a part of the inode table to be
wrongly considered invalid, causing file system to be incorrectly
fixed.

This was reported by TALOS as TALOS-2020-0974 and CVE-2020-6057, but
after closer examination, we don't believe this can be used in any way
to exploit the system or release information about the system, since
all this can do is to cause part of the inode table to be skipped when
it shouldn't be, and this can't be leveraged since any information
about the ASLR of the process is obsolete once e2fsck exits.

Signed-off-by: Theodore Ts'o <tytso@mit.edu>
lib/ext2fs/inode.c

index 75df418dbda9e871c42896c56b3be998b5b3e132..c4377eeba9cae4d7a78481d244b4820051e8022f 100644 (file)
@@ -309,6 +309,7 @@ errcode_t ext2fs_inode_scan_goto_blockgroup(ext2_inode_scan scan,
 {
        scan->current_group = group - 1;
        scan->groups_left = scan->fs->group_desc_count - group;
+       scan->bad_block_ptr = 0;
        return get_next_blockgroup(scan);
 }
 
@@ -332,6 +333,12 @@ static errcode_t check_for_inode_bad_blocks(ext2_inode_scan scan,
        if (blk == 0)
                return 0;
 
+       /* Make sure bad_block_ptr is still valid */
+       if (scan->bad_block_ptr >= bb->num) {
+               scan->scan_flags &= ~EXT2_SF_CHK_BADBLOCKS;
+               return 0;
+       }
+
        /*
         * If the current block is greater than the bad block listed
         * in the bad block list, then advance the pointer until this