[PATCH 06/17] libdwfl: Fix possible unbounded stack usage in cache_sections.

Mark Wielaard mjw at redhat.com
Sat May 23 21:10:19 UTC 2015


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 <mjw at redhat.com>
---
 libdwfl/ChangeLog    |  5 +++++
 libdwfl/derelocate.c | 35 +++++++++++++++++++++++++++--------
 2 files changed, 32 insertions(+), 8 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  <mjw at redhat.com>
+
+	* derelocate.c (cache_sections): Allocate temporary newrefs and
+	sortrefs with malloc, not alloca. Always free them on return.
+
 2015-05-07  Mark Wielaard  <mjw at redhat.com>
 
 	* 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..cec9655 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 (newref == NULL)
+	    {
+	    nomem:
+	      __libdwfl_seterrno (DWFL_E_NOMEM);
+	      nrefs = -1;
+	      goto free_refs;
+	    }
+
 	  newref->scn = scn;
 	  newref->relocs = NULL;
 	  newref->name = name;
@@ -148,12 +157,12 @@ 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;
-    }
+    goto nomem;
+
+  struct secref **sortrefs = malloc (nrefs * sizeof sortrefs[0]);
+  if (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;
 }
 
-- 
1.8.3.1



More information about the elfutils-devel mailing list