]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - arch/s390/kernel/module.c
Merge branch 'x86/urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
[mirror_ubuntu-bionic-kernel.git] / arch / s390 / kernel / module.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Kernel module help for s390.
4 *
5 * S390 version
6 * Copyright IBM Corp. 2002, 2003
7 * Author(s): Arnd Bergmann (arndb@de.ibm.com)
8 * Martin Schwidefsky (schwidefsky@de.ibm.com)
9 *
10 * based on i386 version
11 * Copyright (C) 2001 Rusty Russell.
12 */
13 #include <linux/module.h>
14 #include <linux/elf.h>
15 #include <linux/vmalloc.h>
16 #include <linux/fs.h>
17 #include <linux/string.h>
18 #include <linux/kernel.h>
19 #include <linux/moduleloader.h>
20 #include <linux/bug.h>
21 #include <asm/alternative.h>
22
23 #if 0
24 #define DEBUGP printk
25 #else
26 #define DEBUGP(fmt , ...)
27 #endif
28
29 #define PLT_ENTRY_SIZE 20
30
31 void *module_alloc(unsigned long size)
32 {
33 if (PAGE_ALIGN(size) > MODULES_LEN)
34 return NULL;
35 return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
36 GFP_KERNEL, PAGE_KERNEL_EXEC,
37 0, NUMA_NO_NODE,
38 __builtin_return_address(0));
39 }
40
41 void module_arch_freeing_init(struct module *mod)
42 {
43 if (is_livepatch_module(mod) &&
44 mod->state == MODULE_STATE_LIVE)
45 return;
46
47 vfree(mod->arch.syminfo);
48 mod->arch.syminfo = NULL;
49 }
50
51 static void check_rela(Elf_Rela *rela, struct module *me)
52 {
53 struct mod_arch_syminfo *info;
54
55 info = me->arch.syminfo + ELF_R_SYM (rela->r_info);
56 switch (ELF_R_TYPE (rela->r_info)) {
57 case R_390_GOT12: /* 12 bit GOT offset. */
58 case R_390_GOT16: /* 16 bit GOT offset. */
59 case R_390_GOT20: /* 20 bit GOT offset. */
60 case R_390_GOT32: /* 32 bit GOT offset. */
61 case R_390_GOT64: /* 64 bit GOT offset. */
62 case R_390_GOTENT: /* 32 bit PC rel. to GOT entry shifted by 1. */
63 case R_390_GOTPLT12: /* 12 bit offset to jump slot. */
64 case R_390_GOTPLT16: /* 16 bit offset to jump slot. */
65 case R_390_GOTPLT20: /* 20 bit offset to jump slot. */
66 case R_390_GOTPLT32: /* 32 bit offset to jump slot. */
67 case R_390_GOTPLT64: /* 64 bit offset to jump slot. */
68 case R_390_GOTPLTENT: /* 32 bit rel. offset to jump slot >> 1. */
69 if (info->got_offset == -1UL) {
70 info->got_offset = me->arch.got_size;
71 me->arch.got_size += sizeof(void*);
72 }
73 break;
74 case R_390_PLT16DBL: /* 16 bit PC rel. PLT shifted by 1. */
75 case R_390_PLT32DBL: /* 32 bit PC rel. PLT shifted by 1. */
76 case R_390_PLT32: /* 32 bit PC relative PLT address. */
77 case R_390_PLT64: /* 64 bit PC relative PLT address. */
78 case R_390_PLTOFF16: /* 16 bit offset from GOT to PLT. */
79 case R_390_PLTOFF32: /* 32 bit offset from GOT to PLT. */
80 case R_390_PLTOFF64: /* 16 bit offset from GOT to PLT. */
81 if (info->plt_offset == -1UL) {
82 info->plt_offset = me->arch.plt_size;
83 me->arch.plt_size += PLT_ENTRY_SIZE;
84 }
85 break;
86 case R_390_COPY:
87 case R_390_GLOB_DAT:
88 case R_390_JMP_SLOT:
89 case R_390_RELATIVE:
90 /* Only needed if we want to support loading of
91 modules linked with -shared. */
92 break;
93 }
94 }
95
96 /*
97 * Account for GOT and PLT relocations. We can't add sections for
98 * got and plt but we can increase the core module size.
99 */
100 int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
101 char *secstrings, struct module *me)
102 {
103 Elf_Shdr *symtab;
104 Elf_Sym *symbols;
105 Elf_Rela *rela;
106 char *strings;
107 int nrela, i, j;
108
109 /* Find symbol table and string table. */
110 symtab = NULL;
111 for (i = 0; i < hdr->e_shnum; i++)
112 switch (sechdrs[i].sh_type) {
113 case SHT_SYMTAB:
114 symtab = sechdrs + i;
115 break;
116 }
117 if (!symtab) {
118 printk(KERN_ERR "module %s: no symbol table\n", me->name);
119 return -ENOEXEC;
120 }
121
122 /* Allocate one syminfo structure per symbol. */
123 me->arch.nsyms = symtab->sh_size / sizeof(Elf_Sym);
124 me->arch.syminfo = vmalloc(me->arch.nsyms *
125 sizeof(struct mod_arch_syminfo));
126 if (!me->arch.syminfo)
127 return -ENOMEM;
128 symbols = (void *) hdr + symtab->sh_offset;
129 strings = (void *) hdr + sechdrs[symtab->sh_link].sh_offset;
130 for (i = 0; i < me->arch.nsyms; i++) {
131 if (symbols[i].st_shndx == SHN_UNDEF &&
132 strcmp(strings + symbols[i].st_name,
133 "_GLOBAL_OFFSET_TABLE_") == 0)
134 /* "Define" it as absolute. */
135 symbols[i].st_shndx = SHN_ABS;
136 me->arch.syminfo[i].got_offset = -1UL;
137 me->arch.syminfo[i].plt_offset = -1UL;
138 me->arch.syminfo[i].got_initialized = 0;
139 me->arch.syminfo[i].plt_initialized = 0;
140 }
141
142 /* Search for got/plt relocations. */
143 me->arch.got_size = me->arch.plt_size = 0;
144 for (i = 0; i < hdr->e_shnum; i++) {
145 if (sechdrs[i].sh_type != SHT_RELA)
146 continue;
147 nrela = sechdrs[i].sh_size / sizeof(Elf_Rela);
148 rela = (void *) hdr + sechdrs[i].sh_offset;
149 for (j = 0; j < nrela; j++)
150 check_rela(rela + j, me);
151 }
152
153 /* Increase core size by size of got & plt and set start
154 offsets for got and plt. */
155 me->core_layout.size = ALIGN(me->core_layout.size, 4);
156 me->arch.got_offset = me->core_layout.size;
157 me->core_layout.size += me->arch.got_size;
158 me->arch.plt_offset = me->core_layout.size;
159 me->core_layout.size += me->arch.plt_size;
160 return 0;
161 }
162
163 static int apply_rela_bits(Elf_Addr loc, Elf_Addr val,
164 int sign, int bits, int shift)
165 {
166 unsigned long umax;
167 long min, max;
168
169 if (val & ((1UL << shift) - 1))
170 return -ENOEXEC;
171 if (sign) {
172 val = (Elf_Addr)(((long) val) >> shift);
173 min = -(1L << (bits - 1));
174 max = (1L << (bits - 1)) - 1;
175 if ((long) val < min || (long) val > max)
176 return -ENOEXEC;
177 } else {
178 val >>= shift;
179 umax = ((1UL << (bits - 1)) << 1) - 1;
180 if ((unsigned long) val > umax)
181 return -ENOEXEC;
182 }
183
184 if (bits == 8)
185 *(unsigned char *) loc = val;
186 else if (bits == 12)
187 *(unsigned short *) loc = (val & 0xfff) |
188 (*(unsigned short *) loc & 0xf000);
189 else if (bits == 16)
190 *(unsigned short *) loc = val;
191 else if (bits == 20)
192 *(unsigned int *) loc = (val & 0xfff) << 16 |
193 (val & 0xff000) >> 4 |
194 (*(unsigned int *) loc & 0xf00000ff);
195 else if (bits == 32)
196 *(unsigned int *) loc = val;
197 else if (bits == 64)
198 *(unsigned long *) loc = val;
199 return 0;
200 }
201
202 static int apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab,
203 const char *strtab, struct module *me)
204 {
205 struct mod_arch_syminfo *info;
206 Elf_Addr loc, val;
207 int r_type, r_sym;
208 int rc = -ENOEXEC;
209
210 /* This is where to make the change */
211 loc = base + rela->r_offset;
212 /* This is the symbol it is referring to. Note that all
213 undefined symbols have been resolved. */
214 r_sym = ELF_R_SYM(rela->r_info);
215 r_type = ELF_R_TYPE(rela->r_info);
216 info = me->arch.syminfo + r_sym;
217 val = symtab[r_sym].st_value;
218
219 switch (r_type) {
220 case R_390_NONE: /* No relocation. */
221 rc = 0;
222 break;
223 case R_390_8: /* Direct 8 bit. */
224 case R_390_12: /* Direct 12 bit. */
225 case R_390_16: /* Direct 16 bit. */
226 case R_390_20: /* Direct 20 bit. */
227 case R_390_32: /* Direct 32 bit. */
228 case R_390_64: /* Direct 64 bit. */
229 val += rela->r_addend;
230 if (r_type == R_390_8)
231 rc = apply_rela_bits(loc, val, 0, 8, 0);
232 else if (r_type == R_390_12)
233 rc = apply_rela_bits(loc, val, 0, 12, 0);
234 else if (r_type == R_390_16)
235 rc = apply_rela_bits(loc, val, 0, 16, 0);
236 else if (r_type == R_390_20)
237 rc = apply_rela_bits(loc, val, 1, 20, 0);
238 else if (r_type == R_390_32)
239 rc = apply_rela_bits(loc, val, 0, 32, 0);
240 else if (r_type == R_390_64)
241 rc = apply_rela_bits(loc, val, 0, 64, 0);
242 break;
243 case R_390_PC16: /* PC relative 16 bit. */
244 case R_390_PC16DBL: /* PC relative 16 bit shifted by 1. */
245 case R_390_PC32DBL: /* PC relative 32 bit shifted by 1. */
246 case R_390_PC32: /* PC relative 32 bit. */
247 case R_390_PC64: /* PC relative 64 bit. */
248 val += rela->r_addend - loc;
249 if (r_type == R_390_PC16)
250 rc = apply_rela_bits(loc, val, 1, 16, 0);
251 else if (r_type == R_390_PC16DBL)
252 rc = apply_rela_bits(loc, val, 1, 16, 1);
253 else if (r_type == R_390_PC32DBL)
254 rc = apply_rela_bits(loc, val, 1, 32, 1);
255 else if (r_type == R_390_PC32)
256 rc = apply_rela_bits(loc, val, 1, 32, 0);
257 else if (r_type == R_390_PC64)
258 rc = apply_rela_bits(loc, val, 1, 64, 0);
259 break;
260 case R_390_GOT12: /* 12 bit GOT offset. */
261 case R_390_GOT16: /* 16 bit GOT offset. */
262 case R_390_GOT20: /* 20 bit GOT offset. */
263 case R_390_GOT32: /* 32 bit GOT offset. */
264 case R_390_GOT64: /* 64 bit GOT offset. */
265 case R_390_GOTENT: /* 32 bit PC rel. to GOT entry shifted by 1. */
266 case R_390_GOTPLT12: /* 12 bit offset to jump slot. */
267 case R_390_GOTPLT20: /* 20 bit offset to jump slot. */
268 case R_390_GOTPLT16: /* 16 bit offset to jump slot. */
269 case R_390_GOTPLT32: /* 32 bit offset to jump slot. */
270 case R_390_GOTPLT64: /* 64 bit offset to jump slot. */
271 case R_390_GOTPLTENT: /* 32 bit rel. offset to jump slot >> 1. */
272 if (info->got_initialized == 0) {
273 Elf_Addr *gotent;
274
275 gotent = me->core_layout.base + me->arch.got_offset +
276 info->got_offset;
277 *gotent = val;
278 info->got_initialized = 1;
279 }
280 val = info->got_offset + rela->r_addend;
281 if (r_type == R_390_GOT12 ||
282 r_type == R_390_GOTPLT12)
283 rc = apply_rela_bits(loc, val, 0, 12, 0);
284 else if (r_type == R_390_GOT16 ||
285 r_type == R_390_GOTPLT16)
286 rc = apply_rela_bits(loc, val, 0, 16, 0);
287 else if (r_type == R_390_GOT20 ||
288 r_type == R_390_GOTPLT20)
289 rc = apply_rela_bits(loc, val, 1, 20, 0);
290 else if (r_type == R_390_GOT32 ||
291 r_type == R_390_GOTPLT32)
292 rc = apply_rela_bits(loc, val, 0, 32, 0);
293 else if (r_type == R_390_GOT64 ||
294 r_type == R_390_GOTPLT64)
295 rc = apply_rela_bits(loc, val, 0, 64, 0);
296 else if (r_type == R_390_GOTENT ||
297 r_type == R_390_GOTPLTENT) {
298 val += (Elf_Addr) me->core_layout.base - loc;
299 rc = apply_rela_bits(loc, val, 1, 32, 1);
300 }
301 break;
302 case R_390_PLT16DBL: /* 16 bit PC rel. PLT shifted by 1. */
303 case R_390_PLT32DBL: /* 32 bit PC rel. PLT shifted by 1. */
304 case R_390_PLT32: /* 32 bit PC relative PLT address. */
305 case R_390_PLT64: /* 64 bit PC relative PLT address. */
306 case R_390_PLTOFF16: /* 16 bit offset from GOT to PLT. */
307 case R_390_PLTOFF32: /* 32 bit offset from GOT to PLT. */
308 case R_390_PLTOFF64: /* 16 bit offset from GOT to PLT. */
309 if (info->plt_initialized == 0) {
310 unsigned int *ip;
311 ip = me->core_layout.base + me->arch.plt_offset +
312 info->plt_offset;
313 ip[0] = 0x0d10e310; /* basr 1,0; lg 1,10(1); br 1 */
314 ip[1] = 0x100a0004;
315 ip[2] = 0x07f10000;
316 ip[3] = (unsigned int) (val >> 32);
317 ip[4] = (unsigned int) val;
318 info->plt_initialized = 1;
319 }
320 if (r_type == R_390_PLTOFF16 ||
321 r_type == R_390_PLTOFF32 ||
322 r_type == R_390_PLTOFF64)
323 val = me->arch.plt_offset - me->arch.got_offset +
324 info->plt_offset + rela->r_addend;
325 else {
326 if (!((r_type == R_390_PLT16DBL &&
327 val - loc + 0xffffUL < 0x1ffffeUL) ||
328 (r_type == R_390_PLT32DBL &&
329 val - loc + 0xffffffffULL < 0x1fffffffeULL)))
330 val = (Elf_Addr) me->core_layout.base +
331 me->arch.plt_offset +
332 info->plt_offset;
333 val += rela->r_addend - loc;
334 }
335 if (r_type == R_390_PLT16DBL)
336 rc = apply_rela_bits(loc, val, 1, 16, 1);
337 else if (r_type == R_390_PLTOFF16)
338 rc = apply_rela_bits(loc, val, 0, 16, 0);
339 else if (r_type == R_390_PLT32DBL)
340 rc = apply_rela_bits(loc, val, 1, 32, 1);
341 else if (r_type == R_390_PLT32 ||
342 r_type == R_390_PLTOFF32)
343 rc = apply_rela_bits(loc, val, 0, 32, 0);
344 else if (r_type == R_390_PLT64 ||
345 r_type == R_390_PLTOFF64)
346 rc = apply_rela_bits(loc, val, 0, 64, 0);
347 break;
348 case R_390_GOTOFF16: /* 16 bit offset to GOT. */
349 case R_390_GOTOFF32: /* 32 bit offset to GOT. */
350 case R_390_GOTOFF64: /* 64 bit offset to GOT. */
351 val = val + rela->r_addend -
352 ((Elf_Addr) me->core_layout.base + me->arch.got_offset);
353 if (r_type == R_390_GOTOFF16)
354 rc = apply_rela_bits(loc, val, 0, 16, 0);
355 else if (r_type == R_390_GOTOFF32)
356 rc = apply_rela_bits(loc, val, 0, 32, 0);
357 else if (r_type == R_390_GOTOFF64)
358 rc = apply_rela_bits(loc, val, 0, 64, 0);
359 break;
360 case R_390_GOTPC: /* 32 bit PC relative offset to GOT. */
361 case R_390_GOTPCDBL: /* 32 bit PC rel. off. to GOT shifted by 1. */
362 val = (Elf_Addr) me->core_layout.base + me->arch.got_offset +
363 rela->r_addend - loc;
364 if (r_type == R_390_GOTPC)
365 rc = apply_rela_bits(loc, val, 1, 32, 0);
366 else if (r_type == R_390_GOTPCDBL)
367 rc = apply_rela_bits(loc, val, 1, 32, 1);
368 break;
369 case R_390_COPY:
370 case R_390_GLOB_DAT: /* Create GOT entry. */
371 case R_390_JMP_SLOT: /* Create PLT entry. */
372 case R_390_RELATIVE: /* Adjust by program base. */
373 /* Only needed if we want to support loading of
374 modules linked with -shared. */
375 return -ENOEXEC;
376 default:
377 printk(KERN_ERR "module %s: unknown relocation: %u\n",
378 me->name, r_type);
379 return -ENOEXEC;
380 }
381 if (rc) {
382 printk(KERN_ERR "module %s: relocation error for symbol %s "
383 "(r_type %i, value 0x%lx)\n",
384 me->name, strtab + symtab[r_sym].st_name,
385 r_type, (unsigned long) val);
386 return rc;
387 }
388 return 0;
389 }
390
391 int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
392 unsigned int symindex, unsigned int relsec,
393 struct module *me)
394 {
395 Elf_Addr base;
396 Elf_Sym *symtab;
397 Elf_Rela *rela;
398 unsigned long i, n;
399 int rc;
400
401 DEBUGP("Applying relocate section %u to %u\n",
402 relsec, sechdrs[relsec].sh_info);
403 base = sechdrs[sechdrs[relsec].sh_info].sh_addr;
404 symtab = (Elf_Sym *) sechdrs[symindex].sh_addr;
405 rela = (Elf_Rela *) sechdrs[relsec].sh_addr;
406 n = sechdrs[relsec].sh_size / sizeof(Elf_Rela);
407
408 for (i = 0; i < n; i++, rela++) {
409 rc = apply_rela(rela, base, symtab, strtab, me);
410 if (rc)
411 return rc;
412 }
413 return 0;
414 }
415
416 int module_finalize(const Elf_Ehdr *hdr,
417 const Elf_Shdr *sechdrs,
418 struct module *me)
419 {
420 const Elf_Shdr *s;
421 char *secstrings;
422
423 secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
424 for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
425 if (!strcmp(".altinstructions", secstrings + s->sh_name)) {
426 /* patch .altinstructions */
427 void *aseg = (void *)s->sh_addr;
428
429 apply_alternatives(aseg, aseg + s->sh_size);
430 }
431 }
432
433 jump_label_apply_nops(me);
434 return 0;
435 }