From 929e063c788396d401778c1b40bb6f26af8e358e Mon Sep 17 00:00:00 2001 From: Zhipeng Xie Date: Thu, 28 Sep 2023 10:53:48 +0800 Subject: [PATCH] backport upstream patches Signed-off-by: Zhipeng Xie --- ...gcc-plugin-update-headers-for-gcc-12.patch | 49 ++++++ ...-find_kobj-short-circuit-for-OOT-mod.patch | 59 ++++++++ ...mples-add-proc-version-kpatch-sample.patch | 53 +++++++ ...kpatch-macros-add-KPATCH_STATIC_CALL.patch | 33 +++++ ...de-update-jump-label-static-call-des.patch | 140 ++++++++++++++++++ kpatch.spec | 13 +- 6 files changed, 346 insertions(+), 1 deletion(-) create mode 100644 0044-gcc-plugin-update-headers-for-gcc-12.patch create mode 100644 0045-kpatch-build-Add-find_kobj-short-circuit-for-OOT-mod.patch create mode 100644 0048-examples-add-proc-version-kpatch-sample.patch create mode 100644 0050-kpatch-macros-add-KPATCH_STATIC_CALL.patch create mode 100644 0052-patch-author-guide-update-jump-label-static-call-des.patch diff --git a/0044-gcc-plugin-update-headers-for-gcc-12.patch b/0044-gcc-plugin-update-headers-for-gcc-12.patch new file mode 100644 index 0000000..93df80b --- /dev/null +++ b/0044-gcc-plugin-update-headers-for-gcc-12.patch @@ -0,0 +1,49 @@ +From 13182e50b027c70bd63f53ca43598557d6b41e2e Mon Sep 17 00:00:00 2001 +From: Joe Lawrence +Date: Tue, 27 Sep 2022 16:41:48 -0400 +Subject: [PATCH] gcc-plugin: update headers for gcc-12 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Fix build error seen on gcc (GCC) 12.1.1 20220507 (Red Hat 12.1.1-1): + + g++ -MMD -MP -I../kmod/patch -Iinsn -Wall -Wsign-compare -Wno-sign-conversion -g -Werror -shared -I/usr/lib/gcc/ppc64le-redhat-linux/12/plugin/include -Igcc-plugins -fPIC -fno-rtti -O2 -Wall gcc-plugins/ppc64le-plugin.c -o gcc-plugins/ppc64le-plugin.so + In file included from /usr/include/features.h:490, + from /usr/include/bits/libc-header-start.h:33, + from /usr/include/stdio.h:27, + from /usr/lib/gcc/ppc64le-redhat-linux/12/plugin/include/system.h:46, + from /usr/lib/gcc/ppc64le-redhat-linux/12/plugin/include/gcc-plugin.h:28, + from gcc-plugins/gcc-common.h:6, + from gcc-plugins/ppc64le-plugin.c:1: + /usr/include/bits/error-ldbl.h:23:1: error: type of ‘error’ is unknown + 23 | __LDBL_REDIR_DECL (error) + | ^~~~~~~~~~~~~~~~~ + /usr/include/bits/error-ldbl.h:23:1: error: ‘int error’ redeclared as different kind of entity + 23 | __LDBL_REDIR_DECL (error) + | ^~~~~~~~~~~~~~~~~ + In file included from gcc-plugins/ppc64le-plugin.c:2: + /usr/include/error.h:31:13: note: previous declaration ‘void error(int, int, const char*, ...)’ + 31 | extern void error (int __status, int __errnum, const char *__format, ...) + | ^~~~~ + make[1]: *** [Makefile:39: gcc-plugins/ppc64le-plugin.so] Error 1 + +Signed-off-by: Joe Lawrence +--- + kpatch-build/gcc-plugins/ppc64le-plugin.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kpatch-build/gcc-plugins/ppc64le-plugin.c b/kpatch-build/gcc-plugins/ppc64le-plugin.c +index e3ec20f..ba4a01e 100644 +--- a/kpatch-build/gcc-plugins/ppc64le-plugin.c ++++ b/kpatch-build/gcc-plugins/ppc64le-plugin.c +@@ -1,5 +1,5 @@ +-#include "gcc-common.h" + #include ++#include "gcc-common.h" + + #define PLUGIN_NAME "ppc64le-plugin" + +-- +2.27.0 + diff --git a/0045-kpatch-build-Add-find_kobj-short-circuit-for-OOT-mod.patch b/0045-kpatch-build-Add-find_kobj-short-circuit-for-OOT-mod.patch new file mode 100644 index 0000000..b446be2 --- /dev/null +++ b/0045-kpatch-build-Add-find_kobj-short-circuit-for-OOT-mod.patch @@ -0,0 +1,59 @@ +From 7861240f482aa41bfad41fbb57ac1990cd6b6960 Mon Sep 17 00:00:00 2001 +From: Josh Poimboeuf +Date: Wed, 17 Aug 2022 12:17:19 -0700 +Subject: [PATCH] kpatch-build: Add find_kobj() short-circuit for OOT modules + +When patching an OOT module, the parent object is always the OOT module. +Hard-code that to prevent the need for any further special casing in +find_kobj() (e.g., commit 9143e88f16a1 ("kpatch-build: fix +find_parent_obj")). + +Signed-off-by: Josh Poimboeuf +--- + kpatch-build/kpatch-build | 18 ++++++++++++------ + 1 file changed, 12 insertions(+), 6 deletions(-) + +diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build +index 296fa48..5435a19 100755 +--- a/kpatch-build/kpatch-build ++++ b/kpatch-build/kpatch-build +@@ -479,6 +479,12 @@ find_parent_obj() { + + find_kobj() { + arg="$1" ++ ++ if [[ -n $OOT_MODULE ]]; then ++ KOBJFILE="$OOT_MODULE" ++ return ++ fi ++ + KOBJFILE="$arg" + DEEP_FIND=0 + ERROR_IF_DIFF= +@@ -1093,17 +1099,17 @@ for i in $FILES; do + find_kobj "$i" + cd "$TEMPDIR" || die + if [[ -e "orig/$i" ]]; then +- if [[ "$(basename "$KOBJFILE")" = vmlinux ]]; then +- KOBJFILE_NAME=vmlinux +- KOBJFILE_PATH="$VMLINUX" +- SYMTAB="${TEMPDIR}/${KOBJFILE_NAME}.symtab" +- SYMVERS_FILE="$BUILDDIR/Module.symvers" +- elif [[ "$(basename "$KOBJFILE")" = "$(basename "$OOT_MODULE")" ]]; then ++ if [[ -n $OOT_MODULE ]]; then + KOBJFILE_NAME="$(basename --suffix=.ko "$OOT_MODULE")" + KOBJFILE_NAME="${KOBJFILE_NAME//-/_}" + KOBJFILE_PATH="$OOT_MODULE" + SYMTAB="${TEMPDIR}/module/${KOBJFILE_NAME}.symtab" + SYMVERS_FILE="$TEMPDIR/Module.symvers" ++ elif [[ "$(basename "$KOBJFILE")" = vmlinux ]]; then ++ KOBJFILE_NAME=vmlinux ++ KOBJFILE_PATH="$VMLINUX" ++ SYMTAB="${TEMPDIR}/${KOBJFILE_NAME}.symtab" ++ SYMVERS_FILE="$BUILDDIR/Module.symvers" + else + KOBJFILE_NAME=$(basename "${KOBJFILE%.ko}") + KOBJFILE_NAME="${KOBJFILE_NAME//-/_}" +-- +2.27.0 + diff --git a/0048-examples-add-proc-version-kpatch-sample.patch b/0048-examples-add-proc-version-kpatch-sample.patch new file mode 100644 index 0000000..2c32647 --- /dev/null +++ b/0048-examples-add-proc-version-kpatch-sample.patch @@ -0,0 +1,53 @@ +From 2feeb0f462875906ee2e754bb1526511393faee2 Mon Sep 17 00:00:00 2001 +From: Joe Lawrence +Date: Mon, 7 Nov 2022 11:02:00 -0500 +Subject: [PATCH] examples: add /proc/version kpatch sample + +Create a simple kpatch test that should apply across a wide range of +kernels. The version_proc_show() is a good candidate as it's easy to +verify and hasn't been touched upstream since 2008. + +Signed-off-by: Joe Lawrence +--- + examples/proc-version.patch | 29 +++++++++++++++++++++++++++++ + 1 file changed, 29 insertions(+) + create mode 100644 examples/proc-version.patch + +diff --git a/examples/proc-version.patch b/examples/proc-version.patch +new file mode 100644 +index 0000000..cb43236 +--- /dev/null ++++ b/examples/proc-version.patch +@@ -0,0 +1,29 @@ ++From 64aff1ab8f9a9f5df06c998be73d4981b77e480d Mon Sep 17 00:00:00 2001 ++From: Joe Lawrence ++Date: Mon, 7 Nov 2022 08:21:58 -0500 ++Subject: [PATCH] kpatch: modify /proc/version output ++Content-type: text/plain ++ ++This is a simple kpatch example that modifies version_proc_show() so ++that the output of /proc/version will be prefixed by "kpatch ". ++ ++Signed-off-by: Joe Lawrence ++--- ++ fs/proc/version.c | 1 + ++ 1 file changed, 1 insertion(+) ++ ++diff --git a/fs/proc/version.c b/fs/proc/version.c ++index 02e3c3cd4a9a..957faeea8f5c 100644 ++--- a/fs/proc/version.c +++++ b/fs/proc/version.c ++@@ -9,6 +9,7 @@ ++ ++ static int version_proc_show(struct seq_file *m, void *v) ++ { +++ seq_printf(m, "kpatch "); ++ seq_printf(m, linux_proc_banner, ++ utsname()->sysname, ++ utsname()->release, ++-- ++2.26.3 ++ +-- +2.27.0 + diff --git a/0050-kpatch-macros-add-KPATCH_STATIC_CALL.patch b/0050-kpatch-macros-add-KPATCH_STATIC_CALL.patch new file mode 100644 index 0000000..0d1bfa4 --- /dev/null +++ b/0050-kpatch-macros-add-KPATCH_STATIC_CALL.patch @@ -0,0 +1,33 @@ +From ab2397c03e31f0f697aa8bf943d70b4e5a7def54 Mon Sep 17 00:00:00 2001 +From: Josh Poimboeuf +Date: Mon, 21 Nov 2022 19:41:30 -0800 +Subject: [PATCH] kpatch-macros: add KPATCH_STATIC_CALL() + +Signed-off-by: Josh Poimboeuf +--- + kmod/patch/kpatch-macros.h | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/kmod/patch/kpatch-macros.h b/kmod/patch/kpatch-macros.h +index 8e09702..b797838 100644 +--- a/kmod/patch/kpatch-macros.h ++++ b/kmod/patch/kpatch-macros.h +@@ -141,4 +141,15 @@ struct kpatch_post_unpatch_callback { + printk(_fmt, ## __VA_ARGS__); \ + }) + ++/* ++ * KPATCH_STATIC_CALL macro ++ * ++ * Replace usages of static_call() with this macro, when create-diff-object ++ * recommends it due to the original static call key living in a module. ++ * ++ * This converts the static call to a regular indirect call. ++ */ ++#define KPATCH_STATIC_CALL(name) \ ++ ((typeof(STATIC_CALL_TRAMP(name))*)(STATIC_CALL_KEY(name).func)) ++ + #endif /* __KPATCH_MACROS_H_ */ +-- +2.27.0 + diff --git a/0052-patch-author-guide-update-jump-label-static-call-des.patch b/0052-patch-author-guide-update-jump-label-static-call-des.patch new file mode 100644 index 0000000..9ae9a08 --- /dev/null +++ b/0052-patch-author-guide-update-jump-label-static-call-des.patch @@ -0,0 +1,140 @@ +From 41128c0987ea569dd623d2de70391c5be739d38e Mon Sep 17 00:00:00 2001 +From: Josh Poimboeuf +Date: Wed, 30 Nov 2022 18:48:34 -0800 +Subject: [PATCH] patch-author-guide: update jump label / static call + descriptions + +Now that we have KPATCH_STATIC_CALL(), document its usage. While at it, +give a more thorough description for why jump labels and static calls +aren't supported in some scenarios. + +Signed-off-by: Josh Poimboeuf +--- + doc/patch-author-guide.md | 96 +++++++++++++++++++++++++++------------ + 1 file changed, 68 insertions(+), 28 deletions(-) + +diff --git a/doc/patch-author-guide.md b/doc/patch-author-guide.md +index 0133cec..26daee3 100644 +--- a/doc/patch-author-guide.md ++++ b/doc/patch-author-guide.md +@@ -24,7 +24,7 @@ Table of contents + - [Code removal](#code-removal) + - [Once macros](#once-macros) + - [inline implies notrace](#inline-implies-notrace) +-- [Jump labels](#jump-labels) ++- [Jump labels and static calls](#jump-labels-and-static-calls) + - [Sibling calls](#sibling-calls) + - [Exported symbol versioning](#exported-symbol-versioning) + - [System calls](#system-calls) +@@ -747,41 +747,81 @@ changes to all of `__tcp_mtu_to_mss()` callers (ie, it was inlined as + requested). In this case, a simple workaround is to specify + `__tcp_mtu_to_mss()` as `__always_inline` to force the compiler to do so. + +-Jump labels +------------ ++Jump labels and static calls ++---------------------------- ++ ++### Late module patching vs special section relocations ++ ++Jump labels and static calls can be problematic due to "late module patching", ++which is a feature (design flaw?) in upstream livepatch. When a livepatch ++module patches another module, unfortunately the livepatch module doesn't have ++an official module dependency on the patched module. That means the patched ++module doesn't even have to be loaded when the livepatch module gets loaded. ++In that case the patched module gets patched on demand whenever it might get ++loaded in the future. It also gets unpatched on demand whenever it gets ++unloaded. ++ ++Loading (and patching) the module at some point after loading the livepatch ++module is called "late module patching". In order to support this ++(mis?)feature, all relocations in the livepatch module which reference module ++symbols must be converted to "klp relocations", which get resolved at patching ++time. ++ ++In all modules (livepatch and otherwise), jump labels and static calls rely on ++special sections which trigger jump-label/static-call code patching when a ++module gets loaded. But unfortunately those special sections have relocations ++which need to get resolved, so there's an ordering issue. ++ ++When a (livepatch) module gets loaded, first its relocations are resolved, then ++its special section handling (and code patching) is done. The problem is, for ++klp relocations, if they reference another module's symbols, and that module ++isn't loaded, they're not yet defined. So if a `.static_call_sites` entry ++tries to reference its corresponding `struct static_call_key`, but that key ++lives in another module which is not yet loaded, the key reference won't be ++resolved, and so `mod->static_call_sites` will be corrupted when ++`static_call_module_notify()` runs when the livepatch module first loads. ++ ++### Jump labels ++ ++With pre-5.8 kernels, kpatch-build will error out if it encounters any jump ++labels: ++``` ++oom_kill.o: Found a jump label at out_of_memory()+0x10a, using key cpusets_enabled_key. Jump labels aren't supported with this kernel. Use static_key_enabled() instead. ++``` + +-When modifying a function that contains a jump label, kpatch-build may +-return an error like: `ERROR: oom_kill.o: kpatch_regenerate_special_section: 2109: Found a jump label at out_of_memory()+0x10a, using key cpusets_enabled_key. Jump labels aren't currently supported. Use static_key_enabled() instead.` ++With Linux 5.8+, klp relocation handling is integrated with the module relocation ++code, so jump labels in patched functions are supported when the static key was ++originally defined in the kernel proper (vmlinux). + +-This is due to a limitation in the kernel to process static key +-livepatch relocations (resolved by late-module patching). Older +-versions of kpatch-build may have reported successfully building +-kpatch module, but issue +-[#931](https://github.com/dynup/kpatch/issues/931) revealed potentially +-dangerous behavior if the static key value had been modified from its +-compiled default. ++However, if the static key lives in a module, jump labels are _not_ supported ++in patched code, due to the ordering issue described above. If the jump label ++is a tracepoint, kpatch-build will silently remove the tracepoint. Otherwise, ++there will be an error: ++``` ++vmx.o: Found a jump label at vmx_hardware_enable.cold()+0x23, using key enable_evmcs, which is defined in a module. Use static_key_enabled() instead. ++``` + +-The current workaround is to remove the jump label by explictly checking +-the static key: ++When you get one of the above errors, the fix is to remove the jump label usage ++in the patched function, replacing it with a regular C conditional. + +-```c +-DEFINE_STATIC_KEY_TRUE(true_key); +-DEFINE_STATIC_KEY_FALSE(false_key); ++This can be done by replacing any usages of `static_branch_likely()`, ++`static_branch_unlikely()`, `static_key_true()`, and `static_key_false()` with ++`static_key_enabled()` in the patch file. + +-/* unsupported */ +-if (static_key_true(&true_key)) +-if (static_key_false(&false_key)) +-if (static_branch_likely(&key)) ++### Static calls + +-/* supported */ +-if (static_key_enabled(&true_key)) +-if (static_key_enabled(&false_key)) +-if (likely(static_key_enabled(&key))) ++Similarly, static calls are not supported when the corresponding static call ++key was originally defined in a module. If such a static call is part of a ++tracepoint, kpatch-build will silently remove it. Otherwise, there will be an ++error: ++``` ++cpuid.o: Found a static call at kvm_set_cpuid.cold()+0x32c, using key __SCK__kvm_x86_vcpu_after_set_cpuid, which is defined in a module. Use KPATCH_STATIC_CALL() instead. + ``` + +-Note that with Linux 5.8+, jump labels in patched functions are now supported +-when the static key was originally defined in the kernel proper (vmlinux). The +-above error will not be seen unless the static key lives in a module. ++To fix this error, simply replace such static calls with regular indirect ++branches (or retpolines, if applicable) by adding `#include "kpatch-macros.h"` ++to the patch source and replacing usages of `static_call()` with ++`KPATCH_STATIC_CALL()`. + + Sibling calls + ------------- +-- +2.27.0 + diff --git a/kpatch.spec b/kpatch.spec index 3e859dc..6a4cf68 100644 --- a/kpatch.spec +++ b/kpatch.spec @@ -1,7 +1,7 @@ Name: kpatch Epoch: 1 Version: 0.9.7 -Release: 4 +Release: 5 Summary: A Linux dynamic kernel patching infrastructure License: GPLv2 @@ -56,6 +56,11 @@ Patch0040:0040-create-diff-object-ignore-.llvm.-sections.patch Patch0041:0041-kpatch-cc-Add-more-file-ignores.patch Patch0042:0042-create-diff-object-fix-__UNIQUE_ID-variable-correlat.patch Patch0043:0043-create-diff-object-ignore-__patchable_function_entri.patch +Patch0044:0044-gcc-plugin-update-headers-for-gcc-12.patch +Patch0045:0045-kpatch-build-Add-find_kobj-short-circuit-for-OOT-mod.patch +Patch0046:0048-examples-add-proc-version-kpatch-sample.patch +Patch0047:0050-kpatch-macros-add-KPATCH_STATIC_CALL.patch +Patch0048:0052-patch-author-guide-update-jump-label-static-call-des.patch BuildRequires: gcc elfutils-libelf-devel kernel-devel git Requires: bc make gcc patch bison flex openssl-devel @@ -116,6 +121,12 @@ popd %{_mandir}/man1/*.1.gz %changelog +* Thu Sep 28 2023 Zhipeng Xie -1:0.9.7-5 +- Type:enhancement +- ID:NA +- SUG:NA +- DESC:backport upsteam patches + * Tue Aug 1 2023 Bin Hu -1:0.9.7-4 - Type:enhancement - ID:NA