aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2017-02-05 02:44:08 +0000
committerMark Johnston <markj@FreeBSD.org>2017-02-05 02:44:08 +0000
commit273efb05a21a9b60088b887440fafa062837a392 (patch)
tree66376309890dd477ada06259c1de7a04abd69095
parente801af6fba428bbac170018f9ff69e4596d06b3b (diff)
downloadsrc-273efb05a21a9b60088b887440fafa062837a392.tar.gz
src-273efb05a21a9b60088b887440fafa062837a392.zip
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
Notes
Notes: svn path=/head/; revision=313263
-rw-r--r--cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c8
1 files 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);