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.
This commit is contained in:
Josh Poimboeuf 2017-04-20 15:48:04 -05:00
parent 81ba0afc7e
commit 012ccece85
1 changed files with 13 additions and 18 deletions

View File

@ -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;
}
}