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