Date: Thu, 22 Nov 2012 21:30:01 GMT From: Mark Johnston <markjdb@gmail.com> To: freebsd-bugs@FreeBSD.org Subject: Re: bin/167103: dtrace(1) generates core dump trying to build perl with dtrace enabled Message-ID: <201211222130.qAMLU1ta011153@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
The following reply was made to PR bin/167103; it has been noted by GNATS. From: Mark Johnston <markjdb@gmail.com> To: bug-followup@FreeBSD.org, swills@FreeBSD.org Cc: Subject: Re: bin/167103: dtrace(1) generates core dump trying to build perl with dtrace enabled Date: Thu, 22 Nov 2012 16:22:54 -0500 --9amGYk9869ThD9tj Content-Type: text/plain; charset=us-ascii Content-Disposition: inline The assertion failure is the result of a double free in dt_link.c:process_obj, and it's basically happening because libdtrace is dependant on some internal behaviour of Solaris' libelf. In the block between lines 1358 and 1415, some buffers are injected into a couple of libelf structures (data_str and data_sym). On Solaris, it looks like the overwritten pointers are just pointers into a larger buffer; on FreeBSD, they're allocated on their own and then freed in elf_close(3). Thus the injected buffers get freed by both libdtrace and libelf. I think the right fix is to just #ifdef the free()s out. One could implement a portable fix by saving pointers to the original buffers somewhere (probably in the struct dt_link_pair) and restore them before calling elf_close(). But I don't think fixes to FreeBSD's dtrace port are going to go back upstream anyway, so I've attached a patch with the simple fix. To reproduce this on a recent CURRENT, it'll be necessary to follow one of the workarounds described in bin/171678 first. Now, in the case of perl, we immediately run into another problem after my patch. The build then fails with: dtrace: failed to link script perldtrace.d: an error was encountered while processing pp_ctl.o It looks like this is caused by an unrelated dependance on Solaris libelf's behaviour, but I haven't pinned it down yet. Thanks, -Mark --9amGYk9869ThD9tj Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="dtrace_double_free.patch.txt" diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c index 2d0428a..00c52ab 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c @@ -1092,8 +1092,10 @@ dt_link_error(dtrace_hdl_t *dtp, Elf *elf, int fd, dt_link_pair_t *bufs, while ((pair = bufs) != NULL) { bufs = pair->dlp_next; +#if !defined(__FreeBSD__) dt_free(dtp, pair->dlp_str); dt_free(dtp, pair->dlp_sym); +#endif dt_free(dtp, pair); } @@ -1385,6 +1387,9 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp) bufs = pair; bcopy(data_str->d_buf, pair->dlp_str, data_str->d_size); +#if defined( __FreeBSD__) + free(data_str->d_buf); +#endif data_str->d_buf = pair->dlp_str; data_str->d_size += len; (void) elf_flagdata(data_str, ELF_C_SET, ELF_F_DIRTY); @@ -1393,6 +1398,9 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp) (void) gelf_update_shdr(scn_str, &shdr_str); bcopy(data_sym->d_buf, pair->dlp_sym, data_sym->d_size); +#if defined(__FreeBSD__) + free(data_sym->d_buf); +#endif data_sym->d_buf = pair->dlp_sym; data_sym->d_size += nsym * symsize; (void) elf_flagdata(data_sym, ELF_C_SET, ELF_F_DIRTY); @@ -1576,8 +1584,10 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp) #endif while ((pair = bufs) != NULL) { bufs = pair->dlp_next; +#if !defined(__FreeBSD__) dt_free(dtp, pair->dlp_str); dt_free(dtp, pair->dlp_sym); +#endif dt_free(dtp, pair); } --9amGYk9869ThD9tj--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201211222130.qAMLU1ta011153>