syscare/0032-upatch-diff-fix-memory-leak.patch

612 lines
18 KiB
Diff
Raw Normal View History

From e6eef4077acbff6e43e3c3880fb57d64b73e2567 Mon Sep 17 00:00:00 2001
From: liuxiaobo <liuxiaobo19@huawei.com>
Date: Thu, 27 Jun 2024 14:22:53 +0800
Subject: [PATCH] upatch-diff: fix memory leak
Signed-off-by: liuxiaobo <liuxiaobo19@huawei.com>
---
upatch-diff/create-diff-object.c | 34 +++++---
upatch-diff/elf-correlate.c | 10 +--
upatch-diff/elf-create.c | 83 ++++++++++++--------
upatch-diff/elf-debug.c | 7 +-
upatch-diff/running-elf.c | 2 +-
upatch-diff/running-elf.h | 2 +-
upatch-diff/upatch-elf.c | 128 ++++++++++++++++++++++---------
upatch-diff/upatch-elf.h | 14 +++-
8 files changed, 191 insertions(+), 89 deletions(-)
diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c
index 5ec6f31..8830956 100644
--- a/upatch-diff/create-diff-object.c
+++ b/upatch-diff/create-diff-object.c
@@ -836,8 +836,10 @@ static void include_debug_sections(struct upatch_elf *uelf)
list_for_each_entry_safe(rela, saferela, &sec->relas, list)
// The shndex of symbol is SHN_COMMON, there is no related section
- if (rela->sym && !rela->sym->include)
+ if (rela->sym && !rela->sym->include) {
list_del(&rela->list);
+ free(rela);
+ }
}
if (eh_sec)
@@ -993,15 +995,20 @@ int main(int argc, char*argv[])
mark_ignored_functions_same();
mark_ignored_sections_same();
- upatch_elf_teardown(&uelf_source);
- upatch_elf_free(&uelf_source);
-
include_standard_elements(&uelf_patched);
num_changed = include_changed_functions(&uelf_patched);
new_globals_exist = include_new_globals(&uelf_patched);
if (!num_changed && !new_globals_exist) {
log_normal("No functional changes\n");
+ upatch_elf_destroy(&uelf_source);
+ upatch_elf_destroy(&uelf_patched);
+
+ upatch_elf_close(&uelf_source);
+ upatch_elf_close(&uelf_patched);
+
+ relf_close(&relf);
+
return 0;
}
@@ -1019,9 +1026,6 @@ int main(int argc, char*argv[])
migrate_included_elements(&uelf_patched, &uelf_out);
- /* since out elf still point to it, we only destroy it, not free it */
- upatch_elf_teardown(&uelf_patched);
-
upatch_create_strings_elements(&uelf_out);
upatch_create_patches_sections(&uelf_out, &relf);
@@ -1060,11 +1064,19 @@ int main(int argc, char*argv[])
upatch_write_output_elf(&uelf_out, uelf_patched.elf, arguments.output_obj, 0664);
- relf_destroy(&relf);
- upatch_elf_free(&uelf_patched);
- upatch_elf_teardown(&uelf_out);
- upatch_elf_free(&uelf_out);
+ upatch_elf_destroy(&uelf_source);
+ upatch_elf_destroy(&uelf_patched);
+ upatch_elf_destroy(&uelf_out);
+
+ upatch_elf_close(&uelf_source);
+ upatch_elf_close(&uelf_patched);
+ upatch_elf_close(&uelf_out);
+
+ relf_close(&relf);
log_normal("Done\n");
+ fflush(stdout);
+ fflush(stderr);
+
return 0;
}
diff --git a/upatch-diff/elf-correlate.c b/upatch-diff/elf-correlate.c
index 3e3a536..cc3b925 100644
--- a/upatch-diff/elf-correlate.c
+++ b/upatch-diff/elf-correlate.c
@@ -36,9 +36,8 @@ static void correlate_symbol(struct symbol *sym_orig, struct symbol *sym_patched
sym_orig->status = sym_patched->status = SAME;
if (strcmp(sym_orig->name, sym_patched->name)) {
log_debug("renaming symbol %s to %s \n", sym_patched->name, sym_orig->name);
- sym_patched->name = strdup(sym_orig->name);
- if (!sym_patched->name)
- ERROR("strdup");
+ sym_patched->name = sym_orig->name;
+ sym_patched->name_source = DATA_SOURCE_REF;
}
if (sym_orig->relf_sym && !sym_patched->relf_sym)
sym_patched->relf_sym = sym_orig->relf_sym;
@@ -98,9 +97,8 @@ static void __correlate_section(struct section *sec_orig, struct section *sec_pa
/* Make sure these two sections have the same name */
if (strcmp(sec_orig->name, sec_patched->name)) {
log_debug("renaming section %s to %s \n", sec_patched->name, sec_orig->name);
- sec_patched->name = strdup(sec_orig->name);
- if (!sec_patched->name)
- ERROR("strdup");
+ sec_patched->name = sec_orig->name;
+ sec_patched->name_source = DATA_SOURCE_REF;
}
}
diff --git a/upatch-diff/elf-create.c b/upatch-diff/elf-create.c
index 8ac212a..bd7edf0 100644
--- a/upatch-diff/elf-create.c
+++ b/upatch-diff/elf-create.c
@@ -41,10 +41,12 @@ static struct section *create_section_pair(struct upatch_elf *uelf, char *name,
{
char *relaname;
struct section *sec, *relasec;
+ size_t size = strlen(name) + strlen(".rela") + 1;
- relaname = malloc(strlen(name) + strlen(".rela") + 1);
- if (!relaname)
+ relaname = calloc(1, size);
+ if (!relaname) {
ERROR("relaname malloc failed.");
+ }
strcpy(relaname, ".rela");
strcat(relaname, name);
@@ -52,13 +54,17 @@ static struct section *create_section_pair(struct upatch_elf *uelf, char *name,
/* allocate text section resourcce */
ALLOC_LINK(sec, &uelf->sections);
sec->name = name;
- sec->data = malloc(sizeof(*sec->data));
- if (!sec->data)
+ sec->data = calloc(1, sizeof(Elf_Data));
+ if (!sec->data) {
ERROR("section data malloc failed.");
+ }
+ sec->data_source = DATA_SOURCE_ALLOC;
sec->data->d_buf = calloc(nr, entsize);
- if (!sec->data->d_buf)
+ if (!sec->data->d_buf) {
ERROR("d_buf of section data malloc failed.");
+ }
+ sec->dbuf_source = DATA_SOURCE_ALLOC;
sec->data->d_size = entsize * nr;
sec->data->d_type = ELF_T_BYTE;
@@ -73,12 +79,15 @@ static struct section *create_section_pair(struct upatch_elf *uelf, char *name,
/* set relocation section */
ALLOC_LINK(relasec, &uelf->sections);
relasec->name = relaname;
+ relasec->name_source = DATA_SOURCE_ALLOC;
INIT_LIST_HEAD(&relasec->relas);
/* buffers will be generated by upatch_rebuild_rela_section_data */
- relasec->data = malloc(sizeof(*relasec->data));
- if (!relasec->data)
+ relasec->data = calloc(1, sizeof(Elf_Data));
+ if (!relasec->data) {
ERROR("relasec data malloc failed.");
+ }
+ relasec->data_source = DATA_SOURCE_ALLOC;
relasec->data->d_type = ELF_T_RELA;
@@ -103,9 +112,12 @@ void upatch_create_strings_elements(struct upatch_elf *uelf)
ALLOC_LINK(sec, &uelf->sections);
sec->name = ".upatch.strings";
- sec->data = malloc(sizeof(*sec->data));
- if (!sec->data)
+ sec->data = calloc(1, sizeof(Elf_Data));
+ if (!sec->data) {
ERROR("section data malloc failed");
+ }
+ sec->data_source = DATA_SOURCE_ALLOC;
+
sec->data->d_type = ELF_T_BYTE;
/* set section header */
@@ -310,12 +322,14 @@ void upatch_build_strings_section_data(struct upatch_elf *uelf)
size += strlen(string->name) + 1;
/* allocate section resources */
- strtab = malloc(size);
- if (!strtab)
+ strtab = calloc(1, size);
+ if (!strtab) {
ERROR("strtab malloc failed.");
+ }
sec->data->d_buf = strtab;
sec->data->d_size = size;
+ sec->dbuf_source = DATA_SOURCE_ALLOC;
/* populate strings section data */
list_for_each_entry(string, &uelf->strings, list) {
@@ -407,13 +421,15 @@ static void rebuild_rela_section_data(struct section *sec)
nr++;
size = nr * sizeof(*relas);
- relas = malloc(size);
- if (!relas)
+ relas = calloc(1, size);
+ if (!relas) {
ERROR("relas malloc failed.");
+ }
sec->data->d_buf = relas;
sec->data->d_size = size;
sec->sh.sh_size = size;
+ sec->dbuf_source = DATA_SOURCE_ALLOC;
list_for_each_entry(rela, &sec->relas, list) {
relas[index].r_offset = rela->offset;
@@ -469,18 +485,19 @@ void upatch_create_shstrtab(struct upatch_elf *uelf)
char *buf;
shstrtab = find_section_by_name(&uelf->sections, ".shstrtab");
- if (!shstrtab)
+ if (!shstrtab) {
ERROR("find_section_by_name failed.");
+ }
/* determine size of string table */
size = 1;
list_for_each_entry(sec, &uelf->sections, list)
size += strlen(sec->name) + 1;
- buf = malloc(size);
- if (!buf)
+ buf = calloc(1, size);
+ if (!buf) {
ERROR("malloc shstrtab failed.");
- memset(buf, 0, size);
+ }
offset = 1;
list_for_each_entry(sec, &uelf->sections, list) {
@@ -490,11 +507,14 @@ void upatch_create_shstrtab(struct upatch_elf *uelf)
offset += len;
}
- if (offset != size)
+ if (offset != size) {
+ free(buf);
ERROR("shstrtab size mismatch.");
+ }
shstrtab->data->d_buf = buf;
shstrtab->data->d_size = size;
+ shstrtab->dbuf_source = DATA_SOURCE_ALLOC;
log_debug("shstrtab: ");
print_strtab(buf, size);
@@ -506,25 +526,24 @@ void upatch_create_shstrtab(struct upatch_elf *uelf)
void upatch_create_strtab(struct upatch_elf *uelf)
{
- struct section *strtab;
- struct symbol *sym;
size_t size = 0, offset = 0, len = 0;
- char *buf;
- strtab = find_section_by_name(&uelf->sections, ".strtab");
- if (!strtab)
+ struct section *strtab = find_section_by_name(&uelf->sections, ".strtab");
+ if (!strtab) {
ERROR("find section failed in create strtab.");
+ }
+ struct symbol *sym = NULL;
list_for_each_entry(sym, &uelf->symbols, list) {
if (sym->type == STT_SECTION)
continue;
size += strlen(sym->name) + 1;
}
- buf = malloc(size);
- if (!buf)
+ char *buf = calloc(1, size);
+ if (!buf) {
ERROR("malloc buf failed in create strtab");
- memset(buf, 0, size);
+ }
list_for_each_entry(sym, &uelf->symbols, list) {
if (sym->type == STT_SECTION) {
@@ -537,11 +556,14 @@ void upatch_create_strtab(struct upatch_elf *uelf)
offset += len;
}
- if (offset != size)
+ if (offset != size) {
+ free(buf);
ERROR("shstrtab size mismatch.");
+ }
strtab->data->d_buf = buf;
strtab->data->d_size = size;
+ strtab->dbuf_source = DATA_SOURCE_ALLOC;
log_debug("strtab: ");
print_strtab(buf, size);
@@ -569,10 +591,10 @@ void upatch_create_symtab(struct upatch_elf *uelf)
nr++;
size = nr * symtab->sh.sh_entsize;
- buf = malloc(size);
- if (!buf)
+ buf = calloc(1, size);
+ if (!buf) {
ERROR("malloc buf failed in create symtab.");
- memset(buf, 0, size);
+ }
offset = 0;
list_for_each_entry(sym, &uelf->symbols, list) {
@@ -585,6 +607,7 @@ void upatch_create_symtab(struct upatch_elf *uelf)
symtab->data->d_buf = buf;
symtab->data->d_size = size;
+ symtab->dbuf_source = DATA_SOURCE_ALLOC;
/* update symtab section header */
strtab = find_section_by_name(&uelf->sections, ".strtab");
diff --git a/upatch-diff/elf-debug.c b/upatch-diff/elf-debug.c
index eaabfa1..0490f86 100644
--- a/upatch-diff/elf-debug.c
+++ b/upatch-diff/elf-debug.c
@@ -129,9 +129,10 @@ void upatch_rebuild_eh_frame(struct section *sec)
/* in this time, some relcation entries may have been deleted */
frame_size = 0;
- eh_frame = malloc(sec->data->d_size);
- if (!eh_frame)
+ eh_frame = calloc(1, sec->data->d_size);
+ if (!eh_frame) {
ERROR("malloc eh_frame failed \n");
+ }
/* 8 is the offset of PC begin */
current_offset = 8;
@@ -191,5 +192,7 @@ void upatch_rebuild_eh_frame(struct section *sec)
sec->data->d_buf = eh_frame;
sec->data->d_size = frame_size;
+ sec->dbuf_source = DATA_SOURCE_ALLOC;
+
sec->sh.sh_size = frame_size;
}
diff --git a/upatch-diff/running-elf.c b/upatch-diff/running-elf.c
index 18ff095..c99b395 100644
--- a/upatch-diff/running-elf.c
+++ b/upatch-diff/running-elf.c
@@ -101,7 +101,7 @@ void relf_init(char *elf_name, struct running_elf *relf)
}
}
-int relf_destroy(struct running_elf *relf)
+int relf_close(struct running_elf *relf)
{
free(relf->obj_syms);
elf_end(relf->elf);
diff --git a/upatch-diff/running-elf.h b/upatch-diff/running-elf.h
index 0646780..b02c8e2 100644
--- a/upatch-diff/running-elf.h
+++ b/upatch-diff/running-elf.h
@@ -58,7 +58,7 @@ struct running_elf {
void relf_init(char *, struct running_elf *);
-int relf_destroy(struct running_elf *);
+int relf_close(struct running_elf *);
bool lookup_relf(struct running_elf *, struct symbol *, struct lookup_result *);
diff --git a/upatch-diff/upatch-elf.c b/upatch-diff/upatch-elf.c
index ee38efc..171e88e 100644
--- a/upatch-diff/upatch-elf.c
+++ b/upatch-diff/upatch-elf.c
@@ -67,11 +67,14 @@ static void create_section_list(struct upatch_elf *uelf)
sec->name = elf_strptr(uelf->elf, shstrndx, sec->sh.sh_name);
if (!sec->name)
ERROR("elf_strptr with error %s", elf_errmsg(0));
-
sec->data = elf_getdata(scn, NULL);
if (!sec->data)
ERROR("elf_getdata with error %s", elf_errmsg(0));
+ sec->name_source = DATA_SOURCE_ELF;
+ sec->data_source = DATA_SOURCE_ELF;
+ sec->dbuf_source = DATA_SOURCE_ELF;
+
sec->index = (unsigned int)elf_ndxscn(scn);
/* found extended section header */
if (sec->sh.sh_type == SHT_SYMTAB_SHNDX)
@@ -157,6 +160,8 @@ static void create_rela_list(struct upatch_elf *uelf, struct section *relasec)
struct rela *rela;
int index = 0, skip = 0;
+ INIT_LIST_HEAD(&relasec->relas);
+
/* for relocation sections, sh_info is the index which these informations apply */
relasec->base = find_section_by_index(&uelf->sections, relasec->sh.sh_info);
if (!relasec->base)
@@ -215,10 +220,86 @@ static void create_rela_list(struct upatch_elf *uelf, struct section *relasec)
}
}
+static void destroy_rela_list(struct section *relasec)
+{
+ struct rela *rela = NULL, *saferela = NULL;
+
+ list_for_each_entry_safe(rela, saferela, &relasec->relas, list) {
+ list_del(&rela->list);
+ free(rela);
+ }
+
+ INIT_LIST_HEAD(&relasec->relas);
+}
+
+static void destroy_section_list(struct upatch_elf *uelf)
+{
+ struct section *sec = NULL, *safesec = NULL;
+
+ list_for_each_entry_safe(sec, safesec, &uelf->sections, list) {
+ if (sec->twin) {
+ sec->twin->twin = NULL;
+ }
+
+ if ((sec->name != NULL) && (sec->name_source == DATA_SOURCE_ALLOC)) {
+ free(sec->name);
+ sec->name = NULL;
+ }
+
+ if (sec->data != NULL) {
+ if (sec->dbuf_source == DATA_SOURCE_ALLOC) {
+ free(sec->data->d_buf);
+ sec->data->d_buf = NULL;
+ }
+ if (sec->data_source == DATA_SOURCE_ALLOC) {
+ free(sec->data);
+ sec->data = NULL;
+ }
+ }
+
+ if (is_rela_section(sec)) {
+ destroy_rela_list(sec);
+ }
+
+ list_del(&sec->list);
+ free(sec);
+ }
+
+ INIT_LIST_HEAD(&uelf->sections);
+}
+
+static void destroy_symbol_list(struct upatch_elf *uelf)
+{
+ struct symbol *sym = NULL, *safesym = NULL;
+
+ list_for_each_entry_safe(sym, safesym, &uelf->symbols, list) {
+ if (sym->twin) {
+ sym->twin->twin = NULL;
+ }
+
+ list_del(&sym->list);
+ free(sym);
+ }
+
+ INIT_LIST_HEAD(&uelf->symbols);
+}
+
+static void destroy_string_list(struct upatch_elf *uelf)
+{
+ struct string *str = NULL, *safestr = NULL;
+
+ list_for_each_entry_safe(str, safestr, &uelf->strings, list) {
+ list_del(&str->list);
+ free(str);
+ }
+
+ INIT_LIST_HEAD(&uelf->strings);
+}
+
void upatch_elf_open(struct upatch_elf *uelf, const char *name)
{
GElf_Ehdr ehdr;
- struct section *relasec;
+ struct section *sec;
Elf *elf = NULL;
int fd = 1;
@@ -264,46 +345,21 @@ void upatch_elf_open(struct upatch_elf *uelf, const char *name)
create_section_list(uelf);
create_symbol_list(uelf);
- list_for_each_entry(relasec, &uelf->sections, list) {
- if (!is_rela_section(relasec))
- continue;
- INIT_LIST_HEAD(&relasec->relas);
-
- create_rela_list(uelf, relasec);
- }
-}
-
-void upatch_elf_teardown(struct upatch_elf *uelf)
-{
- struct section *sec, *safesec;
- struct symbol *sym, *safesym;
- struct rela *rela, *saferela;
-
- list_for_each_entry_safe(sec, safesec, &uelf->sections, list) {
- if (sec->twin)
- sec->twin->twin = NULL;
+ list_for_each_entry(sec, &uelf->sections, list) {
if (is_rela_section(sec)) {
- list_for_each_entry_safe(rela, saferela, &sec->relas, list) {
- memset(rela, 0, sizeof(*rela));
- free(rela);
- }
+ create_rela_list(uelf, sec);
}
- memset(sec, 0, sizeof(*sec));
- free(sec);
- }
-
- list_for_each_entry_safe(sym, safesym, &uelf->symbols, list) {
- if (sym->twin)
- sym->twin->twin = NULL;
- memset(sym, 0, sizeof(*sym));
- free(sym);
}
+}
- INIT_LIST_HEAD(&uelf->sections);
- INIT_LIST_HEAD(&uelf->symbols);
+void upatch_elf_destroy(struct upatch_elf *uelf)
+{
+ destroy_section_list(uelf);
+ destroy_symbol_list(uelf);
+ destroy_string_list(uelf);
}
-void upatch_elf_free(struct upatch_elf *uelf)
+void upatch_elf_close(struct upatch_elf *uelf)
{
elf_end(uelf->elf);
close(uelf->fd);
diff --git a/upatch-diff/upatch-elf.h b/upatch-diff/upatch-elf.h
index 3cbb59b..6c62c93 100644
--- a/upatch-diff/upatch-elf.h
+++ b/upatch-diff/upatch-elf.h
@@ -39,6 +39,12 @@ struct section;
struct rela;
struct symbol;
+enum data_source {
+ DATA_SOURCE_ELF,
+ DATA_SOURCE_REF,
+ DATA_SOURCE_ALLOC,
+};
+
enum status {
NEW,
CHANGED,
@@ -61,6 +67,9 @@ struct section {
struct section *twin;
char *name;
Elf_Data *data;
+ enum data_source name_source;
+ enum data_source data_source;
+ enum data_source dbuf_source;
GElf_Shdr sh;
int ignore;
int include;
@@ -102,6 +111,7 @@ struct symbol {
struct section *sec;
GElf_Sym sym;
char *name;
+ enum data_source name_source;
struct debug_symbol *relf_sym;
unsigned int index;
unsigned char bind;
@@ -132,8 +142,8 @@ struct upatch_elf {
void upatch_elf_open(struct upatch_elf *, const char *);
// Destory upatch_elf struct
-void upatch_elf_teardown(struct upatch_elf *);
+void upatch_elf_destroy(struct upatch_elf *);
-void upatch_elf_free(struct upatch_elf *);
+void upatch_elf_close(struct upatch_elf *);
#endif
--
2.34.1