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