summaryrefslogtreecommitdiffstats
path: root/kernel/livepatch
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2020-04-29 17:24:45 +0200
committerJiri Kosina <jkosina@suse.cz>2020-05-08 00:12:42 +0200
commit1d05334d2899bd3ecdf01beb53f0a70884a7f471 (patch)
treeb6e55679f1261a26b7c590c1f2542b1667cd90d0 /kernel/livepatch
parentlivepatch: Apply vmlinux-specific KLP relocations early (diff)
downloadlinux-1d05334d2899bd3ecdf01beb53f0a70884a7f471.tar.xz
linux-1d05334d2899bd3ecdf01beb53f0a70884a7f471.zip
livepatch: Remove .klp.arch
After the previous patch, vmlinux-specific KLP relocations are now applied early during KLP module load. This means that .klp.arch sections are no longer needed for *vmlinux-specific* KLP relocations. One might think they're still needed for *module-specific* KLP relocations. If a to-be-patched module is loaded *after* its corresponding KLP module is loaded, any corresponding KLP relocations will be delayed until the to-be-patched module is loaded. If any special sections (.parainstructions, for example) rely on those relocations, their initializations (apply_paravirt) need to be done afterwards. Thus the apparent need for arch_klp_init_object_loaded() and its corresponding .klp.arch sections -- it allows some of the special section initializations to be done at a later time. But... if you look closer, that dependency between the special sections and the module-specific KLP relocations doesn't actually exist in reality. Looking at the contents of the .altinstructions and .parainstructions sections, there's not a realistic scenario in which a KLP module's .altinstructions or .parainstructions section needs to access a symbol in a to-be-patched module. It might need to access a local symbol or even a vmlinux symbol; but not another module's symbol. When a special section needs to reference a local or vmlinux symbol, a normal rela can be used instead of a KLP rela. Since the special section initializations don't actually have any real dependency on module-specific KLP relocations, .klp.arch and arch_klp_init_object_loaded() no longer have a reason to exist. So remove them. As Peter said much more succinctly: So the reason for .klp.arch was that .klp.rela.* stuff would overwrite paravirt instructions. If that happens you're doing it wrong. Those RELAs are core kernel, not module, and thus should've happened in .rela.* sections at patch-module loading time. Reverting this removes the two apply_{paravirt,alternatives}() calls from the late patching path, and means we don't have to worry about them when removing module_disable_ro(). [ jpoimboe: Rewrote patch description. Tweaked klp_init_object_loaded() error path. ] Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Joe Lawrence <joe.lawrence@redhat.com> Acked-by: Miroslav Benes <mbenes@suse.cz> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'kernel/livepatch')
-rw-r--r--kernel/livepatch/core.c27
1 files changed, 9 insertions, 18 deletions
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index c02791e5c75b..16632e75112a 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -729,12 +729,6 @@ static int klp_init_func(struct klp_object *obj, struct klp_func *func)
func->old_sympos ? func->old_sympos : 1);
}
-/* Arches may override this to finish any remaining arch-specific tasks */
-void __weak arch_klp_init_object_loaded(struct klp_patch *patch,
- struct klp_object *obj)
-{
-}
-
int klp_apply_object_relocs(struct klp_patch *patch, struct klp_object *obj)
{
int i, ret;
@@ -764,10 +758,11 @@ static int klp_init_object_loaded(struct klp_patch *patch,
struct klp_func *func;
int ret;
- mutex_lock(&text_mutex);
- module_disable_ro(patch->mod);
-
if (klp_is_module(obj)) {
+
+ mutex_lock(&text_mutex);
+ module_disable_ro(patch->mod);
+
/*
* Only write module-specific relocations here
* (.klp.rela.{module}.*). vmlinux-specific relocations were
@@ -775,17 +770,13 @@ static int klp_init_object_loaded(struct klp_patch *patch,
* itself.
*/
ret = klp_apply_object_relocs(patch, obj);
- if (ret) {
- module_enable_ro(patch->mod, true);
- mutex_unlock(&text_mutex);
- return ret;
- }
- }
- arch_klp_init_object_loaded(patch, obj);
+ module_enable_ro(patch->mod, true);
+ mutex_unlock(&text_mutex);
- module_enable_ro(patch->mod, true);
- mutex_unlock(&text_mutex);
+ if (ret)
+ return ret;
+ }
klp_for_each_func(obj, func) {
ret = klp_find_object_symbol(obj->name, func->old_name,