libext2fs: Add checks to prevent integer overflows passed to malloc()

This addresses a potential security vulnerability where an untrusted
filesystem can be corrupted in such a way that a program using
libext2fs will allocate a buffer which is far too small.  This can
lead to either a crash or potentially a heap-based buffer overflow
crash.  No known exploits exist, but main concern is where an
untrusted user who possesses privileged access in a guest Xen
environment could corrupt a filesystem which is then accessed by the
pygrub program, running as root in the dom0 host environment, thus
allowing the untrusted user to gain privileged access in the host OS.

Thanks to the McAfee AVERT Research group for reporting this issue.

Addresses CVE-2007-5497.

Signed-off-by: Rafal Wojtczuk <rafal_wojtczuk@mcafee.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
bitmap-optimize
Theodore Ts'o 2007-11-09 19:01:06 -05:00
parent 7ce238977a
commit ee01079a17
17 changed files with 37 additions and 24 deletions

View File

@ -42,7 +42,7 @@ static errcode_t make_u32_list(int size, int num, __u32 *list,
bb->magic = EXT2_ET_MAGIC_BADBLOCKS_LIST;
bb->size = size ? size : 10;
bb->num = num;
retval = ext2fs_get_mem(bb->size * sizeof(blk_t), &bb->list);
retval = ext2fs_get_array(bb->size, sizeof(blk_t), &bb->list);
if (retval) {
ext2fs_free_mem(&bb);
return retval;

View File

@ -68,7 +68,7 @@ errcode_t ext2fs_update_bb_inode(ext2_filsys fs, ext2_badblocks_list bb_list)
rec.bad_block_count = 0;
rec.ind_blocks_size = rec.ind_blocks_ptr = 0;
rec.max_ind_blocks = 10;
retval = ext2fs_get_mem(rec.max_ind_blocks * sizeof(blk_t),
retval = ext2fs_get_array(rec.max_ind_blocks, sizeof(blk_t),
&rec.ind_blocks);
if (retval)
return retval;

View File

@ -313,7 +313,7 @@ errcode_t ext2fs_block_iterate2(ext2_filsys fs,
if (block_buf) {
ctx.ind_buf = block_buf;
} else {
retval = ext2fs_get_mem(fs->blocksize * 3, &ctx.ind_buf);
retval = ext2fs_get_array(3, fs->blocksize, &ctx.ind_buf);
if (retval)
return retval;
}

View File

@ -158,7 +158,7 @@ errcode_t ext2fs_bmap(ext2_filsys fs, ext2_ino_t ino, struct ext2_inode *inode,
addr_per_block = (blk_t) fs->blocksize >> 2;
if (!block_buf) {
retval = ext2fs_get_mem(fs->blocksize * 2, &buf);
retval = ext2fs_get_array(2, fs->blocksize, &buf);
if (retval)
return retval;
block_buf = buf;

View File

@ -108,7 +108,7 @@ errcode_t ext2fs_move_blocks(ext2_filsys fs,
pb.alloc_map = alloc_map ? alloc_map : fs->block_map;
pb.flags = flags;
retval = ext2fs_get_mem(fs->blocksize * 4, &block_buf);
retval = ext2fs_get_array(4, fs->blocksize, &block_buf);
if (retval)
return retval;
pb.buf = block_buf + fs->blocksize * 3;

View File

@ -75,7 +75,8 @@ errcode_t ext2fs_brel_memarray_create(char *name, blk_t max_block,
size = (size_t) (sizeof(struct ext2_block_relocate_entry) *
(max_block+1));
retval = ext2fs_get_mem(size, &ma->entries);
retval = ext2fs_get_array(max_block+1,
sizeof(struct ext2_block_relocate_entry), &ma->entries);
if (retval)
goto errout;
memset(ma->entries, 0, size);

View File

@ -226,8 +226,7 @@ errcode_t ext2fs_flush(ext2_filsys fs)
retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &super_shadow);
if (retval)
goto errout;
retval = ext2fs_get_mem((size_t)(fs->blocksize *
fs->desc_blocks),
retval = ext2fs_get_array(fs->blocksize, fs->desc_blocks,
&group_shadow);
if (retval)
goto errout;

View File

@ -85,7 +85,8 @@ static errcode_t make_dblist(ext2_filsys fs, ext2_ino_t size, ext2_ino_t count,
}
len = (size_t) sizeof(struct ext2_db_entry) * dblist->size;
dblist->count = count;
retval = ext2fs_get_mem(len, &dblist->list);
retval = ext2fs_get_array(dblist->size, sizeof(struct ext2_db_entry),
&dblist->list);
if (retval)
goto cleanup;

View File

@ -59,7 +59,7 @@ errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest)
goto errout;
memcpy(fs->orig_super, src->orig_super, SUPERBLOCK_SIZE);
retval = ext2fs_get_mem((size_t) fs->desc_blocks * fs->blocksize,
retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize,
&fs->group_desc);
if (retval)
goto errout;

View File

@ -965,6 +965,7 @@ extern errcode_t ext2fs_write_bb_FILE(ext2_badblocks_list bb_list,
/* inline functions */
extern errcode_t ext2fs_get_mem(unsigned long size, void *ptr);
extern errcode_t ext2fs_get_array(unsigned long count, unsigned long size, void *ptr);
extern errcode_t ext2fs_free_mem(void *ptr);
extern errcode_t ext2fs_resize_mem(unsigned long old_size,
unsigned long size, void *ptr);
@ -1018,6 +1019,12 @@ _INLINE_ errcode_t ext2fs_get_mem(unsigned long size, void *ptr)
memcpy(ptr, &pp, sizeof (pp));
return 0;
}
_INLINE_ errcode_t ext2fs_get_array(unsigned long count, unsigned long size, void *ptr)
{
if (count && (-1UL)/count<size)
return EXT2_ET_NO_MEMORY; //maybe define EXT2_ET_OVERFLOW ?
return ext2fs_get_mem(count*size, ptr);
}
/*
* Free memory

View File

@ -65,7 +65,7 @@ errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino,
goto fail;
}
retval = ext2fs_get_mem(fs->blocksize * 3, &file->buf);
retval = ext2fs_get_array(3, fs->blocksize, &file->buf);
if (retval)
goto fail;

View File

@ -237,7 +237,8 @@ errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags, unsigned int size,
printf("Icount allocated %u entries, %d bytes.\n",
icount->size, bytes);
#endif
retval = ext2fs_get_mem(bytes, &icount->list);
retval = ext2fs_get_array(icount->size, sizeof(struct ext2_icount_el),
&icount->list);
if (retval)
goto errout;
memset(icount->list, 0, bytes);

View File

@ -351,7 +351,7 @@ ipg_retry:
ext2fs_free_mem(&buf);
retval = ext2fs_get_mem((size_t) fs->desc_blocks * fs->blocksize,
retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize,
&fs->group_desc);
if (retval)
goto cleanup;

View File

@ -90,9 +90,9 @@ static errcode_t create_icache(ext2_filsys fs)
fs->icache->cache_last = -1;
fs->icache->cache_size = 4;
fs->icache->refcount = 1;
retval = ext2fs_get_mem(sizeof(struct ext2_inode_cache_ent)
* fs->icache->cache_size,
&fs->icache->cache);
retval = ext2fs_get_array(fs->icache->cache_size,
sizeof(struct ext2_inode_cache_ent),
&fs->icache->cache);
if (retval) {
ext2fs_free_mem(&fs->icache->buffer);
ext2fs_free_mem(&fs->icache);
@ -146,8 +146,8 @@ errcode_t ext2fs_open_inode_scan(ext2_filsys fs, int buffer_blocks,
group_desc[scan->current_group].bg_inode_table;
scan->inodes_left = EXT2_INODES_PER_GROUP(scan->fs->super);
scan->blocks_left = scan->fs->inode_blocks_per_group;
retval = ext2fs_get_mem((size_t) (scan->inode_buffer_blocks *
fs->blocksize),
retval = ext2fs_get_array(scan->inode_buffer_blocks,
fs->blocksize,
&scan->inode_buffer);
scan->done_group = 0;
scan->done_group_data = 0;

View File

@ -90,21 +90,24 @@ errcode_t ext2fs_irel_memarray_create(char *name, ext2_ino_t max_inode,
irel->priv_data = ma;
size = (size_t) (sizeof(ext2_ino_t) * (max_inode+1));
retval = ext2fs_get_mem(size, &ma->orig_map);
retval = ext2fs_get_array(max_inode+1, sizeof(ext2_ino_t),
&ma->orig_map);
if (retval)
goto errout;
memset(ma->orig_map, 0, size);
size = (size_t) (sizeof(struct ext2_inode_relocate_entry) *
(max_inode+1));
retval = ext2fs_get_mem(size, &ma->entries);
retval = ext2fs_get_array((max_inode+1,
sizeof(struct ext2_inode_relocate_entry), &ma->entries);
if (retval)
goto errout;
memset(ma->entries, 0, size);
size = (size_t) (sizeof(struct inode_reference_entry) *
(max_inode+1));
retval = ext2fs_get_mem(size, &ma->ref_entries);
retval = ext2fs_get_mem(max_inode+1,
sizeof(struct inode_reference_entry), &ma->ref_entries);
if (retval)
goto errout;
memset(ma->ref_entries, 0, size);
@ -249,7 +252,8 @@ static errcode_t ima_add_ref(ext2_irel irel, ext2_ino_t ino,
if (ref_ent->refs == 0) {
size = (size_t) ((sizeof(struct ext2_inode_reference) *
ent->max_refs));
retval = ext2fs_get_mem(size, &ref_ent->refs);
retval = ext2fs_get_array(ent->max_refs,
sizeof(struct ext2_inode_reference), &ref_ent->refs);
if (retval)
return retval;
memset(ref_ent->refs, 0, size);

View File

@ -280,7 +280,7 @@ errcode_t ext2fs_open2(const char *name, const char *io_options,
blocks_per_group);
fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count,
EXT2_DESC_PER_BLOCK(fs->super));
retval = ext2fs_get_mem(fs->desc_blocks * fs->blocksize,
retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize,
&fs->group_desc);
if (retval)
goto cleanup;

View File

@ -73,7 +73,7 @@ errcode_t ext2fs_create_resize_inode(ext2_filsys fs)
sb = fs->super;
retval = ext2fs_get_mem(2 * fs->blocksize, &dindir_buf);
retval = ext2fs_get_array(2, fs->blocksize, &dindir_buf);
if (retval)
goto out_free;
gdt_buf = (__u32 *)((char *)dindir_buf + fs->blocksize);