Skip to content

Commit 9fb4c52

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/livepatching/livepatching
Pull livepatching updates from Jiri Kosina: - simplifications and improvements for issues Peter Ziljstra found during his previous work on W^X cleanups. This allows us to remove livepatch arch-specific .klp.arch sections and add proper support for jump labels in patched code. Also, this patchset removes the last module_disable_ro() usage in the tree. Patches from Josh Poimboeuf and Peter Zijlstra - a few other minor cleanups * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/livepatching/livepatching: MAINTAINERS: add lib/livepatch to LIVE PATCHING livepatch: add arch-specific headers to MAINTAINERS livepatch: Make klp_apply_object_relocs static MAINTAINERS: adjust to livepatch .klp.arch removal module: Make module_enable_ro() static again x86/module: Use text_mutex in apply_relocate_add() module: Remove module_disable_ro() livepatch: Remove module_disable_ro() usage x86/module: Use text_poke() for late relocations s390/module: Use s390_kernel_write() for late relocations s390: Change s390_kernel_write() return type to match memcpy() livepatch: Prevent module-specific KLP rela sections from referencing vmlinux symbols livepatch: Remove .klp.arch livepatch: Apply vmlinux-specific KLP relocations early livepatch: Disallow vmlinux.ko
2 parents a789d5f + f55d989 commit 9fb4c52

File tree

13 files changed

+283
-236
lines changed

13 files changed

+283
-236
lines changed

Documentation/livepatch/module-elf-format.rst

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ This document outlines the Elf format requirements that livepatch modules must f
1414
4. Livepatch symbols
1515
4.1 A livepatch module's symbol table
1616
4.2 Livepatch symbol format
17-
5. Architecture-specific sections
18-
6. Symbol table and Elf section access
17+
5. Symbol table and Elf section access
1918
2019
1. Background and motivation
2120
============================
@@ -298,17 +297,7 @@ Examples:
298297
Note that the 'Ndx' (Section index) for these symbols is SHN_LIVEPATCH (0xff20).
299298
"OS" means OS-specific.
300299

301-
5. Architecture-specific sections
302-
=================================
303-
Architectures may override arch_klp_init_object_loaded() to perform
304-
additional arch-specific tasks when a target module loads, such as applying
305-
arch-specific sections. On x86 for example, we must apply per-object
306-
.altinstructions and .parainstructions sections when a target module loads.
307-
These sections must be prefixed with ".klp.arch.$objname." so that they can
308-
be easily identified when iterating through a patch module's Elf sections
309-
(See arch/x86/kernel/livepatch.c for a complete example).
310-
311-
6. Symbol table and Elf section access
300+
5. Symbol table and Elf section access
312301
======================================
313302
A livepatch module's symbol table is accessible through module->symtab.
314303

MAINTAINERS

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9936,10 +9936,12 @@ S: Maintained
99369936
T: git git://git.kernel.org/pub/scm/linux/kernel/git/livepatching/livepatching.git
99379937
F: Documentation/ABI/testing/sysfs-kernel-livepatch
99389938
F: Documentation/livepatch/
9939+
F: arch/powerpc/include/asm/livepatch.h
9940+
F: arch/s390/include/asm/livepatch.h
99399941
F: arch/x86/include/asm/livepatch.h
9940-
F: arch/x86/kernel/livepatch.c
99419942
F: include/linux/livepatch.h
99429943
F: kernel/livepatch/
9944+
F: lib/livepatch/
99439945
F: samples/livepatch/
99449946
F: tools/testing/selftests/livepatch/
99459947

arch/s390/include/asm/uaccess.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,6 @@ static inline unsigned long __must_check clear_user(void __user *to, unsigned lo
276276
}
277277

278278
int copy_to_user_real(void __user *dest, void *src, unsigned long count);
279-
void s390_kernel_write(void *dst, const void *src, size_t size);
279+
void *s390_kernel_write(void *dst, const void *src, size_t size);
280280

281281
#endif /* __S390_UACCESS_H */

arch/s390/kernel/module.c

Lines changed: 88 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/kasan.h>
2020
#include <linux/moduleloader.h>
2121
#include <linux/bug.h>
22+
#include <linux/memory.h>
2223
#include <asm/alternative.h>
2324
#include <asm/nospec-branch.h>
2425
#include <asm/facility.h>
@@ -174,10 +175,12 @@ int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
174175
}
175176

176177
static int apply_rela_bits(Elf_Addr loc, Elf_Addr val,
177-
int sign, int bits, int shift)
178+
int sign, int bits, int shift,
179+
void *(*write)(void *dest, const void *src, size_t len))
178180
{
179181
unsigned long umax;
180182
long min, max;
183+
void *dest = (void *)loc;
181184

182185
if (val & ((1UL << shift) - 1))
183186
return -ENOEXEC;
@@ -194,26 +197,33 @@ static int apply_rela_bits(Elf_Addr loc, Elf_Addr val,
194197
return -ENOEXEC;
195198
}
196199

197-
if (bits == 8)
198-
*(unsigned char *) loc = val;
199-
else if (bits == 12)
200-
*(unsigned short *) loc = (val & 0xfff) |
200+
if (bits == 8) {
201+
unsigned char tmp = val;
202+
write(dest, &tmp, 1);
203+
} else if (bits == 12) {
204+
unsigned short tmp = (val & 0xfff) |
201205
(*(unsigned short *) loc & 0xf000);
202-
else if (bits == 16)
203-
*(unsigned short *) loc = val;
204-
else if (bits == 20)
205-
*(unsigned int *) loc = (val & 0xfff) << 16 |
206-
(val & 0xff000) >> 4 |
207-
(*(unsigned int *) loc & 0xf00000ff);
208-
else if (bits == 32)
209-
*(unsigned int *) loc = val;
210-
else if (bits == 64)
211-
*(unsigned long *) loc = val;
206+
write(dest, &tmp, 2);
207+
} else if (bits == 16) {
208+
unsigned short tmp = val;
209+
write(dest, &tmp, 2);
210+
} else if (bits == 20) {
211+
unsigned int tmp = (val & 0xfff) << 16 |
212+
(val & 0xff000) >> 4 | (*(unsigned int *) loc & 0xf00000ff);
213+
write(dest, &tmp, 4);
214+
} else if (bits == 32) {
215+
unsigned int tmp = val;
216+
write(dest, &tmp, 4);
217+
} else if (bits == 64) {
218+
unsigned long tmp = val;
219+
write(dest, &tmp, 8);
220+
}
212221
return 0;
213222
}
214223

215224
static int apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab,
216-
const char *strtab, struct module *me)
225+
const char *strtab, struct module *me,
226+
void *(*write)(void *dest, const void *src, size_t len))
217227
{
218228
struct mod_arch_syminfo *info;
219229
Elf_Addr loc, val;
@@ -241,17 +251,17 @@ static int apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab,
241251
case R_390_64: /* Direct 64 bit. */
242252
val += rela->r_addend;
243253
if (r_type == R_390_8)
244-
rc = apply_rela_bits(loc, val, 0, 8, 0);
254+
rc = apply_rela_bits(loc, val, 0, 8, 0, write);
245255
else if (r_type == R_390_12)
246-
rc = apply_rela_bits(loc, val, 0, 12, 0);
256+
rc = apply_rela_bits(loc, val, 0, 12, 0, write);
247257
else if (r_type == R_390_16)
248-
rc = apply_rela_bits(loc, val, 0, 16, 0);
258+
rc = apply_rela_bits(loc, val, 0, 16, 0, write);
249259
else if (r_type == R_390_20)
250-
rc = apply_rela_bits(loc, val, 1, 20, 0);
260+
rc = apply_rela_bits(loc, val, 1, 20, 0, write);
251261
else if (r_type == R_390_32)
252-
rc = apply_rela_bits(loc, val, 0, 32, 0);
262+
rc = apply_rela_bits(loc, val, 0, 32, 0, write);
253263
else if (r_type == R_390_64)
254-
rc = apply_rela_bits(loc, val, 0, 64, 0);
264+
rc = apply_rela_bits(loc, val, 0, 64, 0, write);
255265
break;
256266
case R_390_PC16: /* PC relative 16 bit. */
257267
case R_390_PC16DBL: /* PC relative 16 bit shifted by 1. */
@@ -260,15 +270,15 @@ static int apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab,
260270
case R_390_PC64: /* PC relative 64 bit. */
261271
val += rela->r_addend - loc;
262272
if (r_type == R_390_PC16)
263-
rc = apply_rela_bits(loc, val, 1, 16, 0);
273+
rc = apply_rela_bits(loc, val, 1, 16, 0, write);
264274
else if (r_type == R_390_PC16DBL)
265-
rc = apply_rela_bits(loc, val, 1, 16, 1);
275+
rc = apply_rela_bits(loc, val, 1, 16, 1, write);
266276
else if (r_type == R_390_PC32DBL)
267-
rc = apply_rela_bits(loc, val, 1, 32, 1);
277+
rc = apply_rela_bits(loc, val, 1, 32, 1, write);
268278
else if (r_type == R_390_PC32)
269-
rc = apply_rela_bits(loc, val, 1, 32, 0);
279+
rc = apply_rela_bits(loc, val, 1, 32, 0, write);
270280
else if (r_type == R_390_PC64)
271-
rc = apply_rela_bits(loc, val, 1, 64, 0);
281+
rc = apply_rela_bits(loc, val, 1, 64, 0, write);
272282
break;
273283
case R_390_GOT12: /* 12 bit GOT offset. */
274284
case R_390_GOT16: /* 16 bit GOT offset. */
@@ -283,33 +293,33 @@ static int apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab,
283293
case R_390_GOTPLT64: /* 64 bit offset to jump slot. */
284294
case R_390_GOTPLTENT: /* 32 bit rel. offset to jump slot >> 1. */
285295
if (info->got_initialized == 0) {
286-
Elf_Addr *gotent;
296+
Elf_Addr *gotent = me->core_layout.base +
297+
me->arch.got_offset +
298+
info->got_offset;
287299

288-
gotent = me->core_layout.base + me->arch.got_offset +
289-
info->got_offset;
290-
*gotent = val;
300+
write(gotent, &val, sizeof(*gotent));
291301
info->got_initialized = 1;
292302
}
293303
val = info->got_offset + rela->r_addend;
294304
if (r_type == R_390_GOT12 ||
295305
r_type == R_390_GOTPLT12)
296-
rc = apply_rela_bits(loc, val, 0, 12, 0);
306+
rc = apply_rela_bits(loc, val, 0, 12, 0, write);
297307
else if (r_type == R_390_GOT16 ||
298308
r_type == R_390_GOTPLT16)
299-
rc = apply_rela_bits(loc, val, 0, 16, 0);
309+
rc = apply_rela_bits(loc, val, 0, 16, 0, write);
300310
else if (r_type == R_390_GOT20 ||
301311
r_type == R_390_GOTPLT20)
302-
rc = apply_rela_bits(loc, val, 1, 20, 0);
312+
rc = apply_rela_bits(loc, val, 1, 20, 0, write);
303313
else if (r_type == R_390_GOT32 ||
304314
r_type == R_390_GOTPLT32)
305-
rc = apply_rela_bits(loc, val, 0, 32, 0);
315+
rc = apply_rela_bits(loc, val, 0, 32, 0, write);
306316
else if (r_type == R_390_GOT64 ||
307317
r_type == R_390_GOTPLT64)
308-
rc = apply_rela_bits(loc, val, 0, 64, 0);
318+
rc = apply_rela_bits(loc, val, 0, 64, 0, write);
309319
else if (r_type == R_390_GOTENT ||
310320
r_type == R_390_GOTPLTENT) {
311321
val += (Elf_Addr) me->core_layout.base - loc;
312-
rc = apply_rela_bits(loc, val, 1, 32, 1);
322+
rc = apply_rela_bits(loc, val, 1, 32, 1, write);
313323
}
314324
break;
315325
case R_390_PLT16DBL: /* 16 bit PC rel. PLT shifted by 1. */
@@ -320,25 +330,29 @@ static int apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab,
320330
case R_390_PLTOFF32: /* 32 bit offset from GOT to PLT. */
321331
case R_390_PLTOFF64: /* 16 bit offset from GOT to PLT. */
322332
if (info->plt_initialized == 0) {
323-
unsigned int *ip;
324-
ip = me->core_layout.base + me->arch.plt_offset +
325-
info->plt_offset;
326-
ip[0] = 0x0d10e310; /* basr 1,0 */
327-
ip[1] = 0x100a0004; /* lg 1,10(1) */
333+
unsigned int insn[5];
334+
unsigned int *ip = me->core_layout.base +
335+
me->arch.plt_offset +
336+
info->plt_offset;
337+
338+
insn[0] = 0x0d10e310; /* basr 1,0 */
339+
insn[1] = 0x100a0004; /* lg 1,10(1) */
328340
if (IS_ENABLED(CONFIG_EXPOLINE) && !nospec_disable) {
329341
unsigned int *ij;
330342
ij = me->core_layout.base +
331343
me->arch.plt_offset +
332344
me->arch.plt_size - PLT_ENTRY_SIZE;
333-
ip[2] = 0xa7f40000 + /* j __jump_r1 */
345+
insn[2] = 0xa7f40000 + /* j __jump_r1 */
334346
(unsigned int)(u16)
335347
(((unsigned long) ij - 8 -
336348
(unsigned long) ip) / 2);
337349
} else {
338-
ip[2] = 0x07f10000; /* br %r1 */
350+
insn[2] = 0x07f10000; /* br %r1 */
339351
}
340-
ip[3] = (unsigned int) (val >> 32);
341-
ip[4] = (unsigned int) val;
352+
insn[3] = (unsigned int) (val >> 32);
353+
insn[4] = (unsigned int) val;
354+
355+
write(ip, insn, sizeof(insn));
342356
info->plt_initialized = 1;
343357
}
344358
if (r_type == R_390_PLTOFF16 ||
@@ -357,38 +371,38 @@ static int apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab,
357371
val += rela->r_addend - loc;
358372
}
359373
if (r_type == R_390_PLT16DBL)
360-
rc = apply_rela_bits(loc, val, 1, 16, 1);
374+
rc = apply_rela_bits(loc, val, 1, 16, 1, write);
361375
else if (r_type == R_390_PLTOFF16)
362-
rc = apply_rela_bits(loc, val, 0, 16, 0);
376+
rc = apply_rela_bits(loc, val, 0, 16, 0, write);
363377
else if (r_type == R_390_PLT32DBL)
364-
rc = apply_rela_bits(loc, val, 1, 32, 1);
378+
rc = apply_rela_bits(loc, val, 1, 32, 1, write);
365379
else if (r_type == R_390_PLT32 ||
366380
r_type == R_390_PLTOFF32)
367-
rc = apply_rela_bits(loc, val, 0, 32, 0);
381+
rc = apply_rela_bits(loc, val, 0, 32, 0, write);
368382
else if (r_type == R_390_PLT64 ||
369383
r_type == R_390_PLTOFF64)
370-
rc = apply_rela_bits(loc, val, 0, 64, 0);
384+
rc = apply_rela_bits(loc, val, 0, 64, 0, write);
371385
break;
372386
case R_390_GOTOFF16: /* 16 bit offset to GOT. */
373387
case R_390_GOTOFF32: /* 32 bit offset to GOT. */
374388
case R_390_GOTOFF64: /* 64 bit offset to GOT. */
375389
val = val + rela->r_addend -
376390
((Elf_Addr) me->core_layout.base + me->arch.got_offset);
377391
if (r_type == R_390_GOTOFF16)
378-
rc = apply_rela_bits(loc, val, 0, 16, 0);
392+
rc = apply_rela_bits(loc, val, 0, 16, 0, write);
379393
else if (r_type == R_390_GOTOFF32)
380-
rc = apply_rela_bits(loc, val, 0, 32, 0);
394+
rc = apply_rela_bits(loc, val, 0, 32, 0, write);
381395
else if (r_type == R_390_GOTOFF64)
382-
rc = apply_rela_bits(loc, val, 0, 64, 0);
396+
rc = apply_rela_bits(loc, val, 0, 64, 0, write);
383397
break;
384398
case R_390_GOTPC: /* 32 bit PC relative offset to GOT. */
385399
case R_390_GOTPCDBL: /* 32 bit PC rel. off. to GOT shifted by 1. */
386400
val = (Elf_Addr) me->core_layout.base + me->arch.got_offset +
387401
rela->r_addend - loc;
388402
if (r_type == R_390_GOTPC)
389-
rc = apply_rela_bits(loc, val, 1, 32, 0);
403+
rc = apply_rela_bits(loc, val, 1, 32, 0, write);
390404
else if (r_type == R_390_GOTPCDBL)
391-
rc = apply_rela_bits(loc, val, 1, 32, 1);
405+
rc = apply_rela_bits(loc, val, 1, 32, 1, write);
392406
break;
393407
case R_390_COPY:
394408
case R_390_GLOB_DAT: /* Create GOT entry. */
@@ -412,9 +426,10 @@ static int apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab,
412426
return 0;
413427
}
414428

415-
int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
429+
static int __apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
416430
unsigned int symindex, unsigned int relsec,
417-
struct module *me)
431+
struct module *me,
432+
void *(*write)(void *dest, const void *src, size_t len))
418433
{
419434
Elf_Addr base;
420435
Elf_Sym *symtab;
@@ -430,13 +445,27 @@ int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
430445
n = sechdrs[relsec].sh_size / sizeof(Elf_Rela);
431446

432447
for (i = 0; i < n; i++, rela++) {
433-
rc = apply_rela(rela, base, symtab, strtab, me);
448+
rc = apply_rela(rela, base, symtab, strtab, me, write);
434449
if (rc)
435450
return rc;
436451
}
437452
return 0;
438453
}
439454

455+
int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
456+
unsigned int symindex, unsigned int relsec,
457+
struct module *me)
458+
{
459+
bool early = me->state == MODULE_STATE_UNFORMED;
460+
void *(*write)(void *, const void *, size_t) = memcpy;
461+
462+
if (!early)
463+
write = s390_kernel_write;
464+
465+
return __apply_relocate_add(sechdrs, strtab, symindex, relsec, me,
466+
write);
467+
}
468+
440469
int module_finalize(const Elf_Ehdr *hdr,
441470
const Elf_Shdr *sechdrs,
442471
struct module *me)

arch/s390/mm/maccess.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,19 +55,22 @@ static notrace long s390_kernel_write_odd(void *dst, const void *src, size_t siz
5555
*/
5656
static DEFINE_SPINLOCK(s390_kernel_write_lock);
5757

58-
void notrace s390_kernel_write(void *dst, const void *src, size_t size)
58+
notrace void *s390_kernel_write(void *dst, const void *src, size_t size)
5959
{
60+
void *tmp = dst;
6061
unsigned long flags;
6162
long copied;
6263

6364
spin_lock_irqsave(&s390_kernel_write_lock, flags);
6465
while (size) {
65-
copied = s390_kernel_write_odd(dst, src, size);
66-
dst += copied;
66+
copied = s390_kernel_write_odd(tmp, src, size);
67+
tmp += copied;
6768
src += copied;
6869
size -= copied;
6970
}
7071
spin_unlock_irqrestore(&s390_kernel_write_lock, flags);
72+
73+
return dst;
7174
}
7275

7376
static int __no_sanitize_address __memcpy_real(void *dest, void *src, size_t count)

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/Makefile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ obj-$(CONFIG_X86_MPPARSE) += mpparse.o
9090
obj-y += apic/
9191
obj-$(CONFIG_X86_REBOOTFIXUPS) += reboot_fixups_32.o
9292
obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
93-
obj-$(CONFIG_LIVEPATCH) += livepatch.o
9493
obj-$(CONFIG_FUNCTION_TRACER) += ftrace_$(BITS).o
9594
obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
9695
obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o

0 commit comments

Comments
 (0)