Skip to content

Commit

Permalink
MIPS: Bail on unsupported module relocs
Browse files Browse the repository at this point in the history
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: Paul 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: Ralf Baechle <ralf@linux-mips.org>
  • Loading branch information
Paul Burton authored and Ralf Baechle committed Apr 3, 2016
1 parent f7f797c commit 04211a5
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 6 deletions.
19 changes: 16 additions & 3 deletions arch/mips/kernel/module-rela.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,10 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
struct module *me)
{
Elf_Mips_Rela *rel = (void *) sechdrs[relsec].sh_addr;
int (*handler)(struct module *me, u32 *location, Elf_Addr v);
Elf_Sym *sym;
u32 *location;
unsigned int i;
unsigned int i, type;
Elf_Addr v;
int res;

Expand All @@ -134,9 +135,21 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
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)
return res;
}
Expand Down
19 changes: 16 additions & 3 deletions arch/mips/kernel/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,10 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
struct module *me)
{
Elf_Mips_Rel *rel = (void *) sechdrs[relsec].sh_addr;
int (*handler)(struct module *me, u32 *location, Elf_Addr v);
Elf_Sym *sym;
u32 *location;
unsigned int i;
unsigned int i, type;
Elf_Addr v;
int res;

Expand All @@ -223,9 +224,21 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
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)
return res;
}
Expand Down

0 comments on commit 04211a5

Please sign in to comment.