From 09ee03f3df111c6aedf53b4a15a4709a5879c116 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Tue, 19 Feb 2019 16:10:54 -0600 Subject: [PATCH] Revert "create-diff-object: add jump label support" This reverts commit 87c64519fce02424e00725ddaeff8b619d40d160. The jump label support doesn't work with upstream livepatch. Joe Lawrence found the following ordering issue: load_module apply_relocations /* Livepatch relocation sections are applied by livepatch */ if (info->sechdrs[i].sh_flags & SHF_RELA_LIVEPATCH) continue; post_relocation module_finalize jump_label_apply_nops << crash ... do_init_module do_one_initcall(mod->init) __init patch_init [kpatch-patch] klp_register_patch klp_init_patch klp_init_object klp_init_object_loaded klp_write_object_relocations So jump_label_apply_nops() is called *before* klp_write_object_relocations() has had a chance to write the klp relocations (.klp.rela.kvm_intel.__jump_table, for example). We need to resolve this upstream first. Signed-off-by: Josh Poimboeuf --- kpatch-build/create-diff-object.c | 26 ++++---------------------- kpatch-build/kpatch-build | 25 ++++--------------------- test/unit/objs | 2 +- 3 files changed, 9 insertions(+), 44 deletions(-) diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c index f0ecc3c..96936e7 100644 --- a/kpatch-build/create-diff-object.c +++ b/kpatch-build/create-diff-object.c @@ -1771,21 +1771,6 @@ static int ex_table_group_size(struct kpatch_elf *kelf, int offset) return size; } -static int jump_table_group_size(struct kpatch_elf *kelf, int offset) -{ - static int size = 0; - char *str; - - if (!size) { - str = getenv("JUMP_STRUCT_SIZE"); - if (!str) - ERROR("JUMP_STRUCT_SIZE not set"); - size = atoi(str); - } - - return size; -} - #ifdef __x86_64__ static int parainstructions_group_size(struct kpatch_elf *kelf, int offset) { @@ -1905,10 +1890,6 @@ static struct special_section special_sections[] = { .name = "__ex_table", /* must come after .fixup */ .group_size = ex_table_group_size, }, - { - .name = "__jump_table", - .group_size = jump_table_group_size, - }, #ifdef __x86_64__ { .name = ".smp_locks", @@ -2451,11 +2432,12 @@ static void kpatch_process_special_sections(struct kpatch_elf *kelf) * The following special sections aren't supported, so make sure we * don't ever try to include them. Otherwise the kernel will see the * jump table during module loading and get confused. Generally it - * should be safe to exclude them, it just means that tracepoints won't - * work in a patched function. + * should be safe to exclude them, it just means that you can't modify + * jump labels and enable tracepoints in a patched function. */ list_for_each_entry(sec, &kelf->sections, list) { - if (strcmp(sec->name, "__tracepoints") && + if (strcmp(sec->name, "__jump_table") && + strcmp(sec->name, "__tracepoints") && strcmp(sec->name, "__tracepoints_ptrs") && strcmp(sec->name, "__tracepoints_strings")) continue; diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build index 127ff57..9f9ebdc 100755 --- a/kpatch-build/kpatch-build +++ b/kpatch-build/kpatch-build @@ -227,40 +227,33 @@ gcc_version_check() { } find_special_section_data_ppc64le() { - - [[ "$CONFIG_JUMP_LABEL" -eq 0 ]] && AWK_OPTIONS="-vskip_j=1" - SPECIAL_VARS="$(readelf -wi "$VMLINUX" | gawk --non-decimal-data ' - BEGIN { f = b = e = j = 0 } + BEGIN { f = b = e = 0 } # Set state if name matches f == 0 && /DW_AT_name.* fixup_entry[[:space:]]*$/ {f = 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} # Reset state unless this abbrev describes the struct size f == 1 && !/DW_AT_byte_size/ { f = 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 } # Now that we know the size, stop parsing for it f == 1 {printf("export FIXUP_STRUCT_SIZE=%d\n", $4); f = 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} # Bail out once we have everything - f == 2 && b == 2 && e == 2 && (j == 2 || skip_j) {exit}')" + f == 2 && b == 2 && e == 2 {exit}')" [[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS" [[ -z "$FIXUP_STRUCT_SIZE" ]] && die "can't find special struct fixup_entry 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 } @@ -273,13 +266,12 @@ find_special_section_data() { [[ "$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" # 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 = p = e = o = j = 0 } + BEGIN { a = b = p = e = o = 0 } # Set state if name matches a == 0 && /DW_AT_name.* alt_instr[[:space:]]*$/ {a = 1; next} @@ -287,7 +279,6 @@ 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} - j == 0 && /DW_AT_name.* jump_entry[[:space:]]*$/ {j = 1; next} # Reset state unless this abbrev describes the struct size a == 1 && !/DW_AT_byte_size/ { a = 0; next } @@ -295,7 +286,6 @@ 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 } - j == 1 && !/DW_AT_byte_size/ { j = 0; next } # Now that we know the size, stop parsing for it a == 1 {printf("export ALT_STRUCT_SIZE=%d\n", $4); a = 2} @@ -303,10 +293,9 @@ 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} - j == 1 {printf("export JUMP_STRUCT_SIZE=%d\n", $4); j = 2} # Bail out once we have everything - a == 2 && b == 2 && (p == 2 || skip_p) && e == 2 && (o == 2 || skip_o) && (j == 2 || skip_j) {exit}')" + a == 2 && b == 2 && (p == 2 || skip_p) && e == 2 && (o == 2 || skip_o) {exit}')" [[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS" @@ -315,7 +304,6 @@ find_special_section_data() { [[ -z "$EX_STRUCT_SIZE" ]] && die "can't find special struct paravirt_patch_site 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" - [[ -z "$JUMP_STRUCT_SIZE" && "$CONFIG_JUMP_LABEL" -ne 0 ]] && die "can't find special struct jump_entry size" return } @@ -726,11 +714,6 @@ if grep -q "CONFIG_UNWINDER_ORC=y" "$CONFIGFILE"; then else CONFIG_UNWINDER_ORC=0 fi -if grep -q "CONFIG_JUMP_LABEL=y" "$CONFIGFILE"; then - CONFIG_JUMP_LABEL=1 -else - CONFIG_JUMP_LABEL=0 -fi # unsupported kernel option checking grep -q "CONFIG_DEBUG_INFO_SPLIT=y" "$CONFIGFILE" && die "kernel option 'CONFIG_DEBUG_INFO_SPLIT' not supported" diff --git a/test/unit/objs b/test/unit/objs index 3f91f69..9a5663f 160000 --- a/test/unit/objs +++ b/test/unit/objs @@ -1 +1 @@ -Subproject commit 3f91f6940e8eb71864a90970ef88d73c30966796 +Subproject commit 9a5663f9b52f6f99036185fa1a8e73ab6496abda