diff options
author | Mark Wielaard <mjw@redhat.com> | 2015-06-18 10:50:19 +0200 |
---|---|---|
committer | Mark Wielaard <mjw@redhat.com> | 2015-06-19 13:08:00 +0200 |
commit | 3c57452a45b9ab3ce9fa7994c42eda677483cb46 (patch) | |
tree | ed8c17832a7ff0cc5df667f673d44b05a01dc045 /libelf | |
parent | 77be59bca4057b22af70b0b2d0197f9505577381 (diff) | |
download | android_external_elfutils-3c57452a45b9ab3ce9fa7994c42eda677483cb46.tar.gz android_external_elfutils-3c57452a45b9ab3ce9fa7994c42eda677483cb46.tar.bz2 android_external_elfutils-3c57452a45b9ab3ce9fa7994c42eda677483cb46.zip |
libelf: Don't leak memory on failure paths in elf_updatefile.
When something goes wrong during the update make sure to always free any
temporary allocated memory (shdr_data and/or scns).
Signed-off-by: Mark Wielaard <mjw@redhat.com>
Diffstat (limited to 'libelf')
-rw-r--r-- | libelf/ChangeLog | 5 | ||||
-rw-r--r-- | libelf/elf32_updatefile.c | 29 |
2 files changed, 22 insertions, 12 deletions
diff --git a/libelf/ChangeLog b/libelf/ChangeLog index 2848f00c..bb56e5b2 100644 --- a/libelf/ChangeLog +++ b/libelf/ChangeLog @@ -1,5 +1,10 @@ 2015-06-18 Mark Wielaard <mjw@redhat.com> + * elf32_updatefile.c (updatefile): Always free shdr_data and scns + when allocated on failure paths. + +2015-06-18 Mark Wielaard <mjw@redhat.com> + * nlist.c (nlist): Check symscn shdr exists before use. 2015-06-16 Mark Wielaard <mjw@redhat.com> diff --git a/libelf/elf32_updatefile.c b/libelf/elf32_updatefile.c index 913c3e46..832f852d 100644 --- a/libelf/elf32_updatefile.c +++ b/libelf/elf32_updatefile.c @@ -655,16 +655,18 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum) #endif ElfW2(LIBELFBITS,Shdr) *shdr_data; + ElfW2(LIBELFBITS,Shdr) *shdr_data_mem = NULL; if (change_bo || elf->state.ELFW(elf,LIBELFBITS).shdr == NULL || (elf->flags & ELF_F_DIRTY)) { - shdr_data = (ElfW2(LIBELFBITS,Shdr) *) + shdr_data_mem = (ElfW2(LIBELFBITS,Shdr) *) malloc (shnum * sizeof (ElfW2(LIBELFBITS,Shdr))); - if (unlikely (shdr_data == NULL)) + if (unlikely (shdr_data_mem == NULL)) { __libelf_seterrno (ELF_E_NOMEM); return -1; } + shdr_data = shdr_data_mem; } else shdr_data = elf->state.ELFW(elf,LIBELFBITS).shdr; @@ -675,6 +677,7 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum) Elf_Scn **scns = (Elf_Scn **) malloc (shnum * sizeof (Elf_Scn *)); if (unlikely (scns == NULL)) { + free (shdr_data_mem); __libelf_seterrno (ELF_E_NOMEM); return -1; } @@ -712,7 +715,12 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum) (scn_start + dl->data.d.d_off) - last_offset, fillbuf, &filled) != 0)) - return 1; + { + fail_free: + free (shdr_data_mem); + free (scns); + return 1; + } } if ((scn->flags | dl->flags | elf->flags) & ELF_F_DIRTY) @@ -744,7 +752,7 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum) if (unlikely (buf == NULL)) { __libelf_seterrno (ELF_E_NOMEM); - return 1; + goto fail_free; } } @@ -761,7 +769,7 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum) free (buf); __libelf_seterrno (ELF_E_WRITE_ERROR); - return 1; + goto fail_free; } if (buf != dl->data.d.d_buf && buf != tmpbuf) @@ -786,7 +794,7 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum) if (unlikely (fill (elf->fildes, last_offset, scn_start - last_offset, fillbuf, &filled) != 0)) - return 1; + goto fail_free; } last_offset = scn_start + shdr->sh_size; @@ -814,7 +822,7 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum) && unlikely (fill (elf->fildes, last_offset, shdr_offset - last_offset, fillbuf, &filled) != 0)) - return 1; + goto fail_free; /* Write out the section header table. */ if (shdr_flags & ELF_F_DIRTY @@ -824,13 +832,10 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum) != sizeof (ElfW2(LIBELFBITS,Shdr)) * shnum)) { __libelf_seterrno (ELF_E_WRITE_ERROR); - return 1; + goto fail_free; } - if (change_bo || elf->state.ELFW(elf,LIBELFBITS).shdr == NULL - || (elf->flags & ELF_F_DIRTY)) - free (shdr_data); - + free (shdr_data_mem); free (scns); } |