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:
parent
e801af6fba
commit
273efb05a2
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=313263
@ -1205,6 +1205,7 @@ process_obj(dtrace_hdl_t *dtp, const char *obj, int *eprobesp)
|
|||||||
key_t objkey;
|
key_t objkey;
|
||||||
dt_link_pair_t *pair, *bufs = NULL;
|
dt_link_pair_t *pair, *bufs = NULL;
|
||||||
dt_strtab_t *strtab;
|
dt_strtab_t *strtab;
|
||||||
|
void *tmp;
|
||||||
|
|
||||||
if ((fd = open64(obj, O_RDWR)) == -1) {
|
if ((fd = open64(obj, O_RDWR)) == -1) {
|
||||||
return (dt_link_error(dtp, elf, fd, bufs,
|
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;
|
bufs = pair;
|
||||||
|
|
||||||
bcopy(data_str->d_buf, pair->dlp_str, data_str->d_size);
|
bcopy(data_str->d_buf, pair->dlp_str, data_str->d_size);
|
||||||
|
tmp = data_str->d_buf;
|
||||||
data_str->d_buf = pair->dlp_str;
|
data_str->d_buf = pair->dlp_str;
|
||||||
|
pair->dlp_str = tmp;
|
||||||
data_str->d_size += len;
|
data_str->d_size += len;
|
||||||
(void) elf_flagdata(data_str, ELF_C_SET, ELF_F_DIRTY);
|
(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);
|
(void) gelf_update_shdr(scn_str, &shdr_str);
|
||||||
|
|
||||||
bcopy(data_sym->d_buf, pair->dlp_sym, data_sym->d_size);
|
bcopy(data_sym->d_buf, pair->dlp_sym, data_sym->d_size);
|
||||||
|
tmp = data_sym->d_buf;
|
||||||
data_sym->d_buf = pair->dlp_sym;
|
data_sym->d_buf = pair->dlp_sym;
|
||||||
|
pair->dlp_sym = tmp;
|
||||||
data_sym->d_size += nsym * symsize;
|
data_sym->d_size += nsym * symsize;
|
||||||
(void) elf_flagdata(data_sym, ELF_C_SET, ELF_F_DIRTY);
|
(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) elf_end(elf);
|
||||||
(void) close(fd);
|
(void) close(fd);
|
||||||
|
|
||||||
#ifndef illumos
|
|
||||||
if (nsym > 0)
|
|
||||||
#endif
|
|
||||||
while ((pair = bufs) != NULL) {
|
while ((pair = bufs) != NULL) {
|
||||||
bufs = pair->dlp_next;
|
bufs = pair->dlp_next;
|
||||||
dt_free(dtp, pair->dlp_str);
|
dt_free(dtp, pair->dlp_str);
|
||||||
|
Loading…
Reference in New Issue
Block a user