From 273efb05a21a9b60088b887440fafa062837a392 Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Sun, 5 Feb 2017 02:44:08 +0000 Subject: [PATCH] Fix a double free of libelf data buffers in the USDT link code. libdtrace needs to append to the input object files' string and symbol tables. Currently it does so by allocating a larger buffer, copying the existing sections into them, and swapping pointers in the libelf data descriptors. However, it also frees those buffers when its processing is complete, which leads to a double free since the elftoolchain libelf owns them and also frees them in elf_end(3). Instead, free the buffers originally allocated by libelf. MFC after: 2 weeks --- cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c index ac4af00ee4f2..c52826c6b818 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c @@ -1205,6 +1205,7 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp) key_t objkey; dt_link_pair_t *pair, *bufs = NULL; dt_strtab_t *strtab; + void *tmp; if ((fd = open64(obj, O_RDWR)) == -1) { return (dt_link_error(dtp, elf, fd, bufs, @@ -1463,7 +1464,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); + tmp = data_str->d_buf; data_str->d_buf = pair->dlp_str; + pair->dlp_str = tmp; data_str->d_size += len; (void) elf_flagdata(data_str, ELF_C_SET, ELF_F_DIRTY); @@ -1471,7 +1474,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); + tmp = data_sym->d_buf; data_sym->d_buf = pair->dlp_sym; + pair->dlp_sym = tmp; data_sym->d_size += nsym * symsize; (void) elf_flagdata(data_sym, ELF_C_SET, ELF_F_DIRTY); @@ -1657,9 +1662,6 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp) (void) elf_end(elf); (void) close(fd); -#ifndef illumos - if (nsym > 0) -#endif while ((pair = bufs) != NULL) { bufs = pair->dlp_next; dt_free(dtp, pair->dlp_str);