/* * livepatch.c - x86-specific Kernel Live Patching Core * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . */ #include #include #include #include /* Apply per-object alternatives. Based on x86 module_finalize() */ void arch_klp_init_object_loaded(struct klp_patch *patch, struct klp_object *obj) { int cnt; struct klp_modinfo *info; Elf_Shdr *s, *alt = NULL, *para = NULL; void *aseg, *pseg; const char *objname; char sec_objname[MODULE_NAME_LEN]; char secname[KSYM_NAME_LEN]; info = patch->mod->klp_info; objname = obj->name ? obj->name : "vmlinux"; /* See livepatch core code for BUILD_BUG_ON() explanation */ BUILD_BUG_ON(MODULE_NAME_LEN < 56 || KSYM_NAME_LEN != 128); for (s = info->sechdrs; s < info->sechdrs + info->hdr.e_shnum; s++) { /* Apply per-object .klp.arch sections */ cnt = sscanf(info->secstrings + s->sh_name, ".klp.arch.%55[^.].%127s", sec_objname, secname); if (cnt != 2) continue; if (strcmp(sec_objname, objname)) continue; if (!strcmp(".altinstructions", secname)) alt = s; if (!strcmp(".parainstructions", secname)) para = s; } if (alt) { aseg = (void *) alt->sh_addr; apply_alternatives(aseg, aseg + alt->sh_size); } if (para) { pseg = (void *) para->sh_addr; apply_paravirt(pseg, pseg + para->sh_size); } }