From mboxrd@z Thu Jan 1 00:00:00 1970 Content-Type: multipart/mixed; boundary="===============7147790095540547043==" MIME-Version: 1.0 From: Mark Wielaard To: elfutils-devel@lists.fedorahosted.org Subject: [PATCH] libdwfl: Don't leak core Elf and core file descriptor from argp-std. Date: Tue, 01 Dec 2015 22:18:30 +0100 Message-ID: <1449004710-1795-1-git-send-email-mjw@redhat.com> --===============7147790095540547043== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable 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 --- 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 + + * 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 = * 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 *stat= e) /* 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 =3D=3D NULL) + { + dwfl->user_core =3D calloc (1, sizeof (struct Dwfl_User_Core)); + if (dwfl->user_core =3D=3D NULL) + { + argp_failure (state, EXIT_FAILURE, 0, + _("Not enough memory")); + return ENOMEM; + } + } + dwfl->user_core->core =3D core; + dwfl->user_core->fd =3D fd; = if (result =3D=3D 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 ch= ar *executable) return -1; } = - free (dwfl->executable_for_core); + if (dwfl->user_core !=3D NULL) + free (dwfl->user_core->executable_for_core); if (executable =3D=3D NULL) - dwfl->executable_for_core =3D NULL; + { + if (dwfl->user_core !=3D NULL) + dwfl->user_core->executable_for_core =3D NULL; + } else { - dwfl->executable_for_core =3D strdup (executable); - if (dwfl->executable_for_core =3D=3D NULL) + if (dwfl->user_core =3D=3D NULL) + { + dwfl->user_core =3D calloc (1, sizeof (struct Dwfl_User_Core)); + if (dwfl->user_core =3D=3D NULL) + { + __libdwfl_seterrno (DWFL_E_NOMEM); + return -1; + } + dwfl->user_core->fd =3D -1; + } + dwfl->user_core->executable_for_core =3D strdup (executable); + if (dwfl->user_core->executable_for_core =3D=3D 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 =3D NULL; - if (mod->is_executable && mod->dwfl->executable_for_core !=3D NULL) + if (mod->is_executable + && mod->dwfl->user_core !=3D NULL + && mod->dwfl->user_core->executable_for_core !=3D 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 =3D open (mod->dwfl->executable_for_core, O_RDONLY); + const char *executable =3D mod->dwfl->user_core->executable_for_core; + int fd =3D open (executable, O_RDONLY); if (fd >=3D 0) { - *file_name =3D strdup (mod->dwfl->executable_for_core); + *file_name =3D strdup (executable); if (*file_name !=3D 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 . */ = #include "libdwflP.h" +#include = 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 !=3D NULL) + { + free (dwfl->user_core->executable_for_core); + elf_end (dwfl->user_core->core); + if (dwfl->user_core->fd !=3D -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 >=3D 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 el= fdata, if (name !=3D NULL && name[0] =3D=3D '\0') name =3D NULL; = - if (iterations =3D=3D 1 && dwfl->executable_for_core !=3D NULL) - name =3D dwfl->executable_for_core; + if (iterations =3D=3D 1 + && dwfl->user_core !=3D NULL + && dwfl->user_core->executable_for_core !=3D NULL) + name =3D dwfl->user_core->executable_for_core; = struct r_debug_info_module *r_debug_info_module =3D NULL; if (r_debug_info !=3D NULL) @@ -789,7 +791,9 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, siz= e_t auxv_size, bool in_ok =3D (*memory_callback) (dwfl, phdr_segndx, &in.d_buf, &in.d_size, phdr, phnum * phent, memory_callback_arg); - if (! in_ok && dwfl->executable_for_core !=3D NULL) + if (! in_ok + && dwfl->user_core !=3D NULL + && dwfl->user_core->executable_for_core !=3D 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, siz= e_t auxv_size, EXECUTABLE_FOR_CORE to find where DYNAMIC is located in the core file. */ = - int fd =3D open (dwfl->executable_for_core, O_RDONLY); + int fd =3D open (dwfl->user_core->executable_for_core, O_RDONLY); Elf *elf; Dwfl_Error error =3D DWFL_E_ERRNO; if (fd !=3D -1) -- = 2.5.0 --===============7147790095540547043==--