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] libdwfl: Don't leak core Elf and core file descriptor from argp-std.


Our argp helper would leak the core Elf and core file descriptor when
given by the user. Store both in the Dwfl as a new Dwfl_User_Core so
they get cleaned up by dwfl_end.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
---
 libdwfl/ChangeLog                | 14 ++++++++++++++
 libdwfl/argp-std.c               | 16 ++++++++++++++--
 libdwfl/core-file.c              | 22 ++++++++++++++++++----
 libdwfl/dwfl_build_id_find_elf.c |  9 ++++++---
 libdwfl/dwfl_end.c               | 12 ++++++++++--
 libdwfl/libdwflP.h               | 14 ++++++++++++--
 libdwfl/link_map.c               | 12 ++++++++----
 7 files changed, 82 insertions(+), 17 deletions(-)

diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 3c48b5e..9640b4f 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,17 @@
+2015-12-01  Mark Wielaard  <mjw@redhat.com>
+
+	* libdwflP.h (struct Dwfl_User_Core): New.
+	(struct DWfl): Replace executable_for_core with user_core.
+	* argp-std.c (parse_opt): Store core and fd in Dwfl user_core.
+	* core-file.c (dwfl_core_file_report): Check and store
+	executable_for_core in Dwfl user_core.
+	* dwfl_build_id_find_elf.c (dwfl_build_id_find_elf): Check and use
+	executable_for_core in Dwfl user_core.
+	* dwfl_end.c (dwfl_end): Release resources held in Dwfl user_core.
+	* link-map.c (report_r_debug): Check executable_for_core in Dwfl
+	user_core.
+	(dwfl_link_map_report): Likewise.
+
 2015-11-19  Mark Wielaard  <mjw@redhat.com>
 
 	* dwfl_module.c (__libdwfl_module_free): Remove Dwfl_Module Ebl from
diff --git a/libdwfl/argp-std.c b/libdwfl/argp-std.c
index 2bbf74f..501530a 100644
--- a/libdwfl/argp-std.c
+++ b/libdwfl/argp-std.c
@@ -1,5 +1,5 @@
 /* Standard argp argument parsers for tools using libdwfl.
-   Copyright (C) 2005-2010, 2012 Red Hat, Inc.
+   Copyright (C) 2005-2010, 2012, 2015 Red Hat, Inc.
    This file is part of elfutils.
 
    This file is free software; you can redistribute it and/or modify
@@ -303,7 +303,19 @@ parse_opt (int key, char *arg, struct argp_state *state)
 	    /* Non-fatal to not be able to attach to core, ignore error.  */
 	    INTUSE(dwfl_core_file_attach) (dwfl, core);
 
-	    /* From now we leak FD and CORE.  */
+	    /* Store core Elf and fd in Dwfl to expose with dwfl_end.  */
+	    if (dwfl->user_core == NULL)
+	      {
+		dwfl->user_core = calloc (1, sizeof (struct Dwfl_User_Core));
+		if (dwfl->user_core == NULL)
+		  {
+		    argp_failure (state, EXIT_FAILURE, 0,
+				  _("Not enough memory"));
+		    return ENOMEM;
+		  }
+	      }
+	    dwfl->user_core->core = core;
+	    dwfl->user_core->fd = fd;
 
 	    if (result == 0)
 	      {
diff --git a/libdwfl/core-file.c b/libdwfl/core-file.c
index b317eca..6ba38f7 100644
--- a/libdwfl/core-file.c
+++ b/libdwfl/core-file.c
@@ -441,13 +441,27 @@ dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable)
       return -1;
     }
 
-  free (dwfl->executable_for_core);
+  if (dwfl->user_core != NULL)
+    free (dwfl->user_core->executable_for_core);
   if (executable == NULL)
-    dwfl->executable_for_core = NULL;
+    {
+      if (dwfl->user_core != NULL)
+	dwfl->user_core->executable_for_core = NULL;
+    }
   else
     {
-      dwfl->executable_for_core = strdup (executable);
-      if (dwfl->executable_for_core == NULL)
+      if (dwfl->user_core == NULL)
+	{
+	  dwfl->user_core = calloc (1, sizeof (struct Dwfl_User_Core));
+	  if (dwfl->user_core == NULL)
+	    {
+	      __libdwfl_seterrno (DWFL_E_NOMEM);
+	      return -1;
+	    }
+	  dwfl->user_core->fd = -1;
+	}
+      dwfl->user_core->executable_for_core = strdup (executable);
+      if (dwfl->user_core->executable_for_core == NULL)
 	{
 	  __libdwfl_seterrno (DWFL_E_NOMEM);
 	  return -1;
diff --git a/libdwfl/dwfl_build_id_find_elf.c b/libdwfl/dwfl_build_id_find_elf.c
index 2e30b7a..903e193 100644
--- a/libdwfl/dwfl_build_id_find_elf.c
+++ b/libdwfl/dwfl_build_id_find_elf.c
@@ -140,16 +140,19 @@ dwfl_build_id_find_elf (Dwfl_Module *mod,
 			char **file_name, Elf **elfp)
 {
   *elfp = NULL;
-  if (mod->is_executable && mod->dwfl->executable_for_core != NULL)
+  if (mod->is_executable
+      && mod->dwfl->user_core != NULL
+      && mod->dwfl->user_core->executable_for_core != NULL)
     {
       /* When dwfl_core_file_report was called with a non-NULL executable file
 	 name this callback will replace the Dwfl_Module main.name with the
 	 recorded executable file when MOD was identified as main executable
 	 (which then triggers opening and reporting of the executable).  */
-      int fd = open (mod->dwfl->executable_for_core, O_RDONLY);
+      const char *executable = mod->dwfl->user_core->executable_for_core;
+      int fd = open (executable, O_RDONLY);
       if (fd >= 0)
 	{
-	  *file_name = strdup (mod->dwfl->executable_for_core);
+	  *file_name = strdup (executable);
 	  if (*file_name != NULL)
 	    return fd;
 	  else
diff --git a/libdwfl/dwfl_end.c b/libdwfl/dwfl_end.c
index 33cae48..0b35bd2 100644
--- a/libdwfl/dwfl_end.c
+++ b/libdwfl/dwfl_end.c
@@ -1,5 +1,5 @@
 /* Finish a session using libdwfl.
-   Copyright (C) 2005, 2008, 2012-2013 Red Hat, Inc.
+   Copyright (C) 2005, 2008, 2012-2013, 2015 Red Hat, Inc.
    This file is part of elfutils.
 
    This file is free software; you can redistribute it and/or modify
@@ -27,6 +27,7 @@
    not, see <http://www.gnu.org/licenses/>.  */
 
 #include "libdwflP.h"
+#include <unistd.h>
 
 void
 dwfl_end (Dwfl *dwfl)
@@ -49,6 +50,13 @@ dwfl_end (Dwfl *dwfl)
       __libdwfl_module_free (dead);
     }
 
-  free (dwfl->executable_for_core);
+  if (dwfl->user_core != NULL)
+    {
+      free (dwfl->user_core->executable_for_core);
+      elf_end (dwfl->user_core->core);
+      if (dwfl->user_core->fd != -1)
+	close (dwfl->user_core->fd);
+      free (dwfl->user_core);
+    }
   free (dwfl);
 }
diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h
index 63556d5..2a83646 100644
--- a/libdwfl/libdwflP.h
+++ b/libdwfl/libdwflP.h
@@ -1,5 +1,5 @@
 /* Internal definitions for libdwfl.
-   Copyright (C) 2005-2014 Red Hat, Inc.
+   Copyright (C) 2005-2015 Red Hat, Inc.
    This file is part of elfutils.
 
    This file is free software; you can redistribute it and/or modify
@@ -104,6 +104,16 @@ typedef enum { DWFL_ERRORS DWFL_E_NUM } Dwfl_Error;
 extern int __libdwfl_canon_error (Dwfl_Error) internal_function;
 extern void __libdwfl_seterrno (Dwfl_Error) internal_function;
 
+/* Resources we might keep for the user about the core file that the
+   Dwfl might have been created from.  Can currently only be set
+   through std-argp.  */
+struct Dwfl_User_Core
+{
+  char *executable_for_core;	/* --executable if --core was specified.  */
+  Elf *core;                    /* non-NULL if we need to free it.  */
+  int fd;                       /* close if >= 0.  */
+};
+
 struct Dwfl
 {
   const Dwfl_Callbacks *callbacks;
@@ -130,7 +140,7 @@ struct Dwfl
   GElf_Off lookup_tail_offset;
   int lookup_tail_ndx;
 
-  char *executable_for_core;	/* --executable if --core was specified.  */
+  struct Dwfl_User_Core *user_core;
 };
 
 #define OFFLINE_REDZONE		0x10000
diff --git a/libdwfl/link_map.c b/libdwfl/link_map.c
index 13cac52..e73b219 100644
--- a/libdwfl/link_map.c
+++ b/libdwfl/link_map.c
@@ -356,8 +356,10 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
       if (name != NULL && name[0] == '\0')
 	name = NULL;
 
-      if (iterations == 1 && dwfl->executable_for_core != NULL)
-	name = dwfl->executable_for_core;
+      if (iterations == 1
+	  && dwfl->user_core != NULL
+	  && dwfl->user_core->executable_for_core != NULL)
+	name = dwfl->user_core->executable_for_core;
 
       struct r_debug_info_module *r_debug_info_module = NULL;
       if (r_debug_info != NULL)
@@ -789,7 +791,9 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
 	  bool in_ok = (*memory_callback) (dwfl, phdr_segndx, &in.d_buf,
 					   &in.d_size, phdr, phnum * phent,
 					   memory_callback_arg);
-	  if (! in_ok && dwfl->executable_for_core != NULL)
+	  if (! in_ok
+	      && dwfl->user_core != NULL
+	      && dwfl->user_core->executable_for_core != NULL)
 	    {
 	      /* AUXV -> PHDR -> DYNAMIC
 		 Both AUXV and DYNAMIC should be always present in a core file.
@@ -797,7 +801,7 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
 		 EXECUTABLE_FOR_CORE to find where DYNAMIC is located in the
 		 core file.  */
 
-	      int fd = open (dwfl->executable_for_core, O_RDONLY);
+	      int fd = open (dwfl->user_core->executable_for_core, O_RDONLY);
 	      Elf *elf;
 	      Dwfl_Error error = DWFL_E_ERRNO;
 	      if (fd != -1)
-- 
2.5.0

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