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
get_module_load_offset(void)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 =
56e8a533cbSJason A. Donenfeld get_random_u32_inclusive(1, 1024) * PAGE_SIZE;
579dd721c6SKees Cook mutex_unlock(&module_kaslr_mutex);
58e2b32e67SKees Cook }
59e2b32e67SKees Cook return module_load_offset;
60e2b32e67SKees Cook }
61e2b32e67SKees Cook #else
get_module_load_offset(void)62e2b32e67SKees Cook static unsigned long int get_module_load_offset(void)
63e2b32e67SKees Cook {
64e2b32e67SKees Cook return 0;
65e2b32e67SKees Cook }
66e2b32e67SKees Cook #endif
67e2b32e67SKees Cook
module_alloc(unsigned long size)680fdc83b9SAmerigo Wang void *module_alloc(unsigned long size)
690fdc83b9SAmerigo Wang {
7060115fa5SKefeng 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(),
784c4eb3ecSThomas Gleixner MODULES_END, gfp_mask, PAGE_KERNEL,
794c4eb3ecSThomas Gleixner VM_FLUSH_RESET_PERMS | VM_DEFER_KMEMLEAK,
804c4eb3ecSThomas Gleixner NUMA_NO_NODE, __builtin_return_address(0));
814c4eb3ecSThomas Gleixner
8263840de2SAndrey Konovalov if (p && (kasan_alloc_module_shadow(p, size, gfp_mask) < 0)) {
83bebf56a1SAndrey Ryabinin vfree(p);
84bebf56a1SAndrey Ryabinin return NULL;
85bebf56a1SAndrey Ryabinin }
86bebf56a1SAndrey Ryabinin
87bebf56a1SAndrey Ryabinin return p;
880fdc83b9SAmerigo Wang }
890fdc83b9SAmerigo Wang
900fdc83b9SAmerigo Wang #ifdef CONFIG_X86_32
apply_relocate(Elf32_Shdr * sechdrs,const char * strtab,unsigned int symindex,unsigned int relsec,struct module * me)910fdc83b9SAmerigo Wang int apply_relocate(Elf32_Shdr *sechdrs,
920fdc83b9SAmerigo Wang const char *strtab,
930fdc83b9SAmerigo Wang unsigned int symindex,
940fdc83b9SAmerigo Wang unsigned int relsec,
950fdc83b9SAmerigo Wang struct module *me)
960fdc83b9SAmerigo Wang {
970fdc83b9SAmerigo Wang unsigned int i;
980fdc83b9SAmerigo Wang Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
990fdc83b9SAmerigo Wang Elf32_Sym *sym;
1000fdc83b9SAmerigo Wang uint32_t *location;
1010fdc83b9SAmerigo Wang
102c767a54bSJoe Perches DEBUGP("Applying relocate section %u to %u\n",
103c767a54bSJoe Perches relsec, sechdrs[relsec].sh_info);
1040fdc83b9SAmerigo Wang for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
1050fdc83b9SAmerigo Wang /* This is where to make the change */
1060fdc83b9SAmerigo Wang location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
1070fdc83b9SAmerigo Wang + rel[i].r_offset;
1080fdc83b9SAmerigo Wang /* This is the symbol it is referring to. Note that all
1090fdc83b9SAmerigo Wang undefined symbols have been resolved. */
1100fdc83b9SAmerigo Wang sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
1110fdc83b9SAmerigo Wang + ELF32_R_SYM(rel[i].r_info);
1120fdc83b9SAmerigo Wang
1130fdc83b9SAmerigo Wang switch (ELF32_R_TYPE(rel[i].r_info)) {
1140fdc83b9SAmerigo Wang case R_386_32:
1150fdc83b9SAmerigo Wang /* We add the value into the location given */
1160fdc83b9SAmerigo Wang *location += sym->st_value;
1170fdc83b9SAmerigo Wang break;
1180fdc83b9SAmerigo Wang case R_386_PC32:
119bb73d071SFangrui Song case R_386_PLT32:
1202e76c283SGeert Uytterhoeven /* Add the value, subtract its position */
1210fdc83b9SAmerigo Wang *location += sym->st_value - (uint32_t)location;
1220fdc83b9SAmerigo Wang break;
1230fdc83b9SAmerigo Wang default:
124c767a54bSJoe Perches pr_err("%s: Unknown relocation: %u\n",
1250fdc83b9SAmerigo Wang me->name, ELF32_R_TYPE(rel[i].r_info));
1260fdc83b9SAmerigo Wang return -ENOEXEC;
1270fdc83b9SAmerigo Wang }
1280fdc83b9SAmerigo Wang }
1290fdc83b9SAmerigo Wang return 0;
1300fdc83b9SAmerigo Wang }
1310fdc83b9SAmerigo Wang #else /*X86_64*/
__write_relocate_add(Elf64_Shdr * sechdrs,const char * strtab,unsigned int symindex,unsigned int relsec,struct module * me,void * (* write)(void * dest,const void * src,size_t len),bool apply)1320c05e7bdSSong Liu static int __write_relocate_add(Elf64_Shdr *sechdrs,
1330fdc83b9SAmerigo Wang const char *strtab,
1340fdc83b9SAmerigo Wang unsigned int symindex,
1350fdc83b9SAmerigo Wang unsigned int relsec,
13688fc078aSPeter Zijlstra struct module *me,
1370c05e7bdSSong Liu void *(*write)(void *dest, const void *src, size_t len),
1380c05e7bdSSong Liu bool apply)
1390fdc83b9SAmerigo Wang {
1400fdc83b9SAmerigo Wang unsigned int i;
1410fdc83b9SAmerigo Wang Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr;
1420fdc83b9SAmerigo Wang Elf64_Sym *sym;
1430fdc83b9SAmerigo Wang void *loc;
1440fdc83b9SAmerigo Wang u64 val;
1450c05e7bdSSong Liu u64 zero = 0ULL;
1460fdc83b9SAmerigo Wang
1470c05e7bdSSong Liu DEBUGP("%s relocate section %u to %u\n",
1480c05e7bdSSong Liu apply ? "Applying" : "Clearing",
149c767a54bSJoe Perches relsec, sechdrs[relsec].sh_info);
1500fdc83b9SAmerigo Wang for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
1510c05e7bdSSong Liu size_t size;
1520c05e7bdSSong Liu
1530fdc83b9SAmerigo Wang /* This is where to make the change */
1540fdc83b9SAmerigo Wang loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
1550fdc83b9SAmerigo Wang + rel[i].r_offset;
1560fdc83b9SAmerigo Wang
1570fdc83b9SAmerigo Wang /* This is the symbol it is referring to. Note that all
1580fdc83b9SAmerigo Wang undefined symbols have been resolved. */
1590fdc83b9SAmerigo Wang sym = (Elf64_Sym *)sechdrs[symindex].sh_addr
1600fdc83b9SAmerigo Wang + ELF64_R_SYM(rel[i].r_info);
1610fdc83b9SAmerigo Wang
1620fdc83b9SAmerigo Wang DEBUGP("type %d st_value %Lx r_addend %Lx loc %Lx\n",
1630fdc83b9SAmerigo Wang (int)ELF64_R_TYPE(rel[i].r_info),
1640fdc83b9SAmerigo Wang sym->st_value, rel[i].r_addend, (u64)loc);
1650fdc83b9SAmerigo Wang
1660fdc83b9SAmerigo Wang val = sym->st_value + rel[i].r_addend;
1670fdc83b9SAmerigo Wang
1680fdc83b9SAmerigo Wang switch (ELF64_R_TYPE(rel[i].r_info)) {
1690fdc83b9SAmerigo Wang case R_X86_64_NONE:
1700c05e7bdSSong Liu continue; /* nothing to write */
1710fdc83b9SAmerigo Wang case R_X86_64_64:
1720c05e7bdSSong Liu size = 8;
1730fdc83b9SAmerigo Wang break;
1740fdc83b9SAmerigo Wang case R_X86_64_32:
1750c05e7bdSSong Liu if (val != *(u32 *)&val)
1760fdc83b9SAmerigo Wang goto overflow;
1770c05e7bdSSong Liu size = 4;
1780fdc83b9SAmerigo Wang break;
1790fdc83b9SAmerigo Wang case R_X86_64_32S:
1800c05e7bdSSong Liu if ((s64)val != *(s32 *)&val)
1810fdc83b9SAmerigo Wang goto overflow;
1820c05e7bdSSong Liu size = 4;
1830fdc83b9SAmerigo Wang break;
1840fdc83b9SAmerigo Wang case R_X86_64_PC32:
185b21ebf2fSH.J. Lu case R_X86_64_PLT32:
1860fdc83b9SAmerigo Wang val -= (u64)loc;
1870c05e7bdSSong Liu size = 4;
1880fdc83b9SAmerigo Wang break;
189b40a142bSArd Biesheuvel case R_X86_64_PC64:
190b40a142bSArd Biesheuvel val -= (u64)loc;
1910c05e7bdSSong Liu size = 8;
192b40a142bSArd Biesheuvel break;
1930fdc83b9SAmerigo Wang default:
194c767a54bSJoe Perches pr_err("%s: Unknown rela relocation: %llu\n",
1950fdc83b9SAmerigo Wang me->name, ELF64_R_TYPE(rel[i].r_info));
1960fdc83b9SAmerigo Wang return -ENOEXEC;
1970fdc83b9SAmerigo Wang }
1980fdc83b9SAmerigo Wang
1990c05e7bdSSong Liu if (apply) {
2000c05e7bdSSong Liu if (memcmp(loc, &zero, size)) {
2010c05e7bdSSong Liu pr_err("x86/modules: Invalid relocation target, existing value is nonzero for type %d, loc %p, val %Lx\n",
202eda9cec4SJosh Poimboeuf (int)ELF64_R_TYPE(rel[i].r_info), loc, val);
203eda9cec4SJosh Poimboeuf return -ENOEXEC;
2040c05e7bdSSong Liu }
2050c05e7bdSSong Liu write(loc, &val, size);
2060c05e7bdSSong Liu } else {
2070c05e7bdSSong Liu if (memcmp(loc, &val, size)) {
2080c05e7bdSSong Liu pr_warn("x86/modules: Invalid relocation target, existing value does not match expected value for type %d, loc %p, val %Lx\n",
2090c05e7bdSSong Liu (int)ELF64_R_TYPE(rel[i].r_info), loc, val);
2100c05e7bdSSong Liu return -ENOEXEC;
2110c05e7bdSSong Liu }
2120c05e7bdSSong Liu write(loc, &zero, size);
2130c05e7bdSSong Liu }
2140c05e7bdSSong Liu }
2150c05e7bdSSong Liu return 0;
216eda9cec4SJosh Poimboeuf
2170fdc83b9SAmerigo Wang overflow:
218c767a54bSJoe Perches pr_err("overflow in relocation type %d val %Lx\n",
2190fdc83b9SAmerigo Wang (int)ELF64_R_TYPE(rel[i].r_info), val);
220c767a54bSJoe Perches pr_err("`%s' likely not compiled with -mcmodel=kernel\n",
2210fdc83b9SAmerigo Wang me->name);
2220fdc83b9SAmerigo Wang return -ENOEXEC;
2230fdc83b9SAmerigo Wang }
22488fc078aSPeter Zijlstra
write_relocate_add(Elf64_Shdr * sechdrs,const char * strtab,unsigned int symindex,unsigned int relsec,struct module * me,bool apply)2250c05e7bdSSong Liu static int write_relocate_add(Elf64_Shdr *sechdrs,
22688fc078aSPeter Zijlstra const char *strtab,
22788fc078aSPeter Zijlstra unsigned int symindex,
22888fc078aSPeter Zijlstra unsigned int relsec,
2290c05e7bdSSong Liu struct module *me,
2300c05e7bdSSong Liu bool apply)
23188fc078aSPeter Zijlstra {
23288fc078aSPeter Zijlstra int ret;
23388fc078aSPeter Zijlstra bool early = me->state == MODULE_STATE_UNFORMED;
23488fc078aSPeter Zijlstra void *(*write)(void *, const void *, size_t) = memcpy;
23588fc078aSPeter Zijlstra
2365b384f93SJosh Poimboeuf if (!early) {
23788fc078aSPeter Zijlstra write = text_poke;
2385b384f93SJosh Poimboeuf mutex_lock(&text_mutex);
2395b384f93SJosh Poimboeuf }
24088fc078aSPeter Zijlstra
2410c05e7bdSSong Liu ret = __write_relocate_add(sechdrs, strtab, symindex, relsec, me,
2420c05e7bdSSong Liu write, apply);
24388fc078aSPeter Zijlstra
2445b384f93SJosh Poimboeuf if (!early) {
24588fc078aSPeter Zijlstra text_poke_sync();
2465b384f93SJosh Poimboeuf mutex_unlock(&text_mutex);
2475b384f93SJosh Poimboeuf }
24888fc078aSPeter Zijlstra
24988fc078aSPeter Zijlstra return ret;
25088fc078aSPeter Zijlstra }
25188fc078aSPeter Zijlstra
apply_relocate_add(Elf64_Shdr * sechdrs,const char * strtab,unsigned int symindex,unsigned int relsec,struct module * me)2520c05e7bdSSong Liu int apply_relocate_add(Elf64_Shdr *sechdrs,
2530c05e7bdSSong Liu const char *strtab,
2540c05e7bdSSong Liu unsigned int symindex,
2550c05e7bdSSong Liu unsigned int relsec,
2560c05e7bdSSong Liu struct module *me)
2570c05e7bdSSong Liu {
2580c05e7bdSSong Liu return write_relocate_add(sechdrs, strtab, symindex, relsec, me, true);
2590c05e7bdSSong Liu }
2600c05e7bdSSong Liu
2610c05e7bdSSong Liu #ifdef CONFIG_LIVEPATCH
clear_relocate_add(Elf64_Shdr * sechdrs,const char * strtab,unsigned int symindex,unsigned int relsec,struct module * me)2620c05e7bdSSong Liu void clear_relocate_add(Elf64_Shdr *sechdrs,
2630c05e7bdSSong Liu const char *strtab,
2640c05e7bdSSong Liu unsigned int symindex,
2650c05e7bdSSong Liu unsigned int relsec,
2660c05e7bdSSong Liu struct module *me)
2670c05e7bdSSong Liu {
2680c05e7bdSSong Liu write_relocate_add(sechdrs, strtab, symindex, relsec, me, false);
2690c05e7bdSSong Liu }
2700c05e7bdSSong Liu #endif
2710c05e7bdSSong Liu
2720fdc83b9SAmerigo Wang #endif
2730fdc83b9SAmerigo Wang
module_finalize(const Elf_Ehdr * hdr,const Elf_Shdr * sechdrs,struct module * me)2742d5bf28fSAmerigo Wang int module_finalize(const Elf_Ehdr *hdr,
2752d5bf28fSAmerigo Wang const Elf_Shdr *sechdrs,
2762d5bf28fSAmerigo Wang struct module *me)
2772d5bf28fSAmerigo Wang {
278be84d8edSJulian Pidancet const Elf_Shdr *s, *alt = NULL, *locks = NULL,
27975085009SPeter Zijlstra *para = NULL, *orc = NULL, *orc_ip = NULL,
280eaf44c81SThomas Gleixner *retpolines = NULL, *returns = NULL, *ibt_endbr = NULL,
281931ab636SPeter Zijlstra *calls = NULL, *cfi = NULL;
2822d5bf28fSAmerigo Wang char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
2832d5bf28fSAmerigo Wang
2842d5bf28fSAmerigo Wang for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
2852d5bf28fSAmerigo Wang if (!strcmp(".altinstructions", secstrings + s->sh_name))
2862d5bf28fSAmerigo Wang alt = s;
2872d5bf28fSAmerigo Wang if (!strcmp(".smp_locks", secstrings + s->sh_name))
2882d5bf28fSAmerigo Wang locks = s;
2892d5bf28fSAmerigo Wang if (!strcmp(".parainstructions", secstrings + s->sh_name))
2902d5bf28fSAmerigo Wang para = s;
291ee9f8fceSJosh Poimboeuf if (!strcmp(".orc_unwind", secstrings + s->sh_name))
292ee9f8fceSJosh Poimboeuf orc = s;
293ee9f8fceSJosh Poimboeuf if (!strcmp(".orc_unwind_ip", secstrings + s->sh_name))
294ee9f8fceSJosh Poimboeuf orc_ip = s;
29575085009SPeter Zijlstra if (!strcmp(".retpoline_sites", secstrings + s->sh_name))
29675085009SPeter Zijlstra retpolines = s;
29715e67227SPeter Zijlstra if (!strcmp(".return_sites", secstrings + s->sh_name))
29815e67227SPeter Zijlstra returns = s;
299eaf44c81SThomas Gleixner if (!strcmp(".call_sites", secstrings + s->sh_name))
300eaf44c81SThomas Gleixner calls = s;
301931ab636SPeter Zijlstra if (!strcmp(".cfi_sites", secstrings + s->sh_name))
302931ab636SPeter Zijlstra cfi = s;
303ed53a0d9SPeter Zijlstra if (!strcmp(".ibt_endbr_seal", secstrings + s->sh_name))
304ed53a0d9SPeter Zijlstra ibt_endbr = s;
3052d5bf28fSAmerigo Wang }
3062d5bf28fSAmerigo Wang
3075adf3494SPeter Zijlstra /*
3085adf3494SPeter Zijlstra * See alternative_instructions() for the ordering rules between the
3095adf3494SPeter Zijlstra * various patching types.
3105adf3494SPeter Zijlstra */
3115adf3494SPeter Zijlstra if (para) {
3125adf3494SPeter Zijlstra void *pseg = (void *)para->sh_addr;
3135adf3494SPeter Zijlstra apply_paravirt(pseg, pseg + para->sh_size);
3145adf3494SPeter Zijlstra }
315931ab636SPeter Zijlstra if (retpolines || cfi) {
316931ab636SPeter Zijlstra void *rseg = NULL, *cseg = NULL;
317931ab636SPeter Zijlstra unsigned int rsize = 0, csize = 0;
318931ab636SPeter Zijlstra
319931ab636SPeter Zijlstra if (retpolines) {
320931ab636SPeter Zijlstra rseg = (void *)retpolines->sh_addr;
321931ab636SPeter Zijlstra rsize = retpolines->sh_size;
322931ab636SPeter Zijlstra }
323931ab636SPeter Zijlstra
324931ab636SPeter Zijlstra if (cfi) {
325931ab636SPeter Zijlstra cseg = (void *)cfi->sh_addr;
326931ab636SPeter Zijlstra csize = cfi->sh_size;
327931ab636SPeter Zijlstra }
328931ab636SPeter Zijlstra
329931ab636SPeter Zijlstra apply_fineibt(rseg, rseg + rsize, cseg, cseg + csize);
330931ab636SPeter Zijlstra }
33175085009SPeter Zijlstra if (retpolines) {
33275085009SPeter Zijlstra void *rseg = (void *)retpolines->sh_addr;
33375085009SPeter Zijlstra apply_retpolines(rseg, rseg + retpolines->sh_size);
33475085009SPeter Zijlstra }
33515e67227SPeter Zijlstra if (returns) {
33615e67227SPeter Zijlstra void *rseg = (void *)returns->sh_addr;
33715e67227SPeter Zijlstra apply_returns(rseg, rseg + returns->sh_size);
33815e67227SPeter Zijlstra }
3392d5bf28fSAmerigo Wang if (alt) {
3402d5bf28fSAmerigo Wang /* patch .altinstructions */
3412d5bf28fSAmerigo Wang void *aseg = (void *)alt->sh_addr;
3422d5bf28fSAmerigo Wang apply_alternatives(aseg, aseg + alt->sh_size);
3432d5bf28fSAmerigo Wang }
344eaf44c81SThomas Gleixner if (calls || para) {
345eaf44c81SThomas Gleixner struct callthunk_sites cs = {};
346eaf44c81SThomas Gleixner
347eaf44c81SThomas Gleixner if (calls) {
348eaf44c81SThomas Gleixner cs.call_start = (void *)calls->sh_addr;
349eaf44c81SThomas Gleixner cs.call_end = (void *)calls->sh_addr + calls->sh_size;
350eaf44c81SThomas Gleixner }
351eaf44c81SThomas Gleixner
352eaf44c81SThomas Gleixner if (para) {
353eaf44c81SThomas Gleixner cs.pv_start = (void *)para->sh_addr;
354eaf44c81SThomas Gleixner cs.pv_end = (void *)para->sh_addr + para->sh_size;
355eaf44c81SThomas Gleixner }
356eaf44c81SThomas Gleixner
357eaf44c81SThomas Gleixner callthunks_patch_module_calls(&cs, me);
358eaf44c81SThomas Gleixner }
359ed53a0d9SPeter Zijlstra if (ibt_endbr) {
360ed53a0d9SPeter Zijlstra void *iseg = (void *)ibt_endbr->sh_addr;
361*be0fffa5SPeter Zijlstra apply_seal_endbr(iseg, iseg + ibt_endbr->sh_size);
362ed53a0d9SPeter Zijlstra }
363be84d8edSJulian Pidancet if (locks) {
3642d5bf28fSAmerigo Wang void *lseg = (void *)locks->sh_addr;
365ac3b4328SSong Liu void *text = me->mem[MOD_TEXT].base;
366ac3b4328SSong Liu void *text_end = text + me->mem[MOD_TEXT].size;
3672d5bf28fSAmerigo Wang alternatives_smp_module_add(me, me->name,
3682d5bf28fSAmerigo Wang lseg, lseg + locks->sh_size,
369be84d8edSJulian Pidancet text, text_end);
3702d5bf28fSAmerigo Wang }
3712d5bf28fSAmerigo Wang
372ee9f8fceSJosh Poimboeuf if (orc && orc_ip)
373ee9f8fceSJosh Poimboeuf unwind_module_init(me, (void *)orc_ip->sh_addr, orc_ip->sh_size,
374ee9f8fceSJosh Poimboeuf (void *)orc->sh_addr, orc->sh_size);
375ee9f8fceSJosh Poimboeuf
3765336377dSLinus Torvalds return 0;
3772d5bf28fSAmerigo Wang }
3782d5bf28fSAmerigo Wang
module_arch_cleanup(struct module * mod)3792d5bf28fSAmerigo Wang void module_arch_cleanup(struct module *mod)
3802d5bf28fSAmerigo Wang {
3812d5bf28fSAmerigo Wang alternatives_smp_module_del(mod);
3822d5bf28fSAmerigo Wang }
383