livepatch.c 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  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. #include <linux/module.h>
  18. #include <linux/kallsyms.h>
  19. #include <linux/livepatch.h>
  20. #include <asm/text-patching.h>
  21. /* Apply per-object alternatives. Based on x86 module_finalize() */
  22. void arch_klp_init_object_loaded(struct klp_patch *patch,
  23. struct klp_object *obj)
  24. {
  25. int cnt;
  26. struct klp_modinfo *info;
  27. Elf_Shdr *s, *alt = NULL, *para = NULL;
  28. void *aseg, *pseg;
  29. const char *objname;
  30. char sec_objname[MODULE_NAME_LEN];
  31. char secname[KSYM_NAME_LEN];
  32. info = patch->mod->klp_info;
  33. objname = obj->name ? obj->name : "vmlinux";
  34. /* See livepatch core code for BUILD_BUG_ON() explanation */
  35. BUILD_BUG_ON(MODULE_NAME_LEN < 56 || KSYM_NAME_LEN != 128);
  36. for (s = info->sechdrs; s < info->sechdrs + info->hdr.e_shnum; s++) {
  37. /* Apply per-object .klp.arch sections */
  38. cnt = sscanf(info->secstrings + s->sh_name,
  39. ".klp.arch.%55[^.].%127s",
  40. sec_objname, secname);
  41. if (cnt != 2)
  42. continue;
  43. if (strcmp(sec_objname, objname))
  44. continue;
  45. if (!strcmp(".altinstructions", secname))
  46. alt = s;
  47. if (!strcmp(".parainstructions", secname))
  48. para = s;
  49. }
  50. if (alt) {
  51. aseg = (void *) alt->sh_addr;
  52. apply_alternatives(aseg, aseg + alt->sh_size);
  53. }
  54. if (para) {
  55. pseg = (void *) para->sh_addr;
  56. apply_paravirt(pseg, pseg + para->sh_size);
  57. }
  58. }