diff --git a/zdump/dfi_pv_elf.c b/zdump/dfi_pv_elf.c index e9c899d5..b445aa14 100644 --- a/zdump/dfi_pv_elf.c +++ b/zdump/dfi_pv_elf.c @@ -263,9 +263,9 @@ static int dfi_pv_elf_init(void) * completion configuration data and store it in `@cpl_conf_decr`. In addition, mmap the * configuration storage state area and use the `tweak_nonce`. */ - if (pv_process_section_data(fh->fh, completion_sdata, storage_state_shdr->sh_offset, - storage_state_shdr->sh_size, key, &cpl_conf_decr, &dump_key, - &storage_state_data, &error) < 0) { + if (pv_process_section_data(fh->fh, fh->sb.st_size, completion_sdata, + storage_state_shdr->sh_offset, storage_state_shdr->sh_size, key, + &cpl_conf_decr, &dump_key, &storage_state_data, &error) < 0) { ERR(_("Unable to read decryption information:" ERR_NEWLINE "%s."), error->message); return -EINVAL; } diff --git a/zdump/pv_utils.c b/zdump/pv_utils.c index 43616534..c26fd264 100644 --- a/zdump/pv_utils.c +++ b/zdump/pv_utils.c @@ -677,10 +677,10 @@ struct _storage_state_mmap { gatomicrefcount ref_count; }; -storage_state_mmap_t *storage_state_mmap_new(const int fd, const u64 offset, const u64 size, - GError **error) +storage_state_mmap_t *storage_state_mmap_new(const int fd, const size_t file_size, const u64 offset, + const u64 size, GError **error) { - size_t tweak_components_cnt, start_addr, in_page_offset, mmapped_size; + size_t tweak_components_cnt, start_addr, min_size, in_page_offset, mmapped_size; g_autoptr(storage_state_mmap_t) ret = NULL; int saved_errno = 0; u8 *ptr; @@ -706,6 +706,19 @@ storage_state_mmap_t *storage_state_mmap_new(const int fd, const u64 offset, con start_addr); return NULL; } + + if (G_UNLIKELY(!g_uint64_checked_add(&min_size, start_addr, mmapped_size))) { + g_set_error(error, ZDUMP_PV_UTILS_ERROR, ZDUMP_ERR_PAGE_END_ADDR_OVERFLOW, + _("UInt overflow detected: %s: start_addr %#lx mmap_size %#lx"), + __func__, start_addr, mmapped_size); + return NULL; + } + + if (file_size < min_size) { + g_set_error(error, ZDUMP_PV_UTILS_ERROR, ZDUMP_ERR_MMAP, + _("mmap failed: file too small")); + return NULL; + } ptr = mmap(NULL, mmapped_size, PROT_READ, MAP_POPULATE | MAP_PRIVATE, fd, (ssize_t)start_addr); saved_errno = errno; @@ -814,9 +827,9 @@ static long completion_data_get_version(GBytes *cpl_data, GError **error) return *version; } -int pv_process_section_data(const int fd, GBytes *completion_sec, const u64 storage_state_offset, - const size_t storage_state_size, GBytes *cck, - pv_dump_completion_t **completion_decr, GBytes **dump_key, +int pv_process_section_data(const int fd, const size_t file_size, GBytes *completion_sec, + const u64 storage_state_offset, const size_t storage_state_size, + GBytes *cck, pv_dump_completion_t **completion_decr, GBytes **dump_key, storage_state_mmap_t **storage_state, GError **error) { g_autoptr(pv_dump_completion_t) _completion_decr = NULL; @@ -870,8 +883,8 @@ int pv_process_section_data(const int fd, GBytes *completion_sec, const u64 stor return -1; } - _storage_state_data = - storage_state_mmap_new(fd, storage_state_offset, storage_state_size, error); + _storage_state_data = storage_state_mmap_new(fd, file_size, storage_state_offset, + storage_state_size, error); if (!_storage_state_data) return -1; diff --git a/zdump/pv_utils.h b/zdump/pv_utils.h index db7a9574..6197e3c0 100644 --- a/zdump/pv_utils.h +++ b/zdump/pv_utils.h @@ -258,9 +258,9 @@ bool pv_is_pv_elf(const Elf64_Shdr *shdrs, const unsigned int shnum, const char * * Returns: 0 in case of success, -1 otherwise. */ -int pv_process_section_data(const int fd, GBytes *completion_sec, const u64 storage_state_offset, - const size_t storage_state_size, GBytes *cck, - pv_dump_completion_t **completion_decr, GBytes **dump_key, +int pv_process_section_data(const int fd, const size_t file_size, GBytes *completion_sec, + const u64 storage_state_offset, const size_t storage_state_size, + GBytes *cck, pv_dump_completion_t **completion_decr, GBytes **dump_key, storage_state_mmap_t **storage_state_data, GError **error); /** @@ -283,14 +283,15 @@ int pv_elf_read(const pv_elf_ctx_t *elf_ctx, const u64 start_addr, void *dst, co /** * storage_state_mmap_new: * @fd: file descriptor for which to create the mapping + * @file_size: file size in bytes * @offset: offset in fd to pv_mem_meta section * @size: size of mapping (and pv_mem_meta section) * @error: return value for GError * * Returns: new storage_state_mmap context */ -storage_state_mmap_t *storage_state_mmap_new(const int fd, const u64 offset, const u64 size, - GError **error); +storage_state_mmap_t *storage_state_mmap_new(const int fd, const size_t file_size, const u64 offset, + const u64 size, GError **error); /** * storage_state_ref: