Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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
12static struct klp_patch *patch;
13
14static 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
83err_free_objs:
84 kfree(objs);
85err_free_patch:
86 kfree(patch);
87err:
88 return ret;
89}
90
91static 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
102module_init(livepatch_mod_init);
103module_exit(livepatch_mod_exit);
104MODULE_LICENSE("GPL");
105MODULE_INFO(livepatch, "Y");
106MODULE_DESCRIPTION("Livepatch module");