When an incoming module is considered for livepatching by
klp_module_coming(), it iterates over multiple patches and multiple
kernel objects in this order:
list_for_each_entry(patch, &klp_patches, list) {
klp_for_each_object(patch, obj) {
which means that if one of the kernel objects fails to patch, klp_module_coming()'s error path needs to unpatch and cleanup any kernel objects that were already patched by a previous patch.
Reported-by: Miroslav Benes <
mbenes@suse.cz>
Suggested-by: Petr Mladek <
pmladek@suse.com>
Signed-off-by: Joe Lawrence <
joe.lawrence@redhat.com>
---
v2:
- cleanup comment describing the new function
- s/klp_cleanup_module_objects_limited/klp_cleanup_module_patches_limited
- added a suggested-by tag for Petr since he suggested both code and
commentary :)
kernel/livepatch/core.c | 60 ++++++++++++++++++++++++++++++-------------------
1 file changed, 37 insertions(+), 23 deletions(-)
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index b9628e43c78f..bf8c8fd72589 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -830,6 +830,41 @@ int klp_register_patch(struct klp_patch *patch)
}
EXPORT_SYMBOL_GPL(klp_register_patch);
+/*
+ * Remove parts of patches that touch a given kernel module. The list of
+ * patches processed might be limited. When limit is NULL, all patches
+ * will be handled.
+ */
+static void klp_cleanup_module_patches_limited(struct module *mod,
+ struct klp_patch *limit)
+{
+ struct klp_patch *patch;
+ struct klp_object *obj;
+
+ list_for_each_entry(patch