From: Mark Wielaard Date: Fri, 22 May 2015 16:01:34 +0000 (+0200) Subject: libdwfl: Don't allocate phdrs and dyn on stack in dwfl_segment_report_module. X-Git-Tag: elfutils-0.162~35 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f96ec4a9bb818fe0b38e94406ce4e4ed26effe9d;p=thirdparty%2Felfutils.git libdwfl: Don't allocate phdrs and dyn on stack in dwfl_segment_report_module. Signed-off-by: Mark Wielaard --- diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index 87537832b..772de3ee9 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,9 @@ +2015-05-22 Mark Wielaard + + * dwfl_segment_report_module.c (dwfl_segment_report_module): + Allocate phdrs with malloc, not on stack. free in finish. + Allocate dyn with malloc, not on stack, free after use. + 2015-05-22 Mark Wielaard * find-debuginfo.c (find_debuginfo_in_path): malloc or strdup, diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c index 898457f11..705639d26 100644 --- a/libdwfl/dwfl_segment_report_module.c +++ b/libdwfl/dwfl_segment_report_module.c @@ -1,5 +1,5 @@ /* Sniff out modules from ELF headers visible in memory segments. - Copyright (C) 2008-2012, 2014 Red Hat, Inc. + Copyright (C) 2008-2012, 2014, 2015 Red Hat, Inc. This file is part of elfutils. This file is free software; you can redistribute it and/or modify @@ -36,7 +36,6 @@ #include #include #include -#include #include #include #include @@ -278,8 +277,13 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, Elf *elf = NULL; int fd = -1; + /* We might have to reserve some memory for the phdrs. Set to NULL + here so we can always safely free it. */ + void *phdrsp = NULL; + inline int finish (void) { + free (phdrsp); release_buffer (&buffer, &buffer_available); if (elf != NULL) elf_end (elf); @@ -400,14 +404,19 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, xlatefrom.d_buf = ph_buffer; - union + typedef union { Elf32_Phdr p32[phnum]; Elf64_Phdr p64[phnum]; - } phdrs; + } phdrsn; - xlateto.d_buf = &phdrs; - xlateto.d_size = sizeof phdrs; + phdrsp = malloc (sizeof (phdrsn)); + if (unlikely (phdrsp == NULL)) + return finish (); + phdrsn *phdrs = (phdrsn *) phdrsp; + + xlateto.d_buf = phdrs; + xlateto.d_size = sizeof (phdrsn); /* Track the bounds of the file visible in memory. */ GElf_Off file_trimmed_end = 0; /* Proper p_vaddr + p_filesz end. */ @@ -570,10 +579,10 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, found_bias = false; /* Trigger error check. */ else for (uint_fast16_t i = 0; i < phnum; ++i) - consider_phdr (phdrs.p32[i].p_type, - phdrs.p32[i].p_vaddr, phdrs.p32[i].p_memsz, - phdrs.p32[i].p_offset, phdrs.p32[i].p_filesz, - phdrs.p32[i].p_align); + consider_phdr (phdrs->p32[i].p_type, + phdrs->p32[i].p_vaddr, phdrs->p32[i].p_memsz, + phdrs->p32[i].p_offset, phdrs->p32[i].p_filesz, + phdrs->p32[i].p_align); } else { @@ -581,10 +590,10 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, found_bias = false; /* Trigger error check. */ else for (uint_fast16_t i = 0; i < phnum; ++i) - consider_phdr (phdrs.p64[i].p_type, - phdrs.p64[i].p_vaddr, phdrs.p64[i].p_memsz, - phdrs.p64[i].p_offset, phdrs.p64[i].p_filesz, - phdrs.p64[i].p_align); + consider_phdr (phdrs->p64[i].p_type, + phdrs->p64[i].p_vaddr, phdrs->p64[i].p_memsz, + phdrs->p64[i].p_offset, phdrs->p64[i].p_filesz, + phdrs->p64[i].p_align); } finish_portion (&ph_buffer, &ph_buffer_size); @@ -735,38 +744,44 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, const size_t dyn_entsize = (ei_class == ELFCLASS32 ? sizeof (Elf32_Dyn) : sizeof (Elf64_Dyn)); + void *dyns = NULL; void *dyn_data = NULL; size_t dyn_data_size = 0; if (dyn_filesz != 0 && dyn_filesz % dyn_entsize == 0 && ! read_portion (&dyn_data, &dyn_data_size, dyn_vaddr, dyn_filesz)) { - union + typedef union { Elf32_Dyn d32[dyn_filesz / sizeof (Elf32_Dyn)]; Elf64_Dyn d64[dyn_filesz / sizeof (Elf64_Dyn)]; - } dyn; + } dynn; + dyns = malloc (sizeof (dynn)); + if (unlikely (dyns == NULL)) + return finish (); + dynn *dyn = (dynn *) dyns; xlatefrom.d_type = xlateto.d_type = ELF_T_DYN; xlatefrom.d_buf = (void *) dyn_data; xlatefrom.d_size = dyn_filesz; - xlateto.d_buf = &dyn; - xlateto.d_size = sizeof dyn; + xlateto.d_buf = dyn; + xlateto.d_size = sizeof (dynn); if (ei_class == ELFCLASS32) { if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL) - for (size_t i = 0; i < dyn_filesz / sizeof dyn.d32[0]; ++i) - if (consider_dyn (dyn.d32[i].d_tag, dyn.d32[i].d_un.d_val)) + for (size_t i = 0; i < dyn_filesz / sizeof (Elf32_Dyn); ++i) + if (consider_dyn (dyn->d32[i].d_tag, dyn->d32[i].d_un.d_val)) break; } else { if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL) - for (size_t i = 0; i < dyn_filesz / sizeof dyn.d64[0]; ++i) - if (consider_dyn (dyn.d64[i].d_tag, dyn.d64[i].d_un.d_val)) + for (size_t i = 0; i < dyn_filesz / sizeof (Elf64_Dyn); ++i) + if (consider_dyn (dyn->d64[i].d_tag, dyn->d64[i].d_un.d_val)) break; } } + free (dyns); finish_portion (&dyn_data, &dyn_data_size); /* We'll use the name passed in or a stupid default if not DT_SONAME. */ @@ -881,12 +896,12 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, if (ei_class == ELFCLASS32) for (uint_fast16_t i = 0; i < phnum; ++i) - read_phdr (phdrs.p32[i].p_type, phdrs.p32[i].p_vaddr, - phdrs.p32[i].p_offset, phdrs.p32[i].p_filesz); + read_phdr (phdrs->p32[i].p_type, phdrs->p32[i].p_vaddr, + phdrs->p32[i].p_offset, phdrs->p32[i].p_filesz); else for (uint_fast16_t i = 0; i < phnum; ++i) - read_phdr (phdrs.p64[i].p_type, phdrs.p64[i].p_vaddr, - phdrs.p64[i].p_offset, phdrs.p64[i].p_filesz); + read_phdr (phdrs->p64[i].p_type, phdrs->p64[i].p_vaddr, + phdrs->p64[i].p_offset, phdrs->p64[i].p_filesz); } else {