summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Burton <paul.burton@imgtec.com>2016-02-04 08:05:02 -0500
committerRalf Baechle <ralf@linux-mips.org>2016-04-03 06:32:10 -0400
commit04211a574641e29b529dcc84e75c03d7e9e368cf (patch)
tree8acdcb1e2379f5707734460608a72b0d214ae831
parentf7f797cfc6c80a3505d1a316ee9aa3ec329289e9 (diff)
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: 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>
-rw-r--r--arch/mips/kernel/module-rela.c19
-rw-r--r--arch/mips/kernel/module.c19
2 files changed, 32 insertions, 6 deletions
diff --git a/arch/mips/kernel/module-rela.c b/arch/mips/kernel/module-rela.c
index 2b70723071c3..9083d63b765c 100644
--- a/arch/mips/kernel/module-rela.c
+++ b/arch/mips/kernel/module-rela.c
@@ -109,9 +109,10 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
109 struct module *me) 109 struct module *me)
110{ 110{
111 Elf_Mips_Rela *rel = (void *) sechdrs[relsec].sh_addr; 111 Elf_Mips_Rela *rel = (void *) sechdrs[relsec].sh_addr;
112 int (*handler)(struct module *me, u32 *location, Elf_Addr v);
112 Elf_Sym *sym; 113 Elf_Sym *sym;
113 u32 *location; 114 u32 *location;
114 unsigned int i; 115 unsigned int i, type;
115 Elf_Addr v; 116 Elf_Addr v;
116 int res; 117 int res;
117 118
@@ -134,9 +135,21 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
134 return -ENOENT; 135 return -ENOENT;
135 } 136 }
136 137
137 v = sym->st_value + rel[i].r_addend; 138 type = ELF_MIPS_R_TYPE(rel[i]);
139
140 if (type < ARRAY_SIZE(reloc_handlers_rela))
141 handler = reloc_handlers_rela[type];
142 else
143 handler = NULL;
138 144
139 res = reloc_handlers_rela[ELF_MIPS_R_TYPE(rel[i])](me, location, v); 145 if (!handler) {
146 pr_err("%s: Unknown relocation type %u\n",
147 me->name, type);
148 return -EINVAL;
149 }
150
151 v = sym->st_value + rel[i].r_addend;
152 res = handler(me, location, v);
140 if (res) 153 if (res)
141 return res; 154 return res;
142 } 155 }
diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c
index 1833f5171ccd..f9b2936d598d 100644
--- a/arch/mips/kernel/module.c
+++ b/arch/mips/kernel/module.c
@@ -197,9 +197,10 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
197 struct module *me) 197 struct module *me)
198{ 198{
199 Elf_Mips_Rel *rel = (void *) sechdrs[relsec].sh_addr; 199 Elf_Mips_Rel *rel = (void *) sechdrs[relsec].sh_addr;
200 int (*handler)(struct module *me, u32 *location, Elf_Addr v);
200 Elf_Sym *sym; 201 Elf_Sym *sym;
201 u32 *location; 202 u32 *location;
202 unsigned int i; 203 unsigned int i, type;
203 Elf_Addr v; 204 Elf_Addr v;
204 int res; 205 int res;
205 206
@@ -223,9 +224,21 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
223 return -ENOENT; 224 return -ENOENT;
224 } 225 }
225 226
226 v = sym->st_value; 227 type = ELF_MIPS_R_TYPE(rel[i]);
228
229 if (type < ARRAY_SIZE(reloc_handlers_rel))
230 handler = reloc_handlers_rel[type];
231 else
232 handler = NULL;
227 233
228 res = reloc_handlers_rel[ELF_MIPS_R_TYPE(rel[i])](me, location, v); 234 if (!handler) {
235 pr_err("%s: Unknown relocation type %u\n",
236 me->name, type);
237 return -EINVAL;
238 }
239
240 v = sym->st_value;
241 res = handler(me, location, v);
229 if (res) 242 if (res)
230 return res; 243 return res;
231 } 244 }