Skip to content

Commit eda9cec

Browse files
jpoimboeIngo Molnar
authored andcommitted
x86/module: Detect and skip invalid relocations
There have been some cases where external tooling (e.g., kpatch-build) creates a corrupt relocation which targets the wrong address. This is a silent failure which can corrupt memory in unexpected places. On x86, the bytes of data being overwritten by relocations are always initialized to zero beforehand. Use that knowledge to add sanity checks to detect such cases before they corrupt memory. Signed-off-by: Josh Poimboeuf <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: [email protected] Cc: [email protected] Link: http://lkml.kernel.org/r/37450d6c6225e54db107fba447ce9e56e5f758e9.1509713553.git.jpoimboe@redhat.com [ Restructured the messages, as it's unclear whether the relocation or the target is corrupted. ] Signed-off-by: Ingo Molnar <[email protected]>
1 parent 6753573 commit eda9cec

File tree

1 file changed

+13
-0
lines changed

1 file changed

+13
-0
lines changed

arch/x86/kernel/module.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,19 +172,27 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
172172
case R_X86_64_NONE:
173173
break;
174174
case R_X86_64_64:
175+
if (*(u64 *)loc != 0)
176+
goto invalid_relocation;
175177
*(u64 *)loc = val;
176178
break;
177179
case R_X86_64_32:
180+
if (*(u32 *)loc != 0)
181+
goto invalid_relocation;
178182
*(u32 *)loc = val;
179183
if (val != *(u32 *)loc)
180184
goto overflow;
181185
break;
182186
case R_X86_64_32S:
187+
if (*(s32 *)loc != 0)
188+
goto invalid_relocation;
183189
*(s32 *)loc = val;
184190
if ((s64)val != *(s32 *)loc)
185191
goto overflow;
186192
break;
187193
case R_X86_64_PC32:
194+
if (*(u32 *)loc != 0)
195+
goto invalid_relocation;
188196
val -= (u64)loc;
189197
*(u32 *)loc = val;
190198
#if 0
@@ -200,6 +208,11 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
200208
}
201209
return 0;
202210

211+
invalid_relocation:
212+
pr_err("x86/modules: Skipping invalid relocation target, existing value is nonzero for type %d, loc %p, val %Lx\n",
213+
(int)ELF64_R_TYPE(rel[i].r_info), loc, val);
214+
return -ENOEXEC;
215+
203216
overflow:
204217
pr_err("overflow in relocation type %d val %Lx\n",
205218
(int)ELF64_R_TYPE(rel[i].r_info), val);

0 commit comments

Comments
 (0)