From be17786f9df7a59df24d2c1b4b2d36614da8e241 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Mon, 18 May 2015 16:23:06 +0200 Subject: [PATCH] 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 --- libdwfl/ChangeLog | 5 +++++ libdwfl/derelocate.c | 37 ++++++++++++++++++++++++++++--------- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog index 47f3854..83a2618 100644 --- a/libdwfl/ChangeLog +++ b/libdwfl/ChangeLog @@ -1,3 +1,8 @@ +2015-05-18 Mark Wielaard + + * derelocate.c (cache_sections): Allocate temporary newrefs and + sortrefs with malloc, not alloca. Always free them on return. + 2015-05-07 Mark Wielaard * 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 da67908..2889fe4 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; } -- 2.7.4