MIPS: module: Ensure we always clean up r_mips_hi16_list

If we hit an error whilst processing a reloc then we would return early
from apply_relocate & potentially not free entries in r_mips_hi16_list,
thereby leaking memory. Fix this by ensuring that we always run the code
to free r_mipps_hi16_list when errors occur.

Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Fixes: 861667dc82 ("MIPS: Fix race condition in module relocation code.")
Fixes: 04211a5746 ("MIPS: Bail on unsupported module relocs")
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/15831/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
Paul Burton 2017-03-30 11:37:44 -07:00 коммит произвёл Ralf Baechle
Родитель 59baa24d87
Коммит 351b0940d4
1 изменённых файлов: 16 добавлений и 12 удалений

Просмотреть файл

@ -251,7 +251,7 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
u32 *location; u32 *location;
unsigned int i, type; unsigned int i, type;
Elf_Addr v; Elf_Addr v;
int res; int err = 0;
pr_debug("Applying relocate section %u to %u\n", relsec, pr_debug("Applying relocate section %u to %u\n", relsec,
sechdrs[relsec].sh_info); sechdrs[relsec].sh_info);
@ -270,7 +270,8 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
continue; continue;
pr_warn("%s: Unknown symbol %s\n", pr_warn("%s: Unknown symbol %s\n",
me->name, strtab + sym->st_name); me->name, strtab + sym->st_name);
return -ENOENT; err = -ENOENT;
goto out;
} }
type = ELF_MIPS_R_TYPE(rel[i]); type = ELF_MIPS_R_TYPE(rel[i]);
@ -283,29 +284,32 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
if (!handler) { if (!handler) {
pr_err("%s: Unknown relocation type %u\n", pr_err("%s: Unknown relocation type %u\n",
me->name, type); me->name, type);
return -EINVAL; err = -EINVAL;
goto out;
} }
v = sym->st_value; v = sym->st_value;
res = handler(me, location, v); err = handler(me, location, v);
if (res) if (err)
return res; goto out;
} }
out:
/* /*
* Normally the hi16 list should be deallocated at this point. A * Normally the hi16 list should be deallocated at this point. A
* malformed binary however could contain a series of R_MIPS_HI16 * malformed binary however could contain a series of R_MIPS_HI16
* relocations not followed by a R_MIPS_LO16 relocation. In that * relocations not followed by a R_MIPS_LO16 relocation, or if we hit
* case, free up the list and return an error. * an error processing a reloc we might have gotten here before
* reaching the R_MIPS_LO16. In either case, free up the list and
* return an error.
*/ */
if (me->arch.r_mips_hi16_list) { if (me->arch.r_mips_hi16_list) {
free_relocation_chain(me->arch.r_mips_hi16_list); free_relocation_chain(me->arch.r_mips_hi16_list);
me->arch.r_mips_hi16_list = NULL; me->arch.r_mips_hi16_list = NULL;
err = err ?: -ENOEXEC;
return -ENOEXEC;
} }
return 0; return err;
} }
/* Given an address, look for it in the module exception tables. */ /* Given an address, look for it in the module exception tables. */