From 79ae44b66d0c1adad14da94c1d1c33285d316569 Mon Sep 17 00:00:00 2001 From: Zhipeng Xie Date: Tue, 28 Sep 2021 16:54:29 +0800 Subject: [PATCH] kpatch: fix two issues kpatch: update sympos for duplicate symbols in vmlinux create-diff-object: fix segment fault when sec2->rela is NULL Signed-off-by: Zhipeng Xie --- ...mpos-for-duplicate-symbols-in-vmlinu.patch | 104 ++++++++++++++++++ ...ct-fix-segment-fault-when-sec2-rela-.patch | 30 +++++ kpatch.spec | 11 +- 3 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 0030-kpatch-update-sympos-for-duplicate-symbols-in-vmlinu.patch create mode 100644 0031-create-diff-object-fix-segment-fault-when-sec2-rela-.patch diff --git a/0030-kpatch-update-sympos-for-duplicate-symbols-in-vmlinu.patch b/0030-kpatch-update-sympos-for-duplicate-symbols-in-vmlinu.patch new file mode 100644 index 0000000..dc6ab04 --- /dev/null +++ b/0030-kpatch-update-sympos-for-duplicate-symbols-in-vmlinu.patch @@ -0,0 +1,104 @@ +From 8f5c1ff32fcc519bf061f68a481116f622b9cef8 Mon Sep 17 00:00:00 2001 +From: Zhipeng Xie +Date: Fri, 10 Sep 2021 04:34:40 -0400 +Subject: [PATCH] kpatch: update sympos for duplicate symbols in vmlinux + +kallsyms in vmlinux is sorted by address, so symbol order +in vmlinux is different from /proc/kallsyms, update sympos +when patching duplicate symbol function. + +Signed-off-by: Zhipeng Xie +Signed-off-by: hubin57 +--- + kpatch-build/create-diff-object.c | 26 ++++++-------------------- + kpatch-build/lookup.c | 24 ++++++++++++++++++++++++ + kpatch-build/lookup.h | 2 ++ + 3 files changed, 32 insertions(+), 20 deletions(-) + +diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c +index afd5e3b..ff2b0e4 100644 +--- a/kpatch-build/create-diff-object.c ++++ b/kpatch-build/create-diff-object.c +@@ -2813,26 +2813,12 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf, + funcs[index].new_size = sym->sym.st_size; + funcs[index].sympos = result.pos; + if (lookup_is_duplicate_symbol(table, sym->name, objname, result.pos)) { +- struct lookup_refsym refsym; +- long offset; +- +- if (lookup_ref_symbol_offset(table, sym->name, &refsym, +- objname, &offset)) +- ERROR("unresolvable ambiguity on symbol %s\n", sym->name); +- +- funcs[index].ref_offset = offset; +- +- /* +- * Add a relocation that will populate +- * the funcs[index].ref_name field. +- */ +- ALLOC_LINK(rela, &relasec->relas); +- rela->sym = strsym; +- rela->type = absolute_rela_type; +- rela->addend = offset_of_string(&kelf->strings, refsym.name); +- rela->offset = (unsigned int)(index * sizeof(*funcs) + +- offsetof(struct kpatch_patch_func, ref_name)); +- ++ if (!strcmp(objname, "vmlinux")) { ++ result.pos = get_vmlinux_duplicate_symbol_pos(table, sym->name, result.value); ++ log_debug("update %s sympos from %ld to %ld\n", ++ sym->name, funcs[index].sympos, result.pos); ++ funcs[index].sympos = result.pos; ++ } + } + + +diff --git a/kpatch-build/lookup.c b/kpatch-build/lookup.c +index 888bcc9..aa8527d 100644 +--- a/kpatch-build/lookup.c ++++ b/kpatch-build/lookup.c +@@ -526,6 +526,30 @@ int lookup_global_symbol(struct lookup_table *table, char *name, + return 1; + } + ++/* ++ * In case sometimes the sympos of duplicate symbols are different in vmlinux and ++ * /proc/kallsyms, and causes lookup_local_symbol to save wrong sympos in result, ++ * this function returns correct sympos of the symbol, by comparing ++ * address value with the symbol in vmlinux symbol table. ++ */ ++unsigned long get_vmlinux_duplicate_symbol_pos(struct lookup_table *table, ++ char *name, unsigned long value) ++{ ++ struct object_symbol *sym; ++ unsigned long pos = 1; ++ int i; ++ ++ for_each_obj_symbol(i, sym, table) { ++ if (strcmp(sym->name, name)) ++ continue; ++ ++ if (sym->value < value) ++ pos++; ++ } ++ ++ return pos; ++} ++ + int lookup_is_exported_symbol(struct lookup_table *table, char *name) + { + struct export_symbol *sym, *match = NULL; +diff --git a/kpatch-build/lookup.h b/kpatch-build/lookup.h +index daeea73..c745366 100644 +--- a/kpatch-build/lookup.h ++++ b/kpatch-build/lookup.h +@@ -37,5 +37,7 @@ int lookup_is_duplicate_symbol(struct lookup_table *table, char *name, + int lookup_ref_symbol_offset(struct lookup_table *table, char *name, + struct lookup_refsym *refsym, char *objname, + long *offset); ++unsigned long get_vmlinux_duplicate_symbol_pos(struct lookup_table *table, char *name, ++ unsigned long value); + + #endif /* _LOOKUP_H_ */ +-- +2.27.0 + diff --git a/0031-create-diff-object-fix-segment-fault-when-sec2-rela-.patch b/0031-create-diff-object-fix-segment-fault-when-sec2-rela-.patch new file mode 100644 index 0000000..97919e7 --- /dev/null +++ b/0031-create-diff-object-fix-segment-fault-when-sec2-rela-.patch @@ -0,0 +1,30 @@ +From 8d1e6f4cfe3fc7007f17e0f01e7ec8aa71e18cae Mon Sep 17 00:00:00 2001 +From: Zhipeng Xie +Date: Fri, 17 Sep 2021 10:22:24 +0800 +Subject: [PATCH] create-diff-object: fix segment fault when sec2->rela is NULL + +when patched section has no rela section, we meet segment fault in +__kpatch_correlate_section. add sec2->rela check to fix it. + +Signed-off-by: Zhipeng Xie +Signed-off-by: hubin57 +--- + kpatch-build/create-diff-object.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c +index ff2b0e4..2159cf0 100644 +--- a/kpatch-build/create-diff-object.c ++++ b/kpatch-build/create-diff-object.c +@@ -916,7 +916,7 @@ static void kpatch_correlate_section(struct section *sec1, struct section *sec2) + __kpatch_correlate_section(sec1->base, sec2->base); + sec1 = sec1->base; + sec2 = sec2->base; +- } else if (sec1->rela) { ++ } else if (sec1->rela && sec2->rela) { + __kpatch_correlate_section(sec1->rela, sec2->rela); + } + +-- +2.27.0 + diff --git a/kpatch.spec b/kpatch.spec index 384b17a..1ff3f0c 100644 --- a/kpatch.spec +++ b/kpatch.spec @@ -1,7 +1,7 @@ Name: kpatch Epoch: 1 Version: 0.9.1 -Release: 17 +Release: 18 Summary: A Linux dynamic kernel patching infrastructure License: GPLv2 @@ -41,6 +41,8 @@ Patch0026:0026-support-remove-static-variables-using-KPATCH_IGNORE_.patch Patch0027:0027-create-build-diff-support-for-.cold-functions-with-n.patch Patch0028:0028-lookup-Add-__UNIQUE_ID_-to-maybe_discarded_sym-list.patch Patch0029:0029-create-diff-object-error-on-detect-new-changed-ALTIN.patch +Patch0030:0030-kpatch-update-sympos-for-duplicate-symbols-in-vmlinu.patch +Patch0031:0031-create-diff-object-fix-segment-fault-when-sec2-rela-.patch BuildRequires: gcc elfutils-libelf-devel kernel-devel git Requires: bc make gcc patch bison flex openssl-devel @@ -101,6 +103,13 @@ popd %{_mandir}/man1/*.1.gz %changelog +* Tue Sep 28 2021 Zhipeng Xie -1:0.9.1-18 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:kpatch: update sympos for duplicate symbols in vmlinux + create-diff-object: fix segment fault when sec2->rela is NULL + * Tue Sep 28 2021 Bin Hu -1:0.9.1-17 - Type:bugfix - ID:NA -- Gitee