compare_hash_gnu_hash allocated nentries bytes with alloca. nentries is
sh_size / sh_entsize of the symbol table, which comes from the file, so
a crafted ELF can make it up to 4GB and overflow the stack.

Allocate it on the heap and explicitly free it on every exit path.

Signed-off-by: mohammed mustafa <[email protected]>
---
 src/elflint.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/elflint.c b/src/elflint.c
index dd42dcb4..22b424d6 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -2427,8 +2427,7 @@ hash section [%2zu] '%s' does not contain enough data\n"),
     }

   uint32_t nentries = sym_shdr->sh_size / sym_shdr->sh_entsize;
-  char *used = alloca (nentries);
-  memset (used, '\0', nentries);
+  char *used = xcalloc (nentries ?: 1, 1);

   /* First go over the GNU_HASH table and mark the entries as used.  */
   const Elf32_Word *gnu_hasharr = (Elf32_Word *) gnu_hash_data->d_buf;
@@ -2444,6 +2443,7 @@ hash section [%2zu] '%s' does not contain enough data\n"),
       ERROR (_("\
 hash section [%2zu] '%s' has zero bit mask words\n"),
          gnu_hash_idx, gnu_hash_name);
+      free (used);
       return;
     }

@@ -2455,6 +2455,7 @@ hash section [%2zu] '%s' has zero bit mask words\n"),
       ERROR (_("\
 hash section [%2zu] '%s' uses too much data\n"),
          gnu_hash_idx, gnu_hash_name);
+      free (used);
       return;
     }

@@ -2470,6 +2471,7 @@ hash section [%2zu] '%s' uses too much data\n"),
           ERROR (_("\
 hash section [%2zu] '%s' invalid symbol index %" PRIu32 " (max_nsyms:
%" PRIu32 ", nentries: %" PRIu32 "\n"),
              gnu_hash_idx, gnu_hash_name, symidx, max_nsyms, nentries);
+                 free (used);
           return;
         }
           used[symidx + gnu_symbias] |= 1;
@@ -2488,6 +2490,7 @@ hash section [%2zu] '%s' invalid symbol index %"
PRIu32 " (max_nsyms: %" PRIu32
       ERROR (_("\
 hash section [%2zu] '%s' does not contain enough data\n"),
          hash_idx, hash_name);
+         free (used);
       return;
     }

@@ -2499,6 +2502,7 @@ hash section [%2zu] '%s' does not contain enough data\n"),
       ERROR (_("\
 hash section [%2zu] '%s' uses too much data\n"),
          hash_idx, hash_name);
+         free (used);
       return;
     }

@@ -2523,6 +2527,7 @@ hash section [%2zu] '%s' uses too much data\n"),
       ERROR (_("\
 hash section [%2zu] '%s' does not contain enough data\n"),
          hash_idx, hash_name);
+         free (used);
       return;
     }

@@ -2536,6 +2541,7 @@ hash section [%2zu] '%s' does not contain enough data\n"),
       ERROR (_("\
 hash section [%2zu] '%s' uses too much data\n"),
          hash_idx, hash_name);
+         free (used);
       return;
     }

@@ -2557,6 +2563,7 @@ hash section [%2zu] '%s' uses too much data\n"),
       ERROR (_("\
 hash section [%2zu] '%s' invalid sh_entsize\n"),
          hash_idx, hash_name);
+      free (used);
       return;
     }

@@ -2595,6 +2602,8 @@ symbol %d referenced in old hash table in [%2zu]
'%s' but not in new hash table
              elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name));
       }
       }
+
+  free (used);
 }
-- 
2.53.0

Reply via email to