summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2015-06-18 10:50:19 +0200
committerMark Wielaard <mjw@redhat.com>2015-06-19 13:08:00 +0200
commit3c57452a45b9ab3ce9fa7994c42eda677483cb46 (patch)
treeed8c17832a7ff0cc5df667f673d44b05a01dc045
parent77be59bca4057b22af70b0b2d0197f9505577381 (diff)
downloadelfutils-3c57452a45b9ab3ce9fa7994c42eda677483cb46.tar.gz
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>
-rw-r--r--libelf/ChangeLog5
-rw-r--r--libelf/elf32_updatefile.c29
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);
}