From owner-freebsd-bugs@FreeBSD.ORG Thu Nov 22 21:30:01 2012 Return-Path: Delivered-To: freebsd-bugs@smarthost.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 4EF8AFB6 for ; Thu, 22 Nov 2012 21:30:01 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:1900:2254:206c::16:87]) by mx1.freebsd.org (Postfix) with ESMTP id 348F38FC16 for ; Thu, 22 Nov 2012 21:30:01 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.5/8.14.5) with ESMTP id qAMLU1ec011154 for ; Thu, 22 Nov 2012 21:30:01 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.5/8.14.5/Submit) id qAMLU1ta011153; Thu, 22 Nov 2012 21:30:01 GMT (envelope-from gnats) Date: Thu, 22 Nov 2012 21:30:01 GMT Message-Id: <201211222130.qAMLU1ta011153@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org Cc: From: Mark Johnston Subject: Re: bin/167103: dtrace(1) generates core dump trying to build perl with dtrace enabled X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list Reply-To: Mark Johnston List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 22 Nov 2012 21:30:01 -0000 The following reply was made to PR bin/167103; it has been noted by GNATS. From: Mark Johnston 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--