]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - arch/x86/kernel/livepatch.c
x86/boot/64/clang: Use fixup_pointer() to access 'next_early_pgt'
[karo-tx-linux.git] / arch / x86 / kernel / livepatch.c
1 /*
2  * livepatch.c - x86-specific Kernel Live Patching Core
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include <linux/module.h>
19 #include <linux/kallsyms.h>
20 #include <linux/livepatch.h>
21 #include <asm/text-patching.h>
22
23 /* Apply per-object alternatives. Based on x86 module_finalize() */
24 void arch_klp_init_object_loaded(struct klp_patch *patch,
25                                  struct klp_object *obj)
26 {
27         int cnt;
28         struct klp_modinfo *info;
29         Elf_Shdr *s, *alt = NULL, *para = NULL;
30         void *aseg, *pseg;
31         const char *objname;
32         char sec_objname[MODULE_NAME_LEN];
33         char secname[KSYM_NAME_LEN];
34
35         info = patch->mod->klp_info;
36         objname = obj->name ? obj->name : "vmlinux";
37
38         /* See livepatch core code for BUILD_BUG_ON() explanation */
39         BUILD_BUG_ON(MODULE_NAME_LEN < 56 || KSYM_NAME_LEN != 128);
40
41         for (s = info->sechdrs; s < info->sechdrs + info->hdr.e_shnum; s++) {
42                 /* Apply per-object .klp.arch sections */
43                 cnt = sscanf(info->secstrings + s->sh_name,
44                              ".klp.arch.%55[^.].%127s",
45                              sec_objname, secname);
46                 if (cnt != 2)
47                         continue;
48                 if (strcmp(sec_objname, objname))
49                         continue;
50                 if (!strcmp(".altinstructions", secname))
51                         alt = s;
52                 if (!strcmp(".parainstructions", secname))
53                         para = s;
54         }
55
56         if (alt) {
57                 aseg = (void *) alt->sh_addr;
58                 apply_alternatives(aseg, aseg + alt->sh_size);
59         }
60
61         if (para) {
62                 pseg = (void *) para->sh_addr;
63                 apply_paravirt(pseg, pseg + para->sh_size);
64         }
65 }