diff --git a/0025-Fix-relocation-not-resolved-when-new-functions-expor.patch b/0025-Fix-relocation-not-resolved-when-new-functions-expor.patch new file mode 100644 index 0000000..670a5ba --- /dev/null +++ b/0025-Fix-relocation-not-resolved-when-new-functions-expor.patch @@ -0,0 +1,129 @@ +From 737ab3efcde45cde5fbe43ee977fc18b6912f356 Mon Sep 17 00:00:00 2001 +From: Zhipeng Xie +Date: Sun, 22 Nov 2020 21:40:39 +0800 +Subject: [PATCH] Fix relocation not resolved when new functions exported only + +When no functions changed and new functions exported, kobject is not +created, so livepatch will not call klp_init_object and relocation +in new functions are not resolved. + +Signed-off-by: Zhipeng Xie +--- + kmod/patch/kpatch-patch.h | 4 ++++ + kmod/patch/kpatch.lds.S | 6 ++++++ + kmod/patch/livepatch-patch-hook.c | 19 +++++++++++++++++++ + kpatch-build/create-diff-object.c | 24 ++++++++++++++++++++++++ + 4 files changed, 53 insertions(+) + +diff --git a/kmod/patch/kpatch-patch.h b/kmod/patch/kpatch-patch.h +index 6e39364..33f2056 100644 +--- a/kmod/patch/kpatch-patch.h ++++ b/kmod/patch/kpatch-patch.h +@@ -63,6 +63,10 @@ struct kpatch_post_unpatch_callback { + void (*callback)(void *obj); + char *objname; + }; ++struct kpatch_object { ++ char *objname; ++}; + + extern unsigned long __kpatch_force_funcs[], __kpatch_force_funcs_end[]; ++extern struct kpatch_object __kpatch_objects[], __kpatch_objects_end[]; + #endif /* _KPATCH_PATCH_H_ */ +diff --git a/kmod/patch/kpatch.lds.S b/kmod/patch/kpatch.lds.S +index bc5de82..4c4d77b 100644 +--- a/kmod/patch/kpatch.lds.S ++++ b/kmod/patch/kpatch.lds.S +@@ -47,4 +47,10 @@ SECTIONS + __kpatch_force_funcs_end = . ; + QUAD(0); + } ++ .kpatch.objects : { ++ __kpatch_objects = . ; ++ *(.kpatch.objects) ++ __kpatch_objects_end = . ; ++ QUAD(0); ++ } + } +diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c +index 5a0de7f..d3fb1db 100644 +--- a/kmod/patch/livepatch-patch-hook.c ++++ b/kmod/patch/livepatch-patch-hook.c +@@ -249,6 +249,22 @@ static int patch_is_func_forced(unsigned long addr) + return 0; + } + ++static int add_kpatch_objects(void) ++{ ++ struct kpatch_object *p_kpatch_object; ++ struct patch_object *object; ++ ++ for (p_kpatch_object = __kpatch_objects; ++ p_kpatch_object < __kpatch_objects_end; ++ p_kpatch_object++) { ++ object = patch_find_object_by_name(p_kpatch_object->objname); ++ if (!object) ++ return -ENOMEM; ++ } ++ ++ return 0; ++} ++ + + #ifdef HAVE_CALLBACKS + static int add_callbacks_to_patch_objects(void) +@@ -382,6 +398,9 @@ static int __init patch_init(void) + if (ret) + goto out; + ++ ret = add_kpatch_objects(); ++ if (ret) ++ goto out; + /* past this point, only possible return code is -ENOMEM */ + ret = -ENOMEM; + +diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c +index fca68b8..bea758e 100644 +--- a/kpatch-build/create-diff-object.c ++++ b/kpatch-build/create-diff-object.c +@@ -2553,6 +2553,27 @@ static void kpatch_create_kpatch_arch_section(struct kpatch_elf *kelf, char *obj + karch_sec->sh.sh_size = karch_sec->data->d_size; + } + ++static void kpatch_create_kpatch_object_section(struct kpatch_elf *kelf, char *objname) ++{ ++ struct symbol *strsym; ++ struct rela *rela; ++ struct section *kobj_sec; ++ ++ kobj_sec = create_section_pair(kelf, ".kpatch.objects", sizeof(struct kpatch_object), 1); ++ ++ /* lookup strings symbol */ ++ strsym = find_symbol_by_name(&kelf->symbols, ".kpatch.strings"); ++ if (!strsym) ++ ERROR("can't find .kpatch.strings symbol"); ++ ++ /* entries[index].objname */ ++ ALLOC_LINK(rela, &kobj_sec->rela->relas); ++ rela->sym = strsym; ++ rela->type = absolute_rela_type; ++ rela->addend = offset_of_string(&kelf->strings, objname); ++ rela->offset = (unsigned int)(offsetof(struct kpatch_object, objname)); ++} ++ + static void kpatch_process_special_sections(struct kpatch_elf *kelf) + { + struct special_section *special; +@@ -3710,6 +3731,9 @@ int main(int argc, char *argv[]) + kpatch_create_intermediate_sections(kelf_out, lookup, parent_name, patch_name); + kpatch_create_kpatch_arch_section(kelf_out, parent_name); + kpatch_create_callbacks_objname_rela(kelf_out, parent_name); ++ if (!num_changed && new_globals_exist) { ++ kpatch_create_kpatch_object_section(kelf_out, parent_name); ++ } + kpatch_build_strings_section_data(kelf_out); + + gcc_add_option = getenv("GCC_ADD_OPTION"); +-- +2.18.1 + diff --git a/kpatch.spec b/kpatch.spec index f71b83e..c9f1433 100644 --- a/kpatch.spec +++ b/kpatch.spec @@ -1,7 +1,7 @@ Name: kpatch Epoch: 1 Version: 0.9.1 -Release: 7 +Release: 8 Summary: A Linux dynamic kernel patching infrastructure License: GPLv2 @@ -36,6 +36,7 @@ Patch0021:0021-kpatch-build-don-t-copy-.config-for-out-of-tree-modu.patch Patch0022:0022-support-force-enable-disable-for-x86.patch Patch0023:0023-create-diff-object-fix-duplicate-symbols-for-vmlinux.patch Patch0024:0024-optimize-for-out-of-tree-module.patch +Patch0025:0025-Fix-relocation-not-resolved-when-new-functions-expor.patch BuildRequires: gcc elfutils-libelf-devel uname-build-checks kernel-devel git Requires: bc @@ -95,6 +96,12 @@ popd %{_mandir}/man1/*.1.gz %changelog +* Sun Nov 22 2020 Zhipeng Xie -1:0.9.1-8 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:Fix relocation not resolved when new functions exported only + * Tue Nov 17 2020 Zhipeng Xie -1:0.9.1-7 - Type:enhancement - ID:NA