From 8fff11068c100be627745967992fb88759dea9c1 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 23 Mar 2023 00:44:22 +0000 Subject: ext2simg: clean up integer types and check for too-large fs libsparse assumes 32-bit block numbers. Also, ext2simg might read nearly the entire filesystem into memory. Therefore, make ext2simg use appropriate integer types, and explicitly check for when the filesystem is too large or allocating memory failed. Change-Id: Ic415d0e974dce2b4ff6e7fa9265f6e86d371a274 Signed-off-by: Eric Biggers --- contrib/android/ext2simg.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/contrib/android/ext2simg.c b/contrib/android/ext2simg.c index 811c60d6..13a9d567 100644 --- a/contrib/android/ext2simg.c +++ b/contrib/android/ext2simg.c @@ -80,7 +80,11 @@ static void add_chunk(ext2_filsys fs, struct sparse_file *s, } /* The input file will be overwritten, so make a copy of the blocks. */ + if (len > SIZE_MAX - sizeof(*bi)) + sparse_fatal("filesystem is too large"); bi = calloc(1, sizeof(*bi) + len); + if (!bi) + sparse_fatal("out of memory"); bi->next = buf_list; buf_list = bi; retval = io_channel_read_blk64(fs->io, chunk_start, num_blks, bi->buf); @@ -102,6 +106,16 @@ static void free_chunks(void) } } +static blk_t fs_blocks_count(ext2_filsys fs) +{ + blk64_t blks = ext2fs_blocks_count(fs->super); + + /* libsparse assumes 32-bit block numbers. */ + if ((blk_t)blks != blks) + sparse_fatal("filesystem is too large"); + return blks; +} + static struct sparse_file *ext_to_sparse(const char *in_file) { errcode_t retval; @@ -118,7 +132,7 @@ static struct sparse_file *ext_to_sparse(const char *in_file) if (retval) ext2fs_fatal(retval, "while reading block bitmap of %s", in_file); - fs_blks = ext2fs_blocks_count(fs->super); + fs_blks = fs_blocks_count(fs); s = sparse_file_new(fs->blocksize, (uint64_t)fs_blks * fs->blocksize); if (!s) @@ -132,7 +146,7 @@ static struct sparse_file *ext_to_sparse(const char *in_file) * larger than INT32_MAX (32-bit _and_ 64-bit systems). * Make sure we do not create chunks larger than this limit. */ - int64_t max_blk_per_chunk = (INT32_MAX - 12) / fs->blocksize; + int32_t max_blk_per_chunk = (INT32_MAX - 12) / fs->blocksize; /* * Iterate through the filesystem's blocks, identifying "chunks" that -- cgit v1.2.3