init.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Init code for a livepatch kernel module
  4. */
  5. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  6. #include <linux/kernel.h>
  7. #include <linux/slab.h>
  8. #include <linux/livepatch.h>
  9. static struct klp_patch *patch;
  10. static int __init livepatch_mod_init(void)
  11. {
  12. struct klp_object_ext *obj_exts;
  13. size_t obj_exts_sec_size;
  14. struct klp_object *objs;
  15. unsigned int nr_objs;
  16. int ret;
  17. obj_exts = klp_find_section_by_name(THIS_MODULE, ".init.klp_objects",
  18. &obj_exts_sec_size);
  19. nr_objs = obj_exts_sec_size / sizeof(*obj_exts);
  20. if (!nr_objs) {
  21. pr_err("nothing to patch!\n");
  22. ret = -EINVAL;
  23. goto err;
  24. }
  25. patch = kzalloc_obj(*patch);
  26. if (!patch) {
  27. ret = -ENOMEM;
  28. goto err;
  29. }
  30. objs = kzalloc(sizeof(struct klp_object) * (nr_objs + 1), GFP_KERNEL);
  31. if (!objs) {
  32. ret = -ENOMEM;
  33. goto err_free_patch;
  34. }
  35. for (int i = 0; i < nr_objs; i++) {
  36. struct klp_object_ext *obj_ext = obj_exts + i;
  37. struct klp_func_ext *funcs_ext = obj_ext->funcs;
  38. unsigned int nr_funcs = obj_ext->nr_funcs;
  39. struct klp_func *funcs = objs[i].funcs;
  40. struct klp_object *obj = objs + i;
  41. funcs = kzalloc(sizeof(struct klp_func) * (nr_funcs + 1), GFP_KERNEL);
  42. if (!funcs) {
  43. ret = -ENOMEM;
  44. for (int j = 0; j < i; j++)
  45. kfree(objs[i].funcs);
  46. goto err_free_objs;
  47. }
  48. for (int j = 0; j < nr_funcs; j++) {
  49. funcs[j].old_name = funcs_ext[j].old_name;
  50. funcs[j].new_func = funcs_ext[j].new_func;
  51. funcs[j].old_sympos = funcs_ext[j].sympos;
  52. }
  53. obj->name = obj_ext->name;
  54. obj->funcs = funcs;
  55. memcpy(&obj->callbacks, &obj_ext->callbacks, sizeof(struct klp_callbacks));
  56. }
  57. patch->mod = THIS_MODULE;
  58. patch->objs = objs;
  59. /* TODO patch->states */
  60. #ifdef KLP_NO_REPLACE
  61. patch->replace = false;
  62. #else
  63. patch->replace = true;
  64. #endif
  65. return klp_enable_patch(patch);
  66. err_free_objs:
  67. kfree(objs);
  68. err_free_patch:
  69. kfree(patch);
  70. err:
  71. return ret;
  72. }
  73. static void __exit livepatch_mod_exit(void)
  74. {
  75. struct klp_object *obj;
  76. klp_for_each_object_static(patch, obj)
  77. kfree(obj->funcs);
  78. kfree(patch->objs);
  79. kfree(patch);
  80. }
  81. module_init(livepatch_mod_init);
  82. module_exit(livepatch_mod_exit);
  83. MODULE_LICENSE("GPL");
  84. MODULE_INFO(livepatch, "Y");
  85. MODULE_DESCRIPTION("Livepatch module");