diff options
author | Mark Wielaard <mjw@redhat.com> | 2015-05-22 18:01:34 +0200 |
---|---|---|
committer | Mark Wielaard <mjw@redhat.com> | 2015-05-27 23:04:31 +0200 |
commit | f96ec4a9bb818fe0b38e94406ce4e4ed26effe9d (patch) | |
tree | ea077f2a0124ed7601de979a16a5210b0891bf38 /libdwfl | |
parent | c4f133a956cdc0355eadedcfdc2198107d3e73b6 (diff) | |
download | elfutils-f96ec4a9bb818fe0b38e94406ce4e4ed26effe9d.tar.gz |
libdwfl: Don't allocate phdrs and dyn on stack in dwfl_segment_report_module.
Signed-off-by: Mark Wielaard <mjw@redhat.com>
Diffstat (limited to 'libdwfl')
-rw-r--r-- | libdwfl/ChangeLog | 6 | ||||
-rw-r--r-- | libdwfl/dwfl_segment_report_module.c | 67 |
2 files changed, 47 insertions, 26 deletions
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index 87537832..772de3ee 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,5 +1,11 @@ 2015-05-22 Mark Wielaard <mjw@redhat.com> + * 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 <mjw@redhat.com> + * find-debuginfo.c (find_debuginfo_in_path): malloc or strdup, instead of alloca or strdupa, local strings of unknown size. Call free before return. diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c index 898457f1..705639d2 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 <gelf.h> #include <inttypes.h> #include <sys/param.h> -#include <alloca.h> #include <endian.h> #include <unistd.h> #include <fcntl.h> @@ -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 { |