]> git.ipfire.org Git - thirdparty/e2fsprogs.git/commitdiff
libext2fs: Add checks to prevent integer overflows passed to malloc()
authorTheodore Ts'o <tytso@mit.edu>
Sat, 10 Nov 2007 00:01:06 +0000 (19:01 -0500)
committerTheodore Ts'o <tytso@mit.edu>
Thu, 6 Dec 2007 02:01:35 +0000 (21:01 -0500)
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>
17 files changed:
lib/ext2fs/badblocks.c
lib/ext2fs/bb_inode.c
lib/ext2fs/block.c
lib/ext2fs/bmap.c
lib/ext2fs/bmove.c
lib/ext2fs/brel_ma.c
lib/ext2fs/closefs.c
lib/ext2fs/dblist.c
lib/ext2fs/dupfs.c
lib/ext2fs/ext2fs.h
lib/ext2fs/fileio.c
lib/ext2fs/icount.c
lib/ext2fs/initialize.c
lib/ext2fs/inode.c
lib/ext2fs/irel_ma.c
lib/ext2fs/openfs.c
lib/ext2fs/res_gdt.c

index 50e6336ee7a5928343e1c8c0a1973a1f311e50fb..da7889d210829797fb77d27139732488a2f18979 100644 (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;
index 97a56087f4537e83e508da9062d7965910e1b11f..1f5b4e8a6be25c9762f8617801f500e0434147e3 100644 (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;
index 7685680dfa1c4293c1245a2fbd49b89ca437bb5c..07a64157e6f407b80543922d3ef1612a56474338 100644 (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;
        }
index e84004476f341adc5d751e2129f4cbfe9f9abae2..754fc49a1194d6e4a9f7d290caba76c4c971c11d 100644 (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;
index 9946c463c1a3e44318f10f743566b5513dbd392d..7d4b21af4ba1cb012ffa1f3599fe95e93613ea42 100644 (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;
index d422bb2e923f6dc1fd2a4e5b5ed9f8482d04d471..3753e9fa28189364fe95543378423e749ea34653 100644 (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);
index 474e00e07285904ea36b50e9ae4747838b788555..f3fe533420867d0a23e6d346d0d6a8f4103e9f89 100644 (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;
index d5833d7282487e24c15c8ebcb8fba19314fd89cc..21b36aa6dce8f9085b46833278db2896094633b5 100644 (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;
        
index f8919c2224ae0b22318a168c459cc27352a45417..1cf314ced0902a383b3d0cbdc33055d434ad88b4 100644 (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;
index 76452105832244d5abf9ce3e35d211c8dc9c9f54..06ba9a2f523641db0edc31fdf70c259f3cf3e439 100644 (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
index 3e42cbc32e956a1fcbb676ebce6a21912ca10735..8bf99fb9f721d777b3fa6b03455c43c2fd18cd40 100644 (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;
 
index de0b6144de91f4e1b9c119eddb95af59169b5bab..29056762541813296ae687b34cb0032c3b7268d3 100644 (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);
index 16e9eaae5be08adbe68dc107616a0c265937b467..c8f48b9fee45d1c9c8cb63c4321292981a86546b 100644 (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;
index 49d012c4d345ff19371c911d4f81238b10fd001b..7a0cf4e3d4a73515917cd684709c36614504942d 100644 (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;
index eedbe55c8091e0707a36265bb03bb37122c607f6..c6fa828a8b78921ed093a16395b3ccdad8d45632 100644 (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);
index 1ac1564adec2c4323c2d540e199f2da27e366745..947675e579e33fb5ac2ab5cec96e9b0d654a64b2 100644 (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;
index 9901c6e60a5e05ab3d0643c3f6e69ce873d53364..fa72fc931c42c416343e09229e6d8b0d0db07a53 100644 (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);