From 012ccece850440d98153a3b3c2f210ad1509f8f4 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Thu, 20 Apr 2017 15:48:04 -0500 Subject: [PATCH] create-diff-object: don't create dynrelas for exported vmlinux symbols used by modules Joe saw the following errors when loading Linux commit 128394eff343 ("sg_write()/bsg_write() is not fit to be called under KERNEL_DS"): Skipped dynrela for copy_user_generic_unrolled (0xffffffffa0475942 <- 0xffffffff813211e0): the instruction has been changed already. Skipped dynrela for copy_user_generic_unrolled (0xffffffffa0475a57 <- 0xffffffff813211e0): the instruction has been changed already. That is known issue #580, but it can be avoided by leaving 'copy_user_generic_unrolled' as a normal relocation instead of converting it to a dynrela, because it's an exported symbol. Also remove the manual check for '__fentry__' because it's covered by the exported symbol check. Also remove a duplicate comment about unexported global object symbols being in another .o in the patch object. Fixes #695. --- kpatch-build/create-diff-object.c | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c index aa589ed..e2cb94b 100644 --- a/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c @@ -2123,22 +2123,8 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf, } else { /* * We have a patch to a module which references - * a global symbol. - */ - - /* - * __fentry__ relas can't be converted to - * dynrelas because the ftrace module init code - * runs before the dynrela code can initialize - * them. __fentry__ is exported by the kernel, - * so leave it as a normal rela. - */ - if (!strcmp(rela->sym->name, "__fentry__")) - continue; - - /* - * Try to find the symbol in the module being - * patched. + * a global symbol. Try to find the symbol in + * the module being patched. */ if (lookup_global_symbol(table, rela->sym->name, &result)) { @@ -2151,11 +2137,20 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf, * patch module. */ sym_objname = lookup_exported_symbol_objname(table, rela->sym->name); - - /* Not exported, must be in another .o in patch module */ if (!sym_objname) sym_objname = pmod_name; + /* + * For a symbol exported by vmlinux, use + * the original rela. + * + * For a symbol exported by a module, + * convert to a dynrela because the + * module might not be loaded yet. + */ + if (!strcmp(sym_objname, "vmlinux")) + continue; + external = 1; } }