xref: /linux/scripts/livepatch/init.c (revision 59adee07b568fb78e2bf07df1f22f3fe45b7240a)
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