summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Baron <jbaron@akamai.com>2019-01-09 07:43:24 -0500
committerJiri Kosina <jkosina@suse.cz>2019-01-11 14:51:24 -0500
commit20e55025958e18e671d92c7adea00c301ac93c43 (patch)
tree3c2a116fee563aa31fd637a34d28fb6254885568
parent958ef1e39d24d6cb8bf2a7406130a98c9564230f (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.h19
-rw-r--r--kernel/livepatch/core.c9
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
173int klp_enable_patch(struct klp_patch *); 188int klp_enable_patch(struct klp_patch *);
174 189
175void arch_klp_init_object_loaded(struct klp_patch *patch, 190void 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))