Commit 04211a57 authored by Paul Burton's avatar Paul Burton Committed by Ralf Baechle

MIPS: Bail on unsupported module relocs

When an unsupported reloc is encountered in a module, we currently
blindly branch to whatever would be at its entry in the reloc handler
function pointer arrays. This may be NULL, or if the unsupported reloc
has a type greater than that of the supported reloc with the highest
type then we'll dereference some value after the function pointer array
& branch to that. The result is at best a kernel oops.

Fix this by checking that the reloc type has an entry in the function
pointer array (ie. is less than the number of items in the array) and
that the handler is non-NULL, returning an error code to fail the module
load if no handler is found.
Signed-off-by: default avatarPaul Burton <paul.burton@imgtec.com>
Cc: James Hogan <james.hogan@imgtec.com>
Cc: Steven J. Hill <Steven.Hill@imgtec.com>
Cc: Andrey Ryabinin <ryabinin.a.a@gmail.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/12432/Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent f7f797cf
...@@ -109,9 +109,10 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, ...@@ -109,9 +109,10 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
struct module *me) struct module *me)
{ {
Elf_Mips_Rela *rel = (void *) sechdrs[relsec].sh_addr; Elf_Mips_Rela *rel = (void *) sechdrs[relsec].sh_addr;
int (*handler)(struct module *me, u32 *location, Elf_Addr v);
Elf_Sym *sym; Elf_Sym *sym;
u32 *location; u32 *location;
unsigned int i; unsigned int i, type;
Elf_Addr v; Elf_Addr v;
int res; int res;
...@@ -134,9 +135,21 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, ...@@ -134,9 +135,21 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
return -ENOENT; return -ENOENT;
} }
v = sym->st_value + rel[i].r_addend; type = ELF_MIPS_R_TYPE(rel[i]);
if (type < ARRAY_SIZE(reloc_handlers_rela))
handler = reloc_handlers_rela[type];
else
handler = NULL;
res = reloc_handlers_rela[ELF_MIPS_R_TYPE(rel[i])](me, location, v); if (!handler) {
pr_err("%s: Unknown relocation type %u\n",
me->name, type);
return -EINVAL;
}
v = sym->st_value + rel[i].r_addend;
res = handler(me, location, v);
if (res) if (res)
return res; return res;
} }
......
...@@ -197,9 +197,10 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, ...@@ -197,9 +197,10 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
struct module *me) struct module *me)
{ {
Elf_Mips_Rel *rel = (void *) sechdrs[relsec].sh_addr; Elf_Mips_Rel *rel = (void *) sechdrs[relsec].sh_addr;
int (*handler)(struct module *me, u32 *location, Elf_Addr v);
Elf_Sym *sym; Elf_Sym *sym;
u32 *location; u32 *location;
unsigned int i; unsigned int i, type;
Elf_Addr v; Elf_Addr v;
int res; int res;
...@@ -223,9 +224,21 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab, ...@@ -223,9 +224,21 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
return -ENOENT; return -ENOENT;
} }
v = sym->st_value; type = ELF_MIPS_R_TYPE(rel[i]);
if (type < ARRAY_SIZE(reloc_handlers_rel))
handler = reloc_handlers_rel[type];
else
handler = NULL;
res = reloc_handlers_rel[ELF_MIPS_R_TYPE(rel[i])](me, location, v); if (!handler) {
pr_err("%s: Unknown relocation type %u\n",
me->name, type);
return -EINVAL;
}
v = sym->st_value;
res = handler(me, location, v);
if (res) if (res)
return res; return res;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment