Lines Matching +full:write +full:- +full:0

1 // SPDX-License-Identifier: GPL-2.0+
26 #include <asm/nospec-branch.h>
32 #if 0
43 execmem_free(mod->arch.trampolines_start); in module_arch_cleanup()
50 mod->state == MODULE_STATE_LIVE) in module_arch_freeing_init()
53 vfree(mod->arch.syminfo); in module_arch_freeing_init()
54 mod->arch.syminfo = NULL; in module_arch_freeing_init()
61 info = me->arch.syminfo + ELF_R_SYM (rela->r_info); in check_rela()
62 switch (ELF_R_TYPE (rela->r_info)) { in check_rela()
75 if (info->got_offset == -1UL) { in check_rela()
76 info->got_offset = me->arch.got_size; in check_rela()
77 me->arch.got_size += sizeof(void*); in check_rela()
87 if (info->plt_offset == -1UL) { in check_rela()
88 info->plt_offset = me->arch.plt_size; in check_rela()
89 me->arch.plt_size += PLT_ENTRY_SIZE; in check_rela()
97 modules linked with -shared. */ in check_rela()
118 for (i = 0; i < hdr->e_shnum; i++) in module_frob_arch_sections()
125 printk(KERN_ERR "module %s: no symbol table\n", me->name); in module_frob_arch_sections()
126 return -ENOEXEC; in module_frob_arch_sections()
130 me->arch.nsyms = symtab->sh_size / sizeof(Elf_Sym); in module_frob_arch_sections()
131 me->arch.syminfo = vmalloc(array_size(sizeof(struct mod_arch_syminfo), in module_frob_arch_sections()
132 me->arch.nsyms)); in module_frob_arch_sections()
133 if (!me->arch.syminfo) in module_frob_arch_sections()
134 return -ENOMEM; in module_frob_arch_sections()
135 symbols = (void *) hdr + symtab->sh_offset; in module_frob_arch_sections()
136 strings = (void *) hdr + sechdrs[symtab->sh_link].sh_offset; in module_frob_arch_sections()
137 for (i = 0; i < me->arch.nsyms; i++) { in module_frob_arch_sections()
140 "_GLOBAL_OFFSET_TABLE_") == 0) in module_frob_arch_sections()
143 me->arch.syminfo[i].got_offset = -1UL; in module_frob_arch_sections()
144 me->arch.syminfo[i].plt_offset = -1UL; in module_frob_arch_sections()
145 me->arch.syminfo[i].got_initialized = 0; in module_frob_arch_sections()
146 me->arch.syminfo[i].plt_initialized = 0; in module_frob_arch_sections()
150 me->arch.got_size = me->arch.plt_size = 0; in module_frob_arch_sections()
151 for (i = 0; i < hdr->e_shnum; i++) { in module_frob_arch_sections()
156 for (j = 0; j < nrela; j++) in module_frob_arch_sections()
162 mod_mem = &me->mem[MOD_TEXT]; in module_frob_arch_sections()
163 mod_mem->size = ALIGN(mod_mem->size, 4); in module_frob_arch_sections()
164 me->arch.got_offset = mod_mem->size; in module_frob_arch_sections()
165 mod_mem->size += me->arch.got_size; in module_frob_arch_sections()
166 me->arch.plt_offset = mod_mem->size; in module_frob_arch_sections()
167 if (me->arch.plt_size) { in module_frob_arch_sections()
169 me->arch.plt_size += PLT_ENTRY_SIZE; in module_frob_arch_sections()
170 mod_mem->size += me->arch.plt_size; in module_frob_arch_sections()
172 return 0; in module_frob_arch_sections()
177 void *(*write)(void *dest, const void *src, size_t len)) in apply_rela_bits()
183 if (val & ((1UL << shift) - 1)) in apply_rela_bits()
184 return -ENOEXEC; in apply_rela_bits()
187 min = -(1L << (bits - 1)); in apply_rela_bits()
188 max = (1L << (bits - 1)) - 1; in apply_rela_bits()
190 return -ENOEXEC; in apply_rela_bits()
193 umax = ((1UL << (bits - 1)) << 1) - 1; in apply_rela_bits()
195 return -ENOEXEC; in apply_rela_bits()
200 write(dest, &tmp, 1); in apply_rela_bits()
202 unsigned short tmp = (val & 0xfff) | in apply_rela_bits()
203 (*(unsigned short *) loc & 0xf000); in apply_rela_bits()
204 write(dest, &tmp, 2); in apply_rela_bits()
207 write(dest, &tmp, 2); in apply_rela_bits()
209 unsigned int tmp = (val & 0xfff) << 16 | in apply_rela_bits()
210 (val & 0xff000) >> 4 | (*(unsigned int *) loc & 0xf00000ff); in apply_rela_bits()
211 write(dest, &tmp, 4); in apply_rela_bits()
214 write(dest, &tmp, 4); in apply_rela_bits()
217 write(dest, &tmp, 8); in apply_rela_bits()
219 return 0; in apply_rela_bits()
224 void *(*write)(void *dest, const void *src, size_t len)) in apply_rela()
229 int rc = -ENOEXEC; in apply_rela()
232 loc = base + rela->r_offset; in apply_rela()
235 r_sym = ELF_R_SYM(rela->r_info); in apply_rela()
236 r_type = ELF_R_TYPE(rela->r_info); in apply_rela()
237 info = me->arch.syminfo + r_sym; in apply_rela()
242 rc = 0; in apply_rela()
250 val += rela->r_addend; in apply_rela()
252 rc = apply_rela_bits(loc, val, 0, 8, 0, write); in apply_rela()
254 rc = apply_rela_bits(loc, val, 0, 12, 0, write); in apply_rela()
256 rc = apply_rela_bits(loc, val, 0, 16, 0, write); in apply_rela()
258 rc = apply_rela_bits(loc, val, 1, 20, 0, write); in apply_rela()
260 rc = apply_rela_bits(loc, val, 0, 32, 0, write); in apply_rela()
262 rc = apply_rela_bits(loc, val, 0, 64, 0, write); in apply_rela()
269 val += rela->r_addend - loc; in apply_rela()
271 rc = apply_rela_bits(loc, val, 1, 16, 0, write); in apply_rela()
273 rc = apply_rela_bits(loc, val, 1, 16, 1, write); in apply_rela()
275 rc = apply_rela_bits(loc, val, 1, 32, 1, write); in apply_rela()
277 rc = apply_rela_bits(loc, val, 1, 32, 0, write); in apply_rela()
279 rc = apply_rela_bits(loc, val, 1, 64, 0, write); in apply_rela()
293 if (info->got_initialized == 0) { in apply_rela()
294 Elf_Addr *gotent = me->mem[MOD_TEXT].base + in apply_rela()
295 me->arch.got_offset + in apply_rela()
296 info->got_offset; in apply_rela()
298 write(gotent, &val, sizeof(*gotent)); in apply_rela()
299 info->got_initialized = 1; in apply_rela()
301 val = info->got_offset + rela->r_addend; in apply_rela()
304 rc = apply_rela_bits(loc, val, 0, 12, 0, write); in apply_rela()
307 rc = apply_rela_bits(loc, val, 0, 16, 0, write); in apply_rela()
310 rc = apply_rela_bits(loc, val, 1, 20, 0, write); in apply_rela()
313 rc = apply_rela_bits(loc, val, 0, 32, 0, write); in apply_rela()
316 rc = apply_rela_bits(loc, val, 0, 64, 0, write); in apply_rela()
319 val += (Elf_Addr)me->mem[MOD_TEXT].base + in apply_rela()
320 me->arch.got_offset - loc; in apply_rela()
321 rc = apply_rela_bits(loc, val, 1, 32, 1, write); in apply_rela()
331 if (info->plt_initialized == 0) { in apply_rela()
336 plt_base = me->mem[MOD_TEXT].base + me->arch.plt_offset; in apply_rela()
337 ip = plt_base + info->plt_offset; in apply_rela()
338 *(int *)insn = 0x0d10e310; /* basr 1,0 */ in apply_rela()
339 *(int *)&insn[4] = 0x100c0004; /* lg 1,12(1) */ in apply_rela()
343 jump_r1 = plt_base + me->arch.plt_size - in apply_rela()
345 /* brcl 0xf,__jump_r1 */ in apply_rela()
346 *(short *)&insn[8] = 0xc0f4; in apply_rela()
347 *(int *)&insn[10] = (jump_r1 - (ip + 8)) / 2; in apply_rela()
349 *(int *)&insn[8] = 0x07f10000; /* br %r1 */ in apply_rela()
353 write(ip, insn, sizeof(insn)); in apply_rela()
354 info->plt_initialized = 1; in apply_rela()
359 val = me->arch.plt_offset - me->arch.got_offset + in apply_rela()
360 info->plt_offset + rela->r_addend; in apply_rela()
363 val - loc + 0xffffUL < 0x1ffffeUL) || in apply_rela()
365 val - loc + 0xffffffffULL < 0x1fffffffeULL))) in apply_rela()
366 val = (Elf_Addr) me->mem[MOD_TEXT].base + in apply_rela()
367 me->arch.plt_offset + in apply_rela()
368 info->plt_offset; in apply_rela()
369 val += rela->r_addend - loc; in apply_rela()
372 rc = apply_rela_bits(loc, val, 1, 16, 1, write); in apply_rela()
374 rc = apply_rela_bits(loc, val, 0, 16, 0, write); in apply_rela()
376 rc = apply_rela_bits(loc, val, 1, 32, 1, write); in apply_rela()
379 rc = apply_rela_bits(loc, val, 0, 32, 0, write); in apply_rela()
382 rc = apply_rela_bits(loc, val, 0, 64, 0, write); in apply_rela()
387 val = val + rela->r_addend - in apply_rela()
388 ((Elf_Addr) me->mem[MOD_TEXT].base + me->arch.got_offset); in apply_rela()
390 rc = apply_rela_bits(loc, val, 0, 16, 0, write); in apply_rela()
392 rc = apply_rela_bits(loc, val, 0, 32, 0, write); in apply_rela()
394 rc = apply_rela_bits(loc, val, 0, 64, 0, write); in apply_rela()
398 val = (Elf_Addr) me->mem[MOD_TEXT].base + me->arch.got_offset + in apply_rela()
399 rela->r_addend - loc; in apply_rela()
401 rc = apply_rela_bits(loc, val, 1, 32, 0, write); in apply_rela()
403 rc = apply_rela_bits(loc, val, 1, 32, 1, write); in apply_rela()
410 modules linked with -shared. */ in apply_rela()
411 return -ENOEXEC; in apply_rela()
414 me->name, r_type); in apply_rela()
415 return -ENOEXEC; in apply_rela()
419 "(r_type %i, value 0x%lx)\n", in apply_rela()
420 me->name, strtab + symtab[r_sym].st_name, in apply_rela()
424 return 0; in apply_rela()
430 void *(*write)(void *dest, const void *src, size_t len)) in __apply_relocate_add()
445 for (i = 0; i < n; i++, rela++) { in __apply_relocate_add()
446 rc = apply_rela(rela, base, symtab, strtab, me, write); in __apply_relocate_add()
450 return 0; in __apply_relocate_add()
457 bool early = me->state == MODULE_STATE_UNFORMED; in apply_relocate_add()
458 void *(*write)(void *, const void *, size_t) = memcpy; in apply_relocate_add() local
461 write = s390_kernel_write; in apply_relocate_add()
464 write); in apply_relocate_add()
475 size = FTRACE_HOTPATCH_TRAMPOLINES_SIZE(s->sh_size); in module_alloc_ftrace_hotpatch_trampolines()
479 return -ENOMEM; in module_alloc_ftrace_hotpatch_trampolines()
483 me->arch.trampolines_start = (struct ftrace_hotpatch_trampoline *)start; in module_alloc_ftrace_hotpatch_trampolines()
484 me->arch.trampolines_end = (struct ftrace_hotpatch_trampoline *)end; in module_alloc_ftrace_hotpatch_trampolines()
485 me->arch.next_trampoline = me->arch.trampolines_start; in module_alloc_ftrace_hotpatch_trampolines()
487 return 0; in module_alloc_ftrace_hotpatch_trampolines()
503 !nospec_disable && me->arch.plt_size) { in module_finalize()
506 ij = me->mem[MOD_TEXT].base + me->arch.plt_offset + in module_finalize()
507 me->arch.plt_size - PLT_ENTRY_SIZE; in module_finalize()
508 ij[0] = 0xc6000000; /* exrl %r0,.+10 */ in module_finalize()
509 ij[1] = 0x0005a7f4; /* j . */ in module_finalize()
510 ij[2] = 0x000007f1; /* br %r1 */ in module_finalize()
513 secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; in module_finalize()
514 for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { in module_finalize()
515 aseg = (void *) s->sh_addr; in module_finalize()
516 secname = secstrings + s->sh_name; in module_finalize()
520 apply_alternatives(aseg, aseg + s->sh_size); in module_finalize()
524 nospec_revert(aseg, aseg + s->sh_size); in module_finalize()
528 nospec_revert(aseg, aseg + s->sh_size); in module_finalize()
533 if (ret < 0) in module_finalize()
539 return 0; in module_finalize()