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
This commit is contained in:
Mark Johnston 2017-02-05 02:44:08 +00:00
parent e801af6fba
commit 273efb05a2
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=313263

View File

@ -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);