diff options
author | Jason Baron <jbaron@akamai.com> | 2019-01-09 07:43:24 -0500 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2019-01-11 14:51:24 -0500 |
commit | 20e55025958e18e671d92c7adea00c301ac93c43 (patch) | |
tree | 3c2a116fee563aa31fd637a34d28fb6254885568 | |
parent | 958ef1e39d24d6cb8bf2a7406130a98c9564230f (diff) |
livepatch: Use lists to manage patches, objects and functions
Currently klp_patch contains a pointer to a statically allocated array of
struct klp_object and struct klp_objects contains a pointer to a statically
allocated array of klp_func. In order to allow for the dynamic allocation
of objects and functions, link klp_patch, klp_object, and klp_func together
via linked lists. This allows us to more easily allocate new objects and
functions, while having the iterator be a simple linked list walk.
The static structures are added to the lists early. It allows to add
the dynamically allocated objects before klp_init_object() and
klp_init_func() calls. Therefore it reduces the further changes
to the code.
This patch does not change the existing behavior.
Signed-off-by: Jason Baron <jbaron@akamai.com>
[pmladek@suse.com: Initialize lists before init calls]
Signed-off-by: Petr Mladek <pmladek@suse.com>
Acked-by: Miroslav Benes <mbenes@suse.cz>
Acked-by: Joe Lawrence <joe.lawrence@redhat.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Jiri Kosina <jikos@kernel.org>
Acked-by: Josh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r-- | include/linux/livepatch.h | 19 | ||||
-rw-r--r-- | kernel/livepatch/core.c | 9 |
2 files changed, 24 insertions, 4 deletions
diff --git a/include/linux/livepatch.h b/include/linux/livepatch.h index 8f9c19c69744..e117e20ff771 100644 --- a/include/linux/livepatch.h +++ b/include/linux/livepatch.h | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/ftrace.h> | 25 | #include <linux/ftrace.h> |
26 | #include <linux/completion.h> | 26 | #include <linux/completion.h> |
27 | #include <linux/list.h> | ||
27 | 28 | ||
28 | #if IS_ENABLED(CONFIG_LIVEPATCH) | 29 | #if IS_ENABLED(CONFIG_LIVEPATCH) |
29 | 30 | ||
@@ -42,6 +43,7 @@ | |||
42 | * can be found (optional) | 43 | * can be found (optional) |
43 | * @old_func: pointer to the function being patched | 44 | * @old_func: pointer to the function being patched |
44 | * @kobj: kobject for sysfs resources | 45 | * @kobj: kobject for sysfs resources |
46 | * @node: list node for klp_object func_list | ||
45 | * @stack_node: list node for klp_ops func_stack list | 47 | * @stack_node: list node for klp_ops func_stack list |
46 | * @old_size: size of the old function | 48 | * @old_size: size of the old function |
47 | * @new_size: size of the new function | 49 | * @new_size: size of the new function |
@@ -80,6 +82,7 @@ struct klp_func { | |||
80 | /* internal */ | 82 | /* internal */ |
81 | void *old_func; | 83 | void *old_func; |
82 | struct kobject kobj; | 84 | struct kobject kobj; |
85 | struct list_head node; | ||
83 | struct list_head stack_node; | 86 | struct list_head stack_node; |
84 | unsigned long old_size, new_size; | 87 | unsigned long old_size, new_size; |
85 | bool kobj_added; | 88 | bool kobj_added; |
@@ -117,6 +120,8 @@ struct klp_callbacks { | |||
117 | * @funcs: function entries for functions to be patched in the object | 120 | * @funcs: function entries for functions to be patched in the object |
118 | * @callbacks: functions to be executed pre/post (un)patching | 121 | * @callbacks: functions to be executed pre/post (un)patching |
119 | * @kobj: kobject for sysfs resources | 122 | * @kobj: kobject for sysfs resources |
123 | * @func_list: dynamic list of the function entries | ||
124 | * @node: list node for klp_patch obj_list | ||
120 | * @mod: kernel module associated with the patched object | 125 | * @mod: kernel module associated with the patched object |
121 | * (NULL for vmlinux) | 126 | * (NULL for vmlinux) |
122 | * @kobj_added: @kobj has been added and needs freeing | 127 | * @kobj_added: @kobj has been added and needs freeing |
@@ -130,6 +135,8 @@ struct klp_object { | |||
130 | 135 | ||
131 | /* internal */ | 136 | /* internal */ |
132 | struct kobject kobj; | 137 | struct kobject kobj; |
138 | struct list_head func_list; | ||
139 | struct list_head node; | ||
133 | struct module *mod; | 140 | struct module *mod; |
134 | bool kobj_added; | 141 | bool kobj_added; |
135 | bool patched; | 142 | bool patched; |
@@ -141,6 +148,7 @@ struct klp_object { | |||
141 | * @objs: object entries for kernel objects to be patched | 148 | * @objs: object entries for kernel objects to be patched |
142 | * @list: list node for global list of actively used patches | 149 | * @list: list node for global list of actively used patches |
143 | * @kobj: kobject for sysfs resources | 150 | * @kobj: kobject for sysfs resources |
151 | * @obj_list: dynamic list of the object entries | ||
144 | * @kobj_added: @kobj has been added and needs freeing | 152 | * @kobj_added: @kobj has been added and needs freeing |
145 | * @enabled: the patch is enabled (but operation may be incomplete) | 153 | * @enabled: the patch is enabled (but operation may be incomplete) |
146 | * @forced: was involved in a forced transition | 154 | * @forced: was involved in a forced transition |
@@ -155,6 +163,7 @@ struct klp_patch { | |||
155 | /* internal */ | 163 | /* internal */ |
156 | struct list_head list; | 164 | struct list_head list; |
157 | struct kobject kobj; | 165 | struct kobject kobj; |
166 | struct list_head obj_list; | ||
158 | bool kobj_added; | 167 | bool kobj_added; |
159 | bool enabled; | 168 | bool enabled; |
160 | bool forced; | 169 | bool forced; |
@@ -162,14 +171,20 @@ struct klp_patch { | |||
162 | struct completion finish; | 171 | struct completion finish; |
163 | }; | 172 | }; |
164 | 173 | ||
165 | #define klp_for_each_object(patch, obj) \ | 174 | #define klp_for_each_object_static(patch, obj) \ |
166 | for (obj = patch->objs; obj->funcs || obj->name; obj++) | 175 | for (obj = patch->objs; obj->funcs || obj->name; obj++) |
167 | 176 | ||
168 | #define klp_for_each_func(obj, func) \ | 177 | #define klp_for_each_object(patch, obj) \ |
178 | list_for_each_entry(obj, &patch->obj_list, node) | ||
179 | |||
180 | #define klp_for_each_func_static(obj, func) \ | ||
169 | for (func = obj->funcs; \ | 181 | for (func = obj->funcs; \ |
170 | func->old_name || func->new_func || func->old_sympos; \ | 182 | func->old_name || func->new_func || func->old_sympos; \ |
171 | func++) | 183 | func++) |
172 | 184 | ||
185 | #define klp_for_each_func(obj, func) \ | ||
186 | list_for_each_entry(func, &obj->func_list, node) | ||
187 | |||
173 | int klp_enable_patch(struct klp_patch *); | 188 | int klp_enable_patch(struct klp_patch *); |
174 | 189 | ||
175 | void arch_klp_init_object_loaded(struct klp_patch *patch, | 190 | void arch_klp_init_object_loaded(struct klp_patch *patch, |
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c index bd41b03a72d5..37d0d3645fa6 100644 --- a/kernel/livepatch/core.c +++ b/kernel/livepatch/core.c | |||
@@ -659,20 +659,25 @@ static int klp_init_patch_early(struct klp_patch *patch) | |||
659 | return -EINVAL; | 659 | return -EINVAL; |
660 | 660 | ||
661 | INIT_LIST_HEAD(&patch->list); | 661 | INIT_LIST_HEAD(&patch->list); |
662 | INIT_LIST_HEAD(&patch->obj_list); | ||
662 | patch->kobj_added = false; | 663 | patch->kobj_added = false; |
663 | patch->enabled = false; | 664 | patch->enabled = false; |
664 | patch->forced = false; | 665 | patch->forced = false; |
665 | INIT_WORK(&patch->free_work, klp_free_patch_work_fn); | 666 | INIT_WORK(&patch->free_work, klp_free_patch_work_fn); |
666 | init_completion(&patch->finish); | 667 | init_completion(&patch->finish); |
667 | 668 | ||
668 | klp_for_each_object(patch, obj) { | 669 | klp_for_each_object_static(patch, obj) { |
669 | if (!obj->funcs) | 670 | if (!obj->funcs) |
670 | return -EINVAL; | 671 | return -EINVAL; |
671 | 672 | ||
673 | INIT_LIST_HEAD(&obj->func_list); | ||
672 | obj->kobj_added = false; | 674 | obj->kobj_added = false; |
675 | list_add_tail(&obj->node, &patch->obj_list); | ||
673 | 676 | ||
674 | klp_for_each_func(obj, func) | 677 | klp_for_each_func_static(obj, func) { |
675 | func->kobj_added = false; | 678 | func->kobj_added = false; |
679 | list_add_tail(&func->node, &obj->func_list); | ||
680 | } | ||
676 | } | 681 | } |
677 | 682 | ||
678 | if (!try_module_get(patch->mod)) | 683 | if (!try_module_get(patch->mod)) |