11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 22d5bf28fSAmerigo Wang /* Kernel module help for x86. 32d5bf28fSAmerigo Wang Copyright (C) 2001 Rusty Russell. 42d5bf28fSAmerigo Wang 52d5bf28fSAmerigo Wang */ 6c767a54bSJoe Perches 7c767a54bSJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 8c767a54bSJoe Perches 92d5bf28fSAmerigo Wang #include <linux/moduleloader.h> 102d5bf28fSAmerigo Wang #include <linux/elf.h> 112d5bf28fSAmerigo Wang #include <linux/vmalloc.h> 122d5bf28fSAmerigo Wang #include <linux/fs.h> 132d5bf28fSAmerigo Wang #include <linux/string.h> 142d5bf28fSAmerigo Wang #include <linux/kernel.h> 15bebf56a1SAndrey Ryabinin #include <linux/kasan.h> 162d5bf28fSAmerigo Wang #include <linux/bug.h> 172d5bf28fSAmerigo Wang #include <linux/mm.h> 185a0e3ad6STejun Heo #include <linux/gfp.h> 19d430d3d7SJason Baron #include <linux/jump_label.h> 20e2b32e67SKees Cook #include <linux/random.h> 212d5bf28fSAmerigo Wang 2235de5b06SAndy Lutomirski #include <asm/text-patching.h> 232d5bf28fSAmerigo Wang #include <asm/page.h> 242d5bf28fSAmerigo Wang #include <asm/pgtable.h> 2578cac48cSBorislav Petkov #include <asm/setup.h> 26ee9f8fceSJosh Poimboeuf #include <asm/unwind.h> 272d5bf28fSAmerigo Wang 282d5bf28fSAmerigo Wang #if 0 29c767a54bSJoe Perches #define DEBUGP(fmt, ...) \ 30c767a54bSJoe Perches printk(KERN_DEBUG fmt, ##__VA_ARGS__) 312d5bf28fSAmerigo Wang #else 32c767a54bSJoe Perches #define DEBUGP(fmt, ...) \ 33c767a54bSJoe Perches do { \ 34c767a54bSJoe Perches if (0) \ 35c767a54bSJoe Perches printk(KERN_DEBUG fmt, ##__VA_ARGS__); \ 36c767a54bSJoe Perches } while (0) 372d5bf28fSAmerigo Wang #endif 382d5bf28fSAmerigo Wang 39e2b32e67SKees Cook #ifdef CONFIG_RANDOMIZE_BASE 40e2b32e67SKees Cook static unsigned long module_load_offset; 41e2b32e67SKees Cook 429dd721c6SKees Cook /* Mutex protects the module_load_offset. */ 439dd721c6SKees Cook static DEFINE_MUTEX(module_kaslr_mutex); 449dd721c6SKees Cook 45e2b32e67SKees Cook static unsigned long int get_module_load_offset(void) 46e2b32e67SKees Cook { 4778cac48cSBorislav Petkov if (kaslr_enabled()) { 489dd721c6SKees Cook mutex_lock(&module_kaslr_mutex); 49e2b32e67SKees Cook /* 50e2b32e67SKees Cook * Calculate the module_load_offset the first time this 51e2b32e67SKees Cook * code is called. Once calculated it stays the same until 52e2b32e67SKees Cook * reboot. 53e2b32e67SKees Cook */ 54e2b32e67SKees Cook if (module_load_offset == 0) 55e2b32e67SKees Cook module_load_offset = 56e2b32e67SKees Cook (get_random_int() % 1024 + 1) * PAGE_SIZE; 579dd721c6SKees Cook mutex_unlock(&module_kaslr_mutex); 58e2b32e67SKees Cook } 59e2b32e67SKees Cook return module_load_offset; 60e2b32e67SKees Cook } 61e2b32e67SKees Cook #else 62e2b32e67SKees Cook static unsigned long int get_module_load_offset(void) 63e2b32e67SKees Cook { 64e2b32e67SKees Cook return 0; 65e2b32e67SKees Cook } 66e2b32e67SKees Cook #endif 67e2b32e67SKees Cook 680fdc83b9SAmerigo Wang void *module_alloc(unsigned long size) 690fdc83b9SAmerigo Wang { 70bebf56a1SAndrey Ryabinin void *p; 71bebf56a1SAndrey Ryabinin 72d0a21265SDavid Rientjes if (PAGE_ALIGN(size) > MODULES_LEN) 730fdc83b9SAmerigo Wang return NULL; 74bebf56a1SAndrey Ryabinin 75bebf56a1SAndrey Ryabinin p = __vmalloc_node_range(size, MODULE_ALIGN, 76e2b32e67SKees Cook MODULES_VADDR + get_module_load_offset(), 7719809c2dSMichal Hocko MODULES_END, GFP_KERNEL, 78f2c65fb3SNadav Amit PAGE_KERNEL, 0, NUMA_NO_NODE, 79e2b32e67SKees Cook __builtin_return_address(0)); 80bebf56a1SAndrey Ryabinin if (p && (kasan_module_alloc(p, size) < 0)) { 81bebf56a1SAndrey Ryabinin vfree(p); 82bebf56a1SAndrey Ryabinin return NULL; 83bebf56a1SAndrey Ryabinin } 84bebf56a1SAndrey Ryabinin 85bebf56a1SAndrey Ryabinin return p; 860fdc83b9SAmerigo Wang } 870fdc83b9SAmerigo Wang 880fdc83b9SAmerigo Wang #ifdef CONFIG_X86_32 890fdc83b9SAmerigo Wang int apply_relocate(Elf32_Shdr *sechdrs, 900fdc83b9SAmerigo Wang const char *strtab, 910fdc83b9SAmerigo Wang unsigned int symindex, 920fdc83b9SAmerigo Wang unsigned int relsec, 930fdc83b9SAmerigo Wang struct module *me) 940fdc83b9SAmerigo Wang { 950fdc83b9SAmerigo Wang unsigned int i; 960fdc83b9SAmerigo Wang Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr; 970fdc83b9SAmerigo Wang Elf32_Sym *sym; 980fdc83b9SAmerigo Wang uint32_t *location; 990fdc83b9SAmerigo Wang 100c767a54bSJoe Perches DEBUGP("Applying relocate section %u to %u\n", 101c767a54bSJoe Perches relsec, sechdrs[relsec].sh_info); 1020fdc83b9SAmerigo Wang for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { 1030fdc83b9SAmerigo Wang /* This is where to make the change */ 1040fdc83b9SAmerigo Wang location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr 1050fdc83b9SAmerigo Wang + rel[i].r_offset; 1060fdc83b9SAmerigo Wang /* This is the symbol it is referring to. Note that all 1070fdc83b9SAmerigo Wang undefined symbols have been resolved. */ 1080fdc83b9SAmerigo Wang sym = (Elf32_Sym *)sechdrs[symindex].sh_addr 1090fdc83b9SAmerigo Wang + ELF32_R_SYM(rel[i].r_info); 1100fdc83b9SAmerigo Wang 1110fdc83b9SAmerigo Wang switch (ELF32_R_TYPE(rel[i].r_info)) { 1120fdc83b9SAmerigo Wang case R_386_32: 1130fdc83b9SAmerigo Wang /* We add the value into the location given */ 1140fdc83b9SAmerigo Wang *location += sym->st_value; 1150fdc83b9SAmerigo Wang break; 1160fdc83b9SAmerigo Wang case R_386_PC32: 1172e76c283SGeert Uytterhoeven /* Add the value, subtract its position */ 1180fdc83b9SAmerigo Wang *location += sym->st_value - (uint32_t)location; 1190fdc83b9SAmerigo Wang break; 1200fdc83b9SAmerigo Wang default: 121c767a54bSJoe Perches pr_err("%s: Unknown relocation: %u\n", 1220fdc83b9SAmerigo Wang me->name, ELF32_R_TYPE(rel[i].r_info)); 1230fdc83b9SAmerigo Wang return -ENOEXEC; 1240fdc83b9SAmerigo Wang } 1250fdc83b9SAmerigo Wang } 1260fdc83b9SAmerigo Wang return 0; 1270fdc83b9SAmerigo Wang } 1280fdc83b9SAmerigo Wang #else /*X86_64*/ 129*88fc078aSPeter Zijlstra static int __apply_relocate_add(Elf64_Shdr *sechdrs, 1300fdc83b9SAmerigo Wang const char *strtab, 1310fdc83b9SAmerigo Wang unsigned int symindex, 1320fdc83b9SAmerigo Wang unsigned int relsec, 133*88fc078aSPeter Zijlstra struct module *me, 134*88fc078aSPeter Zijlstra void *(*write)(void *dest, const void *src, size_t len)) 1350fdc83b9SAmerigo Wang { 1360fdc83b9SAmerigo Wang unsigned int i; 1370fdc83b9SAmerigo Wang Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr; 1380fdc83b9SAmerigo Wang Elf64_Sym *sym; 1390fdc83b9SAmerigo Wang void *loc; 1400fdc83b9SAmerigo Wang u64 val; 1410fdc83b9SAmerigo Wang 142c767a54bSJoe Perches DEBUGP("Applying relocate section %u to %u\n", 143c767a54bSJoe Perches relsec, sechdrs[relsec].sh_info); 1440fdc83b9SAmerigo Wang for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { 1450fdc83b9SAmerigo Wang /* This is where to make the change */ 1460fdc83b9SAmerigo Wang loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr 1470fdc83b9SAmerigo Wang + rel[i].r_offset; 1480fdc83b9SAmerigo Wang 1490fdc83b9SAmerigo Wang /* This is the symbol it is referring to. Note that all 1500fdc83b9SAmerigo Wang undefined symbols have been resolved. */ 1510fdc83b9SAmerigo Wang sym = (Elf64_Sym *)sechdrs[symindex].sh_addr 1520fdc83b9SAmerigo Wang + ELF64_R_SYM(rel[i].r_info); 1530fdc83b9SAmerigo Wang 1540fdc83b9SAmerigo Wang DEBUGP("type %d st_value %Lx r_addend %Lx loc %Lx\n", 1550fdc83b9SAmerigo Wang (int)ELF64_R_TYPE(rel[i].r_info), 1560fdc83b9SAmerigo Wang sym->st_value, rel[i].r_addend, (u64)loc); 1570fdc83b9SAmerigo Wang 1580fdc83b9SAmerigo Wang val = sym->st_value + rel[i].r_addend; 1590fdc83b9SAmerigo Wang 1600fdc83b9SAmerigo Wang switch (ELF64_R_TYPE(rel[i].r_info)) { 1610fdc83b9SAmerigo Wang case R_X86_64_NONE: 1620fdc83b9SAmerigo Wang break; 1630fdc83b9SAmerigo Wang case R_X86_64_64: 164eda9cec4SJosh Poimboeuf if (*(u64 *)loc != 0) 165eda9cec4SJosh Poimboeuf goto invalid_relocation; 166*88fc078aSPeter Zijlstra write(loc, &val, 8); 1670fdc83b9SAmerigo Wang break; 1680fdc83b9SAmerigo Wang case R_X86_64_32: 169eda9cec4SJosh Poimboeuf if (*(u32 *)loc != 0) 170eda9cec4SJosh Poimboeuf goto invalid_relocation; 171*88fc078aSPeter Zijlstra write(loc, &val, 4); 1720fdc83b9SAmerigo Wang if (val != *(u32 *)loc) 1730fdc83b9SAmerigo Wang goto overflow; 1740fdc83b9SAmerigo Wang break; 1750fdc83b9SAmerigo Wang case R_X86_64_32S: 176eda9cec4SJosh Poimboeuf if (*(s32 *)loc != 0) 177eda9cec4SJosh Poimboeuf goto invalid_relocation; 178*88fc078aSPeter Zijlstra write(loc, &val, 4); 1790fdc83b9SAmerigo Wang if ((s64)val != *(s32 *)loc) 1800fdc83b9SAmerigo Wang goto overflow; 1810fdc83b9SAmerigo Wang break; 1820fdc83b9SAmerigo Wang case R_X86_64_PC32: 183b21ebf2fSH.J. Lu case R_X86_64_PLT32: 184eda9cec4SJosh Poimboeuf if (*(u32 *)loc != 0) 185eda9cec4SJosh Poimboeuf goto invalid_relocation; 1860fdc83b9SAmerigo Wang val -= (u64)loc; 187*88fc078aSPeter Zijlstra write(loc, &val, 4); 1880fdc83b9SAmerigo Wang #if 0 1890fdc83b9SAmerigo Wang if ((s64)val != *(s32 *)loc) 1900fdc83b9SAmerigo Wang goto overflow; 1910fdc83b9SAmerigo Wang #endif 1920fdc83b9SAmerigo Wang break; 193b40a142bSArd Biesheuvel case R_X86_64_PC64: 194b40a142bSArd Biesheuvel if (*(u64 *)loc != 0) 195b40a142bSArd Biesheuvel goto invalid_relocation; 196b40a142bSArd Biesheuvel val -= (u64)loc; 197*88fc078aSPeter Zijlstra write(loc, &val, 8); 198b40a142bSArd Biesheuvel break; 1990fdc83b9SAmerigo Wang default: 200c767a54bSJoe Perches pr_err("%s: Unknown rela relocation: %llu\n", 2010fdc83b9SAmerigo Wang me->name, ELF64_R_TYPE(rel[i].r_info)); 2020fdc83b9SAmerigo Wang return -ENOEXEC; 2030fdc83b9SAmerigo Wang } 2040fdc83b9SAmerigo Wang } 2050fdc83b9SAmerigo Wang return 0; 2060fdc83b9SAmerigo Wang 207eda9cec4SJosh Poimboeuf invalid_relocation: 208eda9cec4SJosh Poimboeuf pr_err("x86/modules: Skipping invalid relocation target, existing value is nonzero for type %d, loc %p, val %Lx\n", 209eda9cec4SJosh Poimboeuf (int)ELF64_R_TYPE(rel[i].r_info), loc, val); 210eda9cec4SJosh Poimboeuf return -ENOEXEC; 211eda9cec4SJosh Poimboeuf 2120fdc83b9SAmerigo Wang overflow: 213c767a54bSJoe Perches pr_err("overflow in relocation type %d val %Lx\n", 2140fdc83b9SAmerigo Wang (int)ELF64_R_TYPE(rel[i].r_info), val); 215c767a54bSJoe Perches pr_err("`%s' likely not compiled with -mcmodel=kernel\n", 2160fdc83b9SAmerigo Wang me->name); 2170fdc83b9SAmerigo Wang return -ENOEXEC; 2180fdc83b9SAmerigo Wang } 219*88fc078aSPeter Zijlstra 220*88fc078aSPeter Zijlstra int apply_relocate_add(Elf64_Shdr *sechdrs, 221*88fc078aSPeter Zijlstra const char *strtab, 222*88fc078aSPeter Zijlstra unsigned int symindex, 223*88fc078aSPeter Zijlstra unsigned int relsec, 224*88fc078aSPeter Zijlstra struct module *me) 225*88fc078aSPeter Zijlstra { 226*88fc078aSPeter Zijlstra int ret; 227*88fc078aSPeter Zijlstra bool early = me->state == MODULE_STATE_UNFORMED; 228*88fc078aSPeter Zijlstra void *(*write)(void *, const void *, size_t) = memcpy; 229*88fc078aSPeter Zijlstra 230*88fc078aSPeter Zijlstra if (!early) 231*88fc078aSPeter Zijlstra write = text_poke; 232*88fc078aSPeter Zijlstra 233*88fc078aSPeter Zijlstra ret = __apply_relocate_add(sechdrs, strtab, symindex, relsec, me, 234*88fc078aSPeter Zijlstra write); 235*88fc078aSPeter Zijlstra 236*88fc078aSPeter Zijlstra if (!early) 237*88fc078aSPeter Zijlstra text_poke_sync(); 238*88fc078aSPeter Zijlstra 239*88fc078aSPeter Zijlstra return ret; 240*88fc078aSPeter Zijlstra } 241*88fc078aSPeter Zijlstra 2420fdc83b9SAmerigo Wang #endif 2430fdc83b9SAmerigo Wang 2442d5bf28fSAmerigo Wang int module_finalize(const Elf_Ehdr *hdr, 2452d5bf28fSAmerigo Wang const Elf_Shdr *sechdrs, 2462d5bf28fSAmerigo Wang struct module *me) 2472d5bf28fSAmerigo Wang { 2482d5bf28fSAmerigo Wang const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL, 249ee9f8fceSJosh Poimboeuf *para = NULL, *orc = NULL, *orc_ip = NULL; 2502d5bf28fSAmerigo Wang char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; 2512d5bf28fSAmerigo Wang 2522d5bf28fSAmerigo Wang for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { 2532d5bf28fSAmerigo Wang if (!strcmp(".text", secstrings + s->sh_name)) 2542d5bf28fSAmerigo Wang text = s; 2552d5bf28fSAmerigo Wang if (!strcmp(".altinstructions", secstrings + s->sh_name)) 2562d5bf28fSAmerigo Wang alt = s; 2572d5bf28fSAmerigo Wang if (!strcmp(".smp_locks", secstrings + s->sh_name)) 2582d5bf28fSAmerigo Wang locks = s; 2592d5bf28fSAmerigo Wang if (!strcmp(".parainstructions", secstrings + s->sh_name)) 2602d5bf28fSAmerigo Wang para = s; 261ee9f8fceSJosh Poimboeuf if (!strcmp(".orc_unwind", secstrings + s->sh_name)) 262ee9f8fceSJosh Poimboeuf orc = s; 263ee9f8fceSJosh Poimboeuf if (!strcmp(".orc_unwind_ip", secstrings + s->sh_name)) 264ee9f8fceSJosh Poimboeuf orc_ip = s; 2652d5bf28fSAmerigo Wang } 2662d5bf28fSAmerigo Wang 2672d5bf28fSAmerigo Wang if (alt) { 2682d5bf28fSAmerigo Wang /* patch .altinstructions */ 2692d5bf28fSAmerigo Wang void *aseg = (void *)alt->sh_addr; 2702d5bf28fSAmerigo Wang apply_alternatives(aseg, aseg + alt->sh_size); 2712d5bf28fSAmerigo Wang } 2722d5bf28fSAmerigo Wang if (locks && text) { 2732d5bf28fSAmerigo Wang void *lseg = (void *)locks->sh_addr; 2742d5bf28fSAmerigo Wang void *tseg = (void *)text->sh_addr; 2752d5bf28fSAmerigo Wang alternatives_smp_module_add(me, me->name, 2762d5bf28fSAmerigo Wang lseg, lseg + locks->sh_size, 2772d5bf28fSAmerigo Wang tseg, tseg + text->sh_size); 2782d5bf28fSAmerigo Wang } 2792d5bf28fSAmerigo Wang 2802d5bf28fSAmerigo Wang if (para) { 2812d5bf28fSAmerigo Wang void *pseg = (void *)para->sh_addr; 2822d5bf28fSAmerigo Wang apply_paravirt(pseg, pseg + para->sh_size); 2832d5bf28fSAmerigo Wang } 2842d5bf28fSAmerigo Wang 285d9f5ab7bSJason Baron /* make jump label nops */ 286d9f5ab7bSJason Baron jump_label_apply_nops(me); 287d9f5ab7bSJason Baron 288ee9f8fceSJosh Poimboeuf if (orc && orc_ip) 289ee9f8fceSJosh Poimboeuf unwind_module_init(me, (void *)orc_ip->sh_addr, orc_ip->sh_size, 290ee9f8fceSJosh Poimboeuf (void *)orc->sh_addr, orc->sh_size); 291ee9f8fceSJosh Poimboeuf 2925336377dSLinus Torvalds return 0; 2932d5bf28fSAmerigo Wang } 2942d5bf28fSAmerigo Wang 2952d5bf28fSAmerigo Wang void module_arch_cleanup(struct module *mod) 2962d5bf28fSAmerigo Wang { 2972d5bf28fSAmerigo Wang alternatives_smp_module_del(mod); 2982d5bf28fSAmerigo Wang } 299