diff options
| author | Mark Wielaard <[email protected]> | 2015-05-18 16:23:06 +0200 |
|---|---|---|
| committer | Mark Wielaard <[email protected]> | 2015-05-27 23:04:31 +0200 |
| commit | be17786f9df7a59df24d2c1b4b2d36614da8e241 (patch) | |
| tree | 3593ae72fc1957bb2ed6cecdac6ad6fc4109bcea /libdwfl | |
| parent | 390dd3d21c5b92dda139da744edae7093d70fc9b (diff) | |
libdwfl: Fix possible unbounded stack usage in cache_sections.
For modules with lots of sections cache_sections could blow up the stack
theoretically. Don't use alloca, but use malloc with explicit free.
Signed-off-by: Mark Wielaard <[email protected]>
Diffstat (limited to 'libdwfl')
| -rw-r--r-- | libdwfl/ChangeLog | 5 | ||||
| -rw-r--r-- | libdwfl/derelocate.c | 37 |
2 files changed, 33 insertions, 9 deletions
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index 47f3854a..83a26189 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,8 @@ +2015-05-18 Mark Wielaard <[email protected]> + + * derelocate.c (cache_sections): Allocate temporary newrefs and + sortrefs with malloc, not alloca. Always free them on return. + 2015-05-07 Mark Wielaard <[email protected]> * cu.c (intern_cu): Check for EOF and check cuoff points to a real diff --git a/libdwfl/derelocate.c b/libdwfl/derelocate.c index da679089..2889fe41 100644 --- a/libdwfl/derelocate.c +++ b/libdwfl/derelocate.c @@ -1,5 +1,5 @@ /* Recover relocatibility for addresses computed from debug information. - Copyright (C) 2005-2010, 2013 Red Hat, Inc. + Copyright (C) 2005-2010, 2013, 2015 Red Hat, Inc. This file is part of elfutils. This file is free software; you can redistribute it and/or modify @@ -80,7 +80,8 @@ cache_sections (Dwfl_Module *mod) { elf_error: __libdwfl_seterrno (DWFL_E_LIBELF); - return -1; + nrefs = -1; + goto free_refs; } bool check_reloc_sections = false; @@ -112,7 +113,15 @@ cache_sections (Dwfl_Module *mod) if (unlikely (name == NULL)) goto elf_error; - struct secref *newref = alloca (sizeof *newref); + struct secref *newref = malloc (sizeof *newref); + if (unlikely (newref == NULL)) + { + nomem: + __libdwfl_seterrno (DWFL_E_NOMEM); + nrefs = -1; + goto free_refs; + } + newref->scn = scn; newref->relocs = NULL; newref->name = name; @@ -147,13 +156,13 @@ cache_sections (Dwfl_Module *mod) } mod->reloc_info = malloc (offsetof (struct dwfl_relocation, refs[nrefs])); - if (mod->reloc_info == NULL) - { - __libdwfl_seterrno (DWFL_E_NOMEM); - return -1; - } + if (unlikely (mod->reloc_info == NULL)) + goto nomem; + + struct secref **sortrefs = malloc (nrefs * sizeof sortrefs[0]); + if (unlikely (sortrefs == NULL)) + goto nomem; - struct secref **sortrefs = alloca (nrefs * sizeof sortrefs[0]); for (size_t i = nrefs; i-- > 0; refs = refs->next) sortrefs[i] = refs; assert (refs == NULL); @@ -170,6 +179,8 @@ cache_sections (Dwfl_Module *mod) mod->reloc_info->refs[i].end = sortrefs[i]->end; } + free (sortrefs); + if (unlikely (check_reloc_sections)) { /* There was a reloc section that preceded its target section. @@ -199,6 +210,14 @@ cache_sections (Dwfl_Module *mod) } } +free_refs: + while (refs != NULL) + { + struct secref *ref = refs; + refs = ref->next; + free (ref); + } + return nrefs; } |
