Skip to content

Commit 88fc078

Browse files
Peter ZijlstraJiri Kosina
authored andcommitted
x86/module: Use text_poke() for late relocations
Because of late module patching, a livepatch module needs to be able to apply some of its relocations well after it has been loaded. Instead of playing games with module_{dis,en}able_ro(), use existing text poking mechanisms to apply relocations after module loading. So far only x86, s390 and Power have HAVE_LIVEPATCH but only the first two also have STRICT_MODULE_RWX. This will allow removal of the last module_disable_ro() usage in livepatch. The ultimate goal is to completely disallow making executable mappings writable. [ jpoimboe: Split up patches. Use mod state to determine whether memcpy() can be used. Implement text_poke() for UML. ] Cc: [email protected] Suggested-by: Josh Poimboeuf <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Signed-off-by: Josh Poimboeuf <[email protected]> Acked-by: Peter Zijlstra (Intel) <[email protected]> Acked-by: Joe Lawrence <[email protected]> Acked-by: Miroslav Benes <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent be24226 commit 88fc078

File tree

2 files changed

+47
-7
lines changed

2 files changed

+47
-7
lines changed

arch/um/kernel/um_arch.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,3 +362,19 @@ void __init check_bugs(void)
362362
void apply_alternatives(struct alt_instr *start, struct alt_instr *end)
363363
{
364364
}
365+
366+
void *text_poke(void *addr, const void *opcode, size_t len)
367+
{
368+
/*
369+
* In UML, the only reference to this function is in
370+
* apply_relocate_add(), which shouldn't ever actually call this
371+
* because UML doesn't have live patching.
372+
*/
373+
WARN_ON(1);
374+
375+
return memcpy(addr, opcode, len);
376+
}
377+
378+
void text_poke_sync(void)
379+
{
380+
}

arch/x86/kernel/module.c

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,12 @@ int apply_relocate(Elf32_Shdr *sechdrs,
126126
return 0;
127127
}
128128
#else /*X86_64*/
129-
int apply_relocate_add(Elf64_Shdr *sechdrs,
129+
static int __apply_relocate_add(Elf64_Shdr *sechdrs,
130130
const char *strtab,
131131
unsigned int symindex,
132132
unsigned int relsec,
133-
struct module *me)
133+
struct module *me,
134+
void *(*write)(void *dest, const void *src, size_t len))
134135
{
135136
unsigned int i;
136137
Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr;
@@ -162,19 +163,19 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
162163
case R_X86_64_64:
163164
if (*(u64 *)loc != 0)
164165
goto invalid_relocation;
165-
*(u64 *)loc = val;
166+
write(loc, &val, 8);
166167
break;
167168
case R_X86_64_32:
168169
if (*(u32 *)loc != 0)
169170
goto invalid_relocation;
170-
*(u32 *)loc = val;
171+
write(loc, &val, 4);
171172
if (val != *(u32 *)loc)
172173
goto overflow;
173174
break;
174175
case R_X86_64_32S:
175176
if (*(s32 *)loc != 0)
176177
goto invalid_relocation;
177-
*(s32 *)loc = val;
178+
write(loc, &val, 4);
178179
if ((s64)val != *(s32 *)loc)
179180
goto overflow;
180181
break;
@@ -183,7 +184,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
183184
if (*(u32 *)loc != 0)
184185
goto invalid_relocation;
185186
val -= (u64)loc;
186-
*(u32 *)loc = val;
187+
write(loc, &val, 4);
187188
#if 0
188189
if ((s64)val != *(s32 *)loc)
189190
goto overflow;
@@ -193,7 +194,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
193194
if (*(u64 *)loc != 0)
194195
goto invalid_relocation;
195196
val -= (u64)loc;
196-
*(u64 *)loc = val;
197+
write(loc, &val, 8);
197198
break;
198199
default:
199200
pr_err("%s: Unknown rela relocation: %llu\n",
@@ -215,6 +216,29 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
215216
me->name);
216217
return -ENOEXEC;
217218
}
219+
220+
int apply_relocate_add(Elf64_Shdr *sechdrs,
221+
const char *strtab,
222+
unsigned int symindex,
223+
unsigned int relsec,
224+
struct module *me)
225+
{
226+
int ret;
227+
bool early = me->state == MODULE_STATE_UNFORMED;
228+
void *(*write)(void *, const void *, size_t) = memcpy;
229+
230+
if (!early)
231+
write = text_poke;
232+
233+
ret = __apply_relocate_add(sechdrs, strtab, symindex, relsec, me,
234+
write);
235+
236+
if (!early)
237+
text_poke_sync();
238+
239+
return ret;
240+
}
241+
218242
#endif
219243

220244
int module_finalize(const Elf_Ehdr *hdr,

0 commit comments

Comments
 (0)