This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] 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>
---
 libelf/ChangeLog          |  5 +++++
 libelf/elf32_updatefile.c | 29 +++++++++++++++++------------
 2 files changed, 22 insertions(+), 12 deletions(-)

diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index 2d24007..52004f7 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,8 @@
+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-16  Mark Wielaard  <mjw@redhat.com>
 
 	* elf_update.c (write_file): Always also use ftruncate before
diff --git a/libelf/elf32_updatefile.c b/libelf/elf32_updatefile.c
index 913c3e4..832f852 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);
     }
 
-- 
1.8.3.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]