diff options
author | Paul Burton <paul.burton@imgtec.com> | 2017-03-30 11:37:44 -0700 |
---|---|---|
committer | Ben Hutchings <ben@decadent.org.uk> | 2017-10-12 15:27:53 +0100 |
commit | a7947e5ce90a59b948e61cc67e010dbb87d99983 (patch) | |
tree | 4e72ba66198a8ee4e668fc5653fffdf55d524662 /arch/mips | |
parent | 123a250fd59a2cf1d5ea56ae2399745df696276c (diff) |
MIPS: module: Ensure we always clean up r_mips_hi16_list
commit 351b0940d473146923711bc943fc881354a4c1f3 upstream.
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: 861667dc82f5 ("MIPS: Fix race condition in module relocation code.")
Fixes: 04211a574641 ("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>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/kernel/module.c | 28 |
1 files changed, 16 insertions, 12 deletions
diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c index d593fb331031..cd4c8412869d 100644 --- a/arch/mips/kernel/module.c +++ b/arch/mips/kernel/module.c @@ -202,7 +202,7 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, u32 *location; unsigned int i, type; Elf_Addr v; - int res; + int err = 0; pr_debug("Applying relocate section %u to %u\n", relsec, sechdrs[relsec].sh_info); @@ -221,7 +221,8 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, continue; printk(KERN_WARNING "%s: Unknown symbol %s\n", me->name, strtab + sym->st_name); - return -ENOENT; + err = -ENOENT; + goto out; } type = ELF_MIPS_R_TYPE(rel[i]); @@ -234,29 +235,32 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, if (!handler) { pr_err("%s: Unknown relocation type %u\n", me->name, type); - return -EINVAL; + err = -EINVAL; + goto out; } v = sym->st_value; - res = handler(me, location, v); - if (res) - return res; + err = handler(me, location, v); + if (err) + 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 - * relocations not followed by a R_MIPS_LO16 relocation. In that - * case, free up the list and return an error. + * relocations not followed by a R_MIPS_LO16 relocation, or if we hit + * 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) { free_relocation_chain(me->arch.r_mips_hi16_list); me->arch.r_mips_hi16_list = NULL; - - return -ENOEXEC; + err = err ?: -ENOEXEC; } - return 0; + return err; } /* Given an address, look for it in the module exception tables. */ |