diff --git a/SOURCES/1183.patch b/SOURCES/1183.patch new file mode 100644 index 0000000..2963d62 --- /dev/null +++ b/SOURCES/1183.patch @@ -0,0 +1,251 @@ +From 17dcebf077d694d594ad073828687c2ef7b4c08e Mon Sep 17 00:00:00 2001 +From: Song Liu +Date: Fri, 14 May 2021 17:32:41 -0700 +Subject: [PATCH 1/4] kpatch-build: enable klp with replace option by default + +Since 5.1 kernel, klp_patch supports a "replace" option, which does atomic +replace of cumulative patches. Enable building such patch by default. If +replace behavior is not desired, the user can use -R|--non-replace option +to disable it. + +Signed-off-by: Song Liu +--- + kmod/patch/livepatch-patch-hook.c | 15 +++++++++++++++ + kpatch-build/kpatch-build | 25 ++++++++++++++++++++++++- + 2 files changed, 39 insertions(+), 1 deletion(-) + +diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c +index e12fd505..120c637a 100644 +--- a/kmod/patch/livepatch-patch-hook.c ++++ b/kmod/patch/livepatch-patch-hook.c +@@ -74,6 +74,18 @@ + # define HAVE_SIMPLE_ENABLE + #endif + ++#ifdef RHEL_RELEASE_CODE ++# if RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(8, 2) ++# define HAVE_KLP_REPLACE ++# endif ++#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 1, 0) ++# define HAVE_KLP_REPLACE ++#endif ++ ++#ifndef KLP_REPLACE_ENABLE ++#define KLP_REPLACE_ENABLE true ++#endif ++ + /* + * There are quite a few similar structures at play in this file: + * - livepatch.h structs prefixed with klp_* +@@ -385,6 +397,9 @@ static int __init patch_init(void) + goto out; + lpatch->mod = THIS_MODULE; + lpatch->objs = lobjects; ++#ifdef HAVE_KLP_REPLACE ++ lpatch->replace = KLP_REPLACE_ENABLE; ++#endif + #if defined(__powerpc64__) && defined(HAVE_IMMEDIATE) + lpatch->immediate = true; + #endif +diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build +index 617f8578..e40f79b2 100755 +--- a/kpatch-build/kpatch-build ++++ b/kpatch-build/kpatch-build +@@ -55,6 +55,7 @@ DEBUG_KCFLAGS="" + declare -a PATCH_LIST + APPLIED_PATCHES=0 + OOT_MODULE= ++KLP_REPLACE=1 + + warn() { + echo "ERROR: $1" >&2 +@@ -218,6 +219,15 @@ use_klp_arch() + fi + } + ++support_klp_replace() ++{ ++ if kernel_is_rhel; then ++ rhel_kernel_version_gte 4.18.0-193.el8 ++ else ++ kernel_version_gte 5.1.0 ++ fi ++} ++ + find_dirs() { + if [[ -e "$SCRIPTDIR/create-diff-object" ]]; then + # git repo +@@ -514,12 +524,13 @@ usage() { + echo " (can be specified multiple times)" >&2 + echo " -e, --oot-module Enable patching out-of-tree module," >&2 + echo " specify current version of module" >&2 ++ echo " -R, --non-replace Disable replace patch (replace is on by default)" >&2 + echo " --skip-cleanup Skip post-build cleanup" >&2 + echo " --skip-compiler-check Skip compiler version matching check" >&2 + echo " (not recommended)" >&2 + } + +-options="$(getopt -o ha:r:s:c:v:j:t:n:o:de: -l "help,archversion:,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,oot-module:,debug,skip-gcc-check,skip-compiler-check,skip-cleanup" -- "$@")" || die "getopt failed" ++options="$(getopt -o ha:r:s:c:v:j:t:n:o:de:R -l "help,archversion:,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,oot-module:,debug,skip-gcc-check,skip-compiler-check,skip-cleanup,non-replace" -- "$@")" || die "getopt failed" + + eval set -- "$options" + +@@ -582,6 +593,9 @@ while [[ $# -gt 0 ]]; do + OOT_MODULE="$(readlink -f "$2")" + shift + ;; ++ -R|--non-replace) ++ KLP_REPLACE=0 ++ ;; + --skip-cleanup) + echo "Skipping cleanup" + SKIPCLEANUP=1 +@@ -821,6 +835,12 @@ if grep -q "CONFIG_LIVEPATCH=y" "$CONFIGFILE" && (kernel_is_rhel || kernel_versi + KPATCH_LDFLAGS="--unique=.parainstructions --unique=.altinstructions" + CDO_FLAGS="--klp-arch" + fi ++ ++ if [[ "$KLP_REPLACE" -eq 1 ]] ; then ++ support_klp_replace || die "The kernel doesn't support klp replace" ++ else ++ export KBUILD_CFLAGS_MODULE="$KBUILD_CFLAGS_MODULE -DKLP_REPLACE_ENABLE=false" ++ fi + else + # No support for livepatch in the kernel. Kpatch core module is needed. + +@@ -828,6 +848,9 @@ else + # sections. Use with caution! + echo "WARNING: Use of kpatch core module (kpatch.ko) is deprecated! There may be bugs!" >&2 + ++ if [[ "$KLP_REPLACE" -eq 1 ]] ; then ++ die "kpatch core module (kpatch.ko) does not support replace, please add -R|--non-replace" ++ fi + find_core_symvers || die "unable to find Module.symvers for kpatch core module" + KBUILD_EXTRA_SYMBOLS="$SYMVERSFILE" + fi + +From 69e69d59e83a98ca3272c5028fa89f7e9196770d Mon Sep 17 00:00:00 2001 +From: Song Liu +Date: Wed, 19 May 2021 15:18:27 -0700 +Subject: [PATCH 2/4] doc: kpatch-build uses "replace" flag by default + +Add documentation about kpatch-build enables livepatch "replace" flag by +default, and provides -R|--non-replace option to disable the flag. + +Signed-off-by: Song Liu +--- + doc/patch-author-guide.md | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/doc/patch-author-guide.md b/doc/patch-author-guide.md +index 33c1b277..f3dcf736 100644 +--- a/doc/patch-author-guide.md ++++ b/doc/patch-author-guide.md +@@ -39,6 +39,13 @@ recommended that when patching a system which has already been patched, the + second patch should be a cumulative upgrade which is a superset of the first + patch. + ++Since upstream kernel 5.1, livepatch supports a "replace" flag to help the ++management of cumulative patches. With the flag set, the kernel will load ++the cumulative patch and unload all existing patches in one transition. ++kpatch-build enables the replace flag by default. If replace behavior is ++not desired, the user can disable it with -R|--non-replace. ++ ++ + Data structure changes + ---------------------- + + +From 8487a0ca0a5201ca53b33b3a2de5b65320b947c9 Mon Sep 17 00:00:00 2001 +From: Song Liu +Date: Tue, 25 May 2021 15:20:59 -0700 +Subject: [PATCH 3/4] manpages: update kpatch-build with -R | --non-replace + option + +Signed-off-by: Song Liu +--- + man/kpatch-build.1 | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/man/kpatch-build.1 b/man/kpatch-build.1 +index dfd61acf..4483a4a3 100644 +--- a/man/kpatch-build.1 ++++ b/man/kpatch-build.1 +@@ -51,6 +51,10 @@ effect. + Enable patching out-of-tree module, + specify current version of module + ++-R|--non-replace ++ Disable replace flag of KLP ++ (replace is on by default) ++ + --skip-cleanup + Skip post-build cleanup + + +From 4b68be868f40244ff9850bf35f8d273afa12cf12 Mon Sep 17 00:00:00 2001 +From: Song Liu +Date: Mon, 24 May 2021 17:34:24 -0700 +Subject: [PATCH 4/4] kpatch-test: disable replace flag when the kernel doesn't + support it + +For redhat kernel < 4.18.0-193.el8 or non-redhat kernel version < 5.1, +add -R to $KPATCHBUILD_OPTS. + +Signed-off-by: Song Liu +--- + test/integration/kpatch-test | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/test/integration/kpatch-test b/test/integration/kpatch-test +index 4359b463..ca5e7835 100755 +--- a/test/integration/kpatch-test ++++ b/test/integration/kpatch-test +@@ -50,6 +50,7 @@ ERROR=0 + LOG=test.log + DYNDEBUG_CONTROL=/sys/kernel/debug/dynamic_debug/control + DYNDEBUG_ENABLED=1 ++ARCHVERSION="$(uname -r)" + rm -f ./*.log + + PATCHDIR="${PATCHDIR:-$PWD}" +@@ -308,6 +309,27 @@ new_dmesg() { + fi + } + ++kernel_version_gte() { ++ [ "${ARCHVERSION//-*/}" = "$(echo -e "${ARCHVERSION//-*}\\n$1" | sort -rV | head -n1)" ] ++} ++ ++support_klp_replace() ++{ ++ if kernel_is_rhel; then ++ rhel_kernel_version_gte 4.18.0-193.el8 ++ else ++ kernel_version_gte 5.1.0 ++ fi ++} ++ ++kernel_is_rhel() { ++ [[ "$ARCHVERSION" =~ \.el[789] ]] ++} ++ ++rhel_kernel_version_gte() { ++ [ "${ARCHVERSION}" = "$(echo -e "${ARCHVERSION}\\n$1" | sort -rV | head -n1)" ] ++} ++ + # shellcheck disable=SC1091 + source /etc/os-release + if [[ "${ID}" == "rhel" && "${VERSION_ID%%.*}" == "7" && "${VERSION_ID##*.}" -le "6" ]]; then +@@ -315,6 +337,11 @@ if [[ "${ID}" == "rhel" && "${VERSION_ID%%.*}" == "7" && "${VERSION_ID##*.}" -le + echo "Dynamic debug is not supported on '${PRETTY_NAME}', disabling." + fi + ++if ! support_klp_replace ; then ++ KPATCHBUILD_OPTS="$KPATCHBUILD_OPTS -R" ++ echo "KLP replace is not supported on '${PRETTY_NAME}', disabling." ++fi ++ + for file in "${PATCH_LIST[@]}"; do + if [[ $QUICK != 1 || "$file" =~ -FAIL ]]; then + build_module "$file" diff --git a/SPECS/kpatch.spec b/SPECS/kpatch.spec index 2063068..4f5b3be 100644 --- a/SPECS/kpatch.spec +++ b/SPECS/kpatch.spec @@ -2,7 +2,7 @@ Name: kpatch Version: 0.9.3 -Release: 1.1%{?dist} +Release: 1.2%{?dist} Summary: Dynamic kernel patch manager Group: System Environment/Kernel @@ -16,7 +16,10 @@ Patch0: 0001-contrib-disable-upstart-kpatch.conf-install.patch Patch1: 0002-kpatch-clarify-unload-unsupport.patch # Hyperscale only -Patch100: ignore-printk_index.patch +Patch50: ignore-printk_index.patch + +# Upstream backports +Patch100: https://github.com/dynup/kpatch/pull/1183.patch # kpatch-dnf backports Patch200: 0200-Makefile-set-install-permission-modes.patch @@ -61,6 +64,7 @@ kpatch-build is a tool to build patches for kpatch. %setup -q %patch0 -p1 %patch1 -p1 +%patch50 -p1 %patch100 -p1 %setup -D -T -a 1 @@ -102,6 +106,9 @@ echo -e "\t$ dnf kpatch auto" %{_mandir}/man1/kpatch-build.1* %changelog +* Wed May 26 2021 Davide Cavalca - 0.9.3-1.2 +- Backport PR#1183 to add support for atomic replace of cumulative patches + * Wed May 5 2021 Davide Cavalca - 0.9.3-1.1 - Update to 0.9.3 and drop upstreamed patches - Downgrade kpatch-dnf dependency to a Suggests