mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
zdump: check provided sizes for reasonableness
Check the dump provided sizes for reasonableness. This avoids that a corrupted dump leads to allocation of large buffers on the heap. Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com> Reviewed-by: Steffen Eiden <seiden@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
committed by
Jan Höppner
parent
f4ed0b0ec6
commit
1911cba130
@@ -121,7 +121,8 @@ Elf64_Shdr *read_elf_shdrs(const struct zg_fh *fh, const Elf64_Ehdr *ehdr, unsig
|
||||
return shdrs;
|
||||
}
|
||||
|
||||
unsigned char *read_elf_section_data(const struct zg_fh *fh, const Elf64_Shdr *shdr, size_t *size)
|
||||
unsigned char *read_elf_section_data(const struct zg_fh *fh, const Elf64_Shdr *shdr, size_t *size,
|
||||
const size_t max_size)
|
||||
{
|
||||
const size_t sh_size = shdr->sh_size;
|
||||
unsigned char *ret;
|
||||
@@ -133,6 +134,9 @@ unsigned char *read_elf_section_data(const struct zg_fh *fh, const Elf64_Shdr *s
|
||||
if (shdr->sh_offset > OFF_T_MAX)
|
||||
ERR_EXIT("Unsupported offset");
|
||||
|
||||
if (sh_size > max_size)
|
||||
ERR_EXIT("Unsupported section size: %#lx > %#lx", sh_size, max_size);
|
||||
|
||||
ret = util_malloc(sh_size);
|
||||
zg_seek(fh, (off_t)shdr->sh_offset, ZG_CHECK);
|
||||
zg_read(fh, ret, sh_size, ZG_CHECK);
|
||||
@@ -141,7 +145,8 @@ unsigned char *read_elf_section_data(const struct zg_fh *fh, const Elf64_Shdr *s
|
||||
}
|
||||
|
||||
char *read_elf_shstrtab(const struct zg_fh *fh, const Elf64_Ehdr *ehdr, const Elf64_Shdr *shdrs,
|
||||
const unsigned int shnum, size_t *shstrtab_size)
|
||||
const unsigned int shnum, size_t *shstrtab_size,
|
||||
const size_t max_shstrtab_size)
|
||||
{
|
||||
const size_t shstrndx = ehdr->e_shstrndx;
|
||||
Elf64_Xword tmp_shstrtab_size;
|
||||
@@ -166,6 +171,10 @@ char *read_elf_shstrtab(const struct zg_fh *fh, const Elf64_Ehdr *ehdr, const El
|
||||
ERR_EXIT("Unsupported offset");
|
||||
|
||||
tmp_shstrtab_size = shdrs[shstrndx].sh_size;
|
||||
if (tmp_shstrtab_size > max_shstrtab_size)
|
||||
ERR_EXIT("Unsupported shstrtab size: %#lx > %#lx", tmp_shstrtab_size,
|
||||
max_shstrtab_size);
|
||||
|
||||
shstrtab = util_malloc(tmp_shstrtab_size);
|
||||
zg_seek(fh, (off_t)shstrndx_off, ZG_CHECK);
|
||||
zg_read(fh, shstrtab, tmp_shstrtab_size, ZG_CHECK);
|
||||
|
||||
@@ -195,7 +195,8 @@ Elf64_Shdr *read_elf_shdrs(const struct zg_fh *fh, const Elf64_Ehdr *ehdr,
|
||||
*
|
||||
* To read the section content the offset of @fh is changed.
|
||||
*/
|
||||
unsigned char *read_elf_section_data(const struct zg_fh *fh, const Elf64_Shdr *shdr, size_t *size);
|
||||
unsigned char *read_elf_section_data(const struct zg_fh *fh, const Elf64_Shdr *shdr, size_t *size,
|
||||
const size_t max_size);
|
||||
|
||||
/*
|
||||
* Read ELF section header string table
|
||||
@@ -203,7 +204,8 @@ unsigned char *read_elf_section_data(const struct zg_fh *fh, const Elf64_Shdr *s
|
||||
* To read the section header string table the offset of @fh is changed.
|
||||
*/
|
||||
char *read_elf_shstrtab(const struct zg_fh *fh, const Elf64_Ehdr *ehdr, const Elf64_Shdr *shdrs,
|
||||
const unsigned int shnum, size_t *shstrtab_size);
|
||||
const unsigned int shnum, size_t *shstrtab_size,
|
||||
const size_t max_shstrtab_size);
|
||||
|
||||
/*
|
||||
* Find ELF section header by section name
|
||||
|
||||
@@ -46,17 +46,19 @@ WRAPPED_G_DEFINE_AUTOPTR_CLEANUP_FUNC(Elf64_Ehdr, free);
|
||||
* read_elf_section_data_as_gbytes:
|
||||
* @fh: (not nullable): open input file
|
||||
* @shdr: (not nullable): section header of the section to read
|
||||
* @max_size: maximum section data size in bytes
|
||||
*
|
||||
* Try to read section data and return it as #GBytes.
|
||||
*
|
||||
* Returns: #GBytes on success, %NULL if an error occurred
|
||||
*/
|
||||
static GBytes *read_elf_section_data_as_gbytes(const struct zg_fh *fh, const Elf64_Shdr *shdr)
|
||||
static GBytes *read_elf_section_data_as_gbytes(const struct zg_fh *fh, const Elf64_Shdr *shdr,
|
||||
const size_t max_size)
|
||||
{
|
||||
unsigned char *data;
|
||||
size_t size;
|
||||
|
||||
data = read_elf_section_data(fh, shdr, &size);
|
||||
data = read_elf_section_data(fh, shdr, &size, max_size);
|
||||
if (!data)
|
||||
return NULL;
|
||||
return g_bytes_new_with_free_func(data, size, free, data);
|
||||
@@ -106,6 +108,12 @@ static dfi_cpu_t *nt_s390_pv_cpu_data_read(const struct zg_fh *fh, const Elf64_N
|
||||
|
||||
g_assert(dump_key);
|
||||
|
||||
if (note_descsz > PV_MAX_NT_S390_PV_CPU_DATA_SIZE) {
|
||||
g_set_error(error, ZDUMP_PV_UTILS_ERROR, ZDUMP_ERR_CORRUPTED_NOTE,
|
||||
_("Unable to read confidential CPU data. Dump probably corrupted."));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
note_data = g_malloc(note_descsz);
|
||||
if (nt_read(fh, note_hdr, note_data, note_descsz) < 0) {
|
||||
g_set_error(error, ZDUMP_PV_UTILS_ERROR, ZDUMP_ERR_CORRUPTED_NOTE,
|
||||
@@ -224,7 +232,7 @@ static int dfi_pv_elf_init(void)
|
||||
if (!shdrs)
|
||||
return -ENODEV;
|
||||
|
||||
shstrtab = read_elf_shstrtab(fh, ehdr, shdrs, shnum, &shstrtab_size);
|
||||
shstrtab = read_elf_shstrtab(fh, ehdr, shdrs, shnum, &shstrtab_size, PV_MAX_SHSTRTAB_SIZE);
|
||||
if (!shstrtab)
|
||||
return -ENODEV;
|
||||
|
||||
@@ -255,7 +263,8 @@ static int dfi_pv_elf_init(void)
|
||||
return -EINVAL;
|
||||
|
||||
/* Read the PV completion configuration section data */
|
||||
completion_sdata = read_elf_section_data_as_gbytes(fh, completion_shdr);
|
||||
completion_sdata =
|
||||
read_elf_section_data_as_gbytes(fh, completion_shdr, PV_MAX_COMPL_DATA_SIZE);
|
||||
if (!completion_sdata)
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
@@ -20,6 +20,16 @@
|
||||
#define PV_ELF_SECTION_NAME_COMPL "pv_compl"
|
||||
#define PV_ELF_SECTION_NAME_TWEAKS "pv_mem_meta"
|
||||
|
||||
/* Maximum size (in bytes) of completion section data */
|
||||
#define PV_MAX_COMPL_DATA_SIZE ROUNDUP(sizeof(pv_dump_completion_data_v1_t), PAGE_SIZE)
|
||||
/* Maximum size (in bytes) of section header string table */
|
||||
#define PV_MAX_SHSTRTAB_SIZE \
|
||||
ROUNDUP(sizeof(PV_ELF_SECTION_NAME_COMPL) + sizeof(PV_ELF_SECTION_NAME_TWEAKS) + \
|
||||
sizeof(".shstrtab"), \
|
||||
PAGE_SIZE)
|
||||
/* Maximum size of NT_S390_PV_CPU_DATA */
|
||||
#define PV_MAX_NT_S390_PV_CPU_DATA_SIZE ROUNDUP(sizeof(pv_cpu_dump_v1_t), PAGE_SIZE)
|
||||
|
||||
#define PV_COMPL_DATA_VERSION_1 ((uint32_t)1)
|
||||
#define PV_SEC_CPU_DATA_VERSION_1 ((uint32_t)1)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user