Skip to content

Commit

Permalink
[squash] livepatch/klp-convert: fix remaining memory leaks
Browse files Browse the repository at this point in the history
Note: squash with ("livepatch: Add klp-convert tool")

As discovered by running valgrind --leak-check=full --track-origins=yes
against the livepatch sample and selftest modules.

I didn't capture all of the valgrind output to correlate to specific
fixes, but suffice to say that valgrind output is now happy reporting
"0 bytes in 0 blocks in use at exit" in its HEAP SUMMARY.

[joe: fix remaining valgrind leak complaints (non-error paths only)]

Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
  • Loading branch information
joe-lawrence committed Mar 18, 2019
1 parent 4e5f39e commit ad76819
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 15 deletions.
99 changes: 84 additions & 15 deletions scripts/livepatch/elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,18 @@ static int update_shstrtab(struct elf *elf)
shstrtab->elf_data->d_size = shstrtab->size = new_size;
shstrtab->sh.sh_size = new_size;

return 0;
return 1;
}

static void free_shstrtab(struct elf *elf)
{
struct section *shstrtab;

shstrtab = find_section_by_name(elf, ".shstrtab");
if (!shstrtab)
return;

free(shstrtab->elf_data->d_buf);
}

static int update_strtab(struct elf *elf)
Expand Down Expand Up @@ -399,7 +410,19 @@ static int update_strtab(struct elf *elf)
strtab->elf_data->d_size = strtab->size = new_size;
strtab->sh.sh_size = new_size;

return 0;
return 1;
}

static void free_strtab(struct elf *elf)
{
struct section *strtab;

strtab = find_section_by_name(elf, ".strtab");
if (!strtab)
return;

if (strtab->elf_data)
free(strtab->elf_data->d_buf);
}

static int update_symtab(struct elf *elf)
Expand Down Expand Up @@ -455,7 +478,18 @@ static int update_symtab(struct elf *elf)
/* update symtab section header */
symtab->sh.sh_info = nr_locals;

return 0;
return 1;
}

static void free_symtab(struct elf *elf)
{
struct section *symtab;

symtab = find_section_by_name(elf, ".symtab");
if (!symtab)
return;

free(symtab->elf_data->d_buf);
}

static int update_relas(struct elf *elf)
Expand Down Expand Up @@ -500,7 +534,23 @@ static int update_relas(struct elf *elf)
}
}

return 0;
return 1;
}

static void free_relas(struct elf *elf)
{
struct section *sec, *symtab;

symtab = find_section_by_name(elf, ".symtab");
if (!symtab)
return;

list_for_each_entry(sec, &elf->sections, list) {
if (!is_rela_section(sec))
continue;

free(sec->elf_data->d_buf);
}
}

static int write_file(struct elf *elf, const char *file)
Expand Down Expand Up @@ -595,30 +645,49 @@ static int write_file(struct elf *elf, const char *file)
return -1;
}

elf_end(e);

return 0;
}

int elf_write_file(struct elf *elf, const char *file)
{
int ret_shstrtab;
int ret_strtab;
int ret_symtab;
int ret_relas;
int ret;

ret = update_shstrtab(elf);
if (ret)
return ret;
ret_shstrtab = update_shstrtab(elf);
if (ret_shstrtab < 0)
return ret_shstrtab;

ret = update_strtab(elf);
if (ret)
return ret;
ret_strtab = update_strtab(elf);
if (ret_strtab < 0)
return ret_strtab;

ret = update_symtab(elf);
if (ret)
return ret;
ret_symtab = update_symtab(elf);
if (ret_symtab < 0)
return ret_symtab;

ret_relas = update_relas(elf);
if (ret_relas < 0)
return ret_relas;

ret = update_relas(elf);
ret = write_file(elf, file);
if (ret)
return ret;

return write_file(elf, file);
if (ret_relas > 0)
free_relas(elf);
if (ret_symtab > 0)
free_symtab(elf);
if (ret_strtab > 0)
free_strtab(elf);
if (ret_shstrtab > 0)
free_shstrtab(elf);

return 0;
}

struct elf *elf_open(const char *name)
Expand Down
42 changes: 42 additions & 0 deletions scripts/livepatch/klp-convert.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ static bool load_syms_lists(const char *symbols_list)
}

len = 0;
free(sym);
sym = NULL;

/* read file */
Expand Down Expand Up @@ -192,6 +193,12 @@ static void clear_sympos_annontations(struct elf *klp_elf)
continue;
}
if (strncmp(sec->name, ".rela.klp.module_relocs.", 24) == 0) {

struct rela *rela, *tmprela;
list_for_each_entry_safe(rela, tmprela, &sec->relas, list) {
list_del(&rela->list);
free(rela);
}
list_del(&sec->list);
free(sec);
continue;
Expand Down Expand Up @@ -565,6 +572,38 @@ static bool must_convert(struct symbol *sym)
return (!(is_converted(sym->name) || is_exported(sym->name)));
}

/* Checks if a section is a klp rela section */
static bool is_klp_rela_section(char *sname)
{
int len = strlen(KLP_RELA_PREFIX);

if (strncmp(sname, KLP_RELA_PREFIX, len) == 0)
return true;
return false;
}

/*
* Frees the new names and rela sections as created by convert_rela()
*/
static void free_converted_resources(struct elf *klp_elf)
{
struct symbol *sym;
struct section *sec;

list_for_each_entry(sym, &klp_elf->symbols, list) {
if (sym->name && is_converted(sym->name)) {
free(sym->name);
}
}

list_for_each_entry(sec, &klp_elf->sections, list) {
if (is_klp_rela_section(sec->name)) {
free(sec->elf_data);
free(sec->name);
}
}
}

int main(int argc, const char **argv)
{
const char *klp_in_module, *klp_out_module, *symbols_list;
Expand Down Expand Up @@ -619,6 +658,9 @@ int main(int argc, const char **argv)
if (elf_write_file(klp_elf, klp_out_module))
return -1;

free_converted_resources(klp_elf);
elf_close(klp_elf);

return 0;
}

Expand Down

0 comments on commit ad76819

Please sign in to comment.