mirror of https://github.com/dynup/kpatch
Revert "create-diff-object: add jump label support"
This reverts commit 87c64519fc
.
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 <jpoimboe@redhat.com>
This commit is contained in:
parent
b4e6085b6d
commit
09ee03f3df
|
@ -1771,21 +1771,6 @@ static int ex_table_group_size(struct kpatch_elf *kelf, int offset)
|
||||||
return size;
|
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__
|
#ifdef __x86_64__
|
||||||
static int parainstructions_group_size(struct kpatch_elf *kelf, int offset)
|
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 */
|
.name = "__ex_table", /* must come after .fixup */
|
||||||
.group_size = ex_table_group_size,
|
.group_size = ex_table_group_size,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
.name = "__jump_table",
|
|
||||||
.group_size = jump_table_group_size,
|
|
||||||
},
|
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
{
|
{
|
||||||
.name = ".smp_locks",
|
.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
|
* The following special sections aren't supported, so make sure we
|
||||||
* don't ever try to include them. Otherwise the kernel will see the
|
* don't ever try to include them. Otherwise the kernel will see the
|
||||||
* jump table during module loading and get confused. Generally it
|
* jump table during module loading and get confused. Generally it
|
||||||
* should be safe to exclude them, it just means that tracepoints won't
|
* should be safe to exclude them, it just means that you can't modify
|
||||||
* work in a patched function.
|
* jump labels and enable tracepoints in a patched function.
|
||||||
*/
|
*/
|
||||||
list_for_each_entry(sec, &kelf->sections, list) {
|
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_ptrs") &&
|
||||||
strcmp(sec->name, "__tracepoints_strings"))
|
strcmp(sec->name, "__tracepoints_strings"))
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -227,40 +227,33 @@ gcc_version_check() {
|
||||||
}
|
}
|
||||||
|
|
||||||
find_special_section_data_ppc64le() {
|
find_special_section_data_ppc64le() {
|
||||||
|
|
||||||
[[ "$CONFIG_JUMP_LABEL" -eq 0 ]] && AWK_OPTIONS="-vskip_j=1"
|
|
||||||
|
|
||||||
SPECIAL_VARS="$(readelf -wi "$VMLINUX" |
|
SPECIAL_VARS="$(readelf -wi "$VMLINUX" |
|
||||||
gawk --non-decimal-data '
|
gawk --non-decimal-data '
|
||||||
BEGIN { f = b = e = j = 0 }
|
BEGIN { f = b = e = 0 }
|
||||||
|
|
||||||
# Set state if name matches
|
# Set state if name matches
|
||||||
f == 0 && /DW_AT_name.* fixup_entry[[:space:]]*$/ {f = 1; next}
|
f == 0 && /DW_AT_name.* fixup_entry[[:space:]]*$/ {f = 1; next}
|
||||||
b == 0 && /DW_AT_name.* bug_entry[[:space:]]*$/ {b = 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}
|
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
|
# Reset state unless this abbrev describes the struct size
|
||||||
f == 1 && !/DW_AT_byte_size/ { f = 0; next }
|
f == 1 && !/DW_AT_byte_size/ { f = 0; next }
|
||||||
b == 1 && !/DW_AT_byte_size/ { b = 0; next }
|
b == 1 && !/DW_AT_byte_size/ { b = 0; next }
|
||||||
e == 1 && !/DW_AT_byte_size/ { e = 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
|
# Now that we know the size, stop parsing for it
|
||||||
f == 1 {printf("export FIXUP_STRUCT_SIZE=%d\n", $4); f = 2}
|
f == 1 {printf("export FIXUP_STRUCT_SIZE=%d\n", $4); f = 2}
|
||||||
b == 1 {printf("export BUG_STRUCT_SIZE=%d\n", $4); b = 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}
|
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
|
# 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"
|
[[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS"
|
||||||
|
|
||||||
[[ -z "$FIXUP_STRUCT_SIZE" ]] && die "can't find special struct fixup_entry size"
|
[[ -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 "$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 "$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
|
return
|
||||||
}
|
}
|
||||||
|
@ -273,13 +266,12 @@ find_special_section_data() {
|
||||||
|
|
||||||
[[ "$CONFIG_PARAVIRT" -eq 0 ]] && AWK_OPTIONS="-vskip_p=1"
|
[[ "$CONFIG_PARAVIRT" -eq 0 ]] && AWK_OPTIONS="-vskip_p=1"
|
||||||
[[ "$CONFIG_UNWINDER_ORC" -eq 0 ]] && AWK_OPTIONS="$AWK_OPTIONS -vskip_o=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
|
# If $AWK_OPTIONS are blank gawk would treat "" as a blank script
|
||||||
# shellcheck disable=SC2086
|
# shellcheck disable=SC2086
|
||||||
SPECIAL_VARS="$(readelf -wi "$VMLINUX" |
|
SPECIAL_VARS="$(readelf -wi "$VMLINUX" |
|
||||||
gawk --non-decimal-data $AWK_OPTIONS '
|
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
|
# Set state if name matches
|
||||||
a == 0 && /DW_AT_name.* alt_instr[[:space:]]*$/ {a = 1; next}
|
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}
|
p == 0 && /DW_AT_name.* paravirt_patch_site[[:space:]]*$/ {p = 1; next}
|
||||||
e == 0 && /DW_AT_name.* exception_table_entry[[:space:]]*$/ {e = 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}
|
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
|
# Reset state unless this abbrev describes the struct size
|
||||||
a == 1 && !/DW_AT_byte_size/ { a = 0; next }
|
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 }
|
p == 1 && !/DW_AT_byte_size/ { p = 0; next }
|
||||||
e == 1 && !/DW_AT_byte_size/ { e = 0; next }
|
e == 1 && !/DW_AT_byte_size/ { e = 0; next }
|
||||||
o == 1 && !/DW_AT_byte_size/ { o = 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
|
# Now that we know the size, stop parsing for it
|
||||||
a == 1 {printf("export ALT_STRUCT_SIZE=%d\n", $4); a = 2}
|
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}
|
p == 1 {printf("export PARA_STRUCT_SIZE=%d\n", $4); p = 2}
|
||||||
e == 1 {printf("export EX_STRUCT_SIZE=%d\n", $4); e = 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}
|
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
|
# 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"
|
[[ -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 "$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 "$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 "$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
|
return
|
||||||
}
|
}
|
||||||
|
@ -726,11 +714,6 @@ if grep -q "CONFIG_UNWINDER_ORC=y" "$CONFIGFILE"; then
|
||||||
else
|
else
|
||||||
CONFIG_UNWINDER_ORC=0
|
CONFIG_UNWINDER_ORC=0
|
||||||
fi
|
fi
|
||||||
if grep -q "CONFIG_JUMP_LABEL=y" "$CONFIGFILE"; then
|
|
||||||
CONFIG_JUMP_LABEL=1
|
|
||||||
else
|
|
||||||
CONFIG_JUMP_LABEL=0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# unsupported kernel option checking
|
# unsupported kernel option checking
|
||||||
grep -q "CONFIG_DEBUG_INFO_SPLIT=y" "$CONFIGFILE" && die "kernel option 'CONFIG_DEBUG_INFO_SPLIT' not supported"
|
grep -q "CONFIG_DEBUG_INFO_SPLIT=y" "$CONFIGFILE" && die "kernel option 'CONFIG_DEBUG_INFO_SPLIT' not supported"
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 3f91f6940e8eb71864a90970ef88d73c30966796
|
Subproject commit 9a5663f9b52f6f99036185fa1a8e73ab6496abda
|
Loading…
Reference in New Issue