diff options
author | Mark Wielaard <mjw@redhat.com> | 2015-12-02 15:44:10 +0100 |
---|---|---|
committer | Mark Wielaard <mjw@redhat.com> | 2016-01-02 20:37:45 +0100 |
commit | 5c40529883a48e350b37e7de9ad285facdf84f6f (patch) | |
tree | 2f6f7a34aa3c210a6dabf097653e62643df25926 | |
parent | e04da0e6bab6c6cca2d6e1657d18666f50d2ecfa (diff) |
unstrip: Don't leak new section data.
When we copy elided sections some section data is newly allocated.
Track those allocations so we can free them when done.
Signed-off-by: Mark Wielaard <mjw@redhat.com>
-rw-r--r-- | src/ChangeLog | 10 | ||||
-rw-r--r-- | src/unstrip.c | 39 |
2 files changed, 47 insertions, 2 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 27c638f9..be7768f6 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,13 @@ +2015-12-02 Mark Wielaard <mjw@redhat.com> + + * unstrip.c (struct data_list): New. + (new_data_list): Likewise. + (record_new_data): Likewise. + (free_new_data): Likewise. + (adjust_relocs): Call record_new_data. + (add_new_section_symbols): Likewise. + (copy_elided_sections): Call free_new_data. + 2015-12-01 Mark Wielaard <mjw@redhat.com> * elfcmp.c (main): Close ebl1 and ebl2 backends. diff --git a/src/unstrip.c b/src/unstrip.c index bc8ed503..85e0a1da 100644 --- a/src/unstrip.c +++ b/src/unstrip.c @@ -311,6 +311,38 @@ make_directories (const char *path) error (EXIT_FAILURE, errno, _("cannot create directory '%s'"), dir); } +/* Keep track of new section data we are creating, so we can free it + when done. */ +struct data_list +{ + void *data; + struct data_list *next; +}; + +struct data_list *new_data_list; + +static void +record_new_data (void *data) +{ + struct data_list *next = new_data_list; + new_data_list = xmalloc (sizeof (struct data_list)); + new_data_list->data = data; + new_data_list->next = next; +} + +static void +free_new_data (void) +{ + struct data_list *list = new_data_list; + while (list != NULL) + { + struct data_list *next = list->next; + free (list->data); + free (list); + list = next; + } + new_data_list = NULL; +} /* The binutils linker leaves gratuitous section symbols in .symtab that strip has to remove. Older linkers likewise include a @@ -472,6 +504,7 @@ adjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const GElf_Shdr *shdr, if (old_chain[i] != STN_UNDEF) \ new_chain[map[i - 1]] = map[old_chain[i] - 1]; \ \ + record_new_data (new_hash); \ data->d_buf = new_hash; \ data->d_size = nent * sizeof new_hash[0]; \ } @@ -514,6 +547,7 @@ adjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const GElf_Shdr *shdr, ELF_CHECK (v != NULL, _("cannot get symbol version: %s")); } + record_new_data (versym); data->d_buf = versym; data->d_size = nent * shdr->sh_entsize; elf_flagdata (data, ELF_C_SET, ELF_F_DIRTY); @@ -571,6 +605,7 @@ add_new_section_symbols (Elf_Scn *old_symscn, size_t old_shnum, symdata->d_size = shdr->sh_size; symdata->d_buf = xmalloc (symdata->d_size); + record_new_data (symdata->d_buf); /* Copy the existing section symbols. */ Elf_Data *old_symdata = elf_getdata (old_symscn, NULL); @@ -1762,6 +1797,7 @@ more sections in stripped file than debug file -- arguments reversed?")); shdr->sh_size = symdata->d_size = (1 + nsym) * shdr->sh_entsize; symdata->d_buf = xmalloc (symdata->d_size); + record_new_data (symdata->d_buf); GElf_Sym sym; memset (&sym, 0, sizeof sym); @@ -1927,13 +1963,12 @@ more sections in stripped file than debug file -- arguments reversed?")); free (strtab_data->d_buf); } - if (symdata != NULL) - free (symdata->d_buf); if (symstrtab != NULL) { ebl_strtabfree (symstrtab); free (symstrdata->d_buf); } + free_new_data (); } /* Process one pair of files, already opened. */ |