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> 215b384f93SJosh Poimboeuf #include <linux/memory.h> 222d5bf28fSAmerigo Wang 2335de5b06SAndy Lutomirski #include <asm/text-patching.h> 242d5bf28fSAmerigo Wang #include <asm/page.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 { 70*60115fa5SKefeng Wang gfp_t gfp_mask = GFP_KERNEL; 71bebf56a1SAndrey Ryabinin void *p; 72bebf56a1SAndrey Ryabinin 73d0a21265SDavid Rientjes if (PAGE_ALIGN(size) > MODULES_LEN) 740fdc83b9SAmerigo Wang return NULL; 75bebf56a1SAndrey Ryabinin 76bebf56a1SAndrey Ryabinin p = __vmalloc_node_range(size, MODULE_ALIGN, 77e2b32e67SKees Cook MODULES_VADDR + get_module_load_offset(), 78*60115fa5SKefeng Wang MODULES_END, gfp_mask, 79*60115fa5SKefeng Wang PAGE_KERNEL, VM_DEFER_KMEMLEAK, NUMA_NO_NODE, 80e2b32e67SKees Cook __builtin_return_address(0)); 81*60115fa5SKefeng Wang if (p && (kasan_module_alloc(p, size, gfp_mask) < 0)) { 82bebf56a1SAndrey Ryabinin vfree(p); 83bebf56a1SAndrey Ryabinin return NULL; 84bebf56a1SAndrey Ryabinin } 85bebf56a1SAndrey Ryabinin 86bebf56a1SAndrey Ryabinin return p; 870fdc83b9SAmerigo Wang } 880fdc83b9SAmerigo Wang 890fdc83b9SAmerigo Wang #ifdef CONFIG_X86_32 900fdc83b9SAmerigo Wang int apply_relocate(Elf32_Shdr *sechdrs, 910fdc83b9SAmerigo Wang const char *strtab, 920fdc83b9SAmerigo Wang unsigned int symindex, 930fdc83b9SAmerigo Wang unsigned int relsec, 940fdc83b9SAmerigo Wang struct module *me) 950fdc83b9SAmerigo Wang { 960fdc83b9SAmerigo Wang unsigned int i; 970fdc83b9SAmerigo Wang Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr; 980fdc83b9SAmerigo Wang Elf32_Sym *sym; 990fdc83b9SAmerigo Wang uint32_t *location; 1000fdc83b9SAmerigo Wang 101c767a54bSJoe Perches DEBUGP("Applying relocate section %u to %u\n", 102c767a54bSJoe Perches relsec, sechdrs[relsec].sh_info); 1030fdc83b9SAmerigo Wang for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { 1040fdc83b9SAmerigo Wang /* This is where to make the change */ 1050fdc83b9SAmerigo Wang location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr 1060fdc83b9SAmerigo Wang + rel[i].r_offset; 1070fdc83b9SAmerigo Wang /* This is the symbol it is referring to. Note that all 1080fdc83b9SAmerigo Wang undefined symbols have been resolved. */ 1090fdc83b9SAmerigo Wang sym = (Elf32_Sym *)sechdrs[symindex].sh_addr 1100fdc83b9SAmerigo Wang + ELF32_R_SYM(rel[i].r_info); 1110fdc83b9SAmerigo Wang 1120fdc83b9SAmerigo Wang switch (ELF32_R_TYPE(rel[i].r_info)) { 1130fdc83b9SAmerigo Wang case R_386_32: 1140fdc83b9SAmerigo Wang /* We add the value into the location given */ 1150fdc83b9SAmerigo Wang *location += sym->st_value; 1160fdc83b9SAmerigo Wang break; 1170fdc83b9SAmerigo Wang case R_386_PC32: 118bb73d071SFangrui Song case R_386_PLT32: 1192e76c283SGeert Uytterhoeven /* Add the value, subtract its position */ 1200fdc83b9SAmerigo Wang *location += sym->st_value - (uint32_t)location; 1210fdc83b9SAmerigo Wang break; 1220fdc83b9SAmerigo Wang default: 123c767a54bSJoe Perches pr_err("%s: Unknown relocation: %u\n", 1240fdc83b9SAmerigo Wang me->name, ELF32_R_TYPE(rel[i].r_info)); 1250fdc83b9SAmerigo Wang return -ENOEXEC; 1260fdc83b9SAmerigo Wang } 1270fdc83b9SAmerigo Wang } 1280fdc83b9SAmerigo Wang return 0; 1290fdc83b9SAmerigo Wang } 1300fdc83b9SAmerigo Wang #else /*X86_64*/ 13188fc078aSPeter Zijlstra static int __apply_relocate_add(Elf64_Shdr *sechdrs, 1320fdc83b9SAmerigo Wang const char *strtab, 1330fdc83b9SAmerigo Wang unsigned int symindex, 1340fdc83b9SAmerigo Wang unsigned int relsec, 13588fc078aSPeter Zijlstra struct module *me, 13688fc078aSPeter Zijlstra void *(*write)(void *dest, const void *src, size_t len)) 1370fdc83b9SAmerigo Wang { 1380fdc83b9SAmerigo Wang unsigned int i; 1390fdc83b9SAmerigo Wang Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr; 1400fdc83b9SAmerigo Wang Elf64_Sym *sym; 1410fdc83b9SAmerigo Wang void *loc; 1420fdc83b9SAmerigo Wang u64 val; 1430fdc83b9SAmerigo Wang 144c767a54bSJoe Perches DEBUGP("Applying relocate section %u to %u\n", 145c767a54bSJoe Perches relsec, sechdrs[relsec].sh_info); 1460fdc83b9SAmerigo Wang for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { 1470fdc83b9SAmerigo Wang /* This is where to make the change */ 1480fdc83b9SAmerigo Wang loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr 1490fdc83b9SAmerigo Wang + rel[i].r_offset; 1500fdc83b9SAmerigo Wang 1510fdc83b9SAmerigo Wang /* This is the symbol it is referring to. Note that all 1520fdc83b9SAmerigo Wang undefined symbols have been resolved. */ 1530fdc83b9SAmerigo Wang sym = (Elf64_Sym *)sechdrs[symindex].sh_addr 1540fdc83b9SAmerigo Wang + ELF64_R_SYM(rel[i].r_info); 1550fdc83b9SAmerigo Wang 1560fdc83b9SAmerigo Wang DEBUGP("type %d st_value %Lx r_addend %Lx loc %Lx\n", 1570fdc83b9SAmerigo Wang (int)ELF64_R_TYPE(rel[i].r_info), 1580fdc83b9SAmerigo Wang sym->st_value, rel[i].r_addend, (u64)loc); 1590fdc83b9SAmerigo Wang 1600fdc83b9SAmerigo Wang val = sym->st_value + rel[i].r_addend; 1610fdc83b9SAmerigo Wang 1620fdc83b9SAmerigo Wang switch (ELF64_R_TYPE(rel[i].r_info)) { 1630fdc83b9SAmerigo Wang case R_X86_64_NONE: 1640fdc83b9SAmerigo Wang break; 1650fdc83b9SAmerigo Wang case R_X86_64_64: 166eda9cec4SJosh Poimboeuf if (*(u64 *)loc != 0) 167eda9cec4SJosh Poimboeuf goto invalid_relocation; 16888fc078aSPeter Zijlstra write(loc, &val, 8); 1690fdc83b9SAmerigo Wang break; 1700fdc83b9SAmerigo Wang case R_X86_64_32: 171eda9cec4SJosh Poimboeuf if (*(u32 *)loc != 0) 172eda9cec4SJosh Poimboeuf goto invalid_relocation; 17388fc078aSPeter Zijlstra write(loc, &val, 4); 1740fdc83b9SAmerigo Wang if (val != *(u32 *)loc) 1750fdc83b9SAmerigo Wang goto overflow; 1760fdc83b9SAmerigo Wang break; 1770fdc83b9SAmerigo Wang case R_X86_64_32S: 178eda9cec4SJosh Poimboeuf if (*(s32 *)loc != 0) 179eda9cec4SJosh Poimboeuf goto invalid_relocation; 18088fc078aSPeter Zijlstra write(loc, &val, 4); 1810fdc83b9SAmerigo Wang if ((s64)val != *(s32 *)loc) 1820fdc83b9SAmerigo Wang goto overflow; 1830fdc83b9SAmerigo Wang break; 1840fdc83b9SAmerigo Wang case R_X86_64_PC32: 185b21ebf2fSH.J. Lu case R_X86_64_PLT32: 186eda9cec4SJosh Poimboeuf if (*(u32 *)loc != 0) 187eda9cec4SJosh Poimboeuf goto invalid_relocation; 1880fdc83b9SAmerigo Wang val -= (u64)loc; 18988fc078aSPeter Zijlstra write(loc, &val, 4); 1900fdc83b9SAmerigo Wang #if 0 1910fdc83b9SAmerigo Wang if ((s64)val != *(s32 *)loc) 1920fdc83b9SAmerigo Wang goto overflow; 1930fdc83b9SAmerigo Wang #endif 1940fdc83b9SAmerigo Wang break; 195b40a142bSArd Biesheuvel case R_X86_64_PC64: 196b40a142bSArd Biesheuvel if (*(u64 *)loc != 0) 197b40a142bSArd Biesheuvel goto invalid_relocation; 198b40a142bSArd Biesheuvel val -= (u64)loc; 19988fc078aSPeter Zijlstra write(loc, &val, 8); 200b40a142bSArd Biesheuvel break; 2010fdc83b9SAmerigo Wang default: 202c767a54bSJoe Perches pr_err("%s: Unknown rela relocation: %llu\n", 2030fdc83b9SAmerigo Wang me->name, ELF64_R_TYPE(rel[i].r_info)); 2040fdc83b9SAmerigo Wang return -ENOEXEC; 2050fdc83b9SAmerigo Wang } 2060fdc83b9SAmerigo Wang } 2070fdc83b9SAmerigo Wang return 0; 2080fdc83b9SAmerigo Wang 209eda9cec4SJosh Poimboeuf invalid_relocation: 210eda9cec4SJosh Poimboeuf pr_err("x86/modules: Skipping invalid relocation target, existing value is nonzero for type %d, loc %p, val %Lx\n", 211eda9cec4SJosh Poimboeuf (int)ELF64_R_TYPE(rel[i].r_info), loc, val); 212eda9cec4SJosh Poimboeuf return -ENOEXEC; 213eda9cec4SJosh Poimboeuf 2140fdc83b9SAmerigo Wang overflow: 215c767a54bSJoe Perches pr_err("overflow in relocation type %d val %Lx\n", 2160fdc83b9SAmerigo Wang (int)ELF64_R_TYPE(rel[i].r_info), val); 217c767a54bSJoe Perches pr_err("`%s' likely not compiled with -mcmodel=kernel\n", 2180fdc83b9SAmerigo Wang me->name); 2190fdc83b9SAmerigo Wang return -ENOEXEC; 2200fdc83b9SAmerigo Wang } 22188fc078aSPeter Zijlstra 22288fc078aSPeter Zijlstra int apply_relocate_add(Elf64_Shdr *sechdrs, 22388fc078aSPeter Zijlstra const char *strtab, 22488fc078aSPeter Zijlstra unsigned int symindex, 22588fc078aSPeter Zijlstra unsigned int relsec, 22688fc078aSPeter Zijlstra struct module *me) 22788fc078aSPeter Zijlstra { 22888fc078aSPeter Zijlstra int ret; 22988fc078aSPeter Zijlstra bool early = me->state == MODULE_STATE_UNFORMED; 23088fc078aSPeter Zijlstra void *(*write)(void *, const void *, size_t) = memcpy; 23188fc078aSPeter Zijlstra 2325b384f93SJosh Poimboeuf if (!early) { 23388fc078aSPeter Zijlstra write = text_poke; 2345b384f93SJosh Poimboeuf mutex_lock(&text_mutex); 2355b384f93SJosh Poimboeuf } 23688fc078aSPeter Zijlstra 23788fc078aSPeter Zijlstra ret = __apply_relocate_add(sechdrs, strtab, symindex, relsec, me, 23888fc078aSPeter Zijlstra write); 23988fc078aSPeter Zijlstra 2405b384f93SJosh Poimboeuf if (!early) { 24188fc078aSPeter Zijlstra text_poke_sync(); 2425b384f93SJosh Poimboeuf mutex_unlock(&text_mutex); 2435b384f93SJosh Poimboeuf } 24488fc078aSPeter Zijlstra 24588fc078aSPeter Zijlstra return ret; 24688fc078aSPeter Zijlstra } 24788fc078aSPeter Zijlstra 2480fdc83b9SAmerigo Wang #endif 2490fdc83b9SAmerigo Wang 2502d5bf28fSAmerigo Wang int module_finalize(const Elf_Ehdr *hdr, 2512d5bf28fSAmerigo Wang const Elf_Shdr *sechdrs, 2522d5bf28fSAmerigo Wang struct module *me) 2532d5bf28fSAmerigo Wang { 2542d5bf28fSAmerigo Wang const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL, 25575085009SPeter Zijlstra *para = NULL, *orc = NULL, *orc_ip = NULL, 25675085009SPeter Zijlstra *retpolines = NULL; 2572d5bf28fSAmerigo Wang char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; 2582d5bf28fSAmerigo Wang 2592d5bf28fSAmerigo Wang for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { 2602d5bf28fSAmerigo Wang if (!strcmp(".text", secstrings + s->sh_name)) 2612d5bf28fSAmerigo Wang text = s; 2622d5bf28fSAmerigo Wang if (!strcmp(".altinstructions", secstrings + s->sh_name)) 2632d5bf28fSAmerigo Wang alt = s; 2642d5bf28fSAmerigo Wang if (!strcmp(".smp_locks", secstrings + s->sh_name)) 2652d5bf28fSAmerigo Wang locks = s; 2662d5bf28fSAmerigo Wang if (!strcmp(".parainstructions", secstrings + s->sh_name)) 2672d5bf28fSAmerigo Wang para = s; 268ee9f8fceSJosh Poimboeuf if (!strcmp(".orc_unwind", secstrings + s->sh_name)) 269ee9f8fceSJosh Poimboeuf orc = s; 270ee9f8fceSJosh Poimboeuf if (!strcmp(".orc_unwind_ip", secstrings + s->sh_name)) 271ee9f8fceSJosh Poimboeuf orc_ip = s; 27275085009SPeter Zijlstra if (!strcmp(".retpoline_sites", secstrings + s->sh_name)) 27375085009SPeter Zijlstra retpolines = s; 2742d5bf28fSAmerigo Wang } 2752d5bf28fSAmerigo Wang 27675085009SPeter Zijlstra if (retpolines) { 27775085009SPeter Zijlstra void *rseg = (void *)retpolines->sh_addr; 27875085009SPeter Zijlstra apply_retpolines(rseg, rseg + retpolines->sh_size); 27975085009SPeter Zijlstra } 2802d5bf28fSAmerigo Wang if (alt) { 2812d5bf28fSAmerigo Wang /* patch .altinstructions */ 2822d5bf28fSAmerigo Wang void *aseg = (void *)alt->sh_addr; 2832d5bf28fSAmerigo Wang apply_alternatives(aseg, aseg + alt->sh_size); 2842d5bf28fSAmerigo Wang } 2852d5bf28fSAmerigo Wang if (locks && text) { 2862d5bf28fSAmerigo Wang void *lseg = (void *)locks->sh_addr; 2872d5bf28fSAmerigo Wang void *tseg = (void *)text->sh_addr; 2882d5bf28fSAmerigo Wang alternatives_smp_module_add(me, me->name, 2892d5bf28fSAmerigo Wang lseg, lseg + locks->sh_size, 2902d5bf28fSAmerigo Wang tseg, tseg + text->sh_size); 2912d5bf28fSAmerigo Wang } 2922d5bf28fSAmerigo Wang 2932d5bf28fSAmerigo Wang if (para) { 2942d5bf28fSAmerigo Wang void *pseg = (void *)para->sh_addr; 2952d5bf28fSAmerigo Wang apply_paravirt(pseg, pseg + para->sh_size); 2962d5bf28fSAmerigo Wang } 2972d5bf28fSAmerigo Wang 298d9f5ab7bSJason Baron /* make jump label nops */ 299d9f5ab7bSJason Baron jump_label_apply_nops(me); 300d9f5ab7bSJason Baron 301ee9f8fceSJosh Poimboeuf if (orc && orc_ip) 302ee9f8fceSJosh Poimboeuf unwind_module_init(me, (void *)orc_ip->sh_addr, orc_ip->sh_size, 303ee9f8fceSJosh Poimboeuf (void *)orc->sh_addr, orc->sh_size); 304ee9f8fceSJosh Poimboeuf 3055336377dSLinus Torvalds return 0; 3062d5bf28fSAmerigo Wang } 3072d5bf28fSAmerigo Wang 3082d5bf28fSAmerigo Wang void module_arch_cleanup(struct module *mod) 3092d5bf28fSAmerigo Wang { 3102d5bf28fSAmerigo Wang alternatives_smp_module_del(mod); 3112d5bf28fSAmerigo Wang } 312