Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+16 −3
Original line number Diff line number Diff line
@@ -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;

@@ -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;
	}
+16 −3
Original line number Diff line number Diff line
@@ -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;

@@ -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;
	}