1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Author: Hanlu Li <lihanlu@loongson.cn> 4 * Huacai Chen <chenhuacai@loongson.cn> 5 * 6 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited 7 */ 8 9 #define pr_fmt(fmt) "kmod: " fmt 10 11 #include <linux/moduleloader.h> 12 #include <linux/elf.h> 13 #include <linux/mm.h> 14 #include <linux/numa.h> 15 #include <linux/vmalloc.h> 16 #include <linux/slab.h> 17 #include <linux/fs.h> 18 #include <linux/ftrace.h> 19 #include <linux/string.h> 20 #include <linux/kernel.h> 21 #include <asm/alternative.h> 22 #include <asm/inst.h> 23 24 static int rela_stack_push(s64 stack_value, s64 *rela_stack, size_t *rela_stack_top) 25 { 26 if (*rela_stack_top >= RELA_STACK_DEPTH) 27 return -ENOEXEC; 28 29 rela_stack[(*rela_stack_top)++] = stack_value; 30 pr_debug("%s stack_value = 0x%llx\n", __func__, stack_value); 31 32 return 0; 33 } 34 35 static int rela_stack_pop(s64 *stack_value, s64 *rela_stack, size_t *rela_stack_top) 36 { 37 if (*rela_stack_top == 0) 38 return -ENOEXEC; 39 40 *stack_value = rela_stack[--(*rela_stack_top)]; 41 pr_debug("%s stack_value = 0x%llx\n", __func__, *stack_value); 42 43 return 0; 44 } 45 46 static int apply_r_larch_none(struct module *mod, u32 *location, Elf_Addr v, 47 s64 *rela_stack, size_t *rela_stack_top, unsigned int type) 48 { 49 return 0; 50 } 51 52 static int apply_r_larch_error(struct module *me, u32 *location, Elf_Addr v, 53 s64 *rela_stack, size_t *rela_stack_top, unsigned int type) 54 { 55 pr_err("%s: Unsupport relocation type %u, please add its support.\n", me->name, type); 56 return -EINVAL; 57 } 58 59 static int apply_r_larch_32(struct module *mod, u32 *location, Elf_Addr v, 60 s64 *rela_stack, size_t *rela_stack_top, unsigned int type) 61 { 62 *location = v; 63 return 0; 64 } 65 66 static int apply_r_larch_64(struct module *mod, u32 *location, Elf_Addr v, 67 s64 *rela_stack, size_t *rela_stack_top, unsigned int type) 68 { 69 *(Elf_Addr *)location = v; 70 return 0; 71 } 72 73 static int apply_r_larch_sop_push_pcrel(struct module *mod, u32 *location, Elf_Addr v, 74 s64 *rela_stack, size_t *rela_stack_top, unsigned int type) 75 { 76 return rela_stack_push(v - (u64)location, rela_stack, rela_stack_top); 77 } 78 79 static int apply_r_larch_sop_push_absolute(struct module *mod, u32 *location, Elf_Addr v, 80 s64 *rela_stack, size_t *rela_stack_top, unsigned int type) 81 { 82 return rela_stack_push(v, rela_stack, rela_stack_top); 83 } 84 85 static int apply_r_larch_sop_push_dup(struct module *mod, u32 *location, Elf_Addr v, 86 s64 *rela_stack, size_t *rela_stack_top, unsigned int type) 87 { 88 int err = 0; 89 s64 opr1; 90 91 err = rela_stack_pop(&opr1, rela_stack, rela_stack_top); 92 if (err) 93 return err; 94 err = rela_stack_push(opr1, rela_stack, rela_stack_top); 95 if (err) 96 return err; 97 err = rela_stack_push(opr1, rela_stack, rela_stack_top); 98 if (err) 99 return err; 100 101 return 0; 102 } 103 104 static int apply_r_larch_sop_push_plt_pcrel(struct module *mod, 105 Elf_Shdr *sechdrs, u32 *location, Elf_Addr v, 106 s64 *rela_stack, size_t *rela_stack_top, unsigned int type) 107 { 108 ptrdiff_t offset = (void *)v - (void *)location; 109 110 if (offset >= SZ_128M) 111 v = module_emit_plt_entry(mod, sechdrs, v); 112 113 if (offset < -SZ_128M) 114 v = module_emit_plt_entry(mod, sechdrs, v); 115 116 return apply_r_larch_sop_push_pcrel(mod, location, v, rela_stack, rela_stack_top, type); 117 } 118 119 static int apply_r_larch_sop(struct module *mod, u32 *location, Elf_Addr v, 120 s64 *rela_stack, size_t *rela_stack_top, unsigned int type) 121 { 122 int err = 0; 123 s64 opr1, opr2, opr3; 124 125 if (type == R_LARCH_SOP_IF_ELSE) { 126 err = rela_stack_pop(&opr3, rela_stack, rela_stack_top); 127 if (err) 128 return err; 129 } 130 131 err = rela_stack_pop(&opr2, rela_stack, rela_stack_top); 132 if (err) 133 return err; 134 err = rela_stack_pop(&opr1, rela_stack, rela_stack_top); 135 if (err) 136 return err; 137 138 switch (type) { 139 case R_LARCH_SOP_AND: 140 err = rela_stack_push(opr1 & opr2, rela_stack, rela_stack_top); 141 break; 142 case R_LARCH_SOP_ADD: 143 err = rela_stack_push(opr1 + opr2, rela_stack, rela_stack_top); 144 break; 145 case R_LARCH_SOP_SUB: 146 err = rela_stack_push(opr1 - opr2, rela_stack, rela_stack_top); 147 break; 148 case R_LARCH_SOP_SL: 149 err = rela_stack_push(opr1 << opr2, rela_stack, rela_stack_top); 150 break; 151 case R_LARCH_SOP_SR: 152 err = rela_stack_push(opr1 >> opr2, rela_stack, rela_stack_top); 153 break; 154 case R_LARCH_SOP_IF_ELSE: 155 err = rela_stack_push(opr1 ? opr2 : opr3, rela_stack, rela_stack_top); 156 break; 157 default: 158 pr_err("%s: Unsupport relocation type %u\n", mod->name, type); 159 return -EINVAL; 160 } 161 162 return err; 163 } 164 165 static int apply_r_larch_sop_imm_field(struct module *mod, u32 *location, Elf_Addr v, 166 s64 *rela_stack, size_t *rela_stack_top, unsigned int type) 167 { 168 int err = 0; 169 s64 opr1; 170 union loongarch_instruction *insn = (union loongarch_instruction *)location; 171 172 err = rela_stack_pop(&opr1, rela_stack, rela_stack_top); 173 if (err) 174 return err; 175 176 switch (type) { 177 case R_LARCH_SOP_POP_32_U_10_12: 178 if (!unsigned_imm_check(opr1, 12)) 179 goto overflow; 180 181 /* (*(uint32_t *) PC) [21 ... 10] = opr [11 ... 0] */ 182 insn->reg2i12_format.immediate = opr1 & 0xfff; 183 return 0; 184 case R_LARCH_SOP_POP_32_S_10_12: 185 if (!signed_imm_check(opr1, 12)) 186 goto overflow; 187 188 insn->reg2i12_format.immediate = opr1 & 0xfff; 189 return 0; 190 case R_LARCH_SOP_POP_32_S_10_16: 191 if (!signed_imm_check(opr1, 16)) 192 goto overflow; 193 194 insn->reg2i16_format.immediate = opr1 & 0xffff; 195 return 0; 196 case R_LARCH_SOP_POP_32_S_10_16_S2: 197 if (opr1 % 4) 198 goto unaligned; 199 200 if (!signed_imm_check(opr1, 18)) 201 goto overflow; 202 203 insn->reg2i16_format.immediate = (opr1 >> 2) & 0xffff; 204 return 0; 205 case R_LARCH_SOP_POP_32_S_5_20: 206 if (!signed_imm_check(opr1, 20)) 207 goto overflow; 208 209 insn->reg1i20_format.immediate = (opr1) & 0xfffff; 210 return 0; 211 case R_LARCH_SOP_POP_32_S_0_5_10_16_S2: 212 if (opr1 % 4) 213 goto unaligned; 214 215 if (!signed_imm_check(opr1, 23)) 216 goto overflow; 217 218 opr1 >>= 2; 219 insn->reg1i21_format.immediate_l = opr1 & 0xffff; 220 insn->reg1i21_format.immediate_h = (opr1 >> 16) & 0x1f; 221 return 0; 222 case R_LARCH_SOP_POP_32_S_0_10_10_16_S2: 223 if (opr1 % 4) 224 goto unaligned; 225 226 if (!signed_imm_check(opr1, 28)) 227 goto overflow; 228 229 opr1 >>= 2; 230 insn->reg0i26_format.immediate_l = opr1 & 0xffff; 231 insn->reg0i26_format.immediate_h = (opr1 >> 16) & 0x3ff; 232 return 0; 233 case R_LARCH_SOP_POP_32_U: 234 if (!unsigned_imm_check(opr1, 32)) 235 goto overflow; 236 237 /* (*(uint32_t *) PC) = opr */ 238 *location = (u32)opr1; 239 return 0; 240 default: 241 pr_err("%s: Unsupport relocation type %u\n", mod->name, type); 242 return -EINVAL; 243 } 244 245 overflow: 246 pr_err("module %s: opr1 = 0x%llx overflow! dangerous %s (%u) relocation\n", 247 mod->name, opr1, __func__, type); 248 return -ENOEXEC; 249 250 unaligned: 251 pr_err("module %s: opr1 = 0x%llx unaligned! dangerous %s (%u) relocation\n", 252 mod->name, opr1, __func__, type); 253 return -ENOEXEC; 254 } 255 256 static int apply_r_larch_add_sub(struct module *mod, u32 *location, Elf_Addr v, 257 s64 *rela_stack, size_t *rela_stack_top, unsigned int type) 258 { 259 switch (type) { 260 case R_LARCH_ADD32: 261 *(s32 *)location += v; 262 return 0; 263 case R_LARCH_ADD64: 264 *(s64 *)location += v; 265 return 0; 266 case R_LARCH_SUB32: 267 *(s32 *)location -= v; 268 return 0; 269 case R_LARCH_SUB64: 270 *(s64 *)location -= v; 271 return 0; 272 default: 273 pr_err("%s: Unsupport relocation type %u\n", mod->name, type); 274 return -EINVAL; 275 } 276 } 277 278 static int apply_r_larch_b26(struct module *mod, 279 Elf_Shdr *sechdrs, u32 *location, Elf_Addr v, 280 s64 *rela_stack, size_t *rela_stack_top, unsigned int type) 281 { 282 ptrdiff_t offset = (void *)v - (void *)location; 283 union loongarch_instruction *insn = (union loongarch_instruction *)location; 284 285 if (offset >= SZ_128M) 286 v = module_emit_plt_entry(mod, sechdrs, v); 287 288 if (offset < -SZ_128M) 289 v = module_emit_plt_entry(mod, sechdrs, v); 290 291 offset = (void *)v - (void *)location; 292 293 if (offset & 3) { 294 pr_err("module %s: jump offset = 0x%llx unaligned! dangerous R_LARCH_B26 (%u) relocation\n", 295 mod->name, (long long)offset, type); 296 return -ENOEXEC; 297 } 298 299 if (!signed_imm_check(offset, 28)) { 300 pr_err("module %s: jump offset = 0x%llx overflow! dangerous R_LARCH_B26 (%u) relocation\n", 301 mod->name, (long long)offset, type); 302 return -ENOEXEC; 303 } 304 305 offset >>= 2; 306 insn->reg0i26_format.immediate_l = offset & 0xffff; 307 insn->reg0i26_format.immediate_h = (offset >> 16) & 0x3ff; 308 309 return 0; 310 } 311 312 static int apply_r_larch_pcala(struct module *mod, u32 *location, Elf_Addr v, 313 s64 *rela_stack, size_t *rela_stack_top, unsigned int type) 314 { 315 union loongarch_instruction *insn = (union loongarch_instruction *)location; 316 /* Use s32 for a sign-extension deliberately. */ 317 s32 offset_hi20 = (void *)((v + 0x800) & ~0xfff) - 318 (void *)((Elf_Addr)location & ~0xfff); 319 Elf_Addr anchor = (((Elf_Addr)location) & ~0xfff) + offset_hi20; 320 ptrdiff_t offset_rem = (void *)v - (void *)anchor; 321 322 switch (type) { 323 case R_LARCH_PCALA_LO12: 324 insn->reg2i12_format.immediate = v & 0xfff; 325 break; 326 case R_LARCH_PCALA_HI20: 327 v = offset_hi20 >> 12; 328 insn->reg1i20_format.immediate = v & 0xfffff; 329 break; 330 case R_LARCH_PCALA64_LO20: 331 v = offset_rem >> 32; 332 insn->reg1i20_format.immediate = v & 0xfffff; 333 break; 334 case R_LARCH_PCALA64_HI12: 335 v = offset_rem >> 52; 336 insn->reg2i12_format.immediate = v & 0xfff; 337 break; 338 default: 339 pr_err("%s: Unsupport relocation type %u\n", mod->name, type); 340 return -EINVAL; 341 } 342 343 return 0; 344 } 345 346 static int apply_r_larch_got_pc(struct module *mod, 347 Elf_Shdr *sechdrs, u32 *location, Elf_Addr v, 348 s64 *rela_stack, size_t *rela_stack_top, unsigned int type) 349 { 350 Elf_Addr got = module_emit_got_entry(mod, sechdrs, v); 351 352 if (!got) 353 return -EINVAL; 354 355 switch (type) { 356 case R_LARCH_GOT_PC_LO12: 357 type = R_LARCH_PCALA_LO12; 358 break; 359 case R_LARCH_GOT_PC_HI20: 360 type = R_LARCH_PCALA_HI20; 361 break; 362 default: 363 pr_err("%s: Unsupport relocation type %u\n", mod->name, type); 364 return -EINVAL; 365 } 366 367 return apply_r_larch_pcala(mod, location, got, rela_stack, rela_stack_top, type); 368 } 369 370 /* 371 * reloc_handlers_rela() - Apply a particular relocation to a module 372 * @mod: the module to apply the reloc to 373 * @location: the address at which the reloc is to be applied 374 * @v: the value of the reloc, with addend for RELA-style 375 * @rela_stack: the stack used for store relocation info, LOCAL to THIS module 376 * @rela_stac_top: where the stack operation(pop/push) applies to 377 * 378 * Return: 0 upon success, else -ERRNO 379 */ 380 typedef int (*reloc_rela_handler)(struct module *mod, u32 *location, Elf_Addr v, 381 s64 *rela_stack, size_t *rela_stack_top, unsigned int type); 382 383 /* The handlers for known reloc types */ 384 static reloc_rela_handler reloc_rela_handlers[] = { 385 [R_LARCH_NONE ... R_LARCH_RELAX] = apply_r_larch_error, 386 387 [R_LARCH_NONE] = apply_r_larch_none, 388 [R_LARCH_32] = apply_r_larch_32, 389 [R_LARCH_64] = apply_r_larch_64, 390 [R_LARCH_MARK_LA] = apply_r_larch_none, 391 [R_LARCH_MARK_PCREL] = apply_r_larch_none, 392 [R_LARCH_SOP_PUSH_PCREL] = apply_r_larch_sop_push_pcrel, 393 [R_LARCH_SOP_PUSH_ABSOLUTE] = apply_r_larch_sop_push_absolute, 394 [R_LARCH_SOP_PUSH_DUP] = apply_r_larch_sop_push_dup, 395 [R_LARCH_SOP_SUB ... R_LARCH_SOP_IF_ELSE] = apply_r_larch_sop, 396 [R_LARCH_SOP_POP_32_S_10_5 ... R_LARCH_SOP_POP_32_U] = apply_r_larch_sop_imm_field, 397 [R_LARCH_ADD32 ... R_LARCH_SUB64] = apply_r_larch_add_sub, 398 [R_LARCH_PCALA_HI20...R_LARCH_PCALA64_HI12] = apply_r_larch_pcala, 399 }; 400 401 int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, 402 unsigned int symindex, unsigned int relsec, 403 struct module *mod) 404 { 405 int i, err; 406 unsigned int type; 407 s64 rela_stack[RELA_STACK_DEPTH]; 408 size_t rela_stack_top = 0; 409 reloc_rela_handler handler; 410 void *location; 411 Elf_Addr v; 412 Elf_Sym *sym; 413 Elf_Rela *rel = (void *) sechdrs[relsec].sh_addr; 414 415 pr_debug("%s: Applying relocate section %u to %u\n", __func__, relsec, 416 sechdrs[relsec].sh_info); 417 418 rela_stack_top = 0; 419 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { 420 /* This is where to make the change */ 421 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + rel[i].r_offset; 422 /* This is the symbol it is referring to */ 423 sym = (Elf_Sym *)sechdrs[symindex].sh_addr + ELF_R_SYM(rel[i].r_info); 424 if (IS_ERR_VALUE(sym->st_value)) { 425 /* Ignore unresolved weak symbol */ 426 if (ELF_ST_BIND(sym->st_info) == STB_WEAK) 427 continue; 428 pr_warn("%s: Unknown symbol %s\n", mod->name, strtab + sym->st_name); 429 return -ENOENT; 430 } 431 432 type = ELF_R_TYPE(rel[i].r_info); 433 434 if (type < ARRAY_SIZE(reloc_rela_handlers)) 435 handler = reloc_rela_handlers[type]; 436 else 437 handler = NULL; 438 439 if (!handler) { 440 pr_err("%s: Unknown relocation type %u\n", mod->name, type); 441 return -EINVAL; 442 } 443 444 pr_debug("type %d st_value %llx r_addend %llx loc %llx\n", 445 (int)ELF_R_TYPE(rel[i].r_info), 446 sym->st_value, rel[i].r_addend, (u64)location); 447 448 v = sym->st_value + rel[i].r_addend; 449 switch (type) { 450 case R_LARCH_B26: 451 err = apply_r_larch_b26(mod, sechdrs, location, 452 v, rela_stack, &rela_stack_top, type); 453 break; 454 case R_LARCH_GOT_PC_HI20...R_LARCH_GOT_PC_LO12: 455 err = apply_r_larch_got_pc(mod, sechdrs, location, 456 v, rela_stack, &rela_stack_top, type); 457 break; 458 case R_LARCH_SOP_PUSH_PLT_PCREL: 459 err = apply_r_larch_sop_push_plt_pcrel(mod, sechdrs, location, 460 v, rela_stack, &rela_stack_top, type); 461 break; 462 default: 463 err = handler(mod, location, v, rela_stack, &rela_stack_top, type); 464 } 465 if (err) 466 return err; 467 } 468 469 return 0; 470 } 471 472 void *module_alloc(unsigned long size) 473 { 474 return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END, 475 GFP_KERNEL, PAGE_KERNEL, 0, NUMA_NO_NODE, __builtin_return_address(0)); 476 } 477 478 static void module_init_ftrace_plt(const Elf_Ehdr *hdr, 479 const Elf_Shdr *sechdrs, struct module *mod) 480 { 481 #ifdef CONFIG_DYNAMIC_FTRACE 482 struct plt_entry *ftrace_plts; 483 484 ftrace_plts = (void *)sechdrs->sh_addr; 485 486 ftrace_plts[FTRACE_PLT_IDX] = emit_plt_entry(FTRACE_ADDR); 487 488 if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS)) 489 ftrace_plts[FTRACE_REGS_PLT_IDX] = emit_plt_entry(FTRACE_REGS_ADDR); 490 491 mod->arch.ftrace_trampolines = ftrace_plts; 492 #endif 493 } 494 495 int module_finalize(const Elf_Ehdr *hdr, 496 const Elf_Shdr *sechdrs, struct module *mod) 497 { 498 const Elf_Shdr *s, *se; 499 const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; 500 501 for (s = sechdrs, se = sechdrs + hdr->e_shnum; s < se; s++) { 502 if (!strcmp(".altinstructions", secstrs + s->sh_name)) 503 apply_alternatives((void *)s->sh_addr, (void *)s->sh_addr + s->sh_size); 504 if (!strcmp(".ftrace_trampoline", secstrs + s->sh_name)) 505 module_init_ftrace_plt(hdr, s, mod); 506 } 507 508 return 0; 509 } 510