From: Darrick J. Wong Date: Thu, 12 Dec 2013 17:40:31 +0000 (-0500) Subject: libext2fs: don't allow ridiculously large logical block numbers X-Git-Tag: v1.42.9~86 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1e7451493ed67ae94ba5c1d2bed059527bc9848d;p=thirdparty%2Fe2fsprogs.git libext2fs: don't allow ridiculously large logical block numbers 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 Signed-off-by: "Theodore Ts'o" --- diff --git a/lib/ext2fs/bmap.c b/lib/ext2fs/bmap.c index 50745877d..32788f6f8 100644 --- a/lib/ext2fs/bmap.c +++ b/lib/ext2fs/bmap.c @@ -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) diff --git a/lib/ext2fs/ext2fsP.h b/lib/ext2fs/ext2fsP.h index 46a6767d1..99c0c1ba8 100644 --- a/lib/ext2fs/ext2fsP.h +++ b/lib/ext2fs/ext2fsP.h @@ -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); diff --git a/lib/ext2fs/fileio.c b/lib/ext2fs/fileio.c index 6b213b55f..a6bcbe70b 100644 --- a/lib/ext2fs/fileio.c +++ b/lib/ext2fs/fileio.c @@ -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);