rebase from upstream v0.9.0

Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
This commit is contained in:
Zhipeng Xie 2020-02-27 17:15:29 -05:00
parent f7ecdbaac7
commit dc117ba0b6
44 changed files with 2424 additions and 3794 deletions

View File

@ -1,35 +0,0 @@
From 722d27f6bdd4fa012e08db784bf9bb93bb75be2c Mon Sep 17 00:00:00 2001
From: Artem Savkov <asavkov@redhat.com>
Date: Tue, 16 Oct 2018 16:05:01 +0200
Subject: [PATCH] Add "__addressable_" to maybe_discarded_sym().
Starting with 1b1eeca7e4c1 "init: allow initcall tables to be emitted using
relative references" [1] __init functions are generating an "__addressable_"
symbol in a ".discarded.addressable" section so it does not show up in final
vmlinux triggering find_local_syms failures. Add "_addressable_" to the list
in maybe_discarded_sym().
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1b1eeca7e4c19fa76d409d4c7b338dba21f2df45
Signed-off-by: Artem Savkov <asavkov@redhat.com>
---
kpatch-build/lookup.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/kpatch-build/lookup.c b/kpatch-build/lookup.c
index b88dc59..7c8e635 100644
--- a/kpatch-build/lookup.c
+++ b/kpatch-build/lookup.c
@@ -80,7 +80,8 @@ static int maybe_discarded_sym(const char *name)
*/
if (!strncmp(name, "__exitcall_", 11) ||
!strncmp(name, "__brk_reservation_fn_", 21) ||
- !strncmp(name, "__func_stack_frame_non_standard_", 32))
+ !strncmp(name, "__func_stack_frame_non_standard_", 32) ||
+ !strncmp(name, "__addressable_", 14))
return 1;
return 0;
--
1.7.12.4

View File

@ -1,15 +1,15 @@
From 50782f658313574a530f80d2f4b78fe23488c6c2 Mon Sep 17 00:00:00 2001 From 33c4d7a2a31ca10ce943d7ab0603bd814f4ac530 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com> From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Thu, 20 Dec 2018 04:55:38 +0000 Date: Thu, 20 Dec 2018 04:55:38 +0000
Subject: [PATCH] support compile kpatch on aarch64 Subject: [PATCH 01/17] support compile kpatch on aarch64
delete __x86_64__ to support compile kpatch on aarch64. delete __x86_64__ to support compile kpatch on aarch64.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com> Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
--- ---
kpatch-build/Makefile | 3 +++ kpatch-build/Makefile | 3 +++
kpatch-build/create-diff-object.c | 16 +--------------- kpatch-build/create-diff-object.c | 14 +-------------
2 files changed, 4 insertions(+), 15 deletions(-) 2 files changed, 4 insertions(+), 13 deletions(-)
diff --git a/kpatch-build/Makefile b/kpatch-build/Makefile diff --git a/kpatch-build/Makefile b/kpatch-build/Makefile
index 232b336..974e0f2 100644 index 232b336..974e0f2 100644
@ -26,10 +26,10 @@ index 232b336..974e0f2 100644
SOURCES += gcc-plugins/ppc64le-plugin.c SOURCES += gcc-plugins/ppc64le-plugin.c
PLUGIN = gcc-plugins/ppc64le-plugin.so PLUGIN = gcc-plugins/ppc64le-plugin.so
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 97ae0d4..80a76a9 100644 index c9d2cc6..7b1deb0 100644
--- a/kpatch-build/create-diff-object.c --- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c
@@ -426,7 +426,6 @@ out: @@ -470,7 +470,6 @@ out:
log_debug("section %s has changed\n", sec->name); log_debug("section %s has changed\n", sec->name);
} }
@ -37,7 +37,7 @@ index 97ae0d4..80a76a9 100644
/* /*
* Determine if a section has changed only due to a WARN* or might_sleep * Determine if a section has changed only due to a WARN* or might_sleep
* macro call's embedding of the line number into an instruction operand. * macro call's embedding of the line number into an instruction operand.
@@ -537,7 +536,7 @@ static int kpatch_line_macro_change_only(struct section *sec) @@ -581,7 +580,7 @@ static int kpatch_line_macro_change_only(struct section *sec)
return 1; return 1;
} }
@ -46,7 +46,7 @@ index 97ae0d4..80a76a9 100644
#define PPC_INSTR_LEN 4 #define PPC_INSTR_LEN 4
#define PPC_RA_OFFSET 16 #define PPC_RA_OFFSET 16
@@ -603,11 +602,6 @@ static int kpatch_line_macro_change_only(struct section *sec) @@ -647,11 +646,6 @@ static int kpatch_line_macro_change_only(struct section *sec)
return 1; return 1;
} }
@ -56,25 +56,25 @@ index 97ae0d4..80a76a9 100644
- return 0; - return 0;
-} -}
#endif #endif
#define ARM64_INSTR_LEN 4
static int arm64_kpatch_line_macro_change_only(struct section *sec) static void kpatch_compare_sections(struct list_head *seclist)
@@ -1248,7 +1242,6 @@ static void kpatch_compare_correlated_elements(struct kpatch_elf *kelf) @@ -1202,7 +1196,6 @@ static void kpatch_compare_correlated_elements(struct kpatch_elf *kelf)
kpatch_compare_symbols(&kelf->symbols); kpatch_compare_symbols(&kelf->symbols);
} }
-#ifdef __x86_64__ -#ifdef __x86_64__
static void rela_insn(struct section *sec, struct rela *rela, struct insn *insn) static void rela_insn(const struct section *sec, const struct rela *rela,
struct insn *insn)
{ {
unsigned long insn_addr, start, end, rela_addr; @@ -1226,7 +1219,6 @@ static void rela_insn(const struct section *sec, const struct rela *rela,
@@ -1267,7 +1260,6 @@ static void rela_insn(struct section *sec, struct rela *rela, struct insn *insn)
return; return;
} }
} }
-#endif -#endif
/* static bool is_callback_section(struct section *sec) {
* Mangle the relas a little. The compiler will sometimes use section symbols
@@ -1810,7 +1802,6 @@ static int ex_table_group_size(struct kpatch_elf *kelf, int offset) @@ -1771,7 +1763,6 @@ static int jump_table_group_size(struct kpatch_elf *kelf, int offset)
return size; return size;
} }
@ -82,7 +82,7 @@ index 97ae0d4..80a76a9 100644
static int parainstructions_group_size(struct kpatch_elf *kelf, int offset) static int parainstructions_group_size(struct kpatch_elf *kelf, int offset)
{ {
static int size = 0; static int size = 0;
@@ -1845,7 +1836,6 @@ static int smp_locks_group_size(struct kpatch_elf *kelf, int offset) @@ -1806,7 +1797,6 @@ static int smp_locks_group_size(struct kpatch_elf *kelf, int offset)
{ {
return 4; return 4;
} }
@ -90,28 +90,15 @@ index 97ae0d4..80a76a9 100644
#ifdef __powerpc64__ #ifdef __powerpc64__
static int fixup_entry_group_size(struct kpatch_elf *kelf, int offset) static int fixup_entry_group_size(struct kpatch_elf *kelf, int offset)
{ {
@@ -1921,7 +1911,6 @@ static struct special_section special_sections[] = { @@ -1901,7 +1891,6 @@ static struct special_section special_sections[] = {
.name = "__bug_table", .name = "__jump_table",
.group_size = bug_table_group_size, .group_size = jump_table_group_size,
}, },
-#ifdef __x86_64__ -#ifdef __x86_64__
{ {
.name = ".smp_locks", .name = ".smp_locks",
.group_size = smp_locks_group_size, .group_size = smp_locks_group_size,
@@ -1930,7 +1919,6 @@ static struct special_section special_sections[] = { @@ -1914,7 +1903,6 @@ static struct special_section special_sections[] = {
.name = ".parainstructions",
.group_size = parainstructions_group_size,
},
-#endif
{
.name = ".fixup",
.group_size = fixup_group_size,
@@ -1939,12 +1927,10 @@ static struct special_section special_sections[] = {
.name = "__ex_table", /* must come after .fixup */
.group_size = ex_table_group_size,
},
-#ifdef __x86_64__
{
.name = ".altinstructions", .name = ".altinstructions",
.group_size = altinstructions_group_size, .group_size = altinstructions_group_size,
}, },
@ -120,5 +107,5 @@ index 97ae0d4..80a76a9 100644
{ {
.name = "__ftr_fixup", .name = "__ftr_fixup",
-- --
2.19.1 2.18.1

View File

@ -1,36 +0,0 @@
From 17a97b48bcf0d486007b746c48321bab6dedb2d8 Mon Sep 17 00:00:00 2001
From: Artem Savkov <asavkov@redhat.com>
Date: Wed, 14 Nov 2018 15:09:34 +0100
Subject: [PATCH] kmod/patch: fix patch linking with 4.20
4.20 includes commit 69ea912fda74 "kbuild: remove unneeded link_multi_deps"
which changes kbuild so that only '.o' files are given to ld as targets
for linking, leaving out our linker script. Even before this commit we
were still doing this wrong and were succeeding just because ld is smart
enough to detect the script, it even throws a warning:
ld: warning: kpatch.lds contains output sections; did you forget -T?
The right thing to do is to add the script to ldflags either through
kbuilds 'ldflags-y' or by adding it to LDFLAGS/KPATCH_LDFLAGS directly.
Signed-off-by: Artem Savkov <asavkov@redhat.com>
---
kmod/patch/Makefile | 1 +
1 file changed, 1 insertion(+)
diff --git a/kmod/patch/Makefile b/kmod/patch/Makefile
index 96d1fca..7ba0820 100644
--- a/kmod/patch/Makefile
+++ b/kmod/patch/Makefile
@@ -11,6 +11,7 @@ KBUILD_CFLAGS_MODULE += -mcmodel=large
endif
obj-m += $(KPATCH_NAME).o
+ldflags-y += -T $(src)/kpatch.lds
$(KPATCH_NAME)-objs += patch-hook.o kpatch.lds output.o
--
1.7.12.4

View File

@ -0,0 +1,684 @@
From 6dd77e9f5bc044a1f80ad89bb9d7f60756b39755 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Wed, 26 Feb 2020 07:09:50 -0500
Subject: [PATCH 02/17] kpatch-build: support build patch for aarch64
use R_AARCH64_ABS64 for aarch64
exclude line only change for arm64 by compare mov instruction
except immediate part.
add find_special_section_data_arm64 for arm64:
arm64 kernel have no paravirt_patch_site or orc_entry structure
in vmlinux, we don't need to check these two struct for arm64.
support cross compile for aarch64
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/create-diff-object.c | 216 ++++++++++++++++++++++++----
kpatch-build/create-kpatch-module.c | 24 +++-
kpatch-build/kpatch-build | 116 ++++++++++++++-
kpatch-build/kpatch-gcc | 4 +-
4 files changed, 319 insertions(+), 41 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 7b1deb0..58789f1 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -76,6 +76,31 @@ enum subsection {
enum loglevel loglevel = NORMAL;
+#ifndef EM_X86_64
+#define EM_X86_64 62
+#endif
+
+#ifndef EM_AARCH64
+#define EM_AARCH64 183
+#endif
+
+#ifndef R_AARCH64_ABS64
+#define R_AARCH64_NONE 0
+#define R_AARCH64_ABS64 257
+#define R_AARCH64_CALL26 283
+#endif
+
+static unsigned int arch;
+static unsigned int absolute_rela_type;
+
+static unsigned int arch_of_elf(Elf *elf)
+{
+ GElf_Ehdr eh;
+ if (!gelf_getehdr(elf, &eh))
+ ERROR("gelf_getehdr");
+ return eh.e_machine;
+}
+
/*******************
* Data structures
* ****************/
@@ -647,6 +672,67 @@ static int kpatch_line_macro_change_only(struct section *sec)
return 1;
}
#endif
+#define ARM64_INSTR_LEN 4
+static int arm64_kpatch_line_macro_change_only(struct section *sec)
+{
+ unsigned long start1, start2, size, offset;
+ struct rela *rela;
+ int lineonly = 0, found;
+ unsigned int mov_imm_mask = ((1<<16) - 1)<<5;
+
+ if (sec->status != CHANGED ||
+ is_rela_section(sec) ||
+ !is_text_section(sec) ||
+ sec->sh.sh_size != sec->twin->sh.sh_size ||
+ !sec->rela ||
+ sec->rela->status != SAME)
+ return 0;
+
+ start1 = (unsigned long)sec->twin->data->d_buf;
+ start2 = (unsigned long)sec->data->d_buf;
+ size = sec->sh.sh_size;
+ for (offset = 0; offset < size; offset += ARM64_INSTR_LEN) {
+ if (!memcmp((void *)start1 + offset, (void *)start2 + offset,
+ ARM64_INSTR_LEN))
+ continue;
+
+ /* verify it's a mov immediate to w1 */
+ if ((*(int *)(start1 + offset) & ~mov_imm_mask) !=
+ (*(int *)(start2 + offset) & ~mov_imm_mask))
+ return 0;
+
+ found = 0;
+ list_for_each_entry(rela, &sec->rela->relas, list) {
+ if (rela->offset < offset + ARM64_INSTR_LEN)
+ continue;
+ if (rela->string)
+ continue;
+ if (!strncmp(rela->sym->name, "__warned.", 9))
+ continue;
+ if (!strncmp(rela->sym->name, "warn_slowpath_", 14) ||
+ (!strcmp(rela->sym->name, "__warn_printk")) ||
+ (!strcmp(rela->sym->name, "__might_sleep")) ||
+ (!strcmp(rela->sym->name, "___might_sleep")) ||
+ (!strcmp(rela->sym->name, "__might_fault")) ||
+ (!strcmp(rela->sym->name, "printk")) ||
+ (!strcmp(rela->sym->name, "lockdep_rcu_suspicious"))) {
+ found = 1;
+ break;
+ }
+ return 0;
+ }
+ if (!found)
+ return 0;
+
+ lineonly = 1;
+ }
+
+ if (!lineonly)
+ ERROR("no instruction changes detected for changed section %s",
+ sec->name);
+
+ return 1;
+}
static void kpatch_compare_sections(struct list_head *seclist)
{
@@ -662,7 +748,16 @@ static void kpatch_compare_sections(struct list_head *seclist)
/* exclude WARN-only, might_sleep changes */
list_for_each_entry(sec, seclist, list) {
- if (kpatch_line_macro_change_only(sec)) {
+ int line_only;
+
+ if (arch == EM_X86_64)
+ line_only = kpatch_line_macro_change_only(sec);
+ else if (arch == EM_AARCH64)
+ line_only = arm64_kpatch_line_macro_change_only(sec);
+ else
+ line_only = 0;
+
+ if (line_only) {
log_debug("reverting macro / line number section %s status to SAME\n",
sec->name);
sec->status = SAME;
@@ -722,6 +817,8 @@ static void kpatch_compare_correlated_symbol(struct symbol *sym)
if ((sym2->sec->twin && sym2->sec->twin->ignore) ||
kpatch_subsection_changed(sym1->sec, sym2->sec))
sym->status = CHANGED;
+ else if (sym1->name[0] == '$') /* reserved symbols in aarch64 */
+ log_debug("maping symbols: %s", sym1->name); /* do nothing just ignogre */
else
DIFF_FATAL("symbol changed sections: %s", sym1->name);
}
@@ -1289,22 +1386,22 @@ static void kpatch_replace_sections_syms(struct kpatch_elf *kelf)
continue;
}
-#ifdef __powerpc64__
add_off = 0;
-#else
- if (rela->type == R_X86_64_PC32 ||
- rela->type == R_X86_64_PLT32) {
- struct insn insn;
- rela_insn(sec, rela, &insn);
- add_off = (long)insn.next_byte -
- (long)sec->base->data->d_buf -
- rela->offset;
- } else if (rela->type == R_X86_64_64 ||
- rela->type == R_X86_64_32S)
- add_off = 0;
- else
- continue;
-#endif
+ if (arch == EM_X86_64) {
+ if (rela->type == R_X86_64_PC32 ||
+ rela->type == R_X86_64_PLT32) {
+ struct insn insn;
+ rela_insn(sec, rela, &insn);
+ add_off = (long)insn.next_byte -
+ (long)sec->base->data->d_buf -
+ rela->offset;
+ } else if (rela->type == R_X86_64_64 ||
+ rela->type == R_X86_64_32S)
+ add_off = 0;
+ else
+ continue;
+ }
+ /* add_off is always equal to 0 on arm64 */
/*
* Attempt to replace references to unbundled sections
@@ -2401,7 +2498,7 @@ static void kpatch_create_kpatch_arch_section(struct kpatch_elf *kelf, char *obj
/* entries[index].sec */
ALLOC_LINK(rela, &karch_sec->rela->relas);
rela->sym = sec->secsym;
- rela->type = ABSOLUTE_RELA_TYPE;
+ rela->type = absolute_rela_type;
rela->addend = 0;
rela->offset = index * sizeof(struct kpatch_arch) + \
offsetof(struct kpatch_arch, sec);
@@ -2409,7 +2506,7 @@ static void kpatch_create_kpatch_arch_section(struct kpatch_elf *kelf, char *obj
/* entries[index].objname */
ALLOC_LINK(rela, &karch_sec->rela->relas);
rela->sym = strsym;
- rela->type = ABSOLUTE_RELA_TYPE;
+ rela->type = absolute_rela_type;
rela->addend = offset_of_string(&kelf->strings, objname);
rela->offset = index * sizeof(struct kpatch_arch) + \
offsetof(struct kpatch_arch, objname);
@@ -2607,7 +2704,7 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
*/
ALLOC_LINK(rela, &relasec->relas);
rela->sym = sym;
- rela->type = ABSOLUTE_RELA_TYPE;
+ rela->type = absolute_rela_type;
rela->addend = 0;
rela->offset = index * sizeof(*funcs);
@@ -2617,7 +2714,7 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
*/
ALLOC_LINK(rela, &relasec->relas);
rela->sym = strsym;
- rela->type = ABSOLUTE_RELA_TYPE;
+ rela->type = absolute_rela_type;
rela->addend = offset_of_string(&kelf->strings, sym->name);
rela->offset = index * sizeof(*funcs) +
offsetof(struct kpatch_patch_func, name);
@@ -2628,7 +2725,7 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
*/
ALLOC_LINK(rela, &relasec->relas);
rela->sym = strsym;
- rela->type = ABSOLUTE_RELA_TYPE;
+ rela->type = absolute_rela_type;
rela->addend = objname_offset;
rela->offset = index * sizeof(*funcs) +
offsetof(struct kpatch_patch_func,objname);
@@ -2686,7 +2783,10 @@ static int function_ptr_rela(const struct rela *rela)
rela_toc->addend == (int)rela_toc->sym->sym.st_value &&
(rela->type == R_X86_64_32S ||
rela->type == R_PPC64_TOC16_HA ||
- rela->type == R_PPC64_TOC16_LO_DS));
+ rela->type == R_PPC64_TOC16_LO_DS ||
+ rela->type == R_AARCH64_ADR_PREL_PG_HI21 ||
+ rela->type == R_AARCH64_ADD_ABS_LO12_NC));
+
}
static int may_need_dynrela(const struct rela *rela)
@@ -2940,7 +3040,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
/* add rela to fill in ksyms[index].name field */
ALLOC_LINK(rela2, &ksym_sec->rela->relas);
rela2->sym = strsym;
- rela2->type = ABSOLUTE_RELA_TYPE;
+ rela2->type = absolute_rela_type;
rela2->addend = offset_of_string(&kelf->strings, rela->sym->name);
rela2->offset = index * sizeof(*ksyms) + \
offsetof(struct kpatch_symbol, name);
@@ -2948,7 +3048,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
/* add rela to fill in ksyms[index].objname field */
ALLOC_LINK(rela2, &ksym_sec->rela->relas);
rela2->sym = strsym;
- rela2->type = ABSOLUTE_RELA_TYPE;
+ rela2->type = absolute_rela_type;
rela2->addend = offset_of_string(&kelf->strings, sym_objname);
rela2->offset = index * sizeof(*ksyms) + \
offsetof(struct kpatch_symbol, objname);
@@ -2969,7 +3069,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
ERROR("can't create dynrela for section %s (symbol %s): no bundled or section symbol",
sec->name, rela->sym->name);
- rela2->type = ABSOLUTE_RELA_TYPE;
+ rela2->type = absolute_rela_type;
rela2->addend = rela->offset;
rela2->offset = index * sizeof(*krelas) + \
offsetof(struct kpatch_relocation, dest);
@@ -2977,7 +3077,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
/* add rela to fill in krelas[index].objname field */
ALLOC_LINK(rela2, &krela_sec->rela->relas);
rela2->sym = strsym;
- rela2->type = ABSOLUTE_RELA_TYPE;
+ rela2->type = absolute_rela_type;
rela2->addend = offset_of_string(&kelf->strings, objname);
rela2->offset = index * sizeof(*krelas) + \
offsetof(struct kpatch_relocation, objname);
@@ -2985,7 +3085,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
/* add rela to fill in krelas[index].ksym field */
ALLOC_LINK(rela2, &krela_sec->rela->relas);
rela2->sym = ksym_sec_sym;
- rela2->type = ABSOLUTE_RELA_TYPE;
+ rela2->type = absolute_rela_type;
rela2->addend = index * sizeof(*ksyms);
rela2->offset = index * sizeof(*krelas) + \
offsetof(struct kpatch_relocation, ksym);
@@ -3048,7 +3148,7 @@ static void kpatch_create_callbacks_objname_rela(struct kpatch_elf *kelf, char *
if (!strcmp(callbackp->name, sec->name)) {
ALLOC_LINK(rela, &sec->relas);
rela->sym = strsym;
- rela->type = ABSOLUTE_RELA_TYPE;
+ rela->type = absolute_rela_type;
rela->addend = objname_offset;
rela->offset = callbackp->offset;
break;
@@ -3101,6 +3201,7 @@ static void kpatch_create_mcount_sections(struct kpatch_elf *kelf)
/* add rela in .rela__mcount_loc to fill in function pointer */
ALLOC_LINK(rela, &relasec->relas);
rela->sym = sym;
+ if (arch == EM_X86_64) {
rela->type = R_X86_64_64;
rela->addend = 0;
rela->offset = index * sizeof(void*);
@@ -3136,6 +3237,40 @@ static void kpatch_create_mcount_sections(struct kpatch_elf *kelf)
rela->type = R_X86_64_PC32;
}
+ } else if (arch == EM_AARCH64) {
+ unsigned int *insnp;
+ rela->type = R_AARCH64_ABS64;
+ /* bl <__fentry__> is the second insn */
+ rela->addend = 4;
+ rela->offset = index * sizeof(void*);
+
+ newdata = malloc(sym->sec->data->d_size);
+ if (!newdata)
+ ERROR("malloc");
+
+ memcpy(newdata, sym->sec->data->d_buf, sym->sec->data->d_size);
+ sym->sec->data->d_buf = newdata;
+ insnp = newdata;
+
+ /*
+ * mov x9, x30
+ * nop //function in .text.<func>, so it be replaced with nop by recordmcount
+ * mov x30, x9
+ */
+ if (insnp[0] != 0xaa1e03e9 || insnp[1] != 0xd503201f || insnp[2] != 0xaa0903fe)
+ ERROR("%s: unexpected instruction at the start of the function",
+ sym->name);
+
+ /* change the nop to bl __fentry__ */
+ insnp[1] = 0x94000000;
+ rela = list_first_entry(&sym->sec->rela->relas, struct rela,
+ list);
+ rela->type = R_AARCH64_CALL26;
+ rela->offset = 4;
+
+ } else {
+ ERROR("unsupport arch %d\n", arch);
+ }
index++;
}
@@ -3334,6 +3469,8 @@ int main(int argc, char *argv[])
char *hint = NULL, *orig_obj, *patched_obj, *parent_name;
char *parent_symtab, *mod_symvers, *patch_name, *output_obj;
struct sym_compare_type *base_locals, *sym_comp;
+ char *no_profiling_calls = NULL;
+ char *gcc_add_option = NULL, *mlongcall = NULL;
arguments.debug = 0;
argp_parse (&argp, argc, argv, 0, NULL, &arguments);
@@ -3354,6 +3491,13 @@ int main(int argc, char *argv[])
kelf_base = kpatch_elf_open(orig_obj);
kelf_patched = kpatch_elf_open(patched_obj);
+ arch = arch_of_elf(kelf_base->elf);
+ if (arch == EM_X86_64)
+ absolute_rela_type = R_X86_64_64;
+ else if (arch == EM_AARCH64)
+ absolute_rela_type = R_AARCH64_ABS64;
+ else
+ ERROR("only arch x86_64 and arm64 be supported\n");
kpatch_compare_elf_headers(kelf_base->elf, kelf_patched->elf);
kpatch_check_program_headers(kelf_base->elf);
@@ -3392,7 +3536,12 @@ int main(int argc, char *argv[])
*/
kpatch_mark_ignored_sections(kelf_patched);
kpatch_compare_correlated_elements(kelf_patched);
- kpatch_check_func_profiling_calls(kelf_patched);
+ no_profiling_calls = getenv("NO_PROFILING_CALLS");
+ if (!no_profiling_calls)
+ kpatch_check_func_profiling_calls(kelf_patched);
+ else
+ log_debug("NO_PROFILING_CALLS set\n");
+
kpatch_elf_teardown(kelf_base);
kpatch_elf_free(kelf_base);
@@ -3452,7 +3601,14 @@ int main(int argc, char *argv[])
kpatch_create_callbacks_objname_rela(kelf_out, parent_name);
kpatch_build_strings_section_data(kelf_out);
- kpatch_create_mcount_sections(kelf_out);
+ gcc_add_option = getenv("GCC_ADD_OPTION");
+ if (gcc_add_option)
+ mlongcall = strstr(gcc_add_option, "-mlong-calls");
+ if (arch == EM_AARCH64 && mlongcall) {
+ printf("-mlong-calls found, no need to create mcount section\n");
+ } else {
+ kpatch_create_mcount_sections(kelf_out);
+ }
/*
* At this point, the set of output sections and symbols is
diff --git a/kpatch-build/create-kpatch-module.c b/kpatch-build/create-kpatch-module.c
index 43d6809..6f80831 100644
--- a/kpatch-build/create-kpatch-module.c
+++ b/kpatch-build/create-kpatch-module.c
@@ -31,6 +31,17 @@
char *childobj;
enum loglevel loglevel = NORMAL;
+static unsigned int arch;
+static unsigned int absolute_rela_type;
+
+static unsigned int arch_of_elf(Elf *elf)
+{
+ GElf_Ehdr eh;
+ if (!gelf_getehdr(elf, &eh))
+ ERROR("gelf_getehdr");
+ return eh.e_machine;
+}
+
/*
* Create .kpatch.dynrelas from .kpatch.relocations and .kpatch.symbols sections
*
@@ -102,14 +113,14 @@ static void create_dynamic_rela_sections(struct kpatch_elf *kelf, struct section
/* dest */
ALLOC_LINK(rela, &dynsec->rela->relas);
rela->sym = sym;
- rela->type = R_X86_64_64;
+ rela->type = absolute_rela_type;
rela->addend = dest_offset;
rela->offset = index * sizeof(*dynrelas);
/* name */
ALLOC_LINK(rela, &dynsec->rela->relas);
rela->sym = strsec->secsym;
- rela->type = R_X86_64_64;
+ rela->type = absolute_rela_type;
rela->addend = name_offset;
rela->offset = index * sizeof(*dynrelas) + \
offsetof(struct kpatch_patch_dynrela, name);
@@ -117,7 +128,7 @@ static void create_dynamic_rela_sections(struct kpatch_elf *kelf, struct section
/* objname */
ALLOC_LINK(rela, &dynsec->rela->relas);
rela->sym = strsec->secsym;
- rela->type = R_X86_64_64;
+ rela->type = absolute_rela_type;
rela->addend = objname_offset;
rela->offset = index * sizeof(*dynrelas) + \
offsetof(struct kpatch_patch_dynrela, objname);
@@ -200,6 +211,13 @@ int main(int argc, char *argv[])
childobj = basename(arguments.args[0]);
kelf = kpatch_elf_open(arguments.args[0]);
+ arch = arch_of_elf(kelf->elf);
+ if (arch == EM_X86_64)
+ absolute_rela_type = R_X86_64_64;
+ else if (arch == EM_AARCH64)
+ absolute_rela_type = R_AARCH64_ABS64;
+ else
+ ERROR("only arch x86_64 and arm64 be supported\n");
/*
* Sanity checks:
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index ae0733c..17a5e11 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -299,12 +299,72 @@ find_special_section_data_ppc64le() {
return
}
+find_special_section_data_arm64() {
+
+ [[ "$CONFIG_JUMP_LABEL" -eq 0 ]] && AWK_OPTIONS="$AWK_OPTIONS -vskip_j=1"
+
+ # If $AWK_OPTIONS are blank gawk would treat "" as a blank script
+ # shellcheck disable=SC2086
+ SPECIAL_VARS="$(readelf -wi "$VMLINUX" |
+ gawk --non-decimal-data $AWK_OPTIONS '
+ BEGIN { a = b = e = j = c = f = s = i = r = t = h = 0 }
+
+ # Set state if name matches
+ a == 0 && /DW_AT_name.* alt_instr[[:space:]]*$/ {a = 1; next}
+ b == 0 && /DW_AT_name.* bug_entry[[:space:]]*$/ {b = 1; next}
+ e == 0 && /DW_AT_name.* exception_table_entry[[:space:]]*$/ {e = 1; next}
+ j == 0 && /DW_AT_name.* jump_entry[[:space:]]*$/ {j = 1; next}
+ c == 0 && /DW_AT_name.* klp_func[[:space:]]*$/ {c = 1; next}
+ t == 0 && /DW_AT_name.* klp_object[[:space:]]*$/ {t = 1; next}
+
+ # Reset state unless this abbrev describes the struct size
+ a == 1 && !/DW_AT_byte_size/ { a = 0; next }
+ b == 1 && !/DW_AT_byte_size/ { b = 0; next }
+ e == 1 && !/DW_AT_byte_size/ { e = 0; next }
+ j == 1 && !/DW_AT_byte_size/ { j = 0; next }
+ c == 1 && /DW_TAG_structure_type/ { c = 3; next }
+ t == 1 && /DW_TAG_structure_type/ { t = 3; next }
+ c == 1 && /DW_AT_name.* force[[:space:]]*$/ {f = 2; next}
+ c == 1 && /DW_AT_name.* old_sympos[[:space:]]*$/ {s = 2; next}
+ i == 1 && /DW_AT_name.* immediate[[:space:]]*$/ {i = 2; next}
+ t == 1 && /DW_AT_name.* relocs[[:space:]]*$/ {r = 2; next}
+ t == 1 && /DW_AT_name.* hooks_load[[:space:]]*$/ {h = 2; next}
+
+ # Now that we know the size, stop parsing for it
+ a == 1 {printf("export ALT_STRUCT_SIZE=%d\n", $4); a = 2}
+ b == 1 {printf("export BUG_STRUCT_SIZE=%d\n", $4); b = 2}
+ e == 1 {printf("export EX_STRUCT_SIZE=%d\n", $4); e = 2}
+ j == 1 {printf("export JUMP_STRUCT_SIZE=%d\n", $4); j = 2}
+ f == 2 {printf("export KLP_SUPPORT_FORCE=y\n"); f = 3}
+ s == 2 {printf("export KLP_SUPPORT_OLD_SYMPOS=y\n"); s = 3}
+ i == 2 {printf("export KLP_SUPPORT_IMMEDIATE=y\n"); i = 3}
+ r == 2 {printf("export KLP_SUPPORT_RELOCS=y\n"); r = 3}
+ h == 2 {printf("export KLP_SUPPORT_LOADHOOKS=y\n"); h = 3}
+
+ # Bail out once we have everything
+ a == 2 && b == 2 && e == 2 && (j == 2 || skip_j) && c == 3 && t == 3 {exit}')"
+
+ [[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS"
+
+ [[ -z "$ALT_STRUCT_SIZE" ]] && die "can't find special struct alt_instr size"
+ [[ -z "$BUG_STRUCT_SIZE" ]] && die "can't find special struct bug_entry size"
+ [[ -z "$EX_STRUCT_SIZE" ]] && die "can't find special struct exception_table_entry size"
+ [[ -z "$JUMP_STRUCT_SIZE" && "$CONFIG_JUMP_LABEL" -ne 0 ]] && die "can't find special struct jump_entry size"
+
+ return
+}
+
find_special_section_data() {
if [[ "$ARCH" = "ppc64le" ]]; then
find_special_section_data_ppc64le
return
fi
+ if [[ "$ARCH" = "arm64" ]]; then
+ find_special_section_data_arm64
+ return
+ fi
+
[[ "$CONFIG_PARAVIRT" -eq 0 ]] && AWK_OPTIONS="-vskip_p=1"
[[ "$CONFIG_UNWINDER_ORC" -eq 0 ]] && AWK_OPTIONS="$AWK_OPTIONS -vskip_o=1"
[[ "$CONFIG_JUMP_LABEL" -eq 0 ]] && AWK_OPTIONS="$AWK_OPTIONS -vskip_j=1"
@@ -428,6 +488,29 @@ find_kobj() {
done
}
+arch_export() {
+ E_MACHINE=$(od -An -j18 -N2 -d $VMLINUX)
+ if [[ $E_MACHINE -eq 62 ]]; then
+ export ARCH=x86_64
+ export ARCH_COMPILE=
+ export ENDIAN=little
+ export GCC_ADD_OPTION=
+ elif [[ $E_MACHINE -eq 183 ]]; then
+ export ARCH=arm64
+ if [ $(arch) != "aarch64" ]; then
+ export ARCH_COMPILE=aarch64-linux-gnu-
+ fi
+ export ENDIAN=little
+ if grep "\-mlong-calls" /lib/modules/$ARCHVERSION/build//Makefile > /dev/null; then
+ export GCC_ADD_OPTION="-fno-section-anchors -mlong-calls"
+ else
+ export GCC_ADD_OPTION="-fno-section-anchors"
+ fi
+ else
+ die "only support arm64 or x86_64 architecture"
+ fi
+}
+
# Only allow alphanumerics and '_' and '-' in the module name. Everything else
# is replaced with '-'. Also truncate to 48 chars so the full name fits in the
# kernel's 56-byte module name array.
@@ -786,13 +869,13 @@ apply_patches
remove_patches
cp -LR "$DATADIR/patch" "$TEMPDIR" || die
-
+arch_export
if [[ "$ARCH" = "ppc64le" ]]; then
ARCH_KCFLAGS="-mcmodel=large -fplugin=$PLUGINDIR/ppc64le-plugin.so"
fi
export KCFLAGS="-I$DATADIR/patch -ffunction-sections -fdata-sections \
- $ARCH_KCFLAGS $DEBUG_KCFLAGS"
+ $ARCH_KCFLAGS $DEBUG_KCFLAGS ${GCC_ADD_OPTION}"
echo "Reading special section data"
find_special_section_data
@@ -806,7 +889,7 @@ echo "Building original source"
unset KPATCH_GCC_TEMPDIR
# $TARGETS used as list, no quotes.
# shellcheck disable=SC2086
-CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make "-j$CPUS" $TARGETS 2>&1 | logger || die
+CROSS_COMPILE="$TOOLSDIR/kpatch-gcc $ARCH_COMPILE" make "-j$CPUS" $TARGETS 2>&1 | logger || die
echo "Building patched source"
apply_patches
@@ -817,7 +900,7 @@ KPATCH_GCC_SRCDIR="$SRCDIR"
export KPATCH_GCC_SRCDIR
# $TARGETS used as list, no quotes.
# shellcheck disable=SC2086
-CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \
+CROSS_COMPILE="$TOOLSDIR/kpatch-gcc $ARCH_COMPILE" \
KBUILD_MODPOST_WARN=1 \
make "-j$CPUS" $TARGETS 2>&1 | logger || die
@@ -950,6 +1033,26 @@ if "$KPATCH_MODULE"; then
export KCPPFLAGS="-D__KPATCH_MODULE__"
fi
+if [[ -n "$KLP_SUPPORT_FORCE" ]];then
+ export KCPPFLAGS="-D__KLP_SUPPORT_FORCE__ $KCPPFLAGS"
+fi
+
+if [[ -n "$KLP_SUPPORT_OLD_SYMPOS" ]];then
+ export KCPPFLAGS="-DHAVE_SYMPOS $KCPPFLAGS"
+fi
+
+if [[ -n "$KLP_SUPPORT_IMMEDIATE" ]];then
+ export KCPPFLAGS="-DHAVE_IMMEDIATE $KCPPFLAGS"
+fi
+
+if [[ -n "$KLP_SUPPORT_RELOCS" ]];then
+ export KCPPFLAGS="-DHAVE_ELF_RELOCS $KCPPFLAGS"
+fi
+
+if [[ -n "$KLP_SUPPORT_LOADHOOKS" ]];then
+ export KCPPFLAGS="-DHAVE_LOADHOOKS $KCPPFLAGS"
+fi
+
echo "Building patch module: $MODNAME.ko"
if [[ -z "$USERSRCDIR" ]] && [[ "$DISTRO" = ubuntu ]]; then
@@ -962,12 +1065,12 @@ fi
cd "$TEMPDIR/output" || die
# $KPATCH_LDFLAGS and result of find used as list, no quotes.
# shellcheck disable=SC2086,SC2046
-ld -r $KPATCH_LDFLAGS -o ../patch/tmp_output.o $(find . -name "*.o") 2>&1 | logger || die
+${ARCH_COMPILE}ld -r $KPATCH_LDFLAGS -o ../patch/tmp_output.o $(find . -name "*.o") 2>&1 | logger || die
if "$KPATCH_MODULE"; then
# Add .kpatch.checksum for kpatch script
md5sum ../patch/tmp_output.o | awk '{printf "%s\0", $1}' > checksum.tmp || die
- objcopy --add-section .kpatch.checksum=checksum.tmp --set-section-flags .kpatch.checksum=alloc,load,contents,readonly ../patch/tmp_output.o || die
+ ${ARCH_COMPILE}objcopy --add-section .kpatch.checksum=checksum.tmp --set-section-flags .kpatch.checksum=alloc,load,contents,readonly ../patch/tmp_output.o || die
rm -f checksum.tmp
"$TOOLSDIR"/create-kpatch-module "$TEMPDIR"/patch/tmp_output.o "$TEMPDIR"/patch/output.o 2>&1 | logger 1
check_pipe_status create-kpatch-module
@@ -984,6 +1087,7 @@ fi
KPATCH_BUILD="$KPATCH_BUILD" KPATCH_NAME="$MODNAME" \
KBUILD_EXTRA_SYMBOLS="$KBUILD_EXTRA_SYMBOLS" \
KPATCH_LDFLAGS="$KPATCH_LDFLAGS" \
+CROSS_COMPILE="$ARCH_COMPILE" \
make 2>&1 | logger || die
if ! "$KPATCH_MODULE"; then
diff --git a/kpatch-build/kpatch-gcc b/kpatch-build/kpatch-gcc
index 9663290..35d7c1c 100755
--- a/kpatch-build/kpatch-gcc
+++ b/kpatch-build/kpatch-gcc
@@ -13,7 +13,7 @@ fi
declare -a args=("$@")
-if [[ "$TOOLCHAINCMD" =~ "gcc" ]] ; then
+if [[ "$TOOLCHAINCMD" =~ "${ARCH_COMPILE}gcc" ]] ; then
while [ "$#" -gt 0 ]; do
if [ "$1" = "-o" ]; then
obj="$2"
@@ -60,7 +60,7 @@ if [[ "$TOOLCHAINCMD" =~ "gcc" ]] ; then
fi
shift
done
-elif [[ "$TOOLCHAINCMD" = "ld" ]] ; then
+elif [[ "$TOOLCHAINCMD" = "${ARCH_COMPILE}ld" ]] ; then
while [ "$#" -gt 0 ]; do
if [ "$1" = "-o" ]; then
obj="$2"
--
2.18.1

View File

@ -1,8 +1,7 @@
From fc6b9c5b1b3eb5d59186fe35cc90d3c06b07c537 Mon Sep 17 00:00:00 2001 From 3af07fd0f178a4c6e2ae68207c3fedfd10672e65 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com> From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:24:36 +0000 Date: Tue, 25 Feb 2020 22:44:50 -0500
Subject: [PATCH 1004/1015] create-diff-object: new static var should be Subject: [PATCH 03/17] create-diff-object: new static var should be included
included
Before this patch, only global variables(no referenced) will be Before this patch, only global variables(no referenced) will be
included by kpatch-build. But some macros put some static varibles included by kpatch-build. But some macros put some static varibles
@ -15,14 +14,14 @@ cause a problem even the new static variables are in unbundled section.
Signed-off-by: Zhou Chengming <zhouchengming1@huawei.com> Signed-off-by: Zhou Chengming <zhouchengming1@huawei.com>
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com> Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
--- ---
kpatch-build/create-diff-object.c | 15 +++++++++++++++ kpatch-build/create-diff-object.c | 15 +++++++++++++++
1 files changed, 15 insertions(+), 0 deletions(-) 1 file changed, 15 insertions(+)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index d242d01..6e23295 100644 index 58789f1..93570df 100644
--- a/kpatch-build/create-diff-object.c --- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c
@@ -1536,6 +1536,20 @@ static void kpatch_include_force_elements(struct kpatch_elf *kelf) @@ -1689,6 +1689,20 @@ static void kpatch_include_force_elements(struct kpatch_elf *kelf)
sym->include = 0; sym->include = 0;
} }
@ -32,8 +31,8 @@ index d242d01..6e23295 100644
+ +
+ list_for_each_entry(sym, &kelf->symbols, list) { + list_for_each_entry(sym, &kelf->symbols, list) {
+ if (sym->status == NEW && + if (sym->status == NEW &&
+ sym->type == STT_OBJECT && + sym->bind == STB_LOCAL &&
+ sym->bind == STB_LOCAL) + (sym->type == STT_OBJECT || (sym->type == STT_NOTYPE && sym->name[0] != '$')))
+ kpatch_include_symbol(sym); + kpatch_include_symbol(sym);
+ } + }
+ +
@ -43,14 +42,14 @@ index d242d01..6e23295 100644
static int kpatch_include_new_globals(struct kpatch_elf *kelf) static int kpatch_include_new_globals(struct kpatch_elf *kelf)
{ {
struct symbol *sym; struct symbol *sym;
@@ -3211,6 +3225,7 @@ int main(int argc, char *argv[]) @@ -3554,6 +3568,7 @@ int main(int argc, char *argv[])
callbacks_exist = kpatch_include_callback_elements(kelf_patched); callbacks_exist = kpatch_include_callback_elements(kelf_patched);
kpatch_include_force_elements(kelf_patched); kpatch_include_force_elements(kelf_patched);
new_globals_exist = kpatch_include_new_globals(kelf_patched); new_globals_exist = kpatch_include_new_globals(kelf_patched);
+ kpatch_include_new_static_var(kelf_patched); + kpatch_include_new_static_var(kelf_patched);
kpatch_process_special_sections(kelf_patched);
kpatch_print_changes(kelf_patched);
kpatch_dump_kelf(kelf_patched);
-- --
1.7.5.4 2.18.1

View File

@ -1,42 +0,0 @@
From b2f40b03ce1778c7e97586e4111d22d3b28b3330 Mon Sep 17 00:00:00 2001
From: Artem Savkov <asavkov@redhat.com>
Date: Fri, 7 Dec 2018 16:46:08 +0100
Subject: [PATCH] kmod/patch: more linking fixes
While adding proper linker script option my previous patch left the
linker script in the list of source files (on pre-4.20 kernels) for
ld somehow breaking kpatch callback sections. For this to work
properly kpatch.lds needs to be added to 'extra-y' instead of objs. And
for kbuild to process this option properly we need to call make without
the .ko target, i.e. let kbuild decide what to build.
Fixes: 17a97b4 ("kmod/patch: fix patch linking with 4.20")
Signed-off-by: Artem Savkov <asavkov@redhat.com>
---
kmod/patch/Makefile | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/kmod/patch/Makefile b/kmod/patch/Makefile
index 7ba0820..e017b17 100644
--- a/kmod/patch/Makefile
+++ b/kmod/patch/Makefile
@@ -12,13 +12,14 @@ endif
obj-m += $(KPATCH_NAME).o
ldflags-y += -T $(src)/kpatch.lds
+extra-y := kpatch.lds
-$(KPATCH_NAME)-objs += patch-hook.o kpatch.lds output.o
+$(KPATCH_NAME)-objs += patch-hook.o output.o
all: $(KPATCH_NAME).ko
$(KPATCH_NAME).ko:
- $(KPATCH_MAKE) $(KPATCH_NAME).ko
+ $(KPATCH_MAKE)
patch-hook.o: patch-hook.c kpatch-patch-hook.c livepatch-patch-hook.c
$(KPATCH_MAKE) patch-hook.o
--
1.7.12.4

View File

@ -1,75 +0,0 @@
From 942cc3ace7edb7c15f40f931dd6f47a934b9fc77 Mon Sep 17 00:00:00 2001
From: Artem Savkov <asavkov@redhat.com>
Date: Tue, 12 Jun 2018 17:33:17 +0200
Subject: [PATCH] create-diff-object: allow changing subsections
gcc8 can place functions to .text.unlikely and .text.hot subsections
during optimizations. Allow symbols to change subsections instead of
failing.
Signed-off-by: Artem Savkov <asavkov@redhat.com>
backport from:
https://github.com/jpoimboe/kpatch/commit/35cc6ff0162fc8008c4c639fdfcabd61b38a982f
---
kpatch-build/create-diff-object.c | 28 ++++++++++++++++++++++++++--
1 file changed, 26 insertions(+), 2 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 2ddd00d..61ce74f 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -68,6 +68,12 @@
char *childobj;
+enum subsection {
+ SUBSECTION_NORMAL,
+ SUBSECTION_HOT,
+ SUBSECTION_UNLIKELY
+};
+
enum loglevel loglevel = NORMAL;
#ifndef EM_X86_64
@@ -708,6 +714,22 @@ static void kpatch_compare_sections(struct list_head *seclist)
}
}
+static enum subsection kpatch_subsection_type(struct section *sec)
+{
+ if (!strncmp(sec->name, ".text.unlikely.", 15))
+ return SUBSECTION_UNLIKELY;
+
+ if (!strncmp(sec->name, ".text.hot.", 10))
+ return SUBSECTION_HOT;
+
+ return SUBSECTION_NORMAL;
+}
+
+static int kpatch_subsection_changed(struct section *sec1, struct section *sec2)
+{
+ return kpatch_subsection_type(sec1) != kpatch_subsection_type(sec2);
+}
+
static void kpatch_compare_correlated_symbol(struct symbol *sym)
{
struct symbol *sym1 = sym, *sym2 = sym->twin;
@@ -720,10 +742,12 @@ static void kpatch_compare_correlated_symbol(struct symbol *sym)
/*
* If two symbols are correlated but their sections are not, then the
* symbol has changed sections. This is only allowed if the symbol is
- * moving out of an ignored section.
++ * moving out of an ignored section, or moving between normal/hot/unlikely
++ * subsections.
*/
if (sym1->sec && sym2->sec && sym1->sec->twin != sym2->sec) {
- if (sym2->sec->twin && sym2->sec->twin->ignore)
+ if ((sym2->sec->twin && sym2->sec->twin->ignore) ||
+ kpatch_subsection_changed(sym1->sec, sym2->sec))
sym->status = CHANGED;
else if (sym1->name[0] == '$') /* reserved symbols in aarch64 */
log_debug("maping symbols: %s", sym1->name); /* do nothing just ignogre */
--
2.19.1

View File

@ -1,7 +1,7 @@
From 858cc1f1ef2565d6ffa539550fc13af7e62863e4 Mon Sep 17 00:00:00 2001 From c03772c4e29473eae68009c12efc182238d103c7 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com> From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:24:42 +0000 Date: Fri, 2 Nov 2018 17:24:42 +0000
Subject: [PATCH 1005/1015] livepatch, fix: use THIS modname as the name of Subject: [PATCH 04/17] livepatch, fix: use THIS modname as the name of
ddebug_table ddebug_table
We just want a unique name for every module, so put a _ddebug in We just want a unique name for every module, so put a _ddebug in
@ -12,21 +12,21 @@ Suggested-by: Li Bin <huawei.libin@huawei.com>
Signed-off-by: Zhou Chengming <zhouchengming1@huawei.com> Signed-off-by: Zhou Chengming <zhouchengming1@huawei.com>
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com> Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
--- ---
kmod/patch/livepatch-patch-hook.c | 1 + kmod/patch/livepatch-patch-hook.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-) 1 file changed, 1 insertion(+)
diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c
index e59a377..2c0cadd 100644 index e12fd50..613d037 100644
--- a/kmod/patch/livepatch-patch-hook.c --- a/kmod/patch/livepatch-patch-hook.c
+++ b/kmod/patch/livepatch-patch-hook.c +++ b/kmod/patch/livepatch-patch-hook.c
@@ -452,6 +452,7 @@ out: @@ -473,6 +473,7 @@ out:
static void __exit patch_exit(void) static void __exit patch_exit(void)
{ {
+ pr_debug("make THIS modname first\n"); + pr_debug("make THIS modname first\n");
#ifndef HAVE_SIMPLE_ENABLE
WARN_ON(klp_unregister_patch(lpatch)); WARN_ON(klp_unregister_patch(lpatch));
} #endif
-- --
1.7.5.4 2.18.1

View File

@ -1,7 +1,7 @@
From 2f95a0fa6214a97f60a0d5ba4dc0cda152d5c7d4 Mon Sep 17 00:00:00 2001 From 5504f36c6de3abae8a4f7ba11f7a2838ddbc5b58 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com> From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:24:51 +0000 Date: Fri, 2 Nov 2018 17:24:51 +0000
Subject: [PATCH 1006/1015] create-diff-object: fix correlate static local Subject: [PATCH 05/17] create-diff-object: fix correlate static local
variables for __param section variables for __param section
kpatch-build correlate fail when no sections reference kpatch-build correlate fail when no sections reference
@ -27,14 +27,14 @@ copy_module_from_fd.isra.43+0x53/0x150
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com> Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
--- ---
kpatch-build/create-diff-object.c | 4 ++++ kpatch-build/create-diff-object.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-) 1 file changed, 4 insertions(+)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 6e23295..bd7dd37 100644 index 93570df..9f1abc0 100644
--- a/kpatch-build/create-diff-object.c --- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c
@@ -925,6 +925,10 @@ static int kpatch_is_normal_static_local(struct symbol *sym) @@ -1094,6 +1094,10 @@ static int kpatch_is_normal_static_local(struct symbol *sym)
if (is_special_static(sym)) if (is_special_static(sym))
return 0; return 0;
@ -46,5 +46,5 @@ index 6e23295..bd7dd37 100644
} }
-- --
1.7.5.4 2.18.1

View File

@ -1,7 +1,7 @@
From 0a92ec9f158340501151bf350050597414affece Mon Sep 17 00:00:00 2001 From 16aa1e59851c29ce63b18f8ef5c570052c6a95af Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com> From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:24:58 +0000 Date: Fri, 2 Nov 2018 17:24:58 +0000
Subject: [PATCH 1007/1015] create-diff-object: don't create dynamic reloc for Subject: [PATCH 06/17] create-diff-object: don't create dynamic reloc for
symbol exported by patch itself symbol exported by patch itself
when a patch export a new function, ___kcrctab+xxx has a reloc, when a patch export a new function, ___kcrctab+xxx has a reloc,
@ -9,23 +9,23 @@ use origin reloc to get right symbol version.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com> Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
--- ---
kpatch-build/create-diff-object.c | 3 +++ kpatch-build/create-diff-object.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-) 1 file changed, 3 insertions(+)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index bd7dd37..349e483 100644 index 9f1abc0..18ed1f7 100644
--- a/kpatch-build/create-diff-object.c --- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c
@@ -2808,6 +2808,9 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf, @@ -3039,6 +3039,9 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
if (!strcmp(sym_objname, "vmlinux")) if (!strcmp(sym_objname, "vmlinux"))
continue; continue;
+ if (!strcmp(sym_objname, pmod_name)) + if (!strcmp(sym_objname, objname))
+ continue; + continue;
+ +
external = 1; external = 1;
} }
} }
-- --
1.7.5.4 2.18.1

View File

@ -1,8 +1,8 @@
From 78a13a6091a0d4b1a45fe8f378892a64dece7202 Mon Sep 17 00:00:00 2001 From a743990bb6d871fb8cd5ffe6f78ffaa8d5ee7c0a Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com> From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:25:38 +0000 Date: Fri, 2 Nov 2018 17:25:38 +0000
Subject: [PATCH 1012/1015] create-diff-object: create dynamic relocs for Subject: [PATCH 07/17] create-diff-object: create dynamic relocs for changed
changed functions in this object functions in this object
Currently, we only create dynamic relocs for changed functions of Currently, we only create dynamic relocs for changed functions of
other objects, but not this object. It will cause a problem like: other objects, but not this object. It will cause a problem like:
@ -22,14 +22,14 @@ Signed-off-by: Zhou Chengming <zhouchengming1@huawei.com>
Signed-off-by: Li Bin <huawei.libin@huawei.com> Signed-off-by: Li Bin <huawei.libin@huawei.com>
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com> Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
--- ---
kpatch-build/create-diff-object.c | 20 ++++++++++++++++---- kpatch-build/create-diff-object.c | 20 ++++++++++++++++----
1 files changed, 16 insertions(+), 4 deletions(-) 1 file changed, 16 insertions(+), 4 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index b8d3bb4..4fb27da 100644 index 18ed1f7..5cdb97b 100644
--- a/kpatch-build/create-diff-object.c --- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c
@@ -2684,6 +2684,14 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf, @@ -2883,6 +2883,14 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
*/ */
if (may_need_dynrela(rela)) if (may_need_dynrela(rela))
toc_rela(rela)->need_dynrela = 1; toc_rela(rela)->need_dynrela = 1;
@ -44,7 +44,7 @@ index b8d3bb4..4fb27da 100644
} }
} }
@@ -2765,10 +2773,14 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf, @@ -2965,10 +2973,14 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
/* An unchanged local symbol */ /* An unchanged local symbol */
ret = lookup_local_symbol(table, ret = lookup_local_symbol(table,
rela->sym->name, &result); rela->sym->name, &result);
@ -64,5 +64,5 @@ index b8d3bb4..4fb27da 100644
else if (vmlinux) { else if (vmlinux) {
/* /*
-- --
1.7.5.4 2.18.1

View File

@ -1,20 +1,20 @@
From e617351fafaf7504a531fd00a49994653e59a737 Mon Sep 17 00:00:00 2001 From b356b59eb0f4c21ae927b036a45e573899a59378 Mon Sep 17 00:00:00 2001
From: Zhiyu Hu <huzhiyu1@huawei.com> From: Zhiyu Hu <huzhiyu1@huawei.com>
Date: Fri, 28 Dec 2018 07:06:38 +0000 Date: Fri, 28 Dec 2018 07:06:38 +0000
Subject: [PATCH] fix rodata.str problem Subject: [PATCH 08/17] fix rodata.str problem
fix some rodata.str problem fix some rodata.str problem
Signed-off-by: Zhiyu Hu <huzhiyu1@huawei.com> Signed-off-by: Zhiyu Hu <huzhiyu1@huawei.com>
--- ---
kpatch-build/create-diff-object.c | 2 +- kpatch-build/create-diff-object.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-) 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index d2e6aee..f075671 100644 index 5cdb97b..643ae3e 100644
--- a/kpatch-build/create-diff-object.c --- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c
@@ -1552,7 +1552,7 @@ static void kpatch_include_standard_elements(struct kpatch_elf *kelf) @@ -1620,7 +1620,7 @@ static void kpatch_include_standard_elements(struct kpatch_elf *kelf)
!strcmp(sec->name, ".toc") || !strcmp(sec->name, ".toc") ||
!strcmp(sec->name, ".rodata") || !strcmp(sec->name, ".rodata") ||
(!strncmp(sec->name, ".rodata.", 8) && (!strncmp(sec->name, ".rodata.", 8) &&
@ -24,5 +24,5 @@ index d2e6aee..f075671 100644
} }
} }
-- --
1.8.3.1 2.18.1

View File

@ -0,0 +1,52 @@
From c14444fc4049048abd445462676576cd8b043ea3 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Tue, 25 Feb 2020 23:40:37 -0500
Subject: [PATCH 09/17] livepatch-patch-hook: don't active patch when insmod
Don't active patch after loading the patch when
DISABLE_AFTER_LOAD is set.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kmod/patch/livepatch-patch-hook.c | 2 ++
kpatch-build/kpatch-build | 4 ++++
2 files changed, 6 insertions(+)
diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c
index 613d037..163ae1d 100644
--- a/kmod/patch/livepatch-patch-hook.c
+++ b/kmod/patch/livepatch-patch-hook.c
@@ -455,6 +455,7 @@ static int __init patch_init(void)
}
#endif
+#if !defined(DISABLE_AFTER_LOAD)
ret = klp_enable_patch(lpatch);
if (ret) {
#ifndef HAVE_SIMPLE_ENABLE
@@ -463,6 +464,7 @@ static int __init patch_init(void)
patch_free_livepatch(lpatch);
return ret;
}
+#endif
return 0;
out:
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index 17a5e11..894f0ab 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -1053,6 +1053,10 @@ if [[ -n "$KLP_SUPPORT_LOADHOOKS" ]];then
export KCPPFLAGS="-DHAVE_LOADHOOKS $KCPPFLAGS"
fi
+if [[ -n "$DISABLE_AFTER_LOAD" ]];then
+ export KCPPFLAGS="-DDISABLE_AFTER_LOAD $KCPPFLAGS"
+fi
+
echo "Building patch module: $MODNAME.ko"
if [[ -z "$USERSRCDIR" ]] && [[ "$DISTRO" = ubuntu ]]; then
--
2.18.1

View File

@ -0,0 +1,133 @@
From a8cf8f9bd90e0e7fde437a59715aa21622fad7b6 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Wed, 26 Feb 2020 06:44:06 -0500
Subject: [PATCH 10/17] kpatch-build: enhance for out of tree module
support set USERMODBUILDDIR to build patch for out
of tree module.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/kpatch-build | 50 ++++++++++++++++++++++++++++++++-------
1 file changed, 42 insertions(+), 8 deletions(-)
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index 894f0ab..4e38412 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -419,7 +419,11 @@ filter_parent_obj()
local dir="${1}"
local file="${2}"
- grep -v "\.mod\.cmd$" | grep -Fv "${dir}/.${file}.cmd"
+ grep -v "\.mod\.cmd$" | grep -Fv "${dir}/.${file}.cmd" | while read input; do
+ if [ "$(readlink -f $input)" != "$(readlink -f ${dir}/.${file}.cmd)" ];then
+ echo $input;
+ fi
+ done
}
find_parent_obj() {
@@ -441,6 +445,11 @@ find_parent_obj() {
num="$(find . -name ".*.cmd" -print0 | xargs -0 grep -lw "$grepname" | filter_parent_obj "${pdir}" "${file}" | wc -l)"
[[ "$num" -eq 1 ]] && last_deep_find="$(dirname "$parent")"
fi
+ if [[ "$num" -eq 0 ]]; then
+ parent="$(find $USERMODBUILDDIR -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fv "$pdir/.${file}.cmd" | head -n1)"
+ num="$(find $USERMODBUILDDIR -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fvc "$pdir/.${file}.cmd")"
+ [[ "$num" -eq 1 ]] && last_deep_find="$(dirname "$parent")"
+ fi
else
parent="$(grep -lw "$grepname" "$dir"/.*.cmd | filter_parent_obj "${dir}" "${file}" | head -n1)"
num="$(grep -lw "$grepname" "$dir"/.*.cmd | filter_parent_obj "${dir}" "${file}" | wc -l)"
@@ -646,6 +655,10 @@ if [[ -n "$SRCRPM" ]]; then
ARCHVERSION="${ARCHVERSION#alt-}"
fi
+if [[ -n "$USERMODBUILDDIR" ]]; then
+ OOT_MODULE="yes"
+fi
+
if [[ -n "$OOT_MODULE" ]] && [[ -z "$USERSRCDIR" ]]; then
warn "--oot-module requires --sourcedir"
exit 1
@@ -663,7 +676,7 @@ if [[ -n "$USERSRCDIR" ]]; then
fi
SRCDIR="$USERSRCDIR"
- if [[ -z "$OOT_MODULE" ]]; then
+ if [[ -z "$OOT_MODULE" || "$OOT_MODULE" == "yes" ]]; then
[[ -z "$VMLINUX" ]] && VMLINUX="$SRCDIR"/vmlinux
[[ ! -e "$VMLINUX" ]] && die "can't find vmlinux"
@@ -685,7 +698,7 @@ if [[ "$ARCHVERSION" =~ - ]]; then
fi
[[ "$ARCHVERSION" =~ .el7a. ]] && ALT="-alt"
-[[ -z "$TARGETS" ]] && TARGETS="vmlinux modules"
+[[ -z "$OOT_MODULE" ]] && [[ -z "$TARGETS" ]] && TARGETS="vmlinux modules"
# Don't check external file.
# shellcheck disable=SC1090
@@ -889,7 +902,11 @@ echo "Building original source"
unset KPATCH_GCC_TEMPDIR
# $TARGETS used as list, no quotes.
# shellcheck disable=SC2086
-CROSS_COMPILE="$TOOLSDIR/kpatch-gcc $ARCH_COMPILE" make "-j$CPUS" $TARGETS 2>&1 | logger || die
+if [[ -z "$USERMODBUILDDIR" ]]; then
+ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc $ARCH_COMPILE" make "-j$CPUS" $TARGETS 2>&1 | logger || die
+else
+ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc $ARCH_COMPILE" make -C "$USERMODBUILDDIR" M="$USERMODBUILDDIR" "-j$CPUS" $USERMODFLAGS $TARGETS 2>&1 | logger || die
+fi
echo "Building patched source"
apply_patches
@@ -900,9 +917,15 @@ KPATCH_GCC_SRCDIR="$SRCDIR"
export KPATCH_GCC_SRCDIR
# $TARGETS used as list, no quotes.
# shellcheck disable=SC2086
-CROSS_COMPILE="$TOOLSDIR/kpatch-gcc $ARCH_COMPILE" \
- KBUILD_MODPOST_WARN=1 \
- make "-j$CPUS" $TARGETS 2>&1 | logger || die
+if [[ -z "$USERMODBUILDDIR" ]]; then
+ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc $ARCH_COMPILE" \
+ KBUILD_MODPOST_WARN=1 \
+ make "-j$CPUS" $TARGETS 2>&1 | logger || die
+else
+ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc $ARCH_COMPILE" \
+ KBUILD_MODPOST_WARN=1 \
+ make -C "$USERMODBUILDDIR" M="$USERMODBUILDDIR" "-j$CPUS" $USERMODFLAGS $TARGETS 2>&1 | logger || die
+fi
# source.c:(.section+0xFF): undefined reference to `symbol'
grep "undefined reference" "$LOGFILE" | sed -r "s/^.*\`(.*)'$/\\1/" \
@@ -922,7 +945,11 @@ fi
for i in $(cat "$TEMPDIR/changed_objs")
do
mkdir -p "$TEMPDIR/patched/$(dirname "$i")" || die
- cp -f "$SRCDIR/$i" "$TEMPDIR/patched/$i" || die
+ if [ -z "$USERMODBUILDDIR" ];then
+ cp -f "$SRCDIR/$i" "$TEMPDIR/patched/$i" || die
+ else
+ cp -f "$i" "$TEMPDIR/patched/$i" || die
+ fi
done
echo "Extracting new and modified ELF sections"
@@ -987,6 +1014,13 @@ for i in $FILES; do
KOBJFILE_PATH="${TEMPDIR}/module/$KOBJFILE"
SYMTAB="${KOBJFILE_PATH}.symtab"
SYMVERS_FILE="$SRCDIR/Module.symvers"
+
+ if [ "$OOT_MODULE" == "yes" ];then
+ BUILDDIR="/lib/modules/$ARCHVERSION/build/"
+ SYMVERS_FILE="$TEMPDIR/Module.symvers"
+ [[ -e $SRCDIR/Module.symvers ]] && cp "$SRCDIR/Module.symvers" "$SYMVERS_FILE"
+ awk '{ print $1 "\t" $2 "\t" $3 "\t" $4}' "${BUILDDIR}/Module.symvers" >> "$SYMVERS_FILE"
+ fi
fi
readelf -s --wide "$KOBJFILE_PATH" > "$SYMTAB"
--
2.18.1

View File

@ -0,0 +1,193 @@
From 20de56a8393e6be3b556156124aa4b2139b10733 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Wed, 26 Feb 2020 07:36:59 -0500
Subject: [PATCH 11/17] support c plus kernel module
support GNU_UNIQUE type symbols.
support .group section corelation.
ignore compile warning for third party modules.
Signed-off-by: Zhipeng Xie <root@localhost.localdomain>
---
kpatch-build/create-diff-object.c | 62 ++++++++++++++++++++-----------
kpatch-build/kpatch-build | 2 +-
kpatch-build/kpatch-elf.c | 8 +++-
kpatch-build/kpatch-gcc | 3 +-
kpatch-build/lookup.c | 5 ++-
5 files changed, 55 insertions(+), 25 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 643ae3e..190753a 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -454,7 +454,7 @@ static void kpatch_compare_correlated_nonrela_section(struct section *sec)
{
struct section *sec1 = sec, *sec2 = sec->twin;
- if (sec1->sh.sh_type != SHT_NOBITS &&
+ if (sec1->sh.sh_type != SHT_NOBITS && sec1->sh.sh_type != SHT_GROUP &&
memcmp(sec1->data->d_buf, sec2->data->d_buf, sec1->data->d_size))
sec->status = CHANGED;
else
@@ -470,7 +470,7 @@ static void kpatch_compare_correlated_section(struct section *sec)
sec1->sh.sh_flags != sec2->sh.sh_flags ||
sec1->sh.sh_entsize != sec2->sh.sh_entsize ||
(sec1->sh.sh_addralign != sec2->sh.sh_addralign &&
- !is_text_section(sec1)))
+ !is_text_section(sec1) && strcmp(sec1->name, ".rodata")))
DIFF_FATAL("%s section header details differ from %s", sec1->name, sec2->name);
/* Short circuit for mcount sections, we rebuild regardless */
@@ -907,6 +907,33 @@ static void kpatch_correlate_section(struct section *sec1, struct section *sec2)
kpatch_correlate_symbol(sec1->sym, sec2->sym);
}
+static int kpatch_correlate_group_section(struct list_head *seclist1, struct list_head *seclist2, struct section *sec1, struct section *sec2)
+{
+ unsigned int *data1, *end1, *data2;
+ struct section *isec1, *isec2;
+
+ if (sec1->data->d_size != sec2->data->d_size)
+ return 1;
+ data1 = sec1->data->d_buf;
+ data2 = sec2->data->d_buf;
+ end1 = sec1->data->d_buf + sec1->data->d_size;
+ data1++;
+ data2++;
+ while (data1 < end1) {
+ isec1 = find_section_by_index(seclist1, *data1);
+ if (!isec1)
+ ERROR("group section not found");
+ isec2 = find_section_by_index(seclist2, *data2);
+ if (!isec2)
+ ERROR("group section not found");
+ if (strcmp(isec1->name, isec2->name))
+ return 1;
+ data1++;
+ data2++;
+ }
+ return 0;
+}
+
static void kpatch_correlate_sections(struct list_head *seclist1, struct list_head *seclist2)
{
struct section *sec1, *sec2;
@@ -924,15 +951,19 @@ static void kpatch_correlate_sections(struct list_head *seclist1, struct list_he
sec1->secsym))
continue;
- /*
- * Group sections must match exactly to be correlated.
- * Changed group sections are currently not supported.
- */
+ /* Group section的格式为
+ * flag
+ * section index
+ * section index
+ * ...
+ *
+ * 当C++代码发生修改时section index可能会发生变化
+ * 这时候我们就比对一下section index所对应的section的
+ * name如果相同我们就认为这两个group是SAME
+ * */
+
if (sec1->sh.sh_type == SHT_GROUP) {
- if (sec1->data->d_size != sec2->data->d_size)
- continue;
- if (memcmp(sec1->data->d_buf, sec2->data->d_buf,
- sec1->data->d_size))
+ if(kpatch_correlate_group_section(seclist1, seclist2, sec1, sec2))
continue;
}
@@ -1507,17 +1538,6 @@ static void kpatch_verify_patchability(struct kpatch_elf *kelf)
errs++;
}
- if (sec->status != SAME && sec->grouped) {
- log_normal("changed section %s is part of a section group\n",
- sec->name);
- errs++;
- }
-
- if (sec->sh.sh_type == SHT_GROUP && sec->status == NEW) {
- log_normal("new/changed group sections are not supported\n");
- errs++;
- }
-
/*
* ensure we aren't including .data.* or .bss.*
* (.data.unlikely and .data.once is ok b/c it only has __warned vars)
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index 4e38412..4896136 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -1157,7 +1157,7 @@ fi
# column containing lines unique to first file.
UNDEFINED=$(comm -23 <(sort -u "${TEMPDIR}"/undefined_references) \
<(sort -u "${TEMPDIR}"/new_symbols) | tr '\n' ' ')
-[[ -n "$UNDEFINED" ]] && die "Undefined symbols: $UNDEFINED"
+[[ -z "$USERMODBUILDDIR" ]] && [[ -n "$UNDEFINED" ]] && die "Undefined symbols: $UNDEFINED"
cp -f "$TEMPDIR/patch/$MODNAME.ko" "$BASE" || die
diff --git a/kpatch-build/kpatch-elf.c b/kpatch-build/kpatch-elf.c
index 1c0e099..debf028 100644
--- a/kpatch-build/kpatch-elf.c
+++ b/kpatch-build/kpatch-elf.c
@@ -708,8 +708,14 @@ void kpatch_reindex_elements(struct kpatch_elf *kelf)
unsigned int index;
index = 1; /* elf write function handles NULL section 0 */
- list_for_each_entry(sec, &kelf->sections, list)
+ list_for_each_entry(sec, &kelf->sections, list) {
sec->index = index++;
+ /*
+ * since we exclude .group section, we clear SHF_GROUP
+ * for every section in case of link error.
+ * */
+ sec->sh.sh_flags &= (~SHF_GROUP);
+ }
index = 0;
list_for_each_entry(sym, &kelf->symbols, list) {
diff --git a/kpatch-build/kpatch-gcc b/kpatch-build/kpatch-gcc
index 35d7c1c..6ad6ebc 100755
--- a/kpatch-build/kpatch-gcc
+++ b/kpatch-build/kpatch-gcc
@@ -13,7 +13,8 @@ fi
declare -a args=("$@")
-if [[ "$TOOLCHAINCMD" =~ "${ARCH_COMPILE}gcc" ]] ; then
+if [[ "$TOOLCHAINCMD" =~ "${ARCH_COMPILE}gcc" ||
+ "$TOOLCHAINCMD" =~ "${ARCH_COMPILE}g++" ]] ; then
while [ "$#" -gt 0 ]; do
if [ "$1" = "-o" ]; then
obj="$2"
diff --git a/kpatch-build/lookup.c b/kpatch-build/lookup.c
index 8387e8b..4e2fcb9 100644
--- a/kpatch-build/lookup.c
+++ b/kpatch-build/lookup.c
@@ -255,6 +255,8 @@ static void symtab_read(struct lookup_table *table, char *path)
table->obj_syms[i].bind = STB_GLOBAL;
} else if (!strcmp(bind, "WEAK")) {
table->obj_syms[i].bind = STB_WEAK;
+ } else if (!strcmp(bind, "UNIQUE")) {
+ table->obj_syms[i].bind = STB_GNU_UNIQUE;
} else {
ERROR("unknown symbol bind %s", bind);
}
@@ -431,7 +433,8 @@ int lookup_global_symbol(struct lookup_table *table, char *name,
memset(result, 0, sizeof(*result));
for_each_obj_symbol(i, sym, table) {
- if ((sym->bind == STB_GLOBAL || sym->bind == STB_WEAK) &&
+ if ((sym->bind == STB_GLOBAL || sym->bind == STB_WEAK
+ || sym->bind == STB_GNU_UNIQUE) &&
!strcmp(sym->name, name)) {
result->value = sym->value;
result->size = sym->size;
--
2.18.1

View File

@ -0,0 +1,454 @@
From 56ec8b76667fb6c7fbc018a8fe7a77f144232f3f Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Wed, 26 Feb 2020 22:03:55 -0500
Subject: [PATCH 12/17] symbol lookup enhancement
For symbols which have same name in one module or have
length longger than KSYM_NAME_LEN(128 bytes). we add
some work around to lookup another unique symbol and add
relative offset to get the actual symbol. This patch
depend on a kernel patch to deal with new relocation
style.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kmod/patch/kpatch-patch.h | 4 +
kpatch-build/create-diff-object.c | 46 ++++++++++-
kpatch-build/create-klp-module.c | 25 +++++-
kpatch-build/kpatch-build | 12 +++
kpatch-build/kpatch-intermediate.h | 2 +
kpatch-build/lookup.c | 123 ++++++++++++++++++++++++++++-
kpatch-build/lookup.h | 13 +++
7 files changed, 217 insertions(+), 8 deletions(-)
diff --git a/kmod/patch/kpatch-patch.h b/kmod/patch/kpatch-patch.h
index 917ea32..7cd6dae 100644
--- a/kmod/patch/kpatch-patch.h
+++ b/kmod/patch/kpatch-patch.h
@@ -30,6 +30,8 @@ struct kpatch_patch_func {
unsigned long sympos;
char *name;
char *objname;
+ char *ref_name;
+ long ref_offset;
};
struct kpatch_patch_dynrela {
@@ -41,6 +43,8 @@ struct kpatch_patch_dynrela {
char *objname;
int external;
int addend;
+ char *ref_name;
+ long ref_offset;
};
struct kpatch_pre_patch_callback {
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 190753a..55db18c 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -2734,6 +2734,28 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
funcs[index].old_size = result.size;
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 = index * sizeof(*funcs) +
+ offsetof(struct kpatch_patch_func, ref_name);
+
+ }
+
/*
* Add a relocation that will populate
@@ -2753,7 +2775,7 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
ALLOC_LINK(rela, &relasec->relas);
rela->sym = strsym;
rela->type = absolute_rela_type;
- rela->addend = offset_of_string(&kelf->strings, sym->name);
+ rela->addend = offset_of_string(&kelf->strings, strndup(sym->name, KSYM_NAME_LEN-1));
rela->offset = index * sizeof(*funcs) +
offsetof(struct kpatch_patch_func, name);
@@ -2872,6 +2894,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
struct lookup_result result;
char *sym_objname;
int ret, vmlinux, external;
+ long ref_offset;
vmlinux = !strcmp(objname, "vmlinux");
@@ -3080,12 +3103,28 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
log_debug("lookup for %s @ 0x%016lx len %lu\n",
rela->sym->name, result.value, result.size);
+ ref_offset = 0;
/* Fill in ksyms[index] */
if (vmlinux)
ksyms[index].src = result.value;
- else
+ else {
/* for modules, src is discovered at runtime */
ksyms[index].src = 0;
+ if (lookup_is_duplicate_symbol(table, rela->sym->name, objname, result.pos)) {
+ struct lookup_refsym refsym;
+
+ if (lookup_ref_symbol_offset(table, rela->sym->name, &refsym, objname, &ref_offset))
+ ERROR("unresolvable ambiguity on symbol %s\n", rela->sym->name);
+
+ /* add rela to fill in ref_name field */
+ ALLOC_LINK(rela2, &krela_sec->rela->relas);
+ rela2->sym = strsym;
+ rela2->type = absolute_rela_type;
+ rela2->addend = offset_of_string(&kelf->strings, refsym.name);
+ rela2->offset = index * sizeof(*krelas) +
+ offsetof(struct kpatch_relocation, ref_name);
+ }
+ }
ksyms[index].pos = result.pos;
ksyms[index].type = rela->sym->type;
ksyms[index].bind = rela->sym->bind;
@@ -3094,7 +3133,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
ALLOC_LINK(rela2, &ksym_sec->rela->relas);
rela2->sym = strsym;
rela2->type = absolute_rela_type;
- rela2->addend = offset_of_string(&kelf->strings, rela->sym->name);
+ rela2->addend = offset_of_string(&kelf->strings, strndup(rela->sym->name, KSYM_NAME_LEN-1));
rela2->offset = index * sizeof(*ksyms) + \
offsetof(struct kpatch_symbol, name);
@@ -3113,6 +3152,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
krelas[index].addend = rela->addend;
krelas[index].type = rela->type;
krelas[index].external = external;
+ krelas[index].ref_offset = ref_offset;
/* add rela to fill in krelas[index].dest field */
ALLOC_LINK(rela2, &krela_sec->rela->relas);
diff --git a/kpatch-build/create-klp-module.c b/kpatch-build/create-klp-module.c
index d995525..5073a04 100644
--- a/kpatch-build/create-klp-module.c
+++ b/kpatch-build/create-klp-module.c
@@ -38,7 +38,9 @@ enum loglevel loglevel = NORMAL;
*/
static struct symbol *find_or_add_ksym_to_symbols(struct kpatch_elf *kelf,
struct section *ksymsec,
- char *strings, int offset)
+ char *strings, int offset,
+ char *ref_name,
+ long ref_offset)
{
struct kpatch_symbol *ksyms, *ksym;
struct symbol *sym;
@@ -67,9 +69,14 @@ static struct symbol *find_or_add_ksym_to_symbols(struct kpatch_elf *kelf,
objname = strings + rela->addend;
- snprintf(pos, 32, "%lu", ksym->pos);
/* .klp.sym.objname.name,pos */
- snprintf(buf, 256, KLP_SYM_PREFIX "%s.%s,%s", objname, name, pos);
+ if (!ref_name) {
+ snprintf(pos, 32, "%lu", ksym->pos);
+ snprintf(buf, 256, KLP_SYM_PREFIX "%s.%s,%s", objname, name, pos);
+ } else {
+ snprintf(pos, 32, "%ld", ref_offset);
+ snprintf(buf, 256, KLP_SYM_PREFIX "%s-%s,%s", objname, ref_name, pos);
+ }
/* Look for an already allocated symbol */
list_for_each_entry(sym, &kelf->symbols, list) {
@@ -176,6 +183,7 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section
struct rela *rela;
char *objname;
int nr, index, offset, dest_off;
+ char *ref_name;
krelas = krelasec->data->d_buf;
nr = krelasec->data->d_size / sizeof(*krelas);
@@ -200,6 +208,15 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section
objname = strings + rela->addend;
+ /* Get the unique ref_name */
+ rela = find_rela_by_offset(krelasec->rela,
+ offset + offsetof(struct kpatch_relocation, ref_name));
+ if (!rela)
+ ref_name = NULL;
+ else {
+ ref_name = strings + rela->addend;
+ }
+
/* Get the .kpatch.symbol entry for the rela src */
rela = find_rela_by_offset(krelasec->rela,
offset + offsetof(struct kpatch_relocation, ksym));
@@ -207,7 +224,7 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section
ERROR("find_rela_by_offset");
/* Create (or find) a klp symbol from the rela src entry */
- sym = find_or_add_ksym_to_symbols(kelf, ksymsec, strings, rela->addend);
+ sym = find_or_add_ksym_to_symbols(kelf, ksymsec, strings, rela->addend, ref_name, krelas[index].ref_offset);
if (!sym)
ERROR("error finding or adding ksym to symtab");
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index 4896136..8bef7fb 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -1015,6 +1015,18 @@ for i in $FILES; do
SYMTAB="${KOBJFILE_PATH}.symtab"
SYMVERS_FILE="$SRCDIR/Module.symvers"
+ unset KCFLAGS
+ remove_patches
+ cd "$SRCDIR" || die
+ if [ -z "$USERMODBUILDDIR" ];then
+ CROSS_COMPILE="$ARCH_COMPILE" make "-j$CPUS" ${KOBJFILE} 2>&1 | logger || die
+ else
+ CROSS_COMPILE="$ARCH_COMPILE" make -C "$USERMODBUILDDIR" M="$USERMODBUILDDIR" "-j$CPUS" $USERMODFLAGS $TARGETS 2>&1 | logger || die
+ fi
+ cp ${KOBJFILE} ${KOBJFILE_PATH}
+ apply_patches
+ cd "$TEMPDIR" || die
+
if [ "$OOT_MODULE" == "yes" ];then
BUILDDIR="/lib/modules/$ARCHVERSION/build/"
SYMVERS_FILE="$TEMPDIR/Module.symvers"
diff --git a/kpatch-build/kpatch-intermediate.h b/kpatch-build/kpatch-intermediate.h
index 3dea775..59deed0 100644
--- a/kpatch-build/kpatch-intermediate.h
+++ b/kpatch-build/kpatch-intermediate.h
@@ -39,6 +39,8 @@ struct kpatch_relocation {
int external;
char *objname; /* object to which this rela applies to */
struct kpatch_symbol *ksym;
+ char *ref_name;
+ long ref_offset;
};
struct kpatch_arch {
diff --git a/kpatch-build/lookup.c b/kpatch-build/lookup.c
index 4e2fcb9..190a7d8 100644
--- a/kpatch-build/lookup.c
+++ b/kpatch-build/lookup.c
@@ -44,6 +44,7 @@ struct object_symbol {
unsigned long size;
char *name;
int type, bind;
+ int sec_index;
};
struct export_symbol {
@@ -248,6 +249,7 @@ static void symtab_read(struct lookup_table *table, char *path)
table->obj_syms[i].value = value;
table->obj_syms[i].size = strtoul(size, NULL, 0);
+ table->obj_syms[i].sec_index = atoi(ndx);
if (!strcmp(bind, "LOCAL")) {
table->obj_syms[i].bind = STB_LOCAL;
@@ -398,6 +400,15 @@ int lookup_local_symbol(struct lookup_table *table, char *name,
for_each_obj_symbol(i, sym, table) {
if (sym->bind == STB_LOCAL && !strcmp(sym->name, name))
pos++;
+ else {
+ /* symbol name longer than KSYM_NAME_LEN will be truncated
+ * by kernel, so we can not find it using its original
+ * name. we need to add pos for symbols which have same
+ * KSYM_NAME_LEN-1 long prefix.*/
+ if (strlen(name) >= KSYM_NAME_LEN-1 &&
+ !strncmp(sym->name, name, KSYM_NAME_LEN-1))
+ pos++;
+ }
if (table->local_syms == sym) {
in_file = 1;
@@ -429,16 +440,25 @@ int lookup_global_symbol(struct lookup_table *table, char *name,
struct lookup_result *result)
{
struct object_symbol *sym;
+ unsigned long pos = 0;
int i;
memset(result, 0, sizeof(*result));
for_each_obj_symbol(i, sym, table) {
+ /* symbol name longer than KSYM_NAME_LEN will be truncated
+ * by kernel, so we can not find it using its original
+ * name. we need to add pos for symbols which have same
+ * KSYM_NAME_LEN-1 long prefix.*/
+ if (strlen(name) >= KSYM_NAME_LEN-1 &&
+ !strncmp(sym->name, name, KSYM_NAME_LEN-1))
+ pos++;
+
if ((sym->bind == STB_GLOBAL || sym->bind == STB_WEAK
|| sym->bind == STB_GNU_UNIQUE) &&
!strcmp(sym->name, name)) {
result->value = sym->value;
result->size = sym->size;
- result->pos = 0; /* always 0 for global symbols */
+ result->pos = pos;
return 0;
}
}
@@ -485,6 +505,107 @@ char *lookup_exported_symbol_objname(struct lookup_table *table, char *name)
return NULL;
}
+int lookup_is_duplicate_symbol(struct lookup_table *table, char *name,
+ char *objname, unsigned long pos)
+{
+ struct object_symbol *sym;
+ int i, count = 0;
+ char posstr[32], buf[256];
+
+ for_each_obj_symbol(i, sym, table)
+ if (!strcmp(sym->name, name)) {
+ count++;
+ if (count > 1)
+ return 1;
+ }
+
+ /* symbol name longer than KSYM_NAME_LEN will be truncated
+ * by kernel, so we can not find it using its original
+ * name. Here, we consider these long name symbol as duplicated
+ * symbols. since create_klp_module will create symbol name
+ * format like .klp.sym.objname.symbol,pos, so we consider name
+ * length longer than KSYM_NAME_LEN-1 bytes as duplicated symbol*/
+ snprintf(posstr, 32, "%lu", pos);
+ snprintf(buf, 256, KLP_SYM_PREFIX "%s.%s,%s", objname, name, posstr);
+ if (strlen(buf) >= KSYM_NAME_LEN-1)
+ return 1;
+
+ return 0;
+}
+
+struct object_symbol *lookup_find_symbol_by_name(struct lookup_table *table, char *name)
+{
+ struct object_symbol *sym;
+ unsigned long pos = 0;
+ int i, match = 0, in_file = 0;
+
+ if (!table->local_syms)
+ return NULL;
+
+ for_each_obj_symbol(i, sym, table) {
+ if (sym->bind == STB_LOCAL && !strcmp(sym->name, name))
+ pos++;
+
+ if (table->local_syms == sym) {
+ in_file = 1;
+ continue;
+ }
+
+ if (!in_file)
+ continue;
+
+ if (sym->type == STT_FILE)
+ break;
+
+ if (sym->bind == STB_LOCAL && !strcmp(sym->name, name)) {
+ match = 1;
+ break;
+ }
+ }
+
+ if (!match) {
+ for_each_obj_symbol(i, sym, table) {
+ if ((sym->bind == STB_GLOBAL || sym->bind == STB_WEAK) &&
+ !strcmp(sym->name, name)) {
+ return sym;
+ }
+ }
+ return NULL;
+ }
+
+ return sym;
+}
+
+int lookup_ref_symbol_offset(struct lookup_table *table, char *name,
+ struct lookup_refsym *refsym,
+ char *objname, long *offset)
+{
+ struct object_symbol *orig_sym, *sym;
+ int i;
+
+ orig_sym = lookup_find_symbol_by_name(table, name);
+ if (!orig_sym)
+ ERROR("lookup_ref_symbol_offset");
+ memset(refsym, 0, sizeof(*refsym));
+
+ /*find a unique symbol in the same section first*/
+ for_each_obj_symbol(i, sym, table) {
+ if (!strcmp(sym->name, name) || sym->type == STT_FILE ||
+ sym->sec_index != orig_sym->sec_index ||
+ strchr(sym->name, '.'))
+ continue;
+
+ if (!lookup_is_duplicate_symbol(table, sym->name, objname, 1)) {
+ refsym->name = sym->name;
+ refsym->value = sym->value;
+ *offset = (long)orig_sym->value - (long)sym->value;
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
#if 0 /* for local testing */
static void find_this(struct lookup_table *table, char *sym, char *hint)
{
diff --git a/kpatch-build/lookup.h b/kpatch-build/lookup.h
index 420d0f0..fed3fe9 100644
--- a/kpatch-build/lookup.h
+++ b/kpatch-build/lookup.h
@@ -1,6 +1,9 @@
#ifndef _LOOKUP_H_
#define _LOOKUP_H_
+#include "kpatch-elf.h"
+#define KSYM_NAME_LEN 128
+
struct lookup_table;
struct lookup_result {
@@ -14,6 +17,11 @@ struct sym_compare_type {
int type;
};
+struct lookup_refsym {
+ char *name;
+ unsigned long value;
+};
+
struct lookup_table *lookup_open(char *symtab_path, char *symvers_path,
char *hint, struct sym_compare_type *locals);
void lookup_close(struct lookup_table *table);
@@ -23,5 +31,10 @@ int lookup_global_symbol(struct lookup_table *table, char *name,
struct lookup_result *result);
int lookup_is_exported_symbol(struct lookup_table *table, char *name);
char *lookup_exported_symbol_objname(struct lookup_table *table, char *name);
+int lookup_is_duplicate_symbol(struct lookup_table *table, char *name,
+ char *objname, unsigned long pos);
+int lookup_ref_symbol_offset(struct lookup_table *table, char *name,
+ struct lookup_refsym *refsym, char *objname,
+ long *offset);
#endif /* _LOOKUP_H_ */
--
2.18.1

View File

@ -0,0 +1,171 @@
From 05051ffc7abcb953fb1ec51b0826b41f160ce191 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Wed, 26 Feb 2020 20:28:13 -0500
Subject: [PATCH 13/17] Add running kernel symbol table to help symbol lookup
For some duplicate symbols whose section have no other
symbols, we need running kernel symbol table to help
symbol lookup.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/create-diff-object.c | 7 ++-
kpatch-build/lookup.c | 73 ++++++++++++++++++++++++++++++-
kpatch-build/lookup.h | 3 +-
3 files changed, 80 insertions(+), 3 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 55db18c..4589ba4 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -3564,6 +3564,7 @@ int main(int argc, char *argv[])
struct sym_compare_type *base_locals, *sym_comp;
char *no_profiling_calls = NULL;
char *gcc_add_option = NULL, *mlongcall = NULL;
+ char *kallsyms;
arguments.debug = 0;
argp_parse (&argp, argc, argv, 0, NULL, &arguments);
@@ -3677,8 +3678,12 @@ int main(int argc, char *argv[])
*/
kpatch_elf_teardown(kelf_patched);
+ kallsyms = getenv("KALLSYMS");
+ if (kallsyms)
+ log_debug("kallsyms file:%s\n", kallsyms);
+
/* create symbol lookup table */
- lookup = lookup_open(parent_symtab, mod_symvers, hint, base_locals);
+ lookup = lookup_open(parent_symtab, mod_symvers, hint, base_locals, kallsyms);
for (sym_comp = base_locals; sym_comp && sym_comp->name; sym_comp++) {
free(sym_comp->name);
}
diff --git a/kpatch-build/lookup.c b/kpatch-build/lookup.c
index 190a7d8..8f53567 100644
--- a/kpatch-build/lookup.c
+++ b/kpatch-build/lookup.c
@@ -45,6 +45,7 @@ struct object_symbol {
char *name;
int type, bind;
int sec_index;
+ unsigned long kaddr;
};
struct export_symbol {
@@ -284,6 +285,56 @@ static void symtab_read(struct lookup_table *table, char *path)
fclose(file);
}
+static void ksymtab_read(struct lookup_table *table, char *path)
+{
+ FILE *file;
+ struct object_symbol *sym, *sym1, *sym2;
+ unsigned long value;
+ int i, j, idx;
+ char line[256], name[256], type[256], mod[256];
+ idx = 0;
+
+ if ((file = fopen(path, "r")) == NULL)
+ ERROR("fopen");
+
+ while (fgets(line, 256, file)) {
+ if (sscanf(line, "%lx %s %s [%s]\n",
+ &value, type, name, mod) != 4)
+ continue;
+
+ if (name[0] == '$')
+ continue;
+
+ i = idx;
+ for_each_obj_symbol_continue(i, sym, table) {
+ if (!strncmp(sym->name, name, KSYM_NAME_LEN-1)) {
+ sym->kaddr = value;
+ idx = i + 1;
+ break;
+ }
+ }
+ }
+
+ for_each_obj_symbol(i, sym1, table) {
+ if (sym1->kaddr == 0)
+ continue;
+ for_each_obj_symbol(j, sym2, table) {
+ if (sym2->kaddr == 0)
+ continue;
+ if (sym1 == sym2)
+ continue;
+ if (sym1->sec_index != sym2->sec_index)
+ continue;
+ if ((long)sym1->value - (long)sym2->value ==
+ (long)sym1->kaddr - (long)sym2->kaddr)
+ continue;
+
+ ERROR("base mismatch(symbol offset)");
+ }
+ }
+ fclose(file);
+}
+
/*
* Symvers file format is the following for kernels v5.3 and newer:
* <CRC> <Symbol> <Namespace> <Module> <Export Type>
@@ -352,7 +403,8 @@ static void symvers_read(struct lookup_table *table, char *path)
}
struct lookup_table *lookup_open(char *symtab_path, char *symvers_path,
- char *hint, struct sym_compare_type *locals)
+ char *hint, struct sym_compare_type *locals,
+ char *kallsyms)
{
struct lookup_table *table;
@@ -363,6 +415,8 @@ struct lookup_table *lookup_open(char *symtab_path, char *symvers_path,
symtab_read(table, symtab_path);
symvers_read(table, symvers_path);
+ if (kallsyms)
+ ksymtab_read(table, kallsyms);
find_local_syms(table, hint, locals);
return table;
@@ -603,6 +657,23 @@ int lookup_ref_symbol_offset(struct lookup_table *table, char *name,
}
}
+ if (orig_sym->kaddr == 0)
+ return 1;
+
+ /*find a unique symbol has kaddr*/
+ for_each_obj_symbol(i, sym, table) {
+ if (!strcmp(sym->name, name) || sym->type == STT_FILE ||
+ sym->kaddr == 0 || strchr(sym->name, '.'))
+ continue;
+
+ if (!lookup_is_duplicate_symbol(table, sym->name, objname, 1)) {
+ refsym->name = sym->name;
+ refsym->value = 0;
+ *offset = (long)orig_sym->kaddr - (long)sym->kaddr;
+ return 0;
+ }
+ }
+
return 1;
}
diff --git a/kpatch-build/lookup.h b/kpatch-build/lookup.h
index fed3fe9..00b6ccc 100644
--- a/kpatch-build/lookup.h
+++ b/kpatch-build/lookup.h
@@ -23,7 +23,8 @@ struct lookup_refsym {
};
struct lookup_table *lookup_open(char *symtab_path, char *symvers_path,
- char *hint, struct sym_compare_type *locals);
+ char *hint, struct sym_compare_type *locals,
+ char *kallsyms);
void lookup_close(struct lookup_table *table);
int lookup_local_symbol(struct lookup_table *table, char *name,
struct lookup_result *result);
--
2.18.1

View File

@ -1,21 +1,21 @@
From aaaec2d292b7e1d07c35e07ba92917ee05a4a141 Mon Sep 17 00:00:00 2001 From b63c72375420cb098a81167c48d822d596e770a9 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com> From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:25:03 +0000 Date: Wed, 26 Feb 2020 20:43:34 -0500
Subject: [PATCH 1008/1015] livepatch-patch-hook: support force enable/disable Subject: [PATCH 14/17] livepatch-patch-hook: support force enable/disable
function
we use immediate to indicate patch which bypass stack check. we use force to indicate function which bypass stack check
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com> Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
--- ---
kmod/patch/livepatch-patch-hook.c | 11 +++++++++++ kmod/patch/livepatch-patch-hook.c | 18 ++++++++++++++++++
1 files changed, 11 insertions(+), 0 deletions(-) kpatch-build/kpatch-build | 4 ++++
2 files changed, 22 insertions(+)
diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c
index 2c0cadd..625ffbd 100644 index 163ae1d..7e848a7 100644
--- a/kmod/patch/livepatch-patch-hook.c --- a/kmod/patch/livepatch-patch-hook.c
+++ b/kmod/patch/livepatch-patch-hook.c +++ b/kmod/patch/livepatch-patch-hook.c
@@ -228,6 +228,16 @@ extern struct kpatch_pre_patch_callback __kpatch_callbacks_pre_patch[], __kpatch @@ -238,6 +238,17 @@ extern struct kpatch_pre_patch_callback __kpatch_callbacks_pre_patch[], __kpatch
extern struct kpatch_post_patch_callback __kpatch_callbacks_post_patch[], __kpatch_callbacks_post_patch_end[]; extern struct kpatch_post_patch_callback __kpatch_callbacks_post_patch[], __kpatch_callbacks_post_patch_end[];
extern struct kpatch_pre_unpatch_callback __kpatch_callbacks_pre_unpatch[], __kpatch_callbacks_pre_unpatch_end[]; extern struct kpatch_pre_unpatch_callback __kpatch_callbacks_pre_unpatch[], __kpatch_callbacks_pre_unpatch_end[];
extern struct kpatch_post_unpatch_callback __kpatch_callbacks_post_unpatch[], __kpatch_callbacks_post_unpatch_end[]; extern struct kpatch_post_unpatch_callback __kpatch_callbacks_post_unpatch[], __kpatch_callbacks_post_unpatch_end[];
@ -29,17 +29,39 @@ index 2c0cadd..625ffbd 100644
+ return 1; + return 1;
+ return 0; + return 0;
+} +}
+
#ifdef HAVE_CALLBACKS #ifdef HAVE_CALLBACKS
static int add_callbacks_to_patch_objects(void) static int add_callbacks_to_patch_objects(void)
@@ -393,6 +403,7 @@ static int __init patch_init(void) @@ -403,6 +414,13 @@ static int __init patch_init(void)
lfunc = &lfuncs[j]; lfunc = &lfuncs[j];
lfunc->old_name = func->kfunc->name; lfunc->old_name = func->kfunc->name;
lfunc->new_func = (void *)func->kfunc->new_addr; lfunc->new_func = (void *)func->kfunc->new_addr;
+ lfunc->immediate = patch_is_func_forced(lfunc->new_func); +#if defined(__KLP_SUPPORT_FORCE__)
+#ifdef __ALL_FORCE__
+ lfunc->force = 1;
+#else
+ lfunc->force = patch_is_func_forced(func->kfunc->new_addr);
+#endif
+#endif
#ifdef HAVE_SYMPOS #ifdef HAVE_SYMPOS
lfunc->old_sympos = func->kfunc->sympos; lfunc->old_sympos = func->kfunc->sympos;
#else #else
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index 8bef7fb..57487b1 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -1079,6 +1079,10 @@ if "$KPATCH_MODULE"; then
export KCPPFLAGS="-D__KPATCH_MODULE__"
fi
+if [[ -n "$NO_STACK_CHECK" ]];then
+ export KCPPFLAGS="-D__ALL_FORCE__ $KCPPFLAGS"
+fi
+
if [[ -n "$KLP_SUPPORT_FORCE" ]];then
export KCPPFLAGS="-D__KLP_SUPPORT_FORCE__ $KCPPFLAGS"
fi
-- --
1.7.5.4 2.18.1

View File

@ -0,0 +1,64 @@
From 720769ca54d446baf9cbc986fd2a8832da45ce71 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Wed, 26 Feb 2020 21:01:02 -0500
Subject: [PATCH 15/17] kpatch-build: ignore debuginfo in patch
Just ignore all .debug_* sections
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/create-diff-object.c | 18 ++++++++++++++++++
kpatch-build/kpatch-build | 1 +
2 files changed, 19 insertions(+)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 4589ba4..c466eb0 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -2396,6 +2396,23 @@ static void kpatch_include_debug_sections(struct kpatch_elf *kelf)
}
}
+static void kpatch_ignore_debug_sections(struct kpatch_elf *kelf)
+{
+ struct section *sec;
+
+ /* include all .debug_* sections */
+ list_for_each_entry(sec, &kelf->sections, list) {
+ if (is_debug_section(sec)) {
+ sec->include = 0;
+ sec->status = SAME;
+ if (!is_rela_section(sec)) {
+ sec->secsym->include = 0;
+ sec->secsym->status = SAME;
+ }
+ }
+ }
+}
+
static void kpatch_mark_ignored_sections(struct kpatch_elf *kelf)
{
struct section *sec, *strsec, *ignoresec;
@@ -3645,6 +3662,7 @@ int main(int argc, char *argv[])
kpatch_include_standard_elements(kelf_patched);
num_changed = kpatch_include_changed_functions(kelf_patched);
kpatch_include_debug_sections(kelf_patched);
+ kpatch_ignore_debug_sections(kelf_patched);
callbacks_exist = kpatch_include_callback_elements(kelf_patched);
kpatch_include_force_elements(kelf_patched);
new_globals_exist = kpatch_include_new_globals(kelf_patched);
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index 57487b1..c109ee3 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -1143,6 +1143,7 @@ KBUILD_EXTRA_SYMBOLS="$KBUILD_EXTRA_SYMBOLS" \
KPATCH_LDFLAGS="$KPATCH_LDFLAGS" \
CROSS_COMPILE="$ARCH_COMPILE" \
make 2>&1 | logger || die
+${ARCH_COMPILE}strip -g "$TEMPDIR/patch/$MODNAME.ko"
if ! "$KPATCH_MODULE"; then
if [[ -z "$KPATCH_LDFLAGS" ]]; then
--
2.18.1

View File

@ -1,17 +1,17 @@
From d6304fcd36edd4e9df48687517f30965d9a790e9 Mon Sep 17 00:00:00 2001 From dd03a70462783a9e8426ff76e42c41a7eaab644f Mon Sep 17 00:00:00 2001
From: Bin Yang <robin.yb@huawei.com> From: Bin Yang <robin.yb@huawei.com>
Date: Tue, 16 Jul 2019 14:39:27 +0800 Date: Tue, 16 Jul 2019 14:39:27 +0800
Subject: [PATCH] add object in kpatch Subject: [PATCH 16/17] add object in kpatch
--- ---
kpatch-build/kpatch-build | 3 +++ kpatch-build/kpatch-build | 3 +++
1 file changed, 3 insertions(+) 1 file changed, 3 insertions(+)
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index 59af250..f685654 100644 index c109ee3..de448dc 100755
--- a/kpatch-build/kpatch-build --- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build +++ b/kpatch-build/kpatch-build
@@ -1011,6 +1011,8 @@ echo -n "Patched objects:" @@ -1071,6 +1071,8 @@ echo -n "Patched objects:"
for i in $(echo "${objnames[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' ') for i in $(echo "${objnames[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' ')
do do
echo -n " $i" echo -n " $i"
@ -20,8 +20,8 @@ index 59af250..f685654 100644
done done
echo echo
@@ -1113,6 +1115,7 @@ UNDEFINED=$(comm -23 <(sort -u "${TEMPDIR}"/undefined_references) \ @@ -1177,6 +1179,7 @@ UNDEFINED=$(comm -23 <(sort -u "${TEMPDIR}"/undefined_references) \
[[ -z "$USERMODDIR" ]] && [[ ! -z "$UNDEFINED" ]] && die "Undefined symbols: $UNDEFINED" [[ -z "$USERMODBUILDDIR" ]] && [[ -n "$UNDEFINED" ]] && die "Undefined symbols: $UNDEFINED"
cp -f "$TEMPDIR/patch/$MODNAME.ko" "$BASE" || die cp -f "$TEMPDIR/patch/$MODNAME.ko" "$BASE" || die
+cp -f "$TEMPDIR/patch/object" "$BASE" || die +cp -f "$TEMPDIR/patch/object" "$BASE" || die
@ -29,5 +29,5 @@ index 59af250..f685654 100644
[[ "$DEBUG" -eq 0 ]] && rm -f "$LOGFILE" [[ "$DEBUG" -eq 0 ]] && rm -f "$LOGFILE"
-- --
2.17.1 2.18.1

View File

@ -0,0 +1,42 @@
From 96e3ca2fbed32589510c800e9efe31bab2f5e58a Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Thu, 27 Feb 2020 15:36:55 -0500
Subject: [PATCH 17/17] create-diff-object: fix .orc_unwind_ip error
error: .orc_unwind_ip section header details
differ from .orc_unwind_ip
Don't correlate .orc_unwind sections and symbols
Signed-off-by: root <root@localhost.localdomain>
---
kpatch-build/create-diff-object.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index c466eb0..320b239 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -967,6 +967,9 @@ static void kpatch_correlate_sections(struct list_head *seclist1, struct list_he
continue;
}
+ if (strstr(sec1->name, ".orc_unwind"))
+ continue;
+
kpatch_correlate_section(sec1, sec2);
break;
}
@@ -1012,6 +1015,9 @@ static void kpatch_correlate_symbols(struct list_head *symlist1, struct list_hea
sym1->sec->twin != sym2->sec)
continue;
+ if (strstr(sym1->name, ".orc_unwind"))
+ continue;
+
kpatch_correlate_symbol(sym1, sym2);
break;
}
--
2.18.1

View File

@ -1,34 +0,0 @@
From ee167e43252bdb9e84cbefcd8b6fe767c9dc768f Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:24:15 +0000
Subject: [PATCH 1001/1015] livepatch-patch-hook: don't active patch when
insmod
we want to active patch after loading the patch.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kmod/patch/livepatch-patch-hook.c | 7 -------
1 files changed, 0 insertions(+), 7 deletions(-)
diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c
index 7a587a3..e59a377 100644
--- a/kmod/patch/livepatch-patch-hook.c
+++ b/kmod/patch/livepatch-patch-hook.c
@@ -443,13 +443,6 @@ static int __init patch_init(void)
return ret;
}
- ret = klp_enable_patch(lpatch);
- if (ret) {
- WARN_ON(klp_unregister_patch(lpatch));
- patch_free_livepatch(lpatch);
- return ret;
- }
-
return 0;
out:
patch_free_livepatch(lpatch);
--
1.7.5.4

View File

@ -1,208 +0,0 @@
From c27f1093cd47c48e2f403c4ffb29bf066ce0bea5 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:24:24 +0000
Subject: [PATCH 1002/1015] kpatch-build: support third party module make
hotpatch
support out of tree module to make hotpatch.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/kpatch-build | 76 ++++++++++++++++++++++++++++++++++++---------
kpatch-build/kpatch-gcc | 5 +++
2 files changed, 66 insertions(+), 15 deletions(-)
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index a76913f..ccef86d 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -102,7 +102,11 @@ remove_patches() {
for (( ; APPLIED_PATCHES>0; APPLIED_PATCHES-- )); do
idx=$(( APPLIED_PATCHES - 1))
patch="${PATCH_LIST[$idx]}"
- patch -p1 -R -d "$SRCDIR" < "$patch" &> /dev/null
+ if [ -n "$USERMODDIR" ];then
+ patch -p1 -R -d "$USERMODDIR" < "$patch" &> /dev/null
+ else
+ patch -p1 -R -d "$SRCDIR" < "$patch" &> /dev/null
+ fi
done
# If $SRCDIR was a git repo, make sure git actually sees that
@@ -318,8 +322,8 @@ find_parent_obj() {
num="$(grep -l "$grepname" "$last_deep_find"/.*.cmd | grep -Fvc "$pdir/.${file}.cmd")"
fi
if [[ "$num" -eq 0 ]]; then
- parent="$(find ./* -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fv "$pdir/.${file}.cmd" | cut -c3- | head -n1)"
- num="$(find ./* -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fvc "$pdir/.${file}.cmd")"
+ parent="$(find . -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fv "$pdir/.${file}.cmd" | cut -c3- | head -n1)"
+ num="$(find . -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fvc "$pdir/.${file}.cmd")"
[[ "$num" -eq 1 ]] && last_deep_find="$(dirname "$parent")"
fi
else
@@ -335,6 +339,9 @@ find_parent_obj() {
PARENT="${PARENT#.}"
PARENT="${PARENT%.cmd}"
PARENT="$dir/$PARENT"
+ if [ -n "$USERMODDIR" ];then
+ PARENT="$(readlink -f "$PARENT")"
+ fi
[[ ! -e "$PARENT" ]] && die "ERROR: can't find parent $PARENT for $1"
}
@@ -397,7 +404,7 @@ usage() {
echo " (not recommended)" >&2
}
-options="$(getopt -o ha:r:s:c:v:j:t:n:o:d -l "help,archversion:,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,debug,skip-gcc-check,skip-cleanup" -- "$@")" || die "getopt failed"
+options="$(getopt -o ha:r:s:c:v:j:t:n:o:dm:b: -l "help,archversion:,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,debug,skip-gcc-check,skip-cleanup,moduledir,builddir" -- "$@")" || die "getopt failed"
eval set -- "$options"
@@ -463,6 +470,16 @@ while [[ $# -gt 0 ]]; do
echo "WARNING: Skipping gcc version matching check (not recommended)"
SKIPGCCCHECK=1
;;
+ -m|--moduledir)
+ USERMODDIR=$(readlink -f "$2")
+ shift
+ [[ ! -d "$USERMODDIR" ]] && die "module dir $USERMODDIR not found"
+ ;;
+ -b|--builddir)
+ BUILDDIR=$(readlink -f "$2")
+ shift
+ [[ ! -d "$BUILDDIR" ]] && die "kernel develop dir $BUILDDIR not found"
+ ;;
*)
[[ "$1" = "--" ]] && shift && continue
[[ ! -f "$1" ]] && die "patch file '$1' not found"
@@ -528,7 +545,7 @@ if [[ "$ARCHVERSION" =~ - ]]; then
fi
[[ "$ARCHVERSION" =~ .el7a. ]] && ALT="-alt"
-[[ -z "$TARGETS" ]] && TARGETS="vmlinux modules"
+[[ -z "$USERMODDIR" ]] && [[ -z "$TARGETS" ]] && TARGETS="vmlinux modules"
# Don't check external file.
# shellcheck disable=SC1091
@@ -691,7 +708,11 @@ fi
grep -q "CONFIG_DEBUG_INFO_SPLIT=y" "$CONFIGFILE" && die "kernel option 'CONFIG_DEBUG_INFO_SPLIT' not supported"
echo "Testing patch file(s)"
-cd "$SRCDIR" || die
+if [ -z "$USERMODDIR" ];then
+ cd "$SRCDIR" || die
+else
+ cd $USERMODDIR || die
+fi
apply_patches
remove_patches
@@ -709,15 +730,23 @@ find_special_section_data
if [[ $DEBUG -ge 4 ]]; then
export KPATCH_GCC_DEBUG=1
fi
-
-echo "Building original kernel"
-./scripts/setlocalversion --save-scmversion || die
+if [ -z "$USERMODDIR" ];then
+ echo "Building original kernel"
+ ./scripts/setlocalversion --save-scmversion || die
+else
+ echo "Building original module"
+fi
unset KPATCH_GCC_TEMPDIR
# $TARGETS used as list, no quotes.
# shellcheck disable=SC2086
CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make "-j$CPUS" $TARGETS 2>&1 | logger || die
-echo "Building patched kernel"
+sleep 1
+if [ -z "$USERMODDIR" ];then
+ echo "Building patched kernel"
+else
+ echo "Building patched module"
+fi
apply_patches
mkdir -p "$TEMPDIR/orig" "$TEMPDIR/patched"
KPATCH_GCC_TEMPDIR="$TEMPDIR"
@@ -739,14 +768,22 @@ if [[ ! -e "$TEMPDIR/changed_objs" ]]; then
die "no changed objects found"
fi
-grep -q vmlinux "$SRCDIR/Module.symvers" || die "truncated $SRCDIR/Module.symvers file"
+SYMVERS="$SRCDIR/Module.symvers"
+if [ ! -f "$SYMVERS" -a -n "$BUILDDIR" ];then
+ SYMVERS="$BUILDDIR/Module.symvers"
+fi
+grep -q vmlinux "$SYMVERS" || die "truncated $SYMVERS file"
# Read as words, no quotes.
# shellcheck disable=SC2013
for i in $(cat "$TEMPDIR/changed_objs")
do
mkdir -p "$TEMPDIR/patched/$(dirname "$i")" || die
- cp -f "$SRCDIR/$i" "$TEMPDIR/patched/$i" || die
+ if [ -z "$USERMODDIR" ];then
+ cp -f "$SRCDIR/$i" "$TEMPDIR/patched/$i" || die
+ else
+ cp -f "$i" "$TEMPDIR/patched/$i" || die
+ fi
done
echo "Extracting new and modified ELF sections"
@@ -788,7 +825,11 @@ for i in $FILES; do
[[ "$i" = usr/initramfs_data.o ]] && continue
mkdir -p "output/$(dirname "$i")"
- cd "$SRCDIR" || die
+ if [ -z "$USERMODDIR" ];then
+ cd "$SRCDIR" || die
+ else
+ cd $USERMODDIR || die
+ fi
find_kobj "$i"
cd "$TEMPDIR" || die
if [[ -e "orig/$i" ]]; then
@@ -808,7 +849,7 @@ for i in $FILES; do
# create-diff-object orig.o patched.o parent-name parent-symtab
# Module.symvers patch-mod-name output.o
"$TOOLSDIR"/create-diff-object "orig/$i" "patched/$i" "$KOBJFILE_NAME" \
- "$SYMTAB" "$SRCDIR/Module.symvers" "${MODNAME//-/_}" \
+ "$SYMTAB" "$SYMVERS" "${MODNAME//-/_}" \
"output/$i" 2>&1 | logger 1
check_pipe_status create-diff-object
# create-diff-object returns 3 if no functional change is found
@@ -871,7 +912,12 @@ fi
cd "$TEMPDIR/patch" || die
-KPATCH_BUILD="$SRCDIR" KPATCH_NAME="$MODNAME" \
+if [ -z "$BUILDDIR" ];then
+ KPATCH_BUILDIR="$SRCDIR"
+else
+ KPATCH_BUILDIR="$BUILDDIR"
+fi
+KPATCH_BUILD="$KPATCH_BUILDIR" KPATCH_NAME="$MODNAME" \
KBUILD_EXTRA_SYMBOLS="$KBUILD_EXTRA_SYMBOLS" \
KPATCH_LDFLAGS="$KPATCH_LDFLAGS" \
make 2>&1 | logger || die
diff --git a/kpatch-build/kpatch-gcc b/kpatch-build/kpatch-gcc
index 2d56da1..21f7e2e 100755
--- a/kpatch-build/kpatch-gcc
+++ b/kpatch-build/kpatch-gcc
@@ -23,6 +23,11 @@ if [[ "$TOOLCHAINCMD" = "gcc" ]] ; then
[[ "$obj" = */.tmp_mc_*.o ]] && break;
[[ "$obj" = */.tmp_*.o ]] && obj="${obj/.tmp_/}"
+
+ if [[ $obj =~ \/\.[0-9]+\.o ]]; then
+ break;
+ fi
+
case "$obj" in
*.mod.o|\
*built-in.o|\
--
1.7.5.4

View File

@ -1,92 +0,0 @@
From 214de7459555f3f0461cf4127c55f727ccf473d1 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:24:30 +0000
Subject: [PATCH 1003/1015] kpatch-build: support makefile not in third party
module source directory
support makefile not in third party module source directory.
for example:
testmod/build/Makefile
testmod/src/test.c
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/kpatch-build | 32 +++++++++++++++++++++++++++-----
1 files changed, 27 insertions(+), 5 deletions(-)
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index ccef86d..93a0589 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -311,7 +311,10 @@ find_parent_obj() {
dir="$(dirname "$1")"
absdir="$(readlink -f "$dir")"
pwddir="$(readlink -f .)"
- pdir="${absdir#$pwddir/}"
+ pdir="."
+ if [ "$absdir" != "$pwddir" ];then
+ pdir="${absdir#$pwddir/}"
+ fi
file="$(basename "$1")"
grepname="${1%.o}"
grepname="$grepname\\.o"
@@ -326,6 +329,11 @@ find_parent_obj() {
num="$(find . -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fvc "$pdir/.${file}.cmd")"
[[ "$num" -eq 1 ]] && last_deep_find="$(dirname "$parent")"
fi
+ if [[ "$num" -eq 0 ]]; then
+ parent="$(find $USERMODBUILDDIR -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fv "$pdir/.${file}.cmd" | head -n1)"
+ num="$(find $USERMODBUILDDIR -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fvc "$pdir/.${file}.cmd")"
+ [[ "$num" -eq 1 ]] && last_deep_find="$(dirname "$parent")"
+ fi
else
parent="$(grep -l "$grepname" "$dir"/.*.cmd | grep -Fv "$dir/.${file}.cmd" | head -n1)"
num="$(grep -l "$grepname" "$dir"/.*.cmd | grep -Fvc "$dir/.${file}.cmd")"
@@ -730,16 +738,24 @@ find_special_section_data
if [[ $DEBUG -ge 4 ]]; then
export KPATCH_GCC_DEBUG=1
fi
+if [ -z "$USERMODBUILDDIR" ];then
+ USERMODBUILDDIR=$USERMODDIR;
+fi
if [ -z "$USERMODDIR" ];then
echo "Building original kernel"
./scripts/setlocalversion --save-scmversion || die
else
echo "Building original module"
+ [[ -e $USERMODDIR/Module.symvers ]] && cp -f $USERMODDIR/Module.symvers $TEMPDIR/patch/
fi
unset KPATCH_GCC_TEMPDIR
# $TARGETS used as list, no quotes.
# shellcheck disable=SC2086
-CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make "-j$CPUS" $TARGETS 2>&1 | logger || die
+if [ -z "$USERMODDIR" ];then
+ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make "-j$CPUS" $TARGETS 2>&1 | logger || die
+else
+ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make -C "$USERMODBUILDDIR" M="$USERMODBUILDDIR" "-j$CPUS" $USERMODFLAGS $TARGETS 2>&1 | logger || die
+fi
sleep 1
if [ -z "$USERMODDIR" ];then
@@ -753,9 +769,15 @@ KPATCH_GCC_TEMPDIR="$TEMPDIR"
export KPATCH_GCC_TEMPDIR
# $TARGETS used as list, no quotes.
# shellcheck disable=SC2086
-CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \
- KBUILD_MODPOST_WARN=1 \
- make "-j$CPUS" $TARGETS 2>&1 | logger || die
+if [ -z "$USERMODDIR" ];then
+ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \
+ KBUILD_MODPOST_WARN=1 \
+ make "-j$CPUS" $TARGETS 2>&1 | logger || die
+else
+ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \
+ KBUILD_MODPOST_WARN=1 \
+ make -C "$USERMODBUILDDIR" M="$USERMODBUILDDIR" "-j$CPUS" $USERMODFLAGS $TARGETS 2>&1 | logger || die
+fi
# source.c:(.section+0xFF): undefined reference to `symbol'
grep "undefined reference" "$LOGFILE" | sed -r "s/^.*\`(.*)'$/\\1/" \
--
1.7.5.4

View File

@ -1,349 +0,0 @@
From e91d2d2c6778275b16249f7e9d7439018fed70fe Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:25:08 +0000
Subject: [PATCH 1009/1015] kmod/kpatch-build: support build patch for
old kernels
Forward compatible for old kernels
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kmod/patch/kpatch-macros.h | 48 ++++++++++++++
kmod/patch/kpatch-patch.h | 4 +
kmod/patch/kpatch.lds.S | 12 ++++
kmod/patch/livepatch-patch-hook.c | 124 +++++++++++++++++++++++++++++++++++++
kpatch-build/create-diff-object.c | 8 +++
5 files changed, 196 insertions(+), 0 deletions(-)
diff --git a/kmod/patch/kpatch-macros.h b/kmod/patch/kpatch-macros.h
index a60a267..569a18d 100644
--- a/kmod/patch/kpatch-macros.h
+++ b/kmod/patch/kpatch-macros.h
@@ -133,4 +133,52 @@ struct kpatch_post_unpatch_callback {
printk(_fmt, ## __VA_ARGS__); \
})
+typedef void (*kpatch_loadcall_t)(void);
+typedef void (*kpatch_unloadcall_t)(void);
+
+struct kpatch_load {
+ kpatch_loadcall_t fn;
+ char *objname; /* filled in by create-diff-object */
+};
+
+struct kpatch_unload {
+ kpatch_unloadcall_t fn;
+ char *objname; /* filled in by create-diff-object */
+};
+
+/*
+ * KPATCH_LOAD_HOOK macro
+ *
+ * The first line only ensures that the hook being registered has the required
+ * function signature. If not, there is compile error on this line.
+ *
+ * The section line declares a struct kpatch_load to be allocated in a new
+ * .kpatch.hook.load section. This kpatch_load_data symbol is later stripped
+ * by create-diff-object so that it can be declared in multiple objects that
+ * are later linked together, avoiding global symbol collision. Since multiple
+ * hooks can be registered, the .kpatch.hook.load section is a table of struct
+ * kpatch_load elements that will be executed in series by the kpatch core
+ * module at load time, assuming the kernel object (module) is currently
+ * loaded; otherwise, the hook is called when module to be patched is loaded
+ * via the module load notifier.
+ */
+#define KPATCH_LOAD_HOOK(_fn) \
+ static inline kpatch_loadcall_t __loadtest(void) { return _fn; } \
+ struct kpatch_load kpatch_load_data __section(.kpatch.hooks.load) = { \
+ .fn = _fn, \
+ .objname = NULL \
+ };
+
+/*
+ * KPATCH_UNLOAD_HOOK macro
+ *
+ * Same as LOAD hook with s/load/unload/
+ */
+#define KPATCH_UNLOAD_HOOK(_fn) \
+ static inline kpatch_unloadcall_t __unloadtest(void) { return _fn; } \
+ struct kpatch_unload kpatch_unload_data __section(.kpatch.hooks.unload) = { \
+ .fn = _fn, \
+ .objname = NULL \
+ };
+
#endif /* __KPATCH_MACROS_H_ */
diff --git a/kmod/patch/kpatch-patch.h b/kmod/patch/kpatch-patch.h
index 917ea32..4d47d30 100644
--- a/kmod/patch/kpatch-patch.h
+++ b/kmod/patch/kpatch-patch.h
@@ -59,5 +59,9 @@ struct kpatch_post_unpatch_callback {
void (*callback)(void *obj);
char *objname;
};
+struct kpatch_patch_hook {
+ void (*hook)(void);
+ char *objname;
+};
#endif /* _KPATCH_PATCH_H_ */
diff --git a/kmod/patch/kpatch.lds.S b/kmod/patch/kpatch.lds.S
index bc5de82..e3c4e97 100644
--- a/kmod/patch/kpatch.lds.S
+++ b/kmod/patch/kpatch.lds.S
@@ -47,4 +47,16 @@ SECTIONS
__kpatch_force_funcs_end = . ;
QUAD(0);
}
+ .kpatch.hooks.load : {
+ __kpatch_hooks_load = . ;
+ *(.kpatch.hooks.load)
+ __kpatch_hooks_load_end = . ;
+ QUAD(0);
+ }
+ .kpatch.hooks.unload : {
+ __kpatch_hooks_unload = . ;
+ *(.kpatch.hooks.unload)
+ __kpatch_hooks_unload_end = . ;
+ QUAD(0);
+ }
}
diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c
index 625ffbd..8f7d044 100644
--- a/kmod/patch/livepatch-patch-hook.c
+++ b/kmod/patch/livepatch-patch-hook.c
@@ -64,6 +64,15 @@
# define HAVE_CALLBACKS
#endif
+#ifdef EULER_RELEASE_CODE
+# if EULER_RELEASE_CODE <= EULER_RELEASE_VERSION(2, 3)
+# undef HAVE_SYMPOS
+# undef HAVE_IMMEDIATE
+# undef HAVE_ELF_RELOCS
+# define HAVE_LOADHOOKS
+# endif
+#endif
+
/*
* There are quite a few similar structures at play in this file:
* - livepatch.h structs prefixed with klp_*
@@ -95,6 +104,11 @@ struct patch_object {
#endif
const char *name;
int funcs_nr, relocs_nr;
+#ifdef HAVE_LOADHOOKS
+ struct list_head hooks_load;
+ struct list_head hooks_unload;
+ int hooks_load_nr, hooks_unload_nr;
+#endif
};
struct patch_func {
@@ -107,6 +121,13 @@ struct patch_reloc {
struct kpatch_patch_dynrela *kdynrela;
};
+#ifdef HAVE_LOADHOOKS
+struct patch_hook {
+ struct list_head list;
+ struct kpatch_patch_hook *khook;
+};
+#endif
+
static struct patch_object *patch_alloc_new_object(const char *name)
{
struct patch_object *object;
@@ -118,6 +139,10 @@ static struct patch_object *patch_alloc_new_object(const char *name)
#ifndef HAVE_ELF_RELOCS
INIT_LIST_HEAD(&object->relocs);
#endif
+#ifdef HAVE_LOADHOOKS
+ INIT_LIST_HEAD(&object->hooks_load);
+ INIT_LIST_HEAD(&object->hooks_unload);
+#endif
if (strcmp(name, "vmlinux"))
object->name = name;
list_add(&object->list, &patch_objects);
@@ -180,6 +205,37 @@ static int patch_add_reloc_to_object(struct kpatch_patch_dynrela *kdynrela)
}
#endif
+#ifdef HAVE_LOADHOOKS
+static int patch_add_hook_to_object(struct kpatch_patch_hook *khook, bool load)
+{
+ struct patch_hook *hook;
+ struct patch_object *object;
+
+ hook = kzalloc(sizeof(*hook), GFP_KERNEL);
+ if (!hook)
+ return -ENOMEM;
+ INIT_LIST_HEAD(&hook->list);
+ hook->khook = khook;
+
+ object = patch_find_object_by_name(khook->objname);
+ if (!object) {
+ kfree(hook);
+ return -ENOMEM;
+ }
+
+ if (load) {
+ list_add(&hook->list, &object->hooks_load);
+ object->hooks_load_nr++;
+ }
+ else {
+ list_add(&hook->list, &object->hooks_unload);
+ object->hooks_unload_nr++;
+ }
+
+ return 0;
+}
+#endif
+
static void patch_free_scaffold(void) {
struct patch_func *func, *safefunc;
struct patch_object *object, *safeobject;
@@ -217,6 +273,12 @@ static void patch_free_livepatch(struct klp_patch *patch)
if (object->relocs)
kfree(object->relocs);
#endif
+#ifdef HAVE_LOADHOOKS
+ if (object->hooks_load)
+ kfree(object->hooks_load);
+ if (object->hooks_unload)
+ kfree(object->hooks_unload);
+#endif
}
if (patch->objs)
kfree(patch->objs);
@@ -228,6 +290,10 @@ extern struct kpatch_pre_patch_callback __kpatch_callbacks_pre_patch[], __kpatch
extern struct kpatch_post_patch_callback __kpatch_callbacks_post_patch[], __kpatch_callbacks_post_patch_end[];
extern struct kpatch_pre_unpatch_callback __kpatch_callbacks_pre_unpatch[], __kpatch_callbacks_pre_unpatch_end[];
extern struct kpatch_post_unpatch_callback __kpatch_callbacks_post_unpatch[], __kpatch_callbacks_post_unpatch_end[];
+#ifdef HAVE_LOADHOOKS
+extern struct kpatch_patch_hook __kpatch_hooks_load[], __kpatch_hooks_load_end[];
+extern struct kpatch_patch_hook __kpatch_hooks_unload[], __kpatch_hooks_unload_end[];
+#endif
extern unsigned long __kpatch_force_funcs[], __kpatch_force_funcs_end[];
static int patch_is_func_forced(unsigned long addr)
@@ -347,6 +413,11 @@ static int __init patch_init(void)
struct patch_reloc *reloc;
struct klp_reloc *lrelocs, *lreloc;
#endif
+#ifdef HAVE_LOADHOOKS
+ struct patch_hook *hook;
+ struct kpatch_patch_hook *khook_load, *khook_unload;
+ struct klp_hook *lhooks_load, *lhooks_unload, *lhook;
+#endif
/* organize functions and relocs by object in scaffold */
for (kfunc = __kpatch_funcs;
@@ -371,6 +442,24 @@ static int __init patch_init(void)
if (ret)
goto out;
+#ifdef HAVE_LOADHOOKS
+ for (khook_load = __kpatch_hooks_load;
+ khook_load != __kpatch_hooks_load_end;
+ khook_load++) {
+ ret = patch_add_hook_to_object(khook_load, true);
+ if (ret)
+ goto out;
+ }
+
+ for (khook_unload = __kpatch_hooks_unload;
+ khook_unload != __kpatch_hooks_unload_end;
+ khook_unload++) {
+ ret = patch_add_hook_to_object(khook_unload, false);
+ if (ret)
+ goto out;
+ }
+#endif
+
/* past this point, only possible return code is -ENOMEM */
ret = -ENOMEM;
@@ -403,12 +492,21 @@ static int __init patch_init(void)
lfunc = &lfuncs[j];
lfunc->old_name = func->kfunc->name;
lfunc->new_func = (void *)func->kfunc->new_addr;
+#if defined(HAVE_IMMEDIATE)
lfunc->immediate = patch_is_func_forced(lfunc->new_func);
+#endif
#ifdef HAVE_SYMPOS
lfunc->old_sympos = func->kfunc->sympos;
#else
lfunc->old_addr = func->kfunc->old_addr;
#endif
+#ifdef EULER_RELEASE_CODE
+# if EULER_RELEASE_CODE <= EULER_RELEASE_VERSION(2, 3)
+ lfunc->old_size = func->kfunc->old_size;
+ lfunc->new_size = func->kfunc->new_size;
+ lfunc->force = patch_is_func_forced(func->kfunc->new_addr);
+# endif
+#endif
j++;
}
@@ -439,6 +537,32 @@ static int __init patch_init(void)
lobject->callbacks = object->callbacks;
#endif
+#ifdef HAVE_LOADHOOKS
+ lhooks_load = kzalloc(sizeof(struct klp_hook) *
+ (object->hooks_load_nr+1), GFP_KERNEL);
+ if (!lhooks_load)
+ goto out;
+ lobject->hooks_load = lhooks_load;
+ j = 0;
+ list_for_each_entry(hook, &object->hooks_load, list) {
+ lhook = &lhooks_load[j];
+ lhook->hook = hook->khook->hook;
+ j++;
+ }
+
+ lhooks_unload = kzalloc(sizeof(struct klp_hook) *
+ (object->hooks_unload_nr+1), GFP_KERNEL);
+ if (!lhooks_unload)
+ goto out;
+ lobject->hooks_unload = lhooks_unload;
+ j = 0;
+ list_for_each_entry(hook, &object->hooks_unload, list) {
+ lhook = &lhooks_unload[j];
+ lhook->hook = hook->khook->hook;
+ j++;
+ }
+#endif
+
i++;
}
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 349e483..ed96758 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -1463,6 +1463,10 @@ static int kpatch_include_callback_elements(struct kpatch_elf *kelf)
".rela.kpatch.callbacks.post_patch",
".rela.kpatch.callbacks.pre_unpatch",
".rela.kpatch.callbacks.post_unpatch",
+ ".kpatch.hooks.load",
+ ".kpatch.hooks.unload",
+ ".rela.kpatch.hooks.load",
+ ".rela.kpatch.hooks.unload",
NULL,
};
char **callback_section;
@@ -2921,6 +2925,10 @@ static void kpatch_create_callbacks_objname_rela(struct kpatch_elf *kelf, char *
.offset = offsetof(struct kpatch_pre_unpatch_callback, objname) },
{ .name = ".rela.kpatch.callbacks.post_unpatch",
.offset = offsetof(struct kpatch_post_patch_callback, objname) },
+ { .name = ".rela.kpatch.hooks.load",
+ .offset = offsetof(struct kpatch_patch_hook, objname) },
+ { .name = ".rela.kpatch.hooks.unload",
+ .offset = offsetof(struct kpatch_patch_hook, objname) },
{ .name = NULL, .offset = 0 },
};
struct callback *callbackp;
--
1.7.5.4

View File

@ -1,480 +0,0 @@
From be8e5ce9541fc230131be230bd0646c473427895 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:25:20 +0000
Subject: [PATCH 1010/1015] kmod/kpatch-build: support cross compile hotpatch
for aarch64
use R_AARCH64_ABS64 for aarch64, function_ptr_rela and
kpatch_line_macro_change_only are left to implement later.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kmod/patch/livepatch-patch-hook.c | 16 +++---
kpatch-build/create-diff-object.c | 98 ++++++++++++++++++++++++++++++----
kpatch-build/create-kpatch-module.c | 24 ++++++++-
kpatch-build/kpatch-build | 42 ++++++++++++---
kpatch-build/kpatch-gcc | 4 +-
5 files changed, 152 insertions(+), 32 deletions(-)
diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c
index 8f7d044..ee3b2b9 100644
--- a/kmod/patch/livepatch-patch-hook.c
+++ b/kmod/patch/livepatch-patch-hook.c
@@ -66,13 +66,17 @@
#ifdef EULER_RELEASE_CODE
# if EULER_RELEASE_CODE <= EULER_RELEASE_VERSION(2, 3)
-# undef HAVE_SYMPOS
-# undef HAVE_IMMEDIATE
-# undef HAVE_ELF_RELOCS
-# define HAVE_LOADHOOKS
+# define __HULK__
# endif
#endif
+#ifdef __HULK__
+# undef HAVE_SYMPOS
+# undef HAVE_IMMEDIATE
+# undef HAVE_ELF_RELOCS
+# define HAVE_LOADHOOKS
+#endif
+
/*
* There are quite a few similar structures at play in this file:
* - livepatch.h structs prefixed with klp_*
@@ -500,12 +504,10 @@ static int __init patch_init(void)
#else
lfunc->old_addr = func->kfunc->old_addr;
#endif
-#ifdef EULER_RELEASE_CODE
-# if EULER_RELEASE_CODE <= EULER_RELEASE_VERSION(2, 3)
+#ifdef __HULK__
lfunc->old_size = func->kfunc->old_size;
lfunc->new_size = func->kfunc->new_size;
lfunc->force = patch_is_func_forced(func->kfunc->new_addr);
-# endif
#endif
j++;
}
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index ed96758..b8d3bb4 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -70,6 +70,31 @@ char *childobj;
enum loglevel loglevel = NORMAL;
+#ifndef EM_X86_64
+#define EM_X86_64 62
+#endif
+
+#ifndef EM_AARCH64
+#define EM_AARCH64 183
+#endif
+
+#ifndef R_AARCH64_ABS64
+#define R_AARCH64_NONE 0
+#define R_AARCH64_ABS64 257
+#define R_AARCH64_CALL26 283
+#endif
+
+static unsigned int arch;
+static unsigned int absolute_rela_type;
+
+static unsigned int arch_of_elf(Elf *elf)
+{
+ GElf_Ehdr eh;
+ if (!gelf_getehdr(elf, &eh))
+ ERROR("gelf_getehdr");
+ return eh.e_machine;
+}
+
/*******************
* Data structures
* ****************/
@@ -635,6 +660,8 @@ static void kpatch_compare_correlated_symbol(struct symbol *sym)
if (sym1->sec && sym2->sec && sym1->sec->twin != sym2->sec) {
if (sym2->sec->twin && sym2->sec->twin->ignore)
sym->status = CHANGED;
+ else if (sym1->name[0] == '$') /* reserved symbols in aarch64 */
+ log_debug("maping symbols: %s", sym1->name); /* do nothing just ignogre */
else
DIFF_FATAL("symbol changed sections: %s", sym1->name);
}
@@ -2294,7 +2321,7 @@ static void kpatch_create_kpatch_arch_section(struct kpatch_elf *kelf, char *obj
/* entries[index].sec */
ALLOC_LINK(rela, &karch_sec->rela->relas);
rela->sym = sec->secsym;
- rela->type = ABSOLUTE_RELA_TYPE;
+ rela->type = absolute_rela_type;
rela->addend = 0;
rela->offset = index * sizeof(*entries) + \
offsetof(struct kpatch_arch, sec);
@@ -2302,7 +2329,7 @@ static void kpatch_create_kpatch_arch_section(struct kpatch_elf *kelf, char *obj
/* entries[index].objname */
ALLOC_LINK(rela, &karch_sec->rela->relas);
rela->sym = strsym;
- rela->type = ABSOLUTE_RELA_TYPE;
+ rela->type = absolute_rela_type;
rela->addend = offset_of_string(&kelf->strings, objname);
rela->offset = index * sizeof(*entries) + \
offsetof(struct kpatch_arch, objname);
@@ -2500,7 +2527,7 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
*/
ALLOC_LINK(rela, &relasec->relas);
rela->sym = sym;
- rela->type = ABSOLUTE_RELA_TYPE;
+ rela->type = absolute_rela_type;
rela->addend = 0;
rela->offset = index * sizeof(*funcs);
@@ -2510,7 +2537,7 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
*/
ALLOC_LINK(rela, &relasec->relas);
rela->sym = strsym;
- rela->type = ABSOLUTE_RELA_TYPE;
+ rela->type = absolute_rela_type;
rela->addend = offset_of_string(&kelf->strings, sym->name);
rela->offset = index * sizeof(*funcs) +
offsetof(struct kpatch_patch_func, name);
@@ -2521,7 +2548,7 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
*/
ALLOC_LINK(rela, &relasec->relas);
rela->sym = strsym;
- rela->type = ABSOLUTE_RELA_TYPE;
+ rela->type = absolute_rela_type;
rela->addend = objname_offset;
rela->offset = index * sizeof(*funcs) +
offsetof(struct kpatch_patch_func,objname);
@@ -2834,7 +2861,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
/* add rela to fill in ksyms[index].name field */
ALLOC_LINK(rela2, &ksym_sec->rela->relas);
rela2->sym = strsym;
- rela2->type = ABSOLUTE_RELA_TYPE;
+ rela2->type = absolute_rela_type;
rela2->addend = offset_of_string(&kelf->strings, rela->sym->name);
rela2->offset = index * sizeof(*ksyms) + \
offsetof(struct kpatch_symbol, name);
@@ -2842,7 +2869,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
/* add rela to fill in ksyms[index].objname field */
ALLOC_LINK(rela2, &ksym_sec->rela->relas);
rela2->sym = strsym;
- rela2->type = ABSOLUTE_RELA_TYPE;
+ rela2->type = absolute_rela_type;
rela2->addend = offset_of_string(&kelf->strings, sym_objname);
rela2->offset = index * sizeof(*ksyms) + \
offsetof(struct kpatch_symbol, objname);
@@ -2863,7 +2890,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
ERROR("can't create dynrela for section %s (symbol %s): no bundled or section symbol",
sec->name, rela->sym->name);
- rela2->type = ABSOLUTE_RELA_TYPE;
+ rela2->type = absolute_rela_type;
rela2->addend = rela->offset;
rela2->offset = index * sizeof(*krelas) + \
offsetof(struct kpatch_relocation, dest);
@@ -2871,7 +2898,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
/* add rela to fill in krelas[index].objname field */
ALLOC_LINK(rela2, &krela_sec->rela->relas);
rela2->sym = strsym;
- rela2->type = ABSOLUTE_RELA_TYPE;
+ rela2->type = absolute_rela_type;
rela2->addend = offset_of_string(&kelf->strings, objname);
rela2->offset = index * sizeof(*krelas) + \
offsetof(struct kpatch_relocation, objname);
@@ -2879,7 +2906,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
/* add rela to fill in krelas[index].ksym field */
ALLOC_LINK(rela2, &krela_sec->rela->relas);
rela2->sym = ksym_sec_sym;
- rela2->type = ABSOLUTE_RELA_TYPE;
+ rela2->type = absolute_rela_type;
rela2->addend = index * sizeof(*ksyms);
rela2->offset = index * sizeof(*krelas) + \
offsetof(struct kpatch_relocation, ksym);
@@ -2946,7 +2973,7 @@ static void kpatch_create_callbacks_objname_rela(struct kpatch_elf *kelf, char *
if (!strcmp(callbackp->name, sec->name)) {
ALLOC_LINK(rela, &sec->relas);
rela->sym = strsym;
- rela->type = ABSOLUTE_RELA_TYPE;
+ rela->type = absolute_rela_type;
rela->addend = objname_offset;
rela->offset = callbackp->offset;
break;
@@ -3000,6 +3027,7 @@ static void kpatch_create_mcount_sections(struct kpatch_elf *kelf)
/* add rela in .rela__mcount_loc to fill in function pointer */
ALLOC_LINK(rela, &relasec->relas);
rela->sym = sym;
+ if (arch == EM_X86_64) {
rela->type = R_X86_64_64;
rela->addend = 0;
rela->offset = index * sizeof(*funcs);
@@ -3024,6 +3052,37 @@ static void kpatch_create_mcount_sections(struct kpatch_elf *kelf)
rela = list_first_entry(&sym->sec->rela->relas, struct rela,
list);
rela->type = R_X86_64_PC32;
+ } else if (arch == EM_AARCH64) {
+ unsigned int *insnp;
+ rela->type = R_AARCH64_ABS64;
+ /* bl <__fentry__> is the second insn */
+ rela->addend = 4;
+ rela->offset = index * sizeof(*funcs);
+
+ newdata = malloc(sym->sec->data->d_size);
+ memcpy(newdata, sym->sec->data->d_buf, sym->sec->data->d_size);
+ sym->sec->data->d_buf = newdata;
+ insnp = newdata;
+
+ /*
+ * mov x9, x30
+ * nop //function in .text.<func>, so it be replaced with nop by recordmcount
+ * mov x30, x9
+ */
+ if (insnp[0] != 0xaa1e03e9 || insnp[1] != 0xd503201f || insnp[2] != 0xaa0903fe)
+ ERROR("%s: unexpected instruction at the start of the function",
+ sym->name);
+
+ /* change the nop to bl __fentry__ */
+ insnp[1] = 0x94000000;
+ rela = list_first_entry(&sym->sec->rela->relas, struct rela,
+ list);
+ rela->type = R_AARCH64_CALL26;
+ rela->offset = 4;
+
+ } else {
+ ERROR("unsupport arch %d\n", arch);
+ }
index++;
}
@@ -3168,6 +3227,7 @@ int main(int argc, char *argv[])
char *hint = NULL, *orig_obj, *patched_obj, *parent_name;
char *parent_symtab, *mod_symvers, *patch_name, *output_obj;
struct sym_compare_type *base_locals;
+ char *gcc_add_option, *mlongcall;
arguments.debug = 0;
argp_parse (&argp, argc, argv, 0, NULL, &arguments);
@@ -3188,6 +3248,13 @@ int main(int argc, char *argv[])
kelf_base = kpatch_elf_open(orig_obj);
kelf_patched = kpatch_elf_open(patched_obj);
+ arch = arch_of_elf(kelf_base->elf);
+ if (arch == EM_X86_64)
+ absolute_rela_type = R_X86_64_64;
+ else if (arch == EM_AARCH64)
+ absolute_rela_type = R_AARCH64_ABS64;
+ else
+ ERROR("only arch x86_64 and arm64 be supported\n");
kpatch_bundle_symbols(kelf_base);
kpatch_bundle_symbols(kelf_patched);
@@ -3276,7 +3343,14 @@ int main(int argc, char *argv[])
kpatch_create_callbacks_objname_rela(kelf_out, parent_name);
kpatch_build_strings_section_data(kelf_out);
- kpatch_create_mcount_sections(kelf_out);
+ gcc_add_option = getenv("GCC_ADD_OPTION");
+ printf("gcc add option :%s\n", gcc_add_option);
+ mlongcall = strstr(gcc_add_option, "-mlong-calls");
+ if (arch == EM_AARCH64 && mlongcall) {
+ printf("-mlong-calls found, no need to create mcount section\n");
+ } else {
+ kpatch_create_mcount_sections(kelf_out);
+ }
/*
* At this point, the set of output sections and symbols is
diff --git a/kpatch-build/create-kpatch-module.c b/kpatch-build/create-kpatch-module.c
index 67b16b0..9f1c3b9 100644
--- a/kpatch-build/create-kpatch-module.c
+++ b/kpatch-build/create-kpatch-module.c
@@ -31,6 +31,17 @@
char *childobj;
enum loglevel loglevel = NORMAL;
+static unsigned int arch;
+static unsigned int absolute_rela_type;
+
+static unsigned int arch_of_elf(Elf *elf)
+{
+ GElf_Ehdr eh;
+ if (!gelf_getehdr(elf, &eh))
+ ERROR("gelf_getehdr");
+ return eh.e_machine;
+}
+
/*
* Create .kpatch.dynrelas from .kpatch.relocations and .kpatch.symbols sections
*
@@ -102,14 +113,14 @@ static void create_dynamic_rela_sections(struct kpatch_elf *kelf, struct section
/* dest */
ALLOC_LINK(rela, &dynsec->rela->relas);
rela->sym = sym;
- rela->type = R_X86_64_64;
+ rela->type = absolute_rela_type;
rela->addend = dest_offset;
rela->offset = index * sizeof(*dynrelas);
/* name */
ALLOC_LINK(rela, &dynsec->rela->relas);
rela->sym = strsec->secsym;
- rela->type = R_X86_64_64;
+ rela->type = absolute_rela_type;
rela->addend = name_offset;
rela->offset = index * sizeof(*dynrelas) + \
offsetof(struct kpatch_patch_dynrela, name);
@@ -117,7 +128,7 @@ static void create_dynamic_rela_sections(struct kpatch_elf *kelf, struct section
/* objname */
ALLOC_LINK(rela, &dynsec->rela->relas);
rela->sym = strsec->secsym;
- rela->type = R_X86_64_64;
+ rela->type = absolute_rela_type;
rela->addend = objname_offset;
rela->offset = index * sizeof(*dynrelas) + \
offsetof(struct kpatch_patch_dynrela, objname);
@@ -200,6 +211,13 @@ int main(int argc, char *argv[])
childobj = basename(arguments.args[0]);
kelf = kpatch_elf_open(arguments.args[0]);
+ arch = arch_of_elf(kelf->elf);
+ if (arch == EM_X86_64)
+ absolute_rela_type = R_X86_64_64;
+ else if (arch == EM_AARCH64)
+ absolute_rela_type = R_AARCH64_ABS64;
+ else
+ ERROR("only arch x86_64 and arm64 be supported\n");
/*
* Sanity checks:
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index 93a0589..017604c 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -384,6 +384,27 @@ find_kobj() {
done
}
+arch_export() {
+ E_MACHINE=$(od -An -j18 -N2 -d $VMLINUX)
+ if [[ $E_MACHINE -eq 62 ]]; then
+ export ARCH=x86_64
+ export ARCH_COMPILE=
+ export ENDIAN=little
+ export GCC_ADD_OPTION=
+ elif [[ $E_MACHINE -eq 183 ]]; then
+ export ARCH=arm64
+ export ARCH_COMPILE=aarch64-linux-gnu-
+ export ENDIAN=little
+ if grep "\-mlong-calls" $SRCDIR/Makefile > /dev/null; then
+ export GCC_ADD_OPTION="-fno-section-anchors -mlong-calls"
+ else
+ export GCC_ADD_OPTION="-fno-section-anchors"
+ fi
+ else
+ die "only support arm64 or x86_64 architecture"
+ fi
+}
+
# Only allow alphanumerics and '_' and '-' in the module name. Everything else
# is replaced with '-'. Also truncate to 48 chars so the full name fits in the
# kernel's 56-byte module name array.
@@ -725,12 +746,12 @@ apply_patches
remove_patches
cp -LR "$DATADIR/patch" "$TEMPDIR" || die
-
+arch_export
if [[ "$ARCH" = "ppc64le" ]]; then
ARCH_KCFLAGS="-mcmodel=large -fplugin=$PLUGINDIR/ppc64le-plugin.so"
fi
-export KCFLAGS="-I$DATADIR/patch -ffunction-sections -fdata-sections $ARCH_KCFLAGS"
+export KCFLAGS="-I$DATADIR/patch -ffunction-sections -fdata-sections $ARCH_KCFLAGS ${GCC_ADD_OPTION}"
echo "Reading special section data"
find_special_section_data
@@ -752,9 +773,9 @@ unset KPATCH_GCC_TEMPDIR
# $TARGETS used as list, no quotes.
# shellcheck disable=SC2086
if [ -z "$USERMODDIR" ];then
- CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make "-j$CPUS" $TARGETS 2>&1 | logger || die
+ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc $ARCH_COMPILE" make "-j$CPUS" $TARGETS 2>&1 | logger || die
else
- CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make -C "$USERMODBUILDDIR" M="$USERMODBUILDDIR" "-j$CPUS" $USERMODFLAGS $TARGETS 2>&1 | logger || die
+ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc $ARCH_COMPILE" make -C "$USERMODBUILDDIR" M="$USERMODBUILDDIR" "-j$CPUS" $USERMODFLAGS $TARGETS 2>&1 | logger || die
fi
sleep 1
@@ -770,11 +791,11 @@ export KPATCH_GCC_TEMPDIR
# $TARGETS used as list, no quotes.
# shellcheck disable=SC2086
if [ -z "$USERMODDIR" ];then
- CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \
+ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc $ARCH_COMPILE" \
KBUILD_MODPOST_WARN=1 \
make "-j$CPUS" $TARGETS 2>&1 | logger || die
else
- CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \
+ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc $ARCH_COMPILE" \
KBUILD_MODPOST_WARN=1 \
make -C "$USERMODBUILDDIR" M="$USERMODBUILDDIR" "-j$CPUS" $USERMODFLAGS $TARGETS 2>&1 | logger || die
fi
@@ -907,6 +928,10 @@ if "$KPATCH_MODULE"; then
export KCPPFLAGS="-D__KPATCH_MODULE__"
fi
+if grep "hulk" $SRCDIR/Makefile > /dev/null; then
+ export KCPPFLAGS="-D__HULK__ $KCPPFLAGS"
+fi
+
echo "Building patch module: $MODNAME.ko"
if [[ -z "$USERSRCDIR" ]] && [[ "$DISTRO" = ubuntu ]]; then
@@ -919,12 +944,12 @@ fi
cd "$TEMPDIR/output" || die
# $KPATCH_LDFLAGS and result of find used as list, no quotes.
# shellcheck disable=SC2086,SC2046
-ld -r $KPATCH_LDFLAGS -o ../patch/tmp_output.o $(find . -name "*.o") 2>&1 | logger || die
+${ARCH_COMPILE}ld -r $KPATCH_LDFLAGS -o ../patch/tmp_output.o $(find . -name "*.o") 2>&1 | logger || die
if "$KPATCH_MODULE"; then
# Add .kpatch.checksum for kpatch script
md5sum ../patch/tmp_output.o | awk '{printf "%s\0", $1}' > checksum.tmp || die
- objcopy --add-section .kpatch.checksum=checksum.tmp --set-section-flags .kpatch.checksum=alloc,load,contents,readonly ../patch/tmp_output.o || die
+ ${ARCH_COMPILE}objcopy --add-section .kpatch.checksum=checksum.tmp --set-section-flags .kpatch.checksum=alloc,load,contents,readonly ../patch/tmp_output.o || die
rm -f checksum.tmp
"$TOOLSDIR"/create-kpatch-module "$TEMPDIR"/patch/tmp_output.o "$TEMPDIR"/patch/output.o 2>&1 | logger 1
check_pipe_status create-kpatch-module
@@ -942,6 +967,7 @@ fi
KPATCH_BUILD="$KPATCH_BUILDIR" KPATCH_NAME="$MODNAME" \
KBUILD_EXTRA_SYMBOLS="$KBUILD_EXTRA_SYMBOLS" \
KPATCH_LDFLAGS="$KPATCH_LDFLAGS" \
+CROSS_COMPILE="$ARCH_COMPILE" \
make 2>&1 | logger || die
if ! "$KPATCH_MODULE"; then
diff --git a/kpatch-build/kpatch-gcc b/kpatch-build/kpatch-gcc
index 21f7e2e..be18847 100755
--- a/kpatch-build/kpatch-gcc
+++ b/kpatch-build/kpatch-gcc
@@ -13,7 +13,7 @@ fi
declare -a args=("$@")
-if [[ "$TOOLCHAINCMD" = "gcc" ]] ; then
+if [[ "$TOOLCHAINCMD" = ${ARCH_COMPILE}gcc ]] ; then
while [ "$#" -gt 0 ]; do
if [ "$1" = "-o" ]; then
obj="$2"
@@ -64,7 +64,7 @@ if [[ "$TOOLCHAINCMD" = "gcc" ]] ; then
fi
shift
done
-elif [[ "$TOOLCHAINCMD" = "ld" ]] ; then
+elif [[ "$TOOLCHAINCMD" = ${ARCH_COMPILE}ld ]] ; then
while [ "$#" -gt 0 ]; do
if [ "$1" = "-o" ]; then
obj="$2"
--
1.7.5.4

View File

@ -1,48 +0,0 @@
From 868a6e4462bebcffa4bf6beea02262823e7dc3a3 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:25:33 +0000
Subject: [PATCH] kpatch-build: use .klp.rela in euleros 7.5 kernel
use .klp.rela in euleros 7.5 kernel
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/kpatch-build | 13 +++++++++++--
1 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index fb14850..5a70a44 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -157,6 +157,15 @@ is_rhel() {
[[ $1 =~ \.el[78]\. ]]
}
+is_euleros_klp() {
+ if [[ "$1" =~ ^3.10.0-862 ]] ;then
+ if [ $ID == "euleros" ];then
+ return 0;
+ fi
+ fi
+ return 1;
+}
+
find_dirs() {
if [[ -e "$SCRIPTDIR/create-diff-object" ]]; then
# git repo
@@ -708,10 +717,10 @@ KPATCH_MODULE=true
grep -q "CONFIG_DEBUG_INFO=y" "$CONFIGFILE" || die "kernel doesn't have 'CONFIG_DEBUG_INFO' enabled"
if grep -q "CONFIG_LIVEPATCH=y" "$CONFIGFILE"; then
# The kernel supports livepatch.
- if version_gte "${ARCHVERSION//-*/}" 4.7.0 || is_rhel "$ARCHVERSION"; then
+ if version_gte "${ARCHVERSION//-*/}" 4.7.0 || is_rhel "$ARCHVERSION" || is_euleros_klp "$ARCHVERSION"; then
# Use new .klp.rela. sections
KPATCH_MODULE=false
- if version_gte "${ARCHVERSION//-*/}" 4.9.0 || is_rhel "$ARCHVERSION"; then
+ if version_gte "${ARCHVERSION//-*/}" 4.9.0 || is_rhel "$ARCHVERSION" || is_euleros_klp "$ARCHVERSION"; then
KPATCH_LDFLAGS="--unique=.parainstructions --unique=.altinstructions"
fi
fi
--
1.7.5.4

View File

@ -1,365 +0,0 @@
From 1eaabfe01cfae870abd45bfa470caa144f34e74c Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:25:45 +0000
Subject: [PATCH 1013/1015] kmod/kpatch-build: fix duplicate symbol relocation
for hulk kernel
hulk kernel fix it by find a uniq symbol(ref_name) and
use ref_offset to find the duplicate symbol
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kmod/patch/kpatch-patch.h | 4 ++
kmod/patch/livepatch-patch-hook.c | 6 ++
kpatch-build/create-diff-object.c | 44 +++++++++++++++++-
kpatch-build/create-kpatch-module.c | 23 +++++++++-
kpatch-build/kpatch-build | 12 +++++
kpatch-build/kpatch-intermediate.h | 2 +
kpatch-build/lookup.c | 87 ++++++++++++++++++++++++++++++++++-
kpatch-build/lookup.h | 8 +++
8 files changed, 183 insertions(+), 3 deletions(-)
diff --git a/kmod/patch/kpatch-patch.h b/kmod/patch/kpatch-patch.h
index 4d47d30..2eacb37 100644
--- a/kmod/patch/kpatch-patch.h
+++ b/kmod/patch/kpatch-patch.h
@@ -30,6 +30,8 @@ struct kpatch_patch_func {
unsigned long sympos;
char *name;
char *objname;
+ char *ref_name;
+ long ref_offset;
};
struct kpatch_patch_dynrela {
@@ -41,6 +43,8 @@ struct kpatch_patch_dynrela {
char *objname;
int external;
int addend;
+ char *ref_name;
+ long ref_offset;
};
struct kpatch_pre_patch_callback {
diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c
index ee3b2b9..fefc068 100644
--- a/kmod/patch/livepatch-patch-hook.c
+++ b/kmod/patch/livepatch-patch-hook.c
@@ -508,6 +508,8 @@ static int __init patch_init(void)
lfunc->old_size = func->kfunc->old_size;
lfunc->new_size = func->kfunc->new_size;
lfunc->force = patch_is_func_forced(func->kfunc->new_addr);
+ lfunc->ref_name= func->kfunc->ref_name;
+ lfunc->ref_offset = func->kfunc->ref_offset;
#endif
j++;
}
@@ -531,6 +533,10 @@ static int __init patch_init(void)
lreloc->name = reloc->kdynrela->name;
lreloc->addend = reloc->kdynrela->addend;
lreloc->external = reloc->kdynrela->external;
+#ifdef __HULK__
+ lreloc->ref_name = reloc->kdynrela->ref_name;
+ lreloc->ref_offset = reloc->kdynrela->ref_offset;
+#endif
j++;
}
#endif /* HAVE_ELF_RELOCS */
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 4fb27da..e72f6dd 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -2519,6 +2519,29 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
funcs[index].old_size = result.size;
funcs[index].new_size = sym->sym.st_size;
funcs[index].sympos = result.pos;
+ if (lookup_is_duplicate_symbol(table, sym->name)) {
+ struct lookup_refsym refsym;
+ long offset;
+
+ if (lookup_ref_symbol(table, sym->name, &refsym))
+ ERROR("unresolvable ambiguity on symbol %s\n", sym->name);
+
+ offset = (long)result.value - (long)refsym.value;
+ 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 = index * sizeof(*funcs) +
+ offsetof(struct kpatch_patch_func, ref_name);
+
+ }
+
/*
* Add a relocation that will populate
@@ -2653,6 +2676,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
struct lookup_result result;
char *sym_objname;
int ret, vmlinux, external;
+ long ref_offset;
vmlinux = !strcmp(objname, "vmlinux");
@@ -2860,12 +2884,29 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
log_debug("lookup for %s @ 0x%016lx len %lu\n",
rela->sym->name, result.value, result.size);
+ ref_offset = 0;
/* Fill in ksyms[index] */
if (vmlinux)
ksyms[index].src = result.value;
- else
+ else {
/* for modules, src is discovered at runtime */
ksyms[index].src = 0;
+ if (lookup_is_duplicate_symbol(table, rela->sym->name)) {
+ struct lookup_refsym refsym;
+
+ if (lookup_ref_symbol(table, rela->sym->name, &refsym))
+ ERROR("unresolvable ambiguity on symbol %s\n", rela->sym->name);
+
+ ref_offset = (long)result.value - (long)refsym.value;
+ /* add rela to fill in ref_name field */
+ ALLOC_LINK(rela2, &krela_sec->rela->relas);
+ rela2->sym = strsym;
+ rela2->type = absolute_rela_type;
+ rela2->addend = offset_of_string(&kelf->strings, refsym.name);
+ rela2->offset = index * sizeof(*krelas) +
+ offsetof(struct kpatch_relocation, ref_name);
+ }
+ }
ksyms[index].pos = result.pos;
ksyms[index].type = rela->sym->type;
ksyms[index].bind = rela->sym->bind;
@@ -2893,6 +2934,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
krelas[index].addend = rela->addend;
krelas[index].type = rela->type;
krelas[index].external = external;
+ krelas[index].ref_offset = ref_offset;
/* add rela to fill in krelas[index].dest field */
ALLOC_LINK(rela2, &krela_sec->rela->relas);
diff --git a/kpatch-build/create-kpatch-module.c b/kpatch-build/create-kpatch-module.c
index 9f1c3b9..8292dc8 100644
--- a/kpatch-build/create-kpatch-module.c
+++ b/kpatch-build/create-kpatch-module.c
@@ -57,7 +57,7 @@ static void create_dynamic_rela_sections(struct kpatch_elf *kelf, struct section
struct section *dynsec;
struct symbol *sym;
struct rela *rela;
- int index, nr, offset, dest_offset, objname_offset, name_offset;
+ int index, nr, offset, dest_offset, objname_offset, name_offset, ref_name_offset;
ksyms = ksymsec->data->d_buf;
krelas = krelasec->data->d_buf;
@@ -109,6 +109,27 @@ static void create_dynamic_rela_sections(struct kpatch_elf *kelf, struct section
dynrelas[index].type = krelas[index].type;
dynrelas[index].external = krelas[index].external;
dynrelas[index].sympos = ksym->pos;
+ dynrelas[index].ref_name = krelas[index].ref_name;
+ dynrelas[index].ref_offset = krelas[index].ref_offset;
+
+ if (dynrelas[index].ref_offset)
+ {
+ /* Get objname offset */
+ rela = find_rela_by_offset(krelasec->rela,
+ index * sizeof(*krelas) + offsetof(struct kpatch_relocation, ref_name));
+ if (!rela) {
+ ERROR("find_rela_by_offset");
+ }
+ ref_name_offset = rela->addend;
+ /* ref_name */
+ ALLOC_LINK(rela, &dynsec->rela->relas);
+ rela->sym = strsec->secsym;
+ rela->type = absolute_rela_type;
+ rela->addend = ref_name_offset;
+ rela->offset = index * sizeof(*dynrelas) + \
+ offsetof(struct kpatch_patch_dynrela, ref_name);
+
+ }
/* dest */
ALLOC_LINK(rela, &dynsec->rela->relas);
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index 9c40612..80b9607 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -894,6 +894,18 @@ for i in $FILES; do
KOBJFILE_NAME="${KOBJFILE_NAME/-/_}"
KOBJFILE_PATH="${TEMPDIR}/module/$KOBJFILE"
SYMTAB="${KOBJFILE_PATH}.symtab"
+ unset KCFLAGS
+ remove_patches
+ if [ -z "$USERMODDIR" ];then
+ cd "$SRCDIR" || die
+ CROSS_COMPILE="$ARCH_COMPILE" make "-j$CPUS" ${KOBJFILE} 2>&1 | logger || die
+ else
+ cd "$USERMODDIR"
+ CROSS_COMPILE="$ARCH_COMPILE" make -C "$USERMODBUILDDIR" M="$USERMODBUILDDIR" "-j$CPUS" $USERMODFLAGS $TARGETS 2>&1 | logger || die
+ fi
+ cp ${KOBJFILE} ${KOBJFILE_PATH}
+ apply_patches
+ cd "$TEMPDIR" || die
fi
eu-readelf -s "$KOBJFILE_PATH" > "$SYMTAB"
diff --git a/kpatch-build/kpatch-intermediate.h b/kpatch-build/kpatch-intermediate.h
index 3dea775..59deed0 100644
--- a/kpatch-build/kpatch-intermediate.h
+++ b/kpatch-build/kpatch-intermediate.h
@@ -39,6 +39,8 @@ struct kpatch_relocation {
int external;
char *objname; /* object to which this rela applies to */
struct kpatch_symbol *ksym;
+ char *ref_name;
+ long ref_offset;
};
struct kpatch_arch {
diff --git a/kpatch-build/lookup.c b/kpatch-build/lookup.c
index d08c10b..e4677db 100644
--- a/kpatch-build/lookup.c
+++ b/kpatch-build/lookup.c
@@ -44,6 +44,7 @@ struct object_symbol {
unsigned long size;
char *name;
int type, bind;
+ int sec_index;
};
struct export_symbol {
@@ -229,6 +230,7 @@ static void symtab_read(struct lookup_table *table, char *path)
table->obj_syms[i].value = value;
table->obj_syms[i].size = size;
table->obj_syms[i].name = strdup(name);
+ table->obj_syms[i].sec_index = atoi(ndx);
if (!strcmp(bind, "LOCAL")) {
table->obj_syms[i].bind = STB_LOCAL;
@@ -425,7 +427,90 @@ char *lookup_exported_symbol_objname(struct lookup_table *table, char *name)
return match->objname;
return NULL;
- }
+}
+
+int lookup_is_duplicate_symbol(struct lookup_table *table, char *name)
+{
+ struct object_symbol *sym;
+ int i, count = 0;
+
+ for_each_obj_symbol(i, sym, table)
+ if (!strcmp(sym->name, name)) {
+ count++;
+ if (count > 1)
+ return 1;
+ }
+
+ return 0;
+}
+
+struct object_symbol *lookup_find_symbol_by_name(struct lookup_table *table, char *name)
+{
+ struct object_symbol *sym;
+ unsigned long pos = 0;
+ int i, match = 0, in_file = 0;
+
+ if (!table->local_syms)
+ return NULL;
+
+ for_each_obj_symbol(i, sym, table) {
+ if (sym->bind == STB_LOCAL && !strcmp(sym->name, name))
+ pos++;
+
+ if (table->local_syms == sym) {
+ in_file = 1;
+ continue;
+ }
+
+ if (!in_file)
+ continue;
+
+ if (sym->type == STT_FILE)
+ break;
+
+ if (sym->bind == STB_LOCAL && !strcmp(sym->name, name)) {
+ match = 1;
+ break;
+ }
+ }
+
+ if (!match) {
+ for_each_obj_symbol(i, sym, table) {
+ if ((sym->bind == STB_GLOBAL || sym->bind == STB_WEAK) &&
+ !strcmp(sym->name, name)) {
+ return sym;
+ }
+ }
+ return NULL;
+ }
+
+ return sym;
+}
+
+int lookup_ref_symbol(struct lookup_table *table, char *name,
+ struct lookup_refsym *refsym)
+{
+ struct object_symbol *orig_sym, *sym;
+ int i;
+
+ orig_sym = lookup_find_symbol_by_name(table, name);
+ if (!orig_sym)
+ ERROR("lookup_ref_symbol");
+ memset(refsym, 0, sizeof(*refsym));
+ for_each_obj_symbol(i, sym, table) {
+ if (!strcmp(sym->name, name) || sym->type == STT_FILE ||
+ sym->sec_index != orig_sym->sec_index)
+ continue;
+
+ if (!lookup_is_duplicate_symbol(table, sym->name)) {
+ refsym->name = sym->name;
+ refsym->value = sym->value;
+ return 0;
+ }
+ }
+
+ return 1;
+}
#if 0 /* for local testing */
static void find_this(struct lookup_table *table, char *sym, char *hint)
diff --git a/kpatch-build/lookup.h b/kpatch-build/lookup.h
index 420d0f0..5ad9241 100644
--- a/kpatch-build/lookup.h
+++ b/kpatch-build/lookup.h
@@ -14,6 +14,11 @@ struct sym_compare_type {
int type;
};
+struct lookup_refsym {
+ char *name;
+ unsigned long value;
+};
+
struct lookup_table *lookup_open(char *symtab_path, char *symvers_path,
char *hint, struct sym_compare_type *locals);
void lookup_close(struct lookup_table *table);
@@ -23,5 +28,8 @@ int lookup_global_symbol(struct lookup_table *table, char *name,
struct lookup_result *result);
int lookup_is_exported_symbol(struct lookup_table *table, char *name);
char *lookup_exported_symbol_objname(struct lookup_table *table, char *name);
+int lookup_is_duplicate_symbol(struct lookup_table *table, char *name);
+int lookup_ref_symbol(struct lookup_table *table, char *name,
+ struct lookup_refsym *refsym);
#endif /* _LOOKUP_H_ */
--
1.7.5.4

View File

@ -1,31 +0,0 @@
From 83ecafcda5326baceeb68fba90dc13083ff48fe6 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:25:50 +0000
Subject: [PATCH 1014/1015] create-diff-object: add dynamic reloction for
function pointer on aarch64
implement function_ptr_rela for aarch64.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/create-diff-object.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index e72f6dd..f8f3e15 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -2628,7 +2628,9 @@ static int function_ptr_rela(const struct rela *rela)
rela_toc->addend == (int)rela_toc->sym->sym.st_value &&
(rela->type == R_X86_64_32S ||
rela->type == R_PPC64_TOC16_HA ||
- rela->type == R_PPC64_TOC16_LO_DS));
+ rela->type == R_PPC64_TOC16_LO_DS ||
+ rela->type == R_AARCH64_ADR_PREL_PG_HI21 ||
+ rela->type == R_AARCH64_ADD_ABS_LO12_NC));
}
static int may_need_dynrela(const struct rela *rela)
--
1.7.5.4

View File

@ -1,106 +0,0 @@
From d1bbff5da464148e5d277b601a31d7872b4e376b Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:26:00 +0000
Subject: [PATCH 1015/1015] create-diff-object: exclude line only change for
arm64
exclude line only change for arm64 by compare mov instruction
except immediate part.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/create-diff-object.c | 71 ++++++++++++++++++++++++++++++++++++-
1 files changed, 70 insertions(+), 1 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index f8f3e15..12d8bd6 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -609,6 +609,68 @@ static int kpatch_line_macro_change_only(struct section *sec)
return 0;
}
#endif
+#define ARM64_INSTR_LEN 4
+static int arm64_kpatch_line_macro_change_only(struct section *sec)
+{
+ unsigned long start1, start2, size, offset;
+ struct rela *rela;
+ int lineonly = 0, found;
+ unsigned int mov_imm_mask = ((1<<16) - 1)<<5;
+
+ if (sec->status != CHANGED ||
+ is_rela_section(sec) ||
+ !is_text_section(sec) ||
+ sec->sh.sh_size != sec->twin->sh.sh_size ||
+ !sec->rela ||
+ sec->rela->status != SAME)
+ return 0;
+
+ start1 = (unsigned long)sec->twin->data->d_buf;
+ start2 = (unsigned long)sec->data->d_buf;
+ size = sec->sh.sh_size;
+ for (offset = 0; offset < size; offset += ARM64_INSTR_LEN) {
+ if (!memcmp((void *)start1 + offset, (void *)start2 + offset,
+ ARM64_INSTR_LEN))
+ continue;
+
+ /* verify it's a mov immediate to w1 */
+ if ((*(int *)(start1 + offset) & ~mov_imm_mask) !=
+ (*(int *)(start2 + offset) & ~mov_imm_mask))
+ return 0;
+
+ found = 0;
+ list_for_each_entry(rela, &sec->rela->relas, list) {
+ if (rela->offset < offset + ARM64_INSTR_LEN)
+ continue;
+ if (rela->string)
+ continue;
+ if (!strncmp(rela->sym->name, "__warned.", 9))
+ continue;
+ if (!strncmp(rela->sym->name, "warn_slowpath_", 14) ||
+ (!strcmp(rela->sym->name, "__warn_printk")) ||
+ (!strcmp(rela->sym->name, "__might_sleep")) ||
+ (!strcmp(rela->sym->name, "___might_sleep")) ||
+ (!strcmp(rela->sym->name, "__might_fault")) ||
+ (!strcmp(rela->sym->name, "printk")) ||
+ (!strcmp(rela->sym->name, "lockdep_rcu_suspicious"))) {
+ found = 1;
+ break;
+ }
+ return 0;
+ }
+ if (!found)
+ return 0;
+
+ lineonly = 1;
+ }
+
+ if (!lineonly)
+ ERROR("no instruction changes detected for changed section %s",
+ sec->name);
+
+ return 1;
+}
+
static void kpatch_compare_sections(struct list_head *seclist)
{
@@ -624,7 +686,14 @@ static void kpatch_compare_sections(struct list_head *seclist)
/* exclude WARN-only, might_sleep changes */
list_for_each_entry(sec, seclist, list) {
- if (kpatch_line_macro_change_only(sec)) {
+ int line_only;
+ if (arch == EM_X86_64)
+ line_only = kpatch_line_macro_change_only(sec);
+ else if (arch == EM_AARCH64)
+ line_only = arm64_kpatch_line_macro_change_only(sec);
+ else
+ line_only = 0;
+ if (line_only) {
log_debug("reverting macro / line number section %s status to SAME\n",
sec->name);
sec->status = SAME;
--
1.7.5.4

View File

@ -1,31 +0,0 @@
From dc771a1789ea3769777228f792f0902f8b0566ba Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Thu, 22 Nov 2018 21:06:32 +0000
Subject: [PATCH] kpatch-build: include secsym in kpatch_mark_ignored_sections
kpatch_mark_ignored_sections include .rodata.str1.1 section but does
not include its section symbol, causing its section symbol can not be
included any more in kpatch_include_standard_elements. After the
section symbol is freed in kpatch_elf_teardown, we got a segmentation
fault in kpatch_create_intermediate_sections.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/create-diff-object.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 2e54960..97ae0d4 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -2285,6 +2285,7 @@ static void kpatch_mark_ignored_sections(struct kpatch_elf *kelf)
* from the section data comparison, but this is a simpler way.
*/
strsec->include = 1;
+ strsec->secsym->include = 1;
name = strsec->data->d_buf + rela->addend;
ignoresec = find_section_by_name(&kelf->sections, name);
if (!ignoresec)
--
1.7.5.4

View File

@ -1,828 +0,0 @@
From 9d590b5b9fb59c1cd52221feeef2794eb3333571 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Thu, 8 Nov 2018 15:12:06 +0000
Subject: [PATCH] support c plus kernel module
support GNU_UNIQUE type symbols.
support .group section corelation.
support symbol name longger than 128 bytes.
fix object size changed error for __FUNCTION__.xxx.
ignore compile warning for third party modules.
support functions have no fentry call.
support all function force enable/disable
fix sym replacing error for aarch64
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kmod/patch/livepatch-patch-hook.c | 8 ++
kpatch-build/create-diff-object.c | 161 ++++++++++++++++++++++++-----------
kpatch-build/create-klp-module.c | 27 +++++-
kpatch-build/create-kpatch-module.c | 15 +--
kpatch-build/kpatch-build | 7 ++-
kpatch-build/kpatch-elf.c | 8 ++-
kpatch-build/kpatch-gcc | 2 +-
kpatch-build/lookup.c | 125 +++++++++++++++++++++++++--
kpatch-build/lookup.h | 14 ++-
9 files changed, 287 insertions(+), 80 deletions(-)
diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c
index fefc068..ce1c955 100644
--- a/kmod/patch/livepatch-patch-hook.c
+++ b/kmod/patch/livepatch-patch-hook.c
@@ -497,8 +497,12 @@ static int __init patch_init(void)
lfunc->old_name = func->kfunc->name;
lfunc->new_func = (void *)func->kfunc->new_addr;
#if defined(HAVE_IMMEDIATE)
+#ifdef __ALL_FORCE__
+ lfunc->immediate = 1;
+#else
lfunc->immediate = patch_is_func_forced(lfunc->new_func);
#endif
+#endif
#ifdef HAVE_SYMPOS
lfunc->old_sympos = func->kfunc->sympos;
#else
@@ -507,7 +511,11 @@ static int __init patch_init(void)
#ifdef __HULK__
lfunc->old_size = func->kfunc->old_size;
lfunc->new_size = func->kfunc->new_size;
+#ifdef __ALL_FORCE__
+ lfunc->force = 1;
+#else
lfunc->force = patch_is_func_forced(func->kfunc->new_addr);
+#endif
lfunc->ref_name= func->kfunc->ref_name;
lfunc->ref_offset = func->kfunc->ref_offset;
#endif
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 97ae0d4..8bb650d 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -224,6 +224,7 @@ static int is_special_static(struct symbol *sym)
"__func__.",
"_rs.",
"CSWTCH.",
+ "__FUNCTION__.",
NULL,
};
char **prefix;
@@ -386,7 +387,7 @@ static void kpatch_compare_correlated_nonrela_section(struct section *sec)
{
struct section *sec1 = sec, *sec2 = sec->twin;
- if (sec1->sh.sh_type != SHT_NOBITS &&
+ if (sec1->sh.sh_type != SHT_NOBITS && sec1->sh.sh_type != SHT_GROUP &&
memcmp(sec1->data->d_buf, sec2->data->d_buf, sec1->data->d_size))
sec->status = CHANGED;
else
@@ -400,8 +401,9 @@ static void kpatch_compare_correlated_section(struct section *sec)
/* Compare section headers (must match or fatal) */
if (sec1->sh.sh_type != sec2->sh.sh_type ||
sec1->sh.sh_flags != sec2->sh.sh_flags ||
- sec1->sh.sh_addralign != sec2->sh.sh_addralign ||
- sec1->sh.sh_entsize != sec2->sh.sh_entsize)
+ sec1->sh.sh_entsize != sec2->sh.sh_entsize ||
+ (sec1->sh.sh_addralign != sec2->sh.sh_addralign &&
+ strcmp(sec1->name, ".rodata")))
DIFF_FATAL("%s section header details differ", sec1->name);
/* Short circuit for mcount sections, we rebuild regardless */
@@ -763,6 +765,33 @@ static void kpatch_compare_symbols(struct list_head *symlist)
}
}
+static int kpatch_correlate_group_section(struct list_head *seclist1, struct list_head *seclist2, struct section *sec1, struct section *sec2)
+{
+ unsigned int *data1, *end1, *data2;
+ struct section *isec1, *isec2;
+
+ if (sec1->data->d_size != sec2->data->d_size)
+ return 1;
+ data1 = sec1->data->d_buf;
+ data2 = sec2->data->d_buf;
+ end1 = sec1->data->d_buf + sec1->data->d_size;
+ data1++;
+ data2++;
+ while (data1 < end1) {
+ isec1 = find_section_by_index(seclist1, *data1);
+ if (!isec1)
+ ERROR("group section not found");
+ isec2 = find_section_by_index(seclist2, *data2);
+ if (!isec2)
+ ERROR("group section not found");
+ if (strcmp(isec1->name, isec2->name))
+ return 1;
+ data1++;
+ data2++;
+ }
+ return 0;
+}
+
static void kpatch_correlate_sections(struct list_head *seclist1, struct list_head *seclist2)
{
struct section *sec1, *sec2;
@@ -777,15 +806,18 @@ static void kpatch_correlate_sections(struct list_head *seclist1, struct list_he
sec1->secsym))
continue;
- /*
- * Group sections must match exactly to be correlated.
- * Changed group sections are currently not supported.
- */
+ /* Group section的格式为
+ * flag
+ * section index
+ * section index
+ * ...
+ *
+ * 当C++代码发生修改时section index可能会发生变化
+ * 这时候我们就比对一下section index所对应的section的
+ * name如果相同我们就认为这两个group是SAME
+ * */
if (sec1->sh.sh_type == SHT_GROUP) {
- if (sec1->data->d_size != sec2->data->d_size)
- continue;
- if (memcmp(sec1->data->d_buf, sec2->data->d_buf,
- sec1->data->d_size))
+ if(kpatch_correlate_group_section(seclist1, seclist2, sec1, sec2))
continue;
}
sec1->twin = sec2;
@@ -1308,17 +1340,21 @@ static void kpatch_replace_sections_syms(struct kpatch_elf *kelf)
#ifdef __powerpc64__
add_off = 0;
#else
- if (rela->type == R_X86_64_PC32) {
- struct insn insn;
- rela_insn(sec, rela, &insn);
- add_off = (long)insn.next_byte -
- (long)sec->base->data->d_buf -
- rela->offset;
- } else if (rela->type == R_X86_64_64 ||
- rela->type == R_X86_64_32S)
- add_off = 0;
- else
- continue;
+ add_off = 0;
+ if (arch == EM_X86_64) {
+ if (rela->type == R_X86_64_PC32) {
+ struct insn insn;
+ rela_insn(sec, rela, &insn);
+ add_off = (long)insn.next_byte -
+ (long)sec->base->data->d_buf -
+ rela->offset;
+ } else if (rela->type == R_X86_64_64 ||
+ rela->type == R_X86_64_32S)
+ add_off = 0;
+ else
+ continue;
+ }
+ /* add_off is always equal to 0 on arm64 */
#endif
/*
@@ -1421,17 +1457,6 @@ static void kpatch_verify_patchability(struct kpatch_elf *kelf)
errs++;
}
- if (sec->status != SAME && sec->grouped) {
- log_normal("changed section %s is part of a section group\n",
- sec->name);
- errs++;
- }
-
- if (sec->sh.sh_type == SHT_GROUP && sec->status == NEW) {
- log_normal("new/changed group sections are not supported\n");
- errs++;
- }
-
/*
* ensure we aren't including .data.* or .bss.*
* (.data.unlikely and .data.once is ok b/c it only has __warned vars)
@@ -1458,6 +1483,7 @@ static void kpatch_include_section(struct section *sec)
/* Include the section and its section symbol */
if (sec->include)
return;
+
sec->include = 1;
if (sec->secsym)
sec->secsym->include = 1;
@@ -1640,7 +1666,7 @@ static void kpatch_include_force_elements(struct kpatch_elf *kelf)
sym->include = 0;
}
-int kpatch_include_new_static_var(struct kpatch_elf *kelf)
+static int kpatch_include_new_static_var(struct kpatch_elf *kelf)
{
struct symbol *sym;
@@ -2253,6 +2279,23 @@ static void kpatch_include_debug_sections(struct kpatch_elf *kelf)
}
}
+static void kpatch_ignore_debug_sections(struct kpatch_elf *kelf)
+{
+ struct section *sec;
+
+ /* include all .debug_* sections */
+ list_for_each_entry(sec, &kelf->sections, list) {
+ if (is_debug_section(sec)) {
+ sec->include = 0;
+ sec->status = SAME;
+ if (!is_rela_section(sec)) {
+ sec->secsym->include = 0;
+ sec->secsym->status = SAME;
+ }
+ }
+ }
+}
+
static void kpatch_mark_ignored_sections(struct kpatch_elf *kelf)
{
struct section *sec, *strsec, *ignoresec;
@@ -2589,14 +2632,13 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
funcs[index].old_size = result.size;
funcs[index].new_size = sym->sym.st_size;
funcs[index].sympos = result.pos;
- if (lookup_is_duplicate_symbol(table, sym->name)) {
+ if (lookup_is_duplicate_symbol(table, sym->name, objname, result.pos)) {
struct lookup_refsym refsym;
long offset;
- if (lookup_ref_symbol(table, sym->name, &refsym))
+ if (lookup_ref_symbol_offset(table, sym->name, &refsym, objname, &offset))
ERROR("unresolvable ambiguity on symbol %s\n", sym->name);
- offset = (long)result.value - (long)refsym.value;
funcs[index].ref_offset = offset;
/*
@@ -2631,7 +2673,7 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
ALLOC_LINK(rela, &relasec->relas);
rela->sym = strsym;
rela->type = absolute_rela_type;
- rela->addend = offset_of_string(&kelf->strings, sym->name);
+ rela->addend = offset_of_string(&kelf->strings, strndup(sym->name, KSYM_NAME_LEN-1));
rela->offset = index * sizeof(*funcs) +
offsetof(struct kpatch_patch_func, name);
@@ -2780,13 +2822,14 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
*/
if (may_need_dynrela(rela))
toc_rela(rela)->need_dynrela = 1;
+
if (rela->sym->sec) {
if (rela->sym->type == STT_FUNC &&
- rela->sym->status == CHANGED &&
- rela->sym->sec != sec->base &&
- sec->base->sym &&
- sec->base->sym->type == STT_FUNC)
- toc_rela(rela)->need_dynrela = 1;
+ rela->sym->status == CHANGED &&
+ rela->sym->sec != sec->base &&
+ sec->base->sym &&
+ sec->base->sym->type == STT_FUNC)
+ toc_rela(rela)->need_dynrela = 1;
}
}
}
@@ -2820,6 +2863,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
if (!strcmp(sec->name, ".rela.kpatch.funcs") ||
!strcmp(sec->name, ".rela.kpatch.dynrelas"))
continue;
+
list_for_each_entry_safe(rela, safe, &sec->relas, list) {
if (!rela->need_dynrela)
continue;
@@ -2963,13 +3007,12 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
else {
/* for modules, src is discovered at runtime */
ksyms[index].src = 0;
- if (lookup_is_duplicate_symbol(table, rela->sym->name)) {
+ if (lookup_is_duplicate_symbol(table, rela->sym->name, objname, result.pos)) {
struct lookup_refsym refsym;
- if (lookup_ref_symbol(table, rela->sym->name, &refsym))
+ if (lookup_ref_symbol_offset(table, rela->sym->name, &refsym, objname, &ref_offset))
ERROR("unresolvable ambiguity on symbol %s\n", rela->sym->name);
- ref_offset = (long)result.value - (long)refsym.value;
/* add rela to fill in ref_name field */
ALLOC_LINK(rela2, &krela_sec->rela->relas);
rela2->sym = strsym;
@@ -2987,7 +3030,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
ALLOC_LINK(rela2, &ksym_sec->rela->relas);
rela2->sym = strsym;
rela2->type = absolute_rela_type;
- rela2->addend = offset_of_string(&kelf->strings, rela->sym->name);
+ rela2->addend = offset_of_string(&kelf->strings, strndup(rela->sym->name, KSYM_NAME_LEN-1));
rela2->offset = index * sizeof(*ksyms) + \
offsetof(struct kpatch_symbol, name);
@@ -3163,6 +3206,9 @@ static void kpatch_create_mcount_sections(struct kpatch_elf *kelf)
* __fentry__" so that ftrace will be happy.
*/
newdata = malloc(sym->sec->data->d_size);
+ if (!newdata)
+ ERROR("malloc");
+
memcpy(newdata, sym->sec->data->d_buf, sym->sec->data->d_size);
sym->sec->data->d_buf = newdata;
insn = newdata;
@@ -3186,6 +3232,8 @@ static void kpatch_create_mcount_sections(struct kpatch_elf *kelf)
rela->offset = index * sizeof(*funcs);
newdata = malloc(sym->sec->data->d_size);
+ if (!newdata)
+ ERROR("malloc");
memcpy(newdata, sym->sec->data->d_buf, sym->sec->data->d_size);
sym->sec->data->d_buf = newdata;
insnp = newdata;
@@ -3354,6 +3402,8 @@ int main(int argc, char *argv[])
char *parent_symtab, *mod_symvers, *patch_name, *output_obj;
struct sym_compare_type *base_locals;
char *gcc_add_option, *mlongcall;
+ char *no_profiling_calls;
+ char *kallsyms;
arguments.debug = 0;
argp_parse (&argp, argc, argv, 0, NULL, &arguments);
@@ -3400,9 +3450,12 @@ int main(int argc, char *argv[])
return EXIT_STATUS_NO_CHANGE;
}
+ kallsyms = getenv("KALLSYMS");
+ if (kallsyms)
+ log_debug("kallsyms file:%s\n", kallsyms);
/* create symbol lookup table */
base_locals = kpatch_elf_locals(kelf_base);
- lookup = lookup_open(parent_symtab, mod_symvers, hint, base_locals);
+ lookup = lookup_open(parent_symtab, mod_symvers, hint, base_locals, kallsyms);
free(base_locals);
kpatch_mark_grouped_sections(kelf_patched);
@@ -3420,7 +3473,12 @@ int main(int argc, char *argv[])
*/
kpatch_mark_ignored_sections(kelf_patched);
kpatch_compare_correlated_elements(kelf_patched);
- kpatch_check_func_profiling_calls(kelf_patched);
+
+ no_profiling_calls = getenv("NO_PROFILING_CALLS");
+ if (!no_profiling_calls)
+ kpatch_check_func_profiling_calls(kelf_patched);
+ else
+ log_debug("NO_PROFILING_CALLS set\n");
kpatch_elf_teardown(kelf_base);
kpatch_elf_free(kelf_base);
@@ -3430,6 +3488,7 @@ int main(int argc, char *argv[])
kpatch_include_standard_elements(kelf_patched);
num_changed = kpatch_include_changed_functions(kelf_patched);
kpatch_include_debug_sections(kelf_patched);
+ kpatch_ignore_debug_sections(kelf_patched);
callbacks_exist = kpatch_include_callback_elements(kelf_patched);
kpatch_include_force_elements(kelf_patched);
new_globals_exist = kpatch_include_new_globals(kelf_patched);
@@ -3470,10 +3529,10 @@ int main(int argc, char *argv[])
kpatch_build_strings_section_data(kelf_out);
gcc_add_option = getenv("GCC_ADD_OPTION");
- printf("gcc add option :%s\n", gcc_add_option);
+ log_debug("gcc add option :%s\n", gcc_add_option);
mlongcall = strstr(gcc_add_option, "-mlong-calls");
if (arch == EM_AARCH64 && mlongcall) {
- printf("-mlong-calls found, no need to create mcount section\n");
+ log_debug("-mlong-calls found, no need to create mcount section\n");
} else {
kpatch_create_mcount_sections(kelf_out);
}
diff --git a/kpatch-build/create-klp-module.c b/kpatch-build/create-klp-module.c
index 253704b..7a72afd 100644
--- a/kpatch-build/create-klp-module.c
+++ b/kpatch-build/create-klp-module.c
@@ -38,7 +38,9 @@ enum loglevel loglevel = NORMAL;
*/
static struct symbol *find_or_add_ksym_to_symbols(struct kpatch_elf *kelf,
struct section *ksymsec,
- char *strings, int offset)
+ char *strings, int offset,
+ char *ref_name,
+ long ref_offset)
{
struct kpatch_symbol *ksyms, *ksym;
struct symbol *sym;
@@ -71,9 +73,14 @@ static struct symbol *find_or_add_ksym_to_symbols(struct kpatch_elf *kelf,
if (!objname)
ERROR("strdup");
- snprintf(pos, 32, "%lu", ksym->pos);
/* .klp.sym.objname.name,pos */
- snprintf(buf, 256, KLP_SYM_PREFIX "%s.%s,%s", objname, name, pos);
+ if (!ref_name) {
+ snprintf(pos, 32, "%lu", ksym->pos);
+ snprintf(buf, 256, KLP_SYM_PREFIX "%s.%s,%s", objname, name, pos);
+ } else {
+ snprintf(pos, 32, "%ld", ref_offset);
+ snprintf(buf, 256, KLP_SYM_PREFIX "%s-%s,%s", objname, ref_name, pos);
+ }
/* Look for an already allocated symbol */
list_for_each_entry(sym, &kelf->symbols, list) {
@@ -180,6 +187,7 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section
struct rela *rela;
char *objname;
int nr, index, offset, dest_off;
+ char *ref_name;
krelas = krelasec->data->d_buf;
nr = krelasec->data->d_size / sizeof(*krelas);
@@ -206,6 +214,17 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section
if (!objname)
ERROR("strdup");
+ /* Get the unique ref_name */
+ rela = find_rela_by_offset(krelasec->rela,
+ offset + offsetof(struct kpatch_relocation, ref_name));
+ if (!rela)
+ ref_name = NULL;
+ else {
+ ref_name = strdup(strings + rela->addend);
+ if (!ref_name)
+ ERROR("strdup");
+ }
+
/* Get the .kpatch.symbol entry for the rela src */
rela = find_rela_by_offset(krelasec->rela,
offset + offsetof(struct kpatch_relocation, ksym));
@@ -213,7 +232,7 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section
ERROR("find_rela_by_offset");
/* Create (or find) a klp symbol from the rela src entry */
- sym = find_or_add_ksym_to_symbols(kelf, ksymsec, strings, rela->addend);
+ sym = find_or_add_ksym_to_symbols(kelf, ksymsec, strings, rela->addend, ref_name, krelas[index].ref_offset);
if (!sym)
ERROR("error finding or adding ksym to symtab");
diff --git a/kpatch-build/create-kpatch-module.c b/kpatch-build/create-kpatch-module.c
index 8292dc8..3e24b3a 100644
--- a/kpatch-build/create-kpatch-module.c
+++ b/kpatch-build/create-kpatch-module.c
@@ -112,14 +112,10 @@ static void create_dynamic_rela_sections(struct kpatch_elf *kelf, struct section
dynrelas[index].ref_name = krelas[index].ref_name;
dynrelas[index].ref_offset = krelas[index].ref_offset;
- if (dynrelas[index].ref_offset)
- {
- /* Get objname offset */
- rela = find_rela_by_offset(krelasec->rela,
- index * sizeof(*krelas) + offsetof(struct kpatch_relocation, ref_name));
- if (!rela) {
- ERROR("find_rela_by_offset");
- }
+ /* Get ref_name offset */
+ rela = find_rela_by_offset(krelasec->rela,
+ index * sizeof(*krelas) + offsetof(struct kpatch_relocation, ref_name));
+ if (rela) {
ref_name_offset = rela->addend;
/* ref_name */
ALLOC_LINK(rela, &dynsec->rela->relas);
@@ -128,9 +124,8 @@ static void create_dynamic_rela_sections(struct kpatch_elf *kelf, struct section
rela->addend = ref_name_offset;
rela->offset = index * sizeof(*dynrelas) + \
offsetof(struct kpatch_patch_dynrela, ref_name);
-
}
-
+
/* dest */
ALLOC_LINK(rela, &dynsec->rela->relas);
rela->sym = sym;
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index 81a6a44..a860f12 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -953,6 +953,10 @@ if grep "hulk" $SRCDIR/Makefile > /dev/null; then
export KCPPFLAGS="-D__HULK__ $KCPPFLAGS"
fi
+if [[ -n "$NO_STACK_CHECK" ]];then
+ export KCPPFLAGS="-D__ALL_FORCE__ $KCPPFLAGS"
+fi
+
echo "Building patch module: $MODNAME.ko"
if [[ -z "$USERSRCDIR" ]] && [[ "$DISTRO" = ubuntu ]]; then
@@ -990,6 +994,7 @@ KBUILD_EXTRA_SYMBOLS="$KBUILD_EXTRA_SYMBOLS" \
KPATCH_LDFLAGS="$KPATCH_LDFLAGS" \
CROSS_COMPILE="$ARCH_COMPILE" \
make 2>&1 | logger || die
+${ARCH_COMPILE}strip -g "$TEMPDIR/patch/$MODNAME.ko"
if ! "$KPATCH_MODULE"; then
if [[ -z "$KPATCH_LDFLAGS" ]]; then
@@ -1019,7 +1024,7 @@ fi
# column containing lines unique to first file.
UNDEFINED=$(comm -23 <(sort -u "${TEMPDIR}"/undefined_references) \
<(sort -u "${TEMPDIR}"/new_symbols) | tr '\n' ' ')
-[[ ! -z "$UNDEFINED" ]] && die "Undefined symbols: $UNDEFINED"
+[[ -z "$USERMODDIR" ]] && [[ ! -z "$UNDEFINED" ]] && die "Undefined symbols: $UNDEFINED"
cp -f "$TEMPDIR/patch/$MODNAME.ko" "$BASE" || die
diff --git a/kpatch-build/kpatch-elf.c b/kpatch-build/kpatch-elf.c
index fcb7161..0794031 100644
--- a/kpatch-build/kpatch-elf.c
+++ b/kpatch-build/kpatch-elf.c
@@ -700,8 +700,14 @@ void kpatch_reindex_elements(struct kpatch_elf *kelf)
unsigned int index;
index = 1; /* elf write function handles NULL section 0 */
- list_for_each_entry(sec, &kelf->sections, list)
+ list_for_each_entry(sec, &kelf->sections, list) {
sec->index = index++;
+ /*
+ * since we exclude .group section, we clear SHF_GROUP
+ * for every section in case of link error.
+ * */
+ sec->sh.sh_flags &= (~SHF_GROUP);
+ }
index = 0;
list_for_each_entry(sym, &kelf->symbols, list) {
diff --git a/kpatch-build/kpatch-gcc b/kpatch-build/kpatch-gcc
index be18847..d36e67b 100755
--- a/kpatch-build/kpatch-gcc
+++ b/kpatch-build/kpatch-gcc
@@ -13,7 +13,7 @@ fi
declare -a args=("$@")
-if [[ "$TOOLCHAINCMD" = ${ARCH_COMPILE}gcc ]] ; then
+if [[ "$TOOLCHAINCMD" = ${ARCH_COMPILE}gcc || "$TOOLCHAINCMD" = ${ARCH_COMPILE}g++ ]] ; then
while [ "$#" -gt 0 ]; do
if [ "$1" = "-o" ]; then
obj="$2"
diff --git a/kpatch-build/lookup.c b/kpatch-build/lookup.c
index e4677db..2a728f6 100644
--- a/kpatch-build/lookup.c
+++ b/kpatch-build/lookup.c
@@ -45,6 +45,7 @@ struct object_symbol {
char *name;
int type, bind;
int sec_index;
+ unsigned long kaddr;
};
struct export_symbol {
@@ -238,6 +239,8 @@ static void symtab_read(struct lookup_table *table, char *path)
table->obj_syms[i].bind = STB_GLOBAL;
} else if (!strcmp(bind, "WEAK")) {
table->obj_syms[i].bind = STB_WEAK;
+ } else if (!strcmp(bind, "GNU_UNIQUE")) {
+ table->obj_syms[i].bind = STB_GNU_UNIQUE;
} else {
ERROR("unknown symbol bind %s", bind);
}
@@ -263,6 +266,56 @@ static void symtab_read(struct lookup_table *table, char *path)
fclose(file);
}
+static void ksymtab_read(struct lookup_table *table, char *path)
+{
+ FILE *file;
+ struct object_symbol *sym, *sym1, *sym2;
+ unsigned long value;
+ int i, j, idx;
+ char line[256], name[256], type[256], mod[256];
+ idx = 0;
+
+ if ((file = fopen(path, "r")) == NULL)
+ ERROR("fopen");
+
+ while (fgets(line, 256, file)) {
+ if (sscanf(line, "%lx %s %s [%s]\n",
+ &value, type, name, mod) != 4)
+ continue;
+
+ if (name[0] == '$')
+ continue;
+
+ i = idx;
+ for_each_obj_symbol_continue(i, sym, table) {
+ if (!strncmp(sym->name, name, KSYM_NAME_LEN-1)) {
+ sym->kaddr = value;
+ idx = i + 1;
+ break;
+ }
+ }
+ }
+
+ for_each_obj_symbol(i, sym1, table) {
+ if (sym1->kaddr == 0)
+ continue;
+ for_each_obj_symbol(j, sym2, table) {
+ if (sym2->kaddr == 0)
+ continue;
+ if (sym1 == sym2)
+ continue;
+ if (sym1->sec_index != sym2->sec_index)
+ continue;
+ if ((long)sym1->value - (long)sym2->value ==
+ (long)sym1->kaddr - (long)sym2->kaddr)
+ continue;
+
+ ERROR("base mismatch(symbol offset)");
+ }
+ }
+ fclose(file);
+}
+
static void symvers_read(struct lookup_table *table, char *path)
{
FILE *file;
@@ -306,7 +359,8 @@ static void symvers_read(struct lookup_table *table, char *path)
}
struct lookup_table *lookup_open(char *symtab_path, char *symvers_path,
- char *hint, struct sym_compare_type *locals)
+ char *hint, struct sym_compare_type *locals,
+ char *kallsyms)
{
struct lookup_table *table;
@@ -317,6 +371,8 @@ struct lookup_table *lookup_open(char *symtab_path, char *symvers_path,
symtab_read(table, symtab_path);
symvers_read(table, symvers_path);
+ if (kallsyms)
+ ksymtab_read(table, kallsyms);
find_local_syms(table, hint, locals);
return table;
@@ -343,6 +399,15 @@ int lookup_local_symbol(struct lookup_table *table, char *name,
for_each_obj_symbol(i, sym, table) {
if (sym->bind == STB_LOCAL && !strcmp(sym->name, name))
pos++;
+ else {
+ /* symbol name longer than KSYM_NAME_LEN will be truncated
+ * by kernel, so we can not find it using its original
+ * name. we need to add pos for symbols which have same
+ * KSYM_NAME_LEN-1 long prefix.*/
+ if (strlen(name) >= KSYM_NAME_LEN-1 &&
+ !strncmp(sym->name, name, KSYM_NAME_LEN-1))
+ pos++;
+ }
if (table->local_syms == sym) {
in_file = 1;
@@ -374,15 +439,25 @@ int lookup_global_symbol(struct lookup_table *table, char *name,
struct lookup_result *result)
{
struct object_symbol *sym;
+ unsigned long pos = 0;
int i;
memset(result, 0, sizeof(*result));
for_each_obj_symbol(i, sym, table) {
- if ((sym->bind == STB_GLOBAL || sym->bind == STB_WEAK) &&
+ /* symbol name longer than KSYM_NAME_LEN will be truncated
+ * by kernel, so we can not find it using its original
+ * name. we need to add pos for symbols which have same
+ * KSYM_NAME_LEN-1 long prefix.*/
+ if (strlen(name) >= KSYM_NAME_LEN-1 &&
+ !strncmp(sym->name, name, KSYM_NAME_LEN-1))
+ pos++;
+
+ if ((sym->bind == STB_GLOBAL || sym->bind == STB_WEAK
+ || sym->bind == STB_GNU_UNIQUE) &&
!strcmp(sym->name, name)) {
result->value = sym->value;
result->size = sym->size;
- result->pos = 0; /* always 0 for global symbols */
+ result->pos = pos;
return 0;
}
}
@@ -429,10 +504,12 @@ char *lookup_exported_symbol_objname(struct lookup_table *table, char *name)
return NULL;
}
-int lookup_is_duplicate_symbol(struct lookup_table *table, char *name)
+int lookup_is_duplicate_symbol(struct lookup_table *table, char *name,
+ char *objname, unsigned long pos)
{
struct object_symbol *sym;
int i, count = 0;
+ char posstr[32], buf[256];
for_each_obj_symbol(i, sym, table)
if (!strcmp(sym->name, name)) {
@@ -441,6 +518,17 @@ int lookup_is_duplicate_symbol(struct lookup_table *table, char *name)
return 1;
}
+ /* symbol name longer than KSYM_NAME_LEN will be truncated
+ * by kernel, so we can not find it using its original
+ * name. Here, we consider these long name symbol as duplicated
+ * symbols. since create_klp_module will create symbol name
+ * format like .klp.sym.objname.symbol,pos, so we consider name
+ * length longer than KSYM_NAME_LEN-1 bytes as duplicated symbol*/
+ snprintf(posstr, 32, "%lu", pos);
+ snprintf(buf, 256, KLP_SYM_PREFIX "%s.%s,%s", objname, name, posstr);
+ if (strlen(buf) >= KSYM_NAME_LEN-1)
+ return 1;
+
return 0;
}
@@ -487,24 +575,45 @@ struct object_symbol *lookup_find_symbol_by_name(struct lookup_table *table, cha
return sym;
}
-int lookup_ref_symbol(struct lookup_table *table, char *name,
- struct lookup_refsym *refsym)
+int lookup_ref_symbol_offset(struct lookup_table *table, char *name,
+ struct lookup_refsym *refsym,
+ char *objname, long *offset)
{
struct object_symbol *orig_sym, *sym;
int i;
orig_sym = lookup_find_symbol_by_name(table, name);
if (!orig_sym)
- ERROR("lookup_ref_symbol");
+ ERROR("lookup_ref_symbol_offset");
memset(refsym, 0, sizeof(*refsym));
+
+ /*find a unique symbol in the same section first*/
for_each_obj_symbol(i, sym, table) {
if (!strcmp(sym->name, name) || sym->type == STT_FILE ||
sym->sec_index != orig_sym->sec_index)
continue;
- if (!lookup_is_duplicate_symbol(table, sym->name)) {
+ if (!lookup_is_duplicate_symbol(table, sym->name, objname, 1)) {
refsym->name = sym->name;
refsym->value = sym->value;
+ *offset = (long)orig_sym->value - (long)sym->value;
+ return 0;
+ }
+ }
+
+ if (orig_sym->kaddr == 0)
+ return 1;
+
+ /*find a unique symbol has kaddr*/
+ for_each_obj_symbol(i, sym, table) {
+ if (!strcmp(sym->name, name) || sym->type == STT_FILE ||
+ sym->kaddr == 0)
+ continue;
+
+ if (!lookup_is_duplicate_symbol(table, sym->name, objname, 1)) {
+ refsym->name = sym->name;
+ refsym->value = 0;
+ *offset = (long)orig_sym->kaddr - (long)sym->kaddr;
return 0;
}
}
diff --git a/kpatch-build/lookup.h b/kpatch-build/lookup.h
index 5ad9241..00b6ccc 100644
--- a/kpatch-build/lookup.h
+++ b/kpatch-build/lookup.h
@@ -1,6 +1,9 @@
#ifndef _LOOKUP_H_
#define _LOOKUP_H_
+#include "kpatch-elf.h"
+#define KSYM_NAME_LEN 128
+
struct lookup_table;
struct lookup_result {
@@ -20,7 +23,8 @@ struct lookup_refsym {
};
struct lookup_table *lookup_open(char *symtab_path, char *symvers_path,
- char *hint, struct sym_compare_type *locals);
+ char *hint, struct sym_compare_type *locals,
+ char *kallsyms);
void lookup_close(struct lookup_table *table);
int lookup_local_symbol(struct lookup_table *table, char *name,
struct lookup_result *result);
@@ -28,8 +32,10 @@ int lookup_global_symbol(struct lookup_table *table, char *name,
struct lookup_result *result);
int lookup_is_exported_symbol(struct lookup_table *table, char *name);
char *lookup_exported_symbol_objname(struct lookup_table *table, char *name);
-int lookup_is_duplicate_symbol(struct lookup_table *table, char *name);
-int lookup_ref_symbol(struct lookup_table *table, char *name,
- struct lookup_refsym *refsym);
+int lookup_is_duplicate_symbol(struct lookup_table *table, char *name,
+ char *objname, unsigned long pos);
+int lookup_ref_symbol_offset(struct lookup_table *table, char *name,
+ struct lookup_refsym *refsym, char *objname,
+ long *offset);
#endif /* _LOOKUP_H_ */
--
1.7.5.4

View File

@ -1,28 +0,0 @@
From f221fbe8ff0c22b61aaf42687f5ece04f10ec403 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Thu, 17 Jan 2019 20:50:25 +0000
Subject: [PATCH] kpatch-build: adapt for ksymtab in 4.19 kernel
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/create-diff-object.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index f075671..2ddd00d 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -1664,8 +1664,8 @@ static int kpatch_include_new_static_var(struct kpatch_elf *kelf)
list_for_each_entry(sym, &kelf->symbols, list) {
if (sym->status == NEW &&
- sym->type == STT_OBJECT &&
- sym->bind == STB_LOCAL)
+ sym->bind == STB_LOCAL &&
+ (sym->type == STT_OBJECT || (sym->type == STT_NOTYPE && sym->name[0] != '$')))
kpatch_include_symbol(sym);
}
--
1.7.5.4

View File

@ -1,91 +0,0 @@
From 6b7ff79bb40a7dbb28e6aba320e4ac075e4c182d Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 18 Jan 2019 00:07:02 +0000
Subject: [PATCH] support force enable/disable for kernel 4.19
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kmod/patch/livepatch-patch-hook.c | 7 +++++--
kpatch-build/kpatch-build | 12 ++++++++++--
2 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c
index ce1c955..919dfc7 100644
--- a/kmod/patch/livepatch-patch-hook.c
+++ b/kmod/patch/livepatch-patch-hook.c
@@ -511,14 +511,17 @@ static int __init patch_init(void)
#ifdef __HULK__
lfunc->old_size = func->kfunc->old_size;
lfunc->new_size = func->kfunc->new_size;
+ lfunc->ref_name= func->kfunc->ref_name;
+ lfunc->ref_offset = func->kfunc->ref_offset;
+#endif
+#if defined(__HULK__) || defined(__KLP_SUPPORT_FORCE__)
#ifdef __ALL_FORCE__
lfunc->force = 1;
#else
lfunc->force = patch_is_func_forced(func->kfunc->new_addr);
#endif
- lfunc->ref_name= func->kfunc->ref_name;
- lfunc->ref_offset = func->kfunc->ref_offset;
#endif
+
j++;
}
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index a860f12..c227b44 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -279,7 +279,7 @@ find_special_section_data() {
# shellcheck disable=SC2086
SPECIAL_VARS="$(readelf -wi "$VMLINUX" |
gawk --non-decimal-data $AWK_OPTIONS '
- BEGIN { a = b = p = e = o = 0 }
+ BEGIN { a = b = p = e = o = f = 0 }
# Set state if name matches
a == 0 && /DW_AT_name.* alt_instr[[:space:]]*$/ {a = 1; next}
@@ -287,6 +287,7 @@ find_special_section_data() {
p == 0 && /DW_AT_name.* paravirt_patch_site[[:space:]]*$/ {p = 1; next}
e == 0 && /DW_AT_name.* exception_table_entry[[:space:]]*$/ {e = 1; next}
o == 0 && /DW_AT_name.* orc_entry[[:space:]]*$/ {o = 1; next}
+ f == 0 && /DW_AT_name.* klp_func[[:space:]]*$/ {f = 1; next}
# Reset state unless this abbrev describes the struct size
a == 1 && !/DW_AT_byte_size/ { a = 0; next }
@@ -294,6 +295,8 @@ find_special_section_data() {
p == 1 && !/DW_AT_byte_size/ { p = 0; next }
e == 1 && !/DW_AT_byte_size/ { e = 0; next }
o == 1 && !/DW_AT_byte_size/ { o = 0; next }
+ f == 1 && /DW_TAG_structure_type/ { f = 3; next }
+ f == 1 && /DW_AT_name.* force[[:space:]]*$/ {f = 2; next}
# Now that we know the size, stop parsing for it
a == 1 {printf("export ALT_STRUCT_SIZE=%d\n", $4); a = 2}
@@ -301,9 +304,10 @@ find_special_section_data() {
p == 1 {printf("export PARA_STRUCT_SIZE=%d\n", $4); p = 2}
e == 1 {printf("export EX_STRUCT_SIZE=%d\n", $4); e = 2}
o == 1 {printf("export ORC_STRUCT_SIZE=%d\n", $4); o = 2}
+ f == 2 {printf("export KLP_SUPPORT_FORCE=y\n"); f = 3}
# Bail out once we have everything
- a == 2 && b == 2 && (p == 2 || skip_p) && e == 2 && (o == 2 || skip_o) {exit}')"
+ a == 2 && b == 2 && (p == 2 || skip_p) && e == 2 && (o == 2 || skip_o) && f == 3 {exit}')"
[[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS"
@@ -957,6 +961,10 @@ if [[ -n "$NO_STACK_CHECK" ]];then
export KCPPFLAGS="-D__ALL_FORCE__ $KCPPFLAGS"
fi
+if [[ -n "$KLP_SUPPORT_FORCE" ]];then
+ export KCPPFLAGS="-D__KLP_SUPPORT_FORCE__ $KCPPFLAGS"
+fi
+
echo "Building patch module: $MODNAME.ko"
if [[ -z "$USERSRCDIR" ]] && [[ "$DISTRO" = ubuntu ]]; then
--
1.7.5.4

View File

@ -1,118 +0,0 @@
From 87203483495fec8ad1394def83fa884a96b711ec Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Thu, 14 Feb 2019 14:21:20 +0000
Subject: [PATCH] kpatch-build: adapt for native compile_env
we check vmlinux to determine if klp_func and klp_object
have some members and set flag for livepatch-patch-hook.c.
support arm64 native compile enviroment.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/kpatch-build | 46 ++++++++++++++++++++++++++++++++++----------
1 files changed, 35 insertions(+), 11 deletions(-)
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index c227b44..18f79d4 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -279,7 +279,7 @@ find_special_section_data() {
# shellcheck disable=SC2086
SPECIAL_VARS="$(readelf -wi "$VMLINUX" |
gawk --non-decimal-data $AWK_OPTIONS '
- BEGIN { a = b = p = e = o = f = 0 }
+ BEGIN { a = b = p = e = o = c = f = s = i = r = j = h = 0 }
# Set state if name matches
a == 0 && /DW_AT_name.* alt_instr[[:space:]]*$/ {a = 1; next}
@@ -287,7 +287,8 @@ find_special_section_data() {
p == 0 && /DW_AT_name.* paravirt_patch_site[[:space:]]*$/ {p = 1; next}
e == 0 && /DW_AT_name.* exception_table_entry[[:space:]]*$/ {e = 1; next}
o == 0 && /DW_AT_name.* orc_entry[[:space:]]*$/ {o = 1; next}
- f == 0 && /DW_AT_name.* klp_func[[:space:]]*$/ {f = 1; next}
+ c == 0 && /DW_AT_name.* klp_func[[:space:]]*$/ {c = 1; next}
+ j == 0 && /DW_AT_name.* klp_object[[:space:]]*$/ {j = 1; next}
# Reset state unless this abbrev describes the struct size
a == 1 && !/DW_AT_byte_size/ { a = 0; next }
@@ -295,8 +296,13 @@ find_special_section_data() {
p == 1 && !/DW_AT_byte_size/ { p = 0; next }
e == 1 && !/DW_AT_byte_size/ { e = 0; next }
o == 1 && !/DW_AT_byte_size/ { o = 0; next }
- f == 1 && /DW_TAG_structure_type/ { f = 3; next }
- f == 1 && /DW_AT_name.* force[[:space:]]*$/ {f = 2; next}
+ c == 1 && /DW_TAG_structure_type/ { c = 3; next }
+ j == 1 && /DW_TAG_structure_type/ { j = 3; next }
+ c == 1 && /DW_AT_name.* force[[:space:]]*$/ {f = 2; next}
+ c == 1 && /DW_AT_name.* old_sympos[[:space:]]*$/ {s = 2; next}
+ i == 1 && /DW_AT_name.* immediate[[:space:]]*$/ {i = 2; next}
+ j == 1 && /DW_AT_name.* relocs[[:space:]]*$/ {r = 2; next}
+ j == 1 && /DW_AT_name.* hooks_load[[:space:]]*$/ {h = 2; next}
# Now that we know the size, stop parsing for it
a == 1 {printf("export ALT_STRUCT_SIZE=%d\n", $4); a = 2}
@@ -304,10 +310,14 @@ find_special_section_data() {
p == 1 {printf("export PARA_STRUCT_SIZE=%d\n", $4); p = 2}
e == 1 {printf("export EX_STRUCT_SIZE=%d\n", $4); e = 2}
o == 1 {printf("export ORC_STRUCT_SIZE=%d\n", $4); o = 2}
- f == 2 {printf("export KLP_SUPPORT_FORCE=y\n"); f = 3}
+ f == 2 {printf("export KLP_SUPPORT_FORCE=y\n"); f = 3}
+ s == 2 {printf("export KLP_SUPPORT_OLD_SYMPOS=y\n"); s = 3}
+ i == 2 {printf("export KLP_SUPPORT_IMMEDIATE=y\n"); i = 3}
+ r == 2 {printf("export KLP_SUPPORT_RELOCS=y\n"); r = 3}
+ h == 2 {printf("export KLP_SUPPORT_LOADHOOKS=y\n"); h = 3}
# Bail out once we have everything
- a == 2 && b == 2 && (p == 2 || skip_p) && e == 2 && (o == 2 || skip_o) && f == 3 {exit}')"
+ a == 2 && b == 2 && (p == 2 || skip_p) && e == 2 && (o == 2 || skip_o) && c == 3 && j == 3 {exit}')"
[[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS"
@@ -406,7 +416,9 @@ arch_export() {
export GCC_ADD_OPTION=
elif [[ $E_MACHINE -eq 183 ]]; then
export ARCH=arm64
- export ARCH_COMPILE=aarch64-linux-gnu-
+ if [ $(arch) != "aarch64" ]; then
+ export ARCH_COMPILE=aarch64-linux-gnu-
+ fi
export ENDIAN=little
if grep "\-mlong-calls" $SRCDIR/Makefile > /dev/null; then
export GCC_ADD_OPTION="-fno-section-anchors -mlong-calls"
@@ -953,10 +965,6 @@ if "$KPATCH_MODULE"; then
export KCPPFLAGS="-D__KPATCH_MODULE__"
fi
-if grep "hulk" $SRCDIR/Makefile > /dev/null; then
- export KCPPFLAGS="-D__HULK__ $KCPPFLAGS"
-fi
-
if [[ -n "$NO_STACK_CHECK" ]];then
export KCPPFLAGS="-D__ALL_FORCE__ $KCPPFLAGS"
fi
@@ -965,6 +973,22 @@ if [[ -n "$KLP_SUPPORT_FORCE" ]];then
export KCPPFLAGS="-D__KLP_SUPPORT_FORCE__ $KCPPFLAGS"
fi
+if [[ -n "$KLP_SUPPORT_OLD_SYMPOS" ]];then
+ export KCPPFLAGS="-DHAVE_SYMPOS $KCPPFLAGS"
+fi
+
+if [[ -n "$KLP_SUPPORT_IMMEDIATE" ]];then
+ export KCPPFLAGS="-DHAVE_IMMEDIATE $KCPPFLAGS"
+fi
+
+if [[ -n "$KLP_SUPPORT_RELOCS" ]];then
+ export KCPPFLAGS="-DHAVE_ELF_RELOCS $KCPPFLAGS"
+fi
+
+if [[ -n "$KLP_SUPPORT_LOADHOOKS" ]];then
+ export KCPPFLAGS="-DHAVE_LOADHOOKS $KCPPFLAGS"
+fi
+
echo "Building patch module: $MODNAME.ko"
if [[ -z "$USERSRCDIR" ]] && [[ "$DISTRO" = ubuntu ]]; then
--
1.7.5.4

View File

@ -1,96 +0,0 @@
From d53b2d1f87f5e891ba8f6945765134da9ee2d29d Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Thu, 7 Mar 2019 14:38:15 +0000
Subject: [PATCH] add find_special_section_data_arm64 for arm64
arm64 kernel have no paravirt_patch_site or orc_entry structure
in vmlinux, we don't need to check these two struct for arm64.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/kpatch-build | 56 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 55 insertions(+), 1 deletion(-)
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index 18f79d4..59af250 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -266,12 +266,66 @@ find_special_section_data_ppc64le() {
return
}
+find_special_section_data_arm64() {
+
+ # If $AWK_OPTIONS are blank gawk would treat "" as a blank script
+ # shellcheck disable=SC2086
+ SPECIAL_VARS="$(readelf -wi "$VMLINUX" |
+ gawk --non-decimal-data $AWK_OPTIONS '
+ BEGIN { a = b = e = c = f = s = i = r = j = h = 0 }
+
+ # Set state if name matches
+ a == 0 && /DW_AT_name.* alt_instr[[:space:]]*$/ {a = 1; next}
+ b == 0 && /DW_AT_name.* bug_entry[[:space:]]*$/ {b = 1; next}
+ e == 0 && /DW_AT_name.* exception_table_entry[[:space:]]*$/ {e = 1; next}
+ c == 0 && /DW_AT_name.* klp_func[[:space:]]*$/ {c = 1; next}
+ j == 0 && /DW_AT_name.* klp_object[[:space:]]*$/ {j = 1; next}
+
+ # Reset state unless this abbrev describes the struct size
+ a == 1 && !/DW_AT_byte_size/ { a = 0; next }
+ b == 1 && !/DW_AT_byte_size/ { b = 0; next }
+ e == 1 && !/DW_AT_byte_size/ { e = 0; next }
+ c == 1 && /DW_TAG_structure_type/ { c = 3; next }
+ j == 1 && /DW_TAG_structure_type/ { j = 3; next }
+ c == 1 && /DW_AT_name.* force[[:space:]]*$/ {f = 2; next}
+ c == 1 && /DW_AT_name.* old_sympos[[:space:]]*$/ {s = 2; next}
+ i == 1 && /DW_AT_name.* immediate[[:space:]]*$/ {i = 2; next}
+ j == 1 && /DW_AT_name.* relocs[[:space:]]*$/ {r = 2; next}
+ j == 1 && /DW_AT_name.* hooks_load[[:space:]]*$/ {h = 2; next}
+
+ # Now that we know the size, stop parsing for it
+ a == 1 {printf("export ALT_STRUCT_SIZE=%d\n", $4); a = 2}
+ b == 1 {printf("export BUG_STRUCT_SIZE=%d\n", $4); b = 2}
+ e == 1 {printf("export EX_STRUCT_SIZE=%d\n", $4); e = 2}
+ f == 2 {printf("export KLP_SUPPORT_FORCE=y\n"); f = 3}
+ s == 2 {printf("export KLP_SUPPORT_OLD_SYMPOS=y\n"); s = 3}
+ i == 2 {printf("export KLP_SUPPORT_IMMEDIATE=y\n"); i = 3}
+ r == 2 {printf("export KLP_SUPPORT_RELOCS=y\n"); r = 3}
+ h == 2 {printf("export KLP_SUPPORT_LOADHOOKS=y\n"); h = 3}
+
+ # Bail out once we have everything
+ a == 2 && b == 2 && e == 2 && c == 3 && j == 3 {exit}')"
+
+ [[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS"
+
+ [[ -z "$ALT_STRUCT_SIZE" ]] && die "can't find special struct alt_instr size"
+ [[ -z "$BUG_STRUCT_SIZE" ]] && die "can't find special struct bug_entry size"
+ [[ -z "$EX_STRUCT_SIZE" ]] && die "can't find special struct exception_table_entry size"
+
+ return
+}
+
find_special_section_data() {
if [[ "$ARCH" = "ppc64le" ]]; then
find_special_section_data_ppc64le
return
fi
+ if [[ "$ARCH" = "arm64" ]]; then
+ find_special_section_data_arm64
+ return
+ fi
+
[[ "$CONFIG_PARAVIRT" -eq 0 ]] && AWK_OPTIONS="-vskip_p=1"
[[ "$CONFIG_UNWINDER_ORC" -eq 0 ]] && AWK_OPTIONS="$AWK_OPTIONS -vskip_o=1"
@@ -323,7 +377,7 @@ find_special_section_data() {
[[ -z "$ALT_STRUCT_SIZE" ]] && die "can't find special struct alt_instr size"
[[ -z "$BUG_STRUCT_SIZE" ]] && die "can't find special struct bug_entry size"
- [[ -z "$EX_STRUCT_SIZE" ]] && die "can't find special struct paravirt_patch_site size"
+ [[ -z "$EX_STRUCT_SIZE" ]] && die "can't find special struct exception_table_entry size"
[[ -z "$PARA_STRUCT_SIZE" && "$CONFIG_PARAVIRT" -ne 0 ]] && die "can't find special struct paravirt_patch_site size"
[[ -z "$ORC_STRUCT_SIZE" && "$CONFIG_UNWINDER_ORC" -ne 0 ]] && die "can't find special struct orc_entry size"
--
2.19.1

View File

@ -1,31 +0,0 @@
From 1069d212fd848f1f1e2425dffe8e9aea188c6150 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Tue, 21 Dec 2083 12:18:38 +0800
Subject: [PATCH] fix ref static local symbol for longname symbol
static local symbol have a "." which will confuse
the kernel livepatch klp_resolve_symbols. So, pass
static local symbols in lookup_ref_symbol_offset.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/lookup.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/kpatch-build/lookup.c b/kpatch-build/lookup.c
index 2e55862..01abc41 100644
--- a/kpatch-build/lookup.c
+++ b/kpatch-build/lookup.c
@@ -591,7 +591,8 @@ int lookup_ref_symbol_offset(struct lookup_table *table, char *name,
/*find a unique symbol in the same section first*/
for_each_obj_symbol(i, sym, table) {
if (!strcmp(sym->name, name) || sym->type == STT_FILE ||
- sym->sec_index != orig_sym->sec_index)
+ sym->sec_index != orig_sym->sec_index ||
+ strchr(sym->name, '.'))
continue;
if (!lookup_is_duplicate_symbol(table, sym->name, objname, 1)) {
--
2.19.1

View File

@ -1,34 +0,0 @@
From da3eed612df1d26e19b0678763e116f666da13b2 Mon Sep 17 00:00:00 2001
From: Artem Savkov <asavkov@redhat.com>
Date: Wed, 14 Nov 2018 12:33:13 +0100
Subject: [PATCH] kmod/core: fix compilation with
CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
Kernel commit 7290d5809571 "module: use relative references for
__ksymtab entries" changed kernel_symbol structure on some
architectures. Adjust kmod/core/core.c accordingly.
Signed-off-by: Artem Savkov <asavkov@redhat.com>
---
kmod/core/core.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/kmod/core/core.c b/kmod/core/core.c
index 4a73a47..a91d417 100644
--- a/kmod/core/core.c
+++ b/kmod/core/core.c
@@ -651,7 +651,11 @@ static int kpatch_find_external_symbol(const char *objname, const char *name,
sym = find_symbol(name, NULL, NULL, true, true);
preempt_enable();
if (sym) {
+#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
+ *addr = (unsigned long)offset_to_ptr(&sym->value_offset);
+#else
*addr = sym->value;
+#endif
return 0;
}
--
2.19.1

Binary file not shown.

BIN
kpatch-0.9.0.tar.gz Normal file

Binary file not shown.

View File

@ -1,8 +1,8 @@
%global raw_version 0.6.1 %global raw_version 0.9.0
Name: kpatch Name: kpatch
Version: 2.0 Version: 2.0
Release: 3.1.23 Release: 3.1.24
Summary: A Linux dynamic kernel patching infrastructure Summary: A Linux dynamic kernel patching infrastructure
License: GPLv2 License: GPLv2
@ -13,36 +13,23 @@ Source1: os_hotpatch
Source2: livepatch Source2: livepatch
Source3: make_hotpatch Source3: make_hotpatch
Patch9001: 9001-livepatch-patch-hook-don-t-active-patch-when-insmod.patch Patch0001:0001-support-compile-kpatch-on-aarch64.patch
Patch9002: 9002-kpatch-build-support-third-party-module-make-hotpatc.patch Patch0002:0002-kpatch-build-support-build-patch-for-aarch64.patch
Patch9003: 9003-kpatch-build-support-makefile-not-in-third-party-mod.patch Patch0003:0003-create-diff-object-new-static-var-should-be-included.patch
Patch9004: 9004-create-diff-object-new-static-var-should-be-included.patch Patch0004:0004-livepatch-fix-use-THIS-modname-as-the-name-of-ddebug.patch
Patch9005: 9005-livepatch-fix-use-THIS-modname-as-the-name-of-ddebug.patch Patch0005:0005-create-diff-object-fix-correlate-static-local-variab.patch
Patch9006: 9006-create-diff-object-fix-correlate-static-local-variab.patch Patch0006:0006-create-diff-object-don-t-create-dynamic-reloc-for-sy.patch
Patch9007: 9007-create-diff-object-don-t-create-dynamic-reloc-for-sy.patch Patch0007:0007-create-diff-object-create-dynamic-relocs-for-changed.patch
Patch9008: 9008-livepatch-patch-hook-support-force-enable-disable-fu.patch Patch0008:0008-fix-rodata.str-problem.patch
Patch9009: 9009-kmod-kpatch-build-support-build-patch-for-old-kernel.patch Patch0009:0009-livepatch-patch-hook-don-t-active-patch-when-insmod.patch
Patch9010: 9010-kmod-kpatch-build-support-cross-compile-hotpatch-for.patch Patch0010:0010-kpatch-build-enhance-for-out-of-tree-module.patch
Patch9011: 9011-kpatch-build-use-.klp.rela-in-euleros-7.5-kernel.patch Patch0011:0011-support-c-plus-kernel-module.patch
Patch9012: 9012-create-diff-object-create-dynamic-relocs-for-changed.patch Patch0012:0012-symbol-lookup-enhancement.patch
Patch9013: 9013-kmod-kpatch-build-fix-duplicate-symbol-relocation-fo.patch Patch0013:0013-Add-running-kernel-symbol-table-to-help-symbol-looku.patch
Patch9014: 9014-create-diff-object-add-dynamic-reloction-for-functio.patch Patch0014:0014-livepatch-patch-hook-support-force-enable-disable.patch
Patch9015: 9015-create-diff-object-exclude-line-only-change-for-arm6.patch Patch0015:0015-kpatch-build-ignore-debuginfo-in-patch.patch
Patch9016: 9016-kpatch-build-include-secsym-in-kpatch_mark_ignored_s.patch Patch0016:0016-add-object-in-kpatch.patch
Patch9017: 9017-support-compile-kpatch-on-aarch64.patch Patch0017:0017-create-diff-object-fix-.orc_unwind_ip-error.patch
Patch9018: 9018-support-c-plus-kernel-module.patch
Patch9019: 9019-fix-rodata.str-problem.patch
Patch9020: 0001-Add-__addressable_-to-maybe_discarded_sym.patch
Patch9021: 0002-kmod-patch-fix-patch-linking-with-4.20.patch
Patch9022: 0003-kmod-patch-more-linking-fixes.patch
Patch9023: 9023-kpatch-build-adapt-for-ksymtab-in-4.19-kernel.patch
Patch9024: 9024-support-force-enable-disable-for-kernel-4.19.patch
Patch9025: 9025-kpatch-build-adapt-for-native-compile_env.patch
Patch9026: 9026-add-find_special_section_data_arm64-for-arm64.patch
Patch9027: 9027-fix-ref-static-local-symbol-for-longname-symbol.patch
Patch9028: 9028-add-object-in-kpatch.patch
Patch9029: 0004-create-diff-object-allow-changing-subsections.patch
Patch9030: 9030-kmod-core-fix-compilation-with-CONFIG_HAVE_ARCH_PREL.patch
BuildRequires: gcc elfutils-libelf-devel uname-build-checks kernel kernel-devel BuildRequires: gcc elfutils-libelf-devel uname-build-checks kernel kernel-devel
Requires: bc Requires: bc
@ -89,9 +76,6 @@ popd
%{_datadir}/%{name}/* %{_datadir}/%{name}/*
%{_sysconfdir}/init/* %{_sysconfdir}/init/*
/opt/patch_workspace/* /opt/patch_workspace/*
%ifarch x86_64
%{_prefix}/lib/kpatch
%endif
%files runtime %files runtime
%defattr(-,root,root) %defattr(-,root,root)
@ -102,6 +86,12 @@ popd
%{_mandir}/man1/*.1.gz %{_mandir}/man1/*.1.gz
%changelog %changelog
* Wed Feb 26 2020 Zhipeng Xie<kangenbo@huawei.com> -2.0-3.1.24
- Type:enhancement
- ID:NA
- SUG:NA
- DESC:rebase from upstream version v0.9.0
* Mon Feb 17 2020 openEuler Buildteam <buildteam@openeuler.org> -2.0-3.1.23 * Mon Feb 17 2020 openEuler Buildteam <buildteam@openeuler.org> -2.0-3.1.23
- Type:enhancement - Type:enhancement
- ID:NA - ID:NA

View File

@ -1,19 +1,8 @@
#!/bin/bash #!/bin/bash
# Copyright (C) 2019. Huawei Technologies Co., Ltd. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 and
# only version 2 as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
exe_tool=`which os_hotpatch` exe_tool=`which os_hotpatch`
fn_help() fn_help()
{ {
cat <<EOFE cat <<EOFE
Usage: livepatch -l/--load -r/--remove -a/--activate -d/--deactivate <patch> Usage: livepatch -l/--load -r/--remove -a/--activate -d/--deactivate <patch>
-q[patch]/--query[=patch] -q[patch]/--query[=patch]
-h/--help -v/--version -h/--help -v/--version
@ -28,38 +17,38 @@ input_args=`getopt -a -o l:a:r:d:q:v -l load:,activate:,remove:,deactivate:,quer
eval set -- "${input_args}" eval set -- "${input_args}"
while true; while true;
do do
case "$1" in case "$1" in
-l|--load) -l|--load)
$exe_tool -l "$2" $exe_tool -l "$2"
exit $? exit $?
;; ;;
-a|--activate) -a|--activate)
$exe_tool -a "klp_${2#klp_}" $exe_tool -a "klp_${2#klp_}"
exit $? exit $?
;; ;;
-d|--deactivate) -d|--deactivate)
$exe_tool -r "klp_${2#klp_}" $exe_tool -r "klp_${2#klp_}"
exit $? exit $?
;; ;;
-r|--remove) -r|--remove)
$exe_tool -d "klp_${2#klp_}" $exe_tool -d "klp_${2#klp_}"
exit $? exit $?
;; ;;
-q|--query) -q|--query)
$exe_tool -q "klp_${2#klp_}" $exe_tool -q "klp_${2#klp_}"
exit $? exit $?
;; ;;
-h|--help) -h|--help)
fn_help fn_help
exit 0 exit 0
;; ;;
-v|--version) -v|--version)
echo "LKP:livepatch version 2.0-00000" echo "LKP:livepatch version 2.0-00000"
exit 0 exit 0
;; ;;
*) *)
fn_help fn_help
exit 1 exit 1
;; ;;
esac esac
done done

View File

@ -1,14 +1,18 @@
#!/bin/bash #!/usr/bin/bash
# Copyright (C) 2019. Huawei Technologies Co., Ltd. All rights reserved. #********************************************************************
# # Copyright (C) Huawei Technologies, 2015-11
# This program is free software; you can redistribute it and/or modify #
# it under the terms of the GNU General Public License version 2 and # #FileName : make_hotpatch
# only version 2 as published by the Free Software Foundation. # #Description : make hotpatch
# # #Author :
# This program is distributed in the hope that it will be useful, # #Language : shell
# but WITHOUT ANY WARRANTY; without even the implied warranty of # #Environment : Euler compile env
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # #Created : 2015-11
# GNU General Public License for more details. # #History
# 1.Date:
# Author:
# Modification:
#********************************************************************
SHELL_DIR=$(dirname $0) SHELL_DIR=$(dirname $0)
SHELL_DIR=$(cd $SHELL_DIR; pwd) SHELL_DIR=$(cd $SHELL_DIR; pwd)
@ -72,12 +76,12 @@ Options:
-p,--patch -p,--patch
Specifies the patch file Specifies the patch file
--kallsyms --kallsyms
Specifies module kallsyms in running system(cat /proc/kallsyms|grep mod) Specifies module kallsyms in running system(cat /proc/kallsyms|grep mod)
-h,--help -h,--help
help info help info
EOF EOF
return 0 return 0
} }
@ -94,7 +98,7 @@ function fn_do_clean()
unset NO_STACK_CHECK unset NO_STACK_CHECK
unset KALLSYMS unset KALLSYMS
rm -rf $G_TMP_DIR rm -rf $G_TMP_DIR
} }
######################################################### #########################################################
@ -109,7 +113,7 @@ function fn_check_reg_char()
local l_str_maxlen=$2 local l_str_maxlen=$2
local l_str_ex=$3 local l_str_ex=$3
local len_str=${#l_str} local len_str=${#l_str}
if [ -z "$l_str" ];then if [ -z "$l_str" ];then
echo "error: the string is empty, check string failed" echo "error: the string is empty, check string failed"
return 1 return 1
@ -139,10 +143,10 @@ function fn_check_reg_char()
else else
echo "error: string $l_str can only contain characters included by ('0-9', 'a-z', 'A-Z', '-', '_')." echo "error: string $l_str can only contain characters included by ('0-9', 'a-z', 'A-Z', '-', '_')."
fi fi
return 1 return 1
fi fi
} }
######################################################### #########################################################
@ -159,7 +163,7 @@ function fn_check_id()
echo "error: check hotpatch id failed" echo "error: check hotpatch id failed"
return 1 return 1
fi fi
G_HOTPATCH_ID=$l_id G_HOTPATCH_ID=$l_id
G_HOTPATCH=${G_PREFIX}_${G_HOTPATCH_ID}.ko G_HOTPATCH=${G_PREFIX}_${G_HOTPATCH_ID}.ko
G_HOTPATCH_TAR=${G_PREFIX}_${G_HOTPATCH_ID}.tar.gz G_HOTPATCH_TAR=${G_PREFIX}_${G_HOTPATCH_ID}.tar.gz
@ -197,8 +201,8 @@ function fn_check_jobs()
function fn_check_patch(){ function fn_check_patch(){
local l_patch=$1 local l_patch=$1
if [ ! -f $1 ];then if [ ! -f $1 ];then
echo "error:patch file $1 not exit" echo "error:patch file $1 not exist"
return 1 return 1
fi fi
G_PATCHFILE=$l_patch G_PATCHFILE=$l_patch
} }
@ -324,136 +328,136 @@ function fn_verify_input()
fi fi
if [ -z "`echo "$input_param" | grep -w "\-i"`" \ if [ -z "`echo "$input_param" | grep -w "\-i"`" \
-a -z "`echo $input_param | grep -w "\-\-id"`" \ -a -z "`echo $input_param | grep -w "\-\-id"`" \
-a $# -gt 1 ];then -a $# -gt 1 ];then
echo "error: missing param -i or --id" echo "error: missing param -i or --id"
fn_do_clean fn_do_clean
fn_usage fn_usage
exit 1 exit 1
fi fi
if [ -z "`echo "$input_param" | grep -w "\-d"`" \ if [ -z "`echo "$input_param" | grep -w "\-d"`" \
-a -z "`echo $input_param | grep -w "\-\-diffext"`" \ -a -z "`echo $input_param | grep -w "\-\-diffext"`" \
-a -z "`echo $input_param | grep -w "\-p"`" \ -a -z "`echo $input_param | grep -w "\-p"`" \
-a -z "`echo $input_param | grep -w "\-\-patch"`" \ -a -z "`echo $input_param | grep -w "\-\-patch"`" \
-a $# -gt 1 ];then -a $# -gt 1 ];then
echo "error: missing param -d,--diffext or -p,--patch" echo "error: missing param -d,--diffext or -p,--patch"
fn_do_clean fn_do_clean
fn_usage fn_usage
exit 1 exit 1
fi fi
while [ $# -ge 1 ]; do while [ $# -ge 1 ]; do
case "$1" in case "$1" in
-h|--help) -h|--help)
fn_usage
fn_do_clean
exit 0
;;
-j|--jobs)
fn_check_jobs $2
if [ $? -eq 0 ]; then
shift 2
else
fn_do_clean
fn_usage fn_usage
exit 1
fi
;;
-i|--id)
fn_check_id $2
if [ $? -eq 0 ]; then
shift 2
else
fn_do_clean fn_do_clean
fn_usage exit 0
exit 1 ;;
fi -j|--jobs)
;; fn_check_jobs $2
-d|--diffext) if [ $? -eq 0 ]; then
fn_check_diffext $2 shift 2
if [ $? -eq 0 ]; then else
shift 2 fn_do_clean
else fn_usage
fn_do_clean exit 1
fn_usage fi
exit 1 ;;
fi -i|--id)
;; fn_check_id $2
-p|--patch) if [ $? -eq 0 ]; then
fn_check_patch $2 shift 2
if [ $? -eq 0 ]; then else
shift 2 fn_do_clean
else fn_usage
fn_do_clean exit 1
fn_usage fi
exit 1 ;;
fi -d|--diffext)
;; fn_check_diffext $2
-k|--kernelsrc) if [ $? -eq 0 ]; then
fn_check_kernelsrc $2 shift 2
if [ $? -eq 0 ]; then else
shift 2 fn_do_clean
else fn_usage
fn_do_clean exit 1
fn_usage fi
exit 1 ;;
fi -p|--patch)
;; fn_check_patch $2
-m|--modulesrc) if [ $? -eq 0 ]; then
fn_check_modulesrc $2 shift 2
if [ $? -eq 0 ]; then else
shift 2 fn_do_clean
else fn_usage
fn_do_clean exit 1
fn_usage fi
exit 1 ;;
fi -k|--kernelsrc)
;; fn_check_kernelsrc $2
-f|--makefile) if [ $? -eq 0 ]; then
fn_check_makefile $2 shift 2
if [ $? -eq 0 ]; then else
shift 2 fn_do_clean
else fn_usage
fn_do_clean exit 1
fn_usage fi
exit 1 ;;
fi -m|--modulesrc)
;; fn_check_modulesrc $2
--extra_flags) if [ $? -eq 0 ]; then
fn_check_extra_flags $2 shift 2
if [ $? -eq 0 ]; then else
shift 2 fn_do_clean
else fn_usage
fn_do_clean exit 1
fn_usage fi
exit 1 ;;
fi -f|--makefile)
;; fn_check_makefile $2
--no_stack_check) if [ $? -eq 0 ]; then
shift 2
else
fn_do_clean
fn_usage
exit 1
fi
;;
--extra_flags)
fn_check_extra_flags $2
if [ $? -eq 0 ]; then
shift 2
else
fn_do_clean
fn_usage
exit 1
fi
;;
--no_stack_check)
export NO_STACK_CHECK="yes" export NO_STACK_CHECK="yes"
shift 1 shift 1
;; ;;
--debug_info) --debug_info)
G_DEBUG_INFO="-d" G_DEBUG_INFO="-d"
shift 1 shift 1
;; ;;
--kallsyms) --kallsyms)
export KALLSYMS=$(readlink -f $2) if [ "$2" == "" ];then
if [ $? -eq 0 ]; then echo "error: param --kallsyms need file parameter"
fn_do_clean
fn_usage
exit 1
fi
export KALLSYMS=$(readlink -f $2)
shift 2 shift 2
else ;;
*)
echo "error: params is invalid,please check it."
fn_do_clean fn_do_clean
fn_usage fn_usage
exit 1 exit 1
fi ;;
;;
*)
echo "error: params is invalid,please check it."
fn_do_clean
fn_usage
exit 1
;;
esac esac
done done
@ -474,11 +478,11 @@ function fn_init_module_build()
local module= local module=
module=`basename $l_modulesrc` module=`basename $l_modulesrc`
if [ ! -e $G_PRIVATE_MODULE ];then if [ ! -e $G_PRIVATE_MODULE ];then
mkdir -p $G_PRIVATE_MODULE mkdir -p $G_PRIVATE_MODULE
fi fi
rm -rf $G_PRIVATE_MODULE/* rm -rf $G_PRIVATE_MODULE/*
if [ $? -ne 0 ];then if [ $? -ne 0 ];then
echo "error: remove $G_PRIVATE_MODULE/$module or Makefile failed" echo "error: remove $G_PRIVATE_MODULE/$module or Makefile failed"
@ -534,14 +538,15 @@ function fn_makepatch()
G_PATCH_SRC=`readlink -f $G_KERNEL_SRC` G_PATCH_SRC=`readlink -f $G_KERNEL_SRC`
if [ -d "$G_MODULE_SRC" ];then if [ -d "$G_MODULE_SRC" ];then
echo "make out of tree module hotpath" echo "make out of tree module hotpath"
G_PATCH_SRC=$G_MODULE_SRC G_PATCH_SRC=$G_MODULE_SRC
#fn_init_module_build $G_MODULE_SRC $G_MODULE_MAKEFILE #fn_init_module_build $G_MODULE_SRC $G_MODULE_MAKEFILE
#if [ $? -ne 0 ];then #if [ $? -ne 0 ];then
# echo "error: init module build failed" # echo "error: init module build failed"
# return 1 # return 1
#fi #fi
l_extra_module="-m $G_MODULE_SRC" l_extra_module="-m $G_MODULE_SRC"
USERMODBUILDDIR=$G_MODULE_SRC
fi fi
if [ -n "$G_JOBS" ];then if [ -n "$G_JOBS" ];then
@ -551,63 +556,61 @@ function fn_makepatch()
mkdir -p $G_TMP_DIR mkdir -p $G_TMP_DIR
if [ -z "$G_PATCHFILE" ];then if [ -z "$G_PATCHFILE" ];then
#generate src patch file from G_DIFFEXT #generate src patch file from G_DIFFEXT
G_PATCHFILE=$G_TMP_DIR/$G_HOTPATCH_ID.patch G_PATCHFILE=$G_TMP_DIR/$G_HOTPATCH_ID.patch
rm -rf $G_PATCHFILE rm -rf $G_PATCHFILE
cd $G_PATCH_SRC &>/dev/null cd $G_PATCH_SRC &>/dev/null
l_change_file=($(find -L -name "*$G_DIFFEXT" | xargs readlink -f 2>/dev/null| sort | uniq)) l_change_file=($(find -L -name "*$G_DIFFEXT" | xargs readlink -f 2>/dev/null| sort | uniq))
echo "detect change files:${l_change_file[@]}" echo "detect change files:${l_change_file[@]}"
for file in ${l_change_file[@]}; for file in ${l_change_file[@]};
do do
file="./${file#$(readlink -f $G_PATCH_SRC)}" file="./${file#$(readlink -f $G_PATCH_SRC)}"
orig_file=${file%$G_DIFFEXT} orig_file=${file%$G_DIFFEXT}
if [ "${orig_file##*.}" == "h" ]; then if [ "${orig_file##*.}" == "h" ]; then
existflag=1 && break existflag=1 && break
fi fi
diff -u $orig_file $file >> $G_PATCHFILE diff -u $orig_file $file >> $G_PATCHFILE
done done
cd - &>/dev/null cd - &>/dev/null
if [ ${existflag} -eq 1 ]; then if [ ${existflag} -eq 1 ]; then
echo "error: do not modify the header file" echo "error: do not modify the header file"
return 1 return 1
fi fi
if [ -f $G_PATCHFILE ];then if [ -f $G_PATCHFILE ];then
echo "make patch $G_PATCHFILE" echo "make patch $G_PATCHFILE"
else else
echo "no change detected" echo "no change detected"
return 1 return 1
fi fi
else else
cp $G_PATCHFILE $G_TMP_DIR/${G_HOTPATCH_ID}.patch cp $G_PATCHFILE $G_TMP_DIR/${G_HOTPATCH_ID}.patch
G_PATCHFILE=$G_TMP_DIR/${G_HOTPATCH_ID}.patch G_PATCHFILE=$G_TMP_DIR/${G_HOTPATCH_ID}.patch
fi fi
cd $G_TMP_DIR &>/dev/null cd $G_TMP_DIR &>/dev/null
if [ -n "$G_MODULE_MAKEFILE" ];then if [ -n "$G_MODULE_MAKEFILE" ];then
USERMODBUILDDIR=$(dirname $G_MODULE_MAKEFILE) USERMODBUILDDIR=$(dirname $G_MODULE_MAKEFILE)
fi fi
export USERMODBUILDDIR export USERMODBUILDDIR
export USERMODFLAGS=`cat $G_KPATCH_FLAGS` export USERMODFLAGS=`cat $G_KPATCH_FLAGS`
export NO_PROFILING_CALLS=yes export NO_PROFILING_CALLS="yes"
kpatch-build -s $G_KERNEL_SRC $l_extra_module -c $G_KERNEL_CONFIG -v $G_VMLINUX --skip-gcc-check -n "${G_PREFIX}_${G_HOTPATCH_ID}" -b /lib/modules/`uname -r`/build $G_DEBUG_INFO $G_PATCHFILE export DISABLE_AFTER_LOAD="yes"
kpatch-build -s $G_PATCH_SRC -c $G_KERNEL_CONFIG -v $G_VMLINUX --skip-gcc-check -n "${G_PREFIX}_${G_HOTPATCH_ID}" $G_DEBUG_INFO $G_PATCHFILE
l_ret=$? l_ret=$?
cd - &>/dev/null cd - &>/dev/null
if [ $l_ret -eq 0 ] && [ -f "$G_TMP_DIR/$G_HOTPATCH" ];then if [ $l_ret -eq 0 ] && [ -f "$G_TMP_DIR/$G_HOTPATCH" ];then
if grep -q "CONFIG_MODULE_SIG=y" .config ;then cd /tmp &>/dev/null
echo "kernel compile with CONFIG_MODULE_SIG=y,please sign the patch module"
fi
cd /tmp &>/dev/null
l_env_file=$G_TMP_DIR/toolenv l_env_file=$G_TMP_DIR/toolenv
if [ -n "`which rpm 2>/dev/null`" ]; then if [ -n "`which rpm 2>/dev/null`" ]; then
echo "------------------------------------------------------------------------ " > "${l_env_file}" echo "------------------------------------------------------------------------ " > "${l_env_file}"
echo >> "${l_env_file}" echo >> "${l_env_file}"
echo "The kpatch tool version info and release date:" >> "${l_env_file}" echo "The kpatch tool version info and release date:" >> "${l_env_file}"
rpm -qi kpatch >> "${l_env_file}" rpm -qi kpatch >> "${l_env_file}"
echo >> "${l_env_file}" echo >> "${l_env_file}"
echo "------------------------------------------------------------------------ " >> "${l_env_file}" echo "------------------------------------------------------------------------ " >> "${l_env_file}"
else else
echo "------------------------------------------------------------------------ " >> "${l_env_file}" echo "------------------------------------------------------------------------ " >> "${l_env_file}"
fi fi
echo >> "${l_env_file}" echo >> "${l_env_file}"
@ -617,41 +620,41 @@ function fn_makepatch()
echo "------------------------------------------------------------------------ " >> "${l_env_file}" echo "------------------------------------------------------------------------ " >> "${l_env_file}"
if [ -f "/etc/EulerLinux.conf" ]; then if [ -f "/etc/EulerLinux.conf" ]; then
echo >> "${l_env_file}" echo >> "${l_env_file}"
echo "The euler compile env version info:" >> "${l_env_file}" echo "The euler compile env version info:" >> "${l_env_file}"
cat /etc/EulerLinux.conf >> "${l_env_file}" cat /etc/EulerLinux.conf >> "${l_env_file}"
echo >> "${l_env_file}" echo >> "${l_env_file}"
echo "------------------------------------------------------------------------ " >> "${l_env_file}" echo "------------------------------------------------------------------------ " >> "${l_env_file}"
fi fi
if [ -n "${G_MODULE_SRC}" ]; then if [ -n "${G_MODULE_SRC}" ]; then
echo >> "${l_env_file}" echo >> "${l_env_file}"
echo "The module hotpatch compile path info:" >> "${l_env_file}" echo "The module hotpatch compile path info:" >> "${l_env_file}"
echo "MODULE_SRC=${G_MODULE_SRC}" >> "${l_env_file}" echo "MODULE_SRC=${G_MODULE_SRC}" >> "${l_env_file}"
echo "MODULE_MAKEFILE=${G_MODULE_MAKEFILE}" >> "${l_env_file}" echo "MODULE_MAKEFILE=${G_MODULE_MAKEFILE}" >> "${l_env_file}"
echo >> "${l_env_file}" echo >> "${l_env_file}"
echo "------------------------------------------------------------------------ " >> "${l_env_file}" echo "------------------------------------------------------------------------ " >> "${l_env_file}"
fi fi
if [ -f "${G_EXT_FLAGS}" ]; then if [ -f "${G_EXT_FLAGS}" ]; then
echo >> "${l_env_file}" echo >> "${l_env_file}"
echo "The module hotpatch compile flags info:" >> "${l_env_file}" echo "The module hotpatch compile flags info:" >> "${l_env_file}"
cat "${G_EXT_FLAGS}" >> "${l_env_file}" cat "${G_EXT_FLAGS}" >> "${l_env_file}"
echo >> "${l_env_file}" echo >> "${l_env_file}"
echo "------------------------------------------------------------------------ " >> "${l_env_file}" echo "------------------------------------------------------------------------ " >> "${l_env_file}"
fi fi
if [ -n "${G_DEBUG_INFO}" ]; then if [ -n "${G_DEBUG_INFO}" ]; then
echo >> "${l_env_file}" echo >> "${l_env_file}"
echo "The debug option info:" >> "${l_env_file}" echo "The debug option info:" >> "${l_env_file}"
echo "${G_DEBUG_INFO}" >> "${l_env_file}" echo "${G_DEBUG_INFO}" >> "${l_env_file}"
echo >> "${l_env_file}" echo >> "${l_env_file}"
echo "------------------------------------------------------------------------ " >> "${l_env_file}" echo "------------------------------------------------------------------------ " >> "${l_env_file}"
fi fi
tar -czf $G_HOTPATCH_TAR ${G_PREFIX}_${G_HOTPATCH_ID} tar -czf $G_HOTPATCH_TAR ${G_PREFIX}_${G_HOTPATCH_ID}
mv ${G_HOTPATCH_TAR} ${G_HOTPATCH_DIR} mv ${G_HOTPATCH_TAR} ${G_HOTPATCH_DIR}
cd - &>/dev/null cd - &>/dev/null
if [ $? -ne 0 ];then if [ $? -ne 0 ];then
echo "error: move ${G_HOTPATCH} to ${G_KSPLICE_HOTPATCH} failed" echo "error: move ${G_HOTPATCH} to ${G_KSPLICE_HOTPATCH} failed"
return 1 return 1
@ -682,43 +685,43 @@ function fn_main()
fn_do_clean fn_do_clean
return 1 return 1
fi fi
fn_do_clean fn_do_clean
return 0 return 0
} }
function fn_prepare() function fn_prepare()
{ {
kerver=`uname -r` kerver=`uname -r`
kerver=${kerver%.x86_64} kerver=${kerver%.x86_64}
kerver=${kerver%.aarch64} kerver=${kerver%.aarch64}
echo kernel version:$kerver echo kernel version:$kerver
if [ ! -L kernel-source ];then if [ ! -L kernel-source ];then
if [ -d /arm/arm_kernel ];then if [ -d /arm/arm_kernel ];then
ln -s /arm/arm_kernel/linux-$kerver kernel-source ln -s /arm/arm_kernel/linux-$kerver kernel-source
else else
ln -s /usr/src/kernels/linux-$kerver kernel-source ln -s /usr/src/kernels/linux-$kerver kernel-source
cp /lib/modules/`uname -r`/build/Makefile /usr/src/kernels/linux-$kerver cp /lib/modules/`uname -r`/build/Makefile /usr/src/kernels/linux-$kerver
fi fi
fi fi
if [ ! -L .config ];then if [ ! -L .config ];then
if [ -d /arm/arm_kernel ];then if [ -d /arm/arm_kernel ];then
ln -s /arm/arm_kernel/linux-$kerver/.config .config ln -s /arm/arm_kernel/linux-$kerver/.config .config
else else
ln -s /usr/src/kernels/linux-$kerver/.config .config ln -s /usr/src/kernels/linux-$kerver/.config .config
cp /lib/modules/`uname -r`/build/.config /usr/src/kernels/linux-$kerver cp /lib/modules/`uname -r`/build/.config /usr/src/kernels/linux-$kerver
fi fi
fi fi
rm -rf $G_KPATCH_FLAGS rm -rf $G_KPATCH_FLAGS
touch $G_KPATCH_FLAGS touch $G_KPATCH_FLAGS
} }
G_NUM=`pidof -x make_hotpatch | wc -w` G_NUM=`pidof -x make_hotpatch | wc -w`
if [ $G_NUM -gt 2 ];then if [ $G_NUM -gt 2 ];then
echo "[$0]someone is making, please try again later." echo "[$0]someone is making, please try again later."
exit 1 exit 1
fi fi
fn_prepare fn_prepare

View File

@ -1,17 +1,21 @@
#!/bin/sh #!/bin/sh
# Copyright (C) 2019. Huawei Technologies Co., Ltd. All rights reserved. #********************************************************************
# # Copyright (C) Huawei Technologies, 2015-11
# This program is free software; you can redistribute it and/or modify #
# it under the terms of the GNU General Public License version 2 and # #FileName : make_hotpatch
# only version 2 as published by the Free Software Foundation. # #Description : make hotpatch
# # #Author :
# This program is distributed in the hope that it will be useful, # #Language : shell
# but WITHOUT ANY WARRANTY; without even the implied warranty of # #Environment : Euler compile env
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # #Created : 2015-11
# GNU General Public License for more details. # #History
# 1.Date:
# Author:
# Modification:2015-12-7
#********************************************************************
SYS_LIVEPATCH=/sys/kernel/livepatch SYS_LIVEPATCH=/sys/kernel/livepatch
G_TMP_DIR=/tmp/hotpatch.$$ G_TMP_DIR=/lib/modules/hotpatch.$$
G_PATCH_FILE= G_PATCH_FILE=
######################################################### #########################################################
@ -21,14 +25,14 @@ G_PATCH_FILE=
######################################################### #########################################################
OS_HP_HELP() OS_HP_HELP()
{ {
echo "usage: os_hotpatch" echo "usage: os_hotpatch"
echo "-w|--check <filepath> : check hotpatch" echo "-w|--check <filepath> : check hotpatch"
echo "-l|--load <filepath> : load hotpatch" echo "-l|--load <filepath> : load hotpatch"
echo "-a|--active <patchname> : active hotpatch" echo "-a|--active <patchname> : active hotpatch"
echo "-r|--rollback <patchname> : rollback/deactive hotpatch" echo "-r|--rollback <patchname> : rollback/deactive hotpatch"
echo "-d|--delete <patchname> : delete/unload hotpatch" echo "-d|--delete <patchname> : delete/unload hotpatch"
echo "-q|--query <patchname>/all : query hotpatch" echo "-q|--query <patchname>/all : query hotpatch"
echo "-h|--help : show this help information" echo "-h|--help : show this help information"
} }
######################################################### #########################################################
@ -39,20 +43,20 @@ OS_HP_HELP()
######################################################### #########################################################
OS_HP_CHECK() OS_HP_CHECK()
{ {
path=$1 path=$1
if [ ! -f "$path" ]; then if [ ! -f "$path" ]; then
echo "The file $path is not exit" echo "The file $path is not exit"
exit 1; exit 1;
fi fi
EXTRACT_HP $path EXTRACT_HP $path
if [ $? -ne 0 -o ! -f "$G_PATCH_FILE" ];then if [ $? -ne 0 -o ! -f "$G_PATCH_FILE" ];then
echo "The file $path is invalid" echo "The file $path is invalid"
CLEAN_UP
exit 1;
fi
CLEAN_UP CLEAN_UP
exit 1; echo "The file $path is valid"
fi exit 0
CLEAN_UP
echo "The file $path is valid"
exit 0
} }
######################################################### #########################################################
@ -63,30 +67,30 @@ OS_HP_CHECK()
######################################################### #########################################################
OS_HP_ACTIVE() OS_HP_ACTIVE()
{ {
file=$1 file=$1
patch_name=`echo ${file%.tar.gz}|tr '-' '_'` patch_name=`echo ${file%.tar.gz}|tr '-' '_'`
patch_install=`lsmod | grep -w $patch_name` patch_install=`lsmod | grep -w $patch_name`
if [ "$patch_install" == "" ]; then if [ "$patch_install" == "" ]; then
echo "patch $file not load" echo "patch $file not load"
exit 1 exit 1
fi fi
is_active=`cat ${SYS_LIVEPATCH}/${patch_name}/enabled` is_active=`cat ${SYS_LIVEPATCH}/${patch_name}/enabled`
if [ ${is_active} == 1 ]; then if [ ${is_active} == 1 ]; then
echo "patch already active" echo "patch already active"
exit 0 exit 0
fi fi
echo 1 > ${SYS_LIVEPATCH}/${patch_name}/enabled echo 1 > ${SYS_LIVEPATCH}/${patch_name}/enabled
is_active=`cat ${SYS_LIVEPATCH}/${patch_name}/enabled` is_active=`cat ${SYS_LIVEPATCH}/${patch_name}/enabled`
if [ ${is_active} == 1 ]; then if [ ${is_active} == 1 ]; then
echo "active patch $file success" echo "active patch $file success"
exit 0 exit 0
else else
echo "active patch $file fail" echo "active patch $file fail"
exit 1 exit 1
fi fi
} }
######################################################### #########################################################
@ -97,30 +101,30 @@ OS_HP_ACTIVE()
######################################################### #########################################################
OS_HP_DEACTIVE() OS_HP_DEACTIVE()
{ {
file=$1 file=$1
patch_name=`echo ${file%.tar.gz}|tr '-' '_'` patch_name=`echo ${file%.tar.gz}|tr '-' '_'`
patch_install=`lsmod | grep -w $patch_name` patch_install=`lsmod | grep -w $patch_name`
if [ "$patch_install" == "" ]; then if [ "$patch_install" == "" ]; then
echo "patch $file not load" echo "patch $file not load"
exit 1 exit 1
fi fi
is_active=`cat ${SYS_LIVEPATCH}/${patch_name}/enabled` is_active=`cat ${SYS_LIVEPATCH}/${patch_name}/enabled`
if [ ${is_active} == 0 ]; then if [ ${is_active} == 0 ]; then
echo "patch $file already deactive" echo "patch $file already deactive"
exit 0 exit 0
else
echo 0 > ${SYS_LIVEPATCH}/${patch_name}/enabled
is_active=`cat ${SYS_LIVEPATCH}/${patch_name}/enabled`
if [ ${is_active} != 1 ]; then
echo "deactive patch $file success"
exit 0
else else
echo "deactive patch $file fail" echo 0 > ${SYS_LIVEPATCH}/${patch_name}/enabled
exit 1 is_active=`cat ${SYS_LIVEPATCH}/${patch_name}/enabled`
fi if [ ${is_active} != 1 ]; then
fi echo "deactive patch $file success"
exit 0
else
echo "deactive patch $file fail"
exit 1
fi
fi
} }
######################################################### #########################################################
@ -131,31 +135,31 @@ OS_HP_DEACTIVE()
######################################################### #########################################################
OS_HP_REMOVE() OS_HP_REMOVE()
{ {
file=$1 file=$1
patch_name=`echo ${file%.tar.gz}|tr '-' '_'` patch_name=`echo ${file%.tar.gz}|tr '-' '_'`
patch_install=`lsmod | grep -w $patch_name` patch_install=`lsmod | grep -w $patch_name`
if [ "$patch_install" == "" ]; then if [ "$patch_install" == "" ]; then
echo "patch $file not load" echo "patch $file not load"
exit 1 exit 1
fi fi
is_active=`cat ${SYS_LIVEPATCH}/${patch_name}/enabled`
if [ ${is_active} == 0 ]; then
rmmod ${patch_name}
else
echo 0 > ${SYS_LIVEPATCH}/${patch_name}/enabled
rmmod ${patch_name}
fi
patch_install=`lsmod | grep -w $patch_name` is_active=`cat ${SYS_LIVEPATCH}/${patch_name}/enabled`
if [ "$patch_install" == "" ]; then if [ ${is_active} == 0 ]; then
echo "remove patch $file success" rmmod ${patch_name}
exit 0 else
else echo 0 > ${SYS_LIVEPATCH}/${patch_name}/enabled
echo "remove patch $file failed" rmmod ${patch_name}
exit 1 fi
fi
patch_install=`lsmod | grep -w $patch_name`
if [ "$patch_install" == "" ]; then
echo "remove patch $file success"
exit 0
else
echo "remove patch $file failed"
exit 1
fi
} }
######################################################### #########################################################
@ -166,61 +170,61 @@ OS_HP_REMOVE()
######################################################### #########################################################
OS_HP_INQUIRY() OS_HP_INQUIRY()
{ {
file=$1 file=$1
lret=0 lret=0
if [ "all" == $file ];then if [ "all" == $file ];then
cd ${SYS_LIVEPATCH} cd ${SYS_LIVEPATCH}
if [ -z "`ls -d */ 2>/dev/null`" ];then if [ -z "`ls -d */ 2>/dev/null`" ];then
exit 0
fi
for patch in `ls -d */ 2>/dev/null`
do
patch_id=${patch%/}
patch_id=${patch_id#klp_}
echo "Patch Name: ${patch_id}"
lstate=`cat /${SYS_LIVEPATCH}/${patch}/enabled 2>/dev/null`
if [ -z "$lstate" ];then
echo "Patch State: Removing"
echo "-----------------------------------------------------------"
continue
fi
if [ $lstate -eq 1 ];then
echo "Patch State: Active"
else
echo "Patch State: Deactive"
fi
cd ${SYS_LIVEPATCH}/${patch} 2>/dev/null
depends=`ls -d */ 2>/dev/null`
echo "Changes:"
ls -l ${SYS_LIVEPATCH}/${patch}/*/ 2>/dev/null|grep '^d'|awk -F ' ' '{print "\t"$9}'
echo "Denpendency: ${depends%/}"
echo "-----------------------------------------------------------"
done
exit 0 exit 0
fi fi
for patch in `ls -d */ 2>/dev/null` patch=`echo ${file%.tar.gz}|tr '-' '_'`
do patch_install=`lsmod | grep -w $patch`
patch_id=${patch%/} if [ "$patch_install" == "" ]; then
patch_id=${patch_id#klp_} exit 1
echo "Patch Name: ${patch_id}" fi
lstate=`cat /${SYS_LIVEPATCH}/${patch}/enabled 2>/dev/null` patch_id=${patch%/}
if [ -z "$lstate" ];then patch_id=${patch_id#klp_}
echo "Patch State: Removing" echo "Patch Name: ${patch_id}"
echo "-----------------------------------------------------------" if [ `cat /${SYS_LIVEPATCH}/${patch}/enabled` -eq 1 ];then
continue echo "Patch State: Active"
fi lret=3
if [ $lstate -eq 1 ];then else
echo "Patch State: Active" echo "Patch State: Deactive"
else lret=2
echo "Patch State: Deactive" fi
fi cd ${SYS_LIVEPATCH}/${patch}
cd ${SYS_LIVEPATCH}/${patch} 2>/dev/null depends=`ls -d */ 2>/dev/null`
depends=`ls -d */ 2>/dev/null` echo "Changes:"
echo "Changes:" ls -l ${SYS_LIVEPATCH}/${patch}/*/ 2>/dev/null|grep '^d'|awk -F ' ' '{print "\t"$9}'
ls -l ${SYS_LIVEPATCH}/${patch}/*/ 2>/dev/null|grep '^d'|awk -F ' ' '{print "\t"$9}' echo "Denpendency: ${depends%/}"
echo "Denpendency: ${depends%/}" echo "-----------------------------------------------------------"
echo "-----------------------------------------------------------"
done
exit 0
fi
patch=`echo ${file%.tar.gz}|tr '-' '_'`
patch_install=`lsmod | grep -w $patch`
if [ "$patch_install" == "" ]; then
exit 1
fi
patch_id=${patch%/}
patch_id=${patch_id#klp_}
echo "Patch Name: ${patch_id}"
if [ `cat /${SYS_LIVEPATCH}/${patch}/enabled` -eq 1 ];then
echo "Patch State: Active"
lret=3
else
echo "Patch State: Deactive"
lret=2
fi
cd ${SYS_LIVEPATCH}/${patch}
depends=`ls -d */ 2>/dev/null`
echo "Changes:"
ls -l ${SYS_LIVEPATCH}/${patch}/*/ 2>/dev/null|grep '^d'|awk -F ' ' '{print "\t"$9}'
echo "Denpendency: ${depends%/}"
echo "-----------------------------------------------------------"
exit $lret exit $lret
} }
######################################################### #########################################################
# Description: extract hotpatch tar to tmp dir # Description: extract hotpatch tar to tmp dir
@ -230,11 +234,12 @@ OS_HP_INQUIRY()
######################################################### #########################################################
EXTRACT_HP() EXTRACT_HP()
{ {
mkdir $G_TMP_DIR rm -rf $G_TMP_DIR
mkdir -p $G_TMP_DIR
tar xzf $1 -C $G_TMP_DIR tar xzf $1 -C $G_TMP_DIR
l_ret=$? l_ret=$?
if [ $l_ret -eq 0 ];then if [ $l_ret -eq 0 ];then
#find the hotpatch module #find the hotpatch module
G_PATCH_FILE=$(find $G_TMP_DIR|grep -w "klp.*\.ko") G_PATCH_FILE=$(find $G_TMP_DIR|grep -w "klp.*\.ko")
return 0 return 0
else else
@ -248,7 +253,7 @@ EXTRACT_HP()
######################################################### #########################################################
CLEAN_UP() CLEAN_UP()
{ {
rm -rf $G_TMP_DIR rm -rf $G_TMP_DIR
} }
######################################################### #########################################################
# Description: install a hotpatch # Description: install a hotpatch
@ -258,80 +263,80 @@ CLEAN_UP()
######################################################### #########################################################
OS_HP_INSTALL() OS_HP_INSTALL()
{ {
path=$1 path=$1
if [ ! -f "$path" ]; then if [ ! -f "$path" ]; then
echo "The file $path is not exit" echo "The file $path is not exit"
exit 1; exit 1;
fi fi
EXTRACT_HP $path EXTRACT_HP $path
if [ $? -ne 0 -o ! -f "$G_PATCH_FILE" ];then if [ $? -ne 0 -o ! -f "$G_PATCH_FILE" ];then
echo "The file $path is invalid!" echo "The file $path is invalid!"
CLEAN_UP
exit 1;
fi
patch_name=`echo ${G_PATCH_FILE%.ko}|tr '-' '_'`
patch_name=${patch_name##*/}
patch_install=`lsmod | grep -w $patch_name`
if [ "$patch_install" == "" ]; then
echo "insmod $G_PATCH_FILE"
insmod $G_PATCH_FILE
L_RET=$?
if [ 0 -ne ${L_RET} ]; then
echo "install patch $path fail"
CLEAN_UP
return 1
else
echo "install patch $path success"
fi
else
echo "patch $path already install"
fi
CLEAN_UP CLEAN_UP
exit 1; return 0
fi
patch_name=`echo ${G_PATCH_FILE%.ko}|tr '-' '_'`
patch_name=${patch_name##*/}
patch_install=`lsmod | grep -w $patch_name`
if [ "$patch_install" == "" ]; then
echo "insmod $G_PATCH_FILE"
insmod $G_PATCH_FILE
L_RET=$?
if [ 0 -ne ${L_RET} ]; then
echo "install patch $path fail"
CLEAN_UP
return 1
else
echo "install patch $path success"
fi
else
echo "patch $path already install"
fi
CLEAN_UP
return 0
} }
#----------------------------main-------------------------# #----------------------------main-------------------------#
if [ ! -d ${SYS_LIVEPATCH} ];then if [ ! -d ${SYS_LIVEPATCH} ];then
echo "this OS does not support kernel livepatch" echo "this OS does not support kernel livepatch"
exit 1 exit 1
fi fi
input_args=`getopt -a -o l:a:r:d:w:q: -l load:,active:,delete:,check:,rollback:,query:,help, -- "$@" 2>&1` input_args=`getopt -a -o l:a:r:d:w:q: -l load:,active:,delete:,check:,rollback:,query:,help, -- "$@" 2>&1`
eval set -- "${input_args}" eval set -- "${input_args}"
while true; while true;
do do
case "$1" in case "$1" in
-w|--check) -w|--check)
OS_HP_CHECK "$2" OS_HP_CHECK "$2"
exit $? exit $?
;; ;;
-l|--load) -l|--load)
OS_HP_INSTALL "$2" OS_HP_INSTALL "$2"
exit $? exit $?
;; ;;
-a|--active) -a|--active)
OS_HP_ACTIVE "$2" OS_HP_ACTIVE "$2"
exit $? exit $?
;; ;;
-r|--rollback) -r|--rollback)
OS_HP_DEACTIVE "$2" OS_HP_DEACTIVE "$2"
exit $? exit $?
;; ;;
-d|--delete) -d|--delete)
OS_HP_REMOVE "$2" OS_HP_REMOVE "$2"
exit $? exit $?
;; ;;
-q|--query) -q|--query)
OS_HP_INQUIRY "$2" OS_HP_INQUIRY "$2"
exit $? exit $?
;; ;;
-h|--help) -h|--help)
OS_HP_HELP OS_HP_HELP
exit 0 exit 0
;; ;;
*) *)
OS_HP_HELP OS_HP_HELP
exit 1 exit 1
;; ;;
esac esac
done done