]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
libext2fs: don't allow ridiculously large logical block numbers
authorDarrick J. Wong <darrick.wong@oracle.com>
Thu, 12 Dec 2013 17:40:31 +0000 (12:40 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Thu, 12 Dec 2013 17:40:58 +0000 (12:40 -0500)
Forbid clients from trying to map logical block numbers that are
larger than the lblk->pblk data structures are capable of handling.
While we're at it, don't let clients set the file size to a number
that's beyond what can be mapped.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
lib/ext2fs/bmap.c
lib/ext2fs/ext2fsP.h
lib/ext2fs/fileio.c

index 50745877de2427ae5302ad898c614c01703c74a2..32788f6f8e179a560f80c1f393d9c74da3f49ee5 100644 (file)
@@ -238,6 +238,27 @@ got_block:
        return 0;
 }
 
+int ext2fs_file_block_offset_too_big(ext2_filsys fs,
+                                    struct ext2_inode *inode,
+                                    blk64_t offset)
+{
+       blk64_t addr_per_block, max_map_block;
+
+       /* Kernel seems to cut us off at 4294967294 blocks */
+       if (offset >= (1ULL << 32) - 1)
+               return 1;
+
+       if (inode->i_flags & EXT4_EXTENTS_FL)
+               return 0;
+
+       addr_per_block = fs->blocksize >> 2;
+       max_map_block = addr_per_block;
+       max_map_block += addr_per_block * addr_per_block;
+       max_map_block += addr_per_block * addr_per_block * addr_per_block;
+       max_map_block += 12;
+
+       return offset >= max_map_block;
+}
 
 errcode_t ext2fs_bmap2(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode,
                       char *block_buf, int bmap_flags, blk64_t block,
@@ -266,6 +287,9 @@ errcode_t ext2fs_bmap2(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode,
        }
        addr_per_block = (blk_t) fs->blocksize >> 2;
 
+       if (ext2fs_file_block_offset_too_big(fs, inode, block))
+               return EXT2_ET_FILE_TOO_BIG;
+
        if (!block_buf) {
                retval = ext2fs_get_array(2, fs->blocksize, &buf);
                if (retval)
index 46a6767d143e988d1df14103ad53e7884002dd74..99c0c1ba8eda009c499b2556f0da7d149bc4b26d 100644 (file)
@@ -141,3 +141,7 @@ extern errcode_t ext2fs_get_generic_bmap_range(ext2fs_generic_bitmap bitmap,
 extern void ext2fs_warn_bitmap32(ext2fs_generic_bitmap bitmap,const char *func);
 
 extern int ext2fs_mem_is_zero(const char *mem, size_t len);
+
+int ext2fs_file_block_offset_too_big(ext2_filsys fs,
+                                    struct ext2_inode *inode,
+                                    blk64_t offset);
index 6b213b55ffc44b706fbe949c482396dd81a02603..a6bcbe70b1dee0700db06c67d38e403bb4c7a40e 100644 (file)
@@ -392,6 +392,9 @@ errcode_t ext2fs_file_set_size2(ext2_file_t file, ext2_off64_t size)
 
        EXT2_CHECK_MAGIC(file, EXT2_ET_MAGIC_EXT2_FILE);
 
+       if (size && ext2fs_file_block_offset_too_big(file->fs, &file->inode,
+                                       (size - 1) / file->fs->blocksize))
+               return EXT2_ET_FILE_TOO_BIG;
        truncate_block = ((size + file->fs->blocksize - 1) >>
                          EXT2_BLOCK_SIZE_BITS(file->fs->super));
        old_size = EXT2_I_SIZE(&file->inode);