backport upstream patches

Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
This commit is contained in:
Zhipeng Xie 2023-09-28 10:53:48 +08:00
parent 3cde64d336
commit 929e063c78
6 changed files with 346 additions and 1 deletions

View File

@ -0,0 +1,49 @@
From 13182e50b027c70bd63f53ca43598557d6b41e2e Mon Sep 17 00:00:00 2001
From: Joe Lawrence <joe.lawrence@redhat.com>
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 <joe.lawrence@redhat.com>
---
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 <error.h>
+#include "gcc-common.h"
#define PLUGIN_NAME "ppc64le-plugin"
--
2.27.0

View File

@ -0,0 +1,59 @@
From 7861240f482aa41bfad41fbb57ac1990cd6b6960 Mon Sep 17 00:00:00 2001
From: Josh Poimboeuf <jpoimboe@redhat.com>
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 <jpoimboe@redhat.com>
---
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

View File

@ -0,0 +1,53 @@
From 2feeb0f462875906ee2e754bb1526511393faee2 Mon Sep 17 00:00:00 2001
From: Joe Lawrence <joe.lawrence@redhat.com>
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 <joe.lawrence@redhat.com>
---
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 <joe.lawrence@redhat.com>
+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 <joe.lawrence@redhat.com>
+---
+ 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

View File

@ -0,0 +1,33 @@
From ab2397c03e31f0f697aa8bf943d70b4e5a7def54 Mon Sep 17 00:00:00 2001
From: Josh Poimboeuf <jpoimboe@redhat.com>
Date: Mon, 21 Nov 2022 19:41:30 -0800
Subject: [PATCH] kpatch-macros: add KPATCH_STATIC_CALL()
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
---
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

View File

@ -0,0 +1,140 @@
From 41128c0987ea569dd623d2de70391c5be739d38e Mon Sep 17 00:00:00 2001
From: Josh Poimboeuf <jpoimboe@redhat.com>
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 <jpoimboe@redhat.com>
---
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

View File

@ -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 <xiezhipeng1@huawei.com> -1:0.9.7-5
- Type:enhancement
- ID:NA
- SUG:NA
- DESC:backport upsteam patches
* Tue Aug 1 2023 Bin Hu <hubin73@huawei.com> -1:0.9.7-4
- Type:enhancement
- ID:NA