From cd8e5ddc31df07e7853f1d784954dde8783126ae Mon Sep 17 00:00:00 2001 From: chenziyang Date: Sat, 16 Sep 2023 19:02:35 +0800 Subject: [PATCH 1/3] backport upstream kpatch and use patch0047 to accommondate kernel 6.4.0 fix issue:I7ZH8O --- ...etlocalversion-issue-with-6.3-kernel.patch | 110 +++++ ...-support-Linux-5.19-.cmd-file-format.patch | 400 ++++++++++++++++++ ...uild_ignore_init_version-timestamp_o.patch | 29 ++ ...ybe_discarded_sym-add-__pfx_-pattern.patch | 26 ++ README.md | 8 +- kpatch.spec | 12 +- 6 files changed, 583 insertions(+), 2 deletions(-) create mode 100644 0044-kpatch-build-Fix-setlocalversion-issue-with-6.3-kernel.patch create mode 100644 0045-kpatch-build-support-Linux-5.19-.cmd-file-format.patch create mode 100644 0046-kpatch-build_ignore_init_version-timestamp_o.patch create mode 100644 0047-lookup.c-maybe_discarded_sym-add-__pfx_-pattern.patch diff --git a/0044-kpatch-build-Fix-setlocalversion-issue-with-6.3-kernel.patch b/0044-kpatch-build-Fix-setlocalversion-issue-with-6.3-kernel.patch new file mode 100644 index 0000000..84a4fa4 --- /dev/null +++ b/0044-kpatch-build-Fix-setlocalversion-issue-with-6.3-kernel.patch @@ -0,0 +1,110 @@ +From 629b5acf3dab0311e1bebbffec4908999273d58d Mon Sep 17 00:00:00 2001 +From: Josh Poimboeuf +Date: Mon, 13 Mar 2023 13:51:01 -0700 +Subject: [PATCH] kpatch-build: Fix setlocalversion issue with 6.3 kernel + +The kernel has a VERMAGIC_STRING, e.g. "6.2.0". The module loader uses +that string to ensure that all loaded modules' version strings match the +kernel's. + +If the kernel source is in a git tree, and if there are uncommitted +changes, the version string will have a '+' or "-dirty" appended to it, +like "6.1.0+" or "6.2.0-dirty". This dirty tree detection is done by +the setlocalversion script. + +This affects kpatch-build in a few ways. When it builds the original +kernel, in some cases there are uncommitted changes to the makefiles. +When it builds the patched kernel, there are additional uncommitted +changes due to the .patch file being applied. + +We want to avoid the VERMAGIC_STRING changing between builds. Otherwise +it would cause problems: + + - object code which uses that string would change unnecessarily, + causing a false positive change detected by create-diff-object + + - the linked patch module would report the wrong version, resulting in + the module failing to load due to version mismatch. + +Up until now, the version was prevented from changing by running +`setlocalversion --save-scmversion` before the build. That command +hard-codes the version by saving it to a file which is then +automatically read later during future invocations of the kernel build. + +Unfortunately that feature was removed in the 6.3 merge window with +commit f6e09b07cc12 ("kbuild: do not put .scmversion into the source +tarball"). So we need to come up with a new approach. + +Fix it by temporarily replacing the setlocalversion script with a +one-liner which just echo's the original version. I think this is +unfortunately the best we can do, as we really can't handle +VERMAGIC_STRING changing, either during/between kernel builds or during +the module link. + +Fixes #1335. + +Signed-off-by: Josh Poimboeuf +--- + kpatch-build/kpatch-build | 29 +++++++++++++++++++++-------- + 1 file changed, 21 insertions(+), 8 deletions(-) + +diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build +index 45e8b14b..568cc341 100755 +--- a/kpatch-build/kpatch-build ++++ b/kpatch-build/kpatch-build +@@ -166,18 +166,13 @@ remove_patches() { + } + + cleanup() { +- rm -f "$BUILDDIR/.scmversion" +- + remove_patches + +- # restore original vmlinux if it was overwritten by sourcedir build ++ # restore any files that were modified for the build + [[ -e "$TEMPDIR/vmlinux" ]] && mv -f "$TEMPDIR/vmlinux" "$KERNEL_SRCDIR/" +- +- # restore original link-vmlinux.sh if we updated it for the build + [[ -e "$TEMPDIR/link-vmlinux.sh" ]] && mv -f "$TEMPDIR/link-vmlinux.sh" "$KERNEL_SRCDIR/scripts" +- +- # restore original Makefile.modfinal if we updated it for the build + [[ -e "$TEMPDIR/Makefile.modfinal" ]] && mv -f "$TEMPDIR/Makefile.modfinal" "$KERNEL_SRCDIR/scripts" ++ [[ -e "$TEMPDIR/setlocalversion" ]] && mv -f "$TEMPDIR/setlocalversion" "$KERNEL_SRCDIR/scripts" + + [[ "$DEBUG" -eq 0 ]] && rm -rf "$TEMPDIR" + rm -rf "$RPMTOPDIR" +@@ -989,6 +984,25 @@ if [[ -z "$OOT_MODULE" && ! "$CONFIGFILE" -ef "$KERNEL_SRCDIR"/.config ]] ; then + cp -f "$CONFIGFILE" "$KERNEL_SRCDIR/.config" || die + fi + ++# When the kernel source is in a git repo, applying the patch (plus the ++# Makefile sed hacks we do) can cause it to be built with "+" or "dirty" ++# appended to the kernel version string (VERMAGIC_STRING), even if the original ++# kernel was not dirty. That can complicate both the build (create-diff-object ++# false positive changes) and the patch module link (module version mismatch ++# load failures). ++# ++# Prevent that by replacing the original setlocalversion with a friendlier one ++# which just echo's the original version. This should be done before any ++# changes to the source. ++if [[ -n "$USERSRCDIR" && -e "$KERNEL_SRCDIR/.git" ]]; then ++ cd "$KERNEL_SRCDIR" || die ++ cp -f scripts/setlocalversion "$TEMPDIR" || die ++ LOCALVERSION="$(make kernelversion)" ++ LOCALVERSION="$(KERNELVERSION="$LOCALVERSION" ./scripts/setlocalversion)" ++ [[ -n "$LOCALVERSION" ]] || die "setlocalversion failed" ++ echo "echo $LOCALVERSION" > scripts/setlocalversion ++fi ++ + # kernel option checking + + trace_off "reading .config" +@@ -1099,7 +1113,6 @@ fi + save_env + + echo "Building original source" +-[[ -n "$OOT_MODULE" ]] || ./scripts/setlocalversion --save-scmversion || die + unset KPATCH_GCC_TEMPDIR + + KPATCH_CC_PREFIX="$TOOLSDIR/kpatch-cc " + diff --git a/0045-kpatch-build-support-Linux-5.19-.cmd-file-format.patch b/0045-kpatch-build-support-Linux-5.19-.cmd-file-format.patch new file mode 100644 index 0000000..f16fdb7 --- /dev/null +++ b/0045-kpatch-build-support-Linux-5.19-.cmd-file-format.patch @@ -0,0 +1,400 @@ +From 1d7e8a74bb6c282ebe6c9193e4bd0218ec689e46 Mon Sep 17 00:00:00 2001 +From: Josh Poimboeuf +Date: Wed, 17 Aug 2022 12:21:04 -0700 +Subject: [PATCH] kpatch-build: support Linux 5.19 .cmd file format + +Rewrite kobj_find() to deal with Linux 5.19, where the .cmd files use +object file paths relative to the .cmd file rather than relative to the +root of the kernel tree. + +While at it, add several performance enhancements to prevent all +currently known deep finds. + +This is all quite fiddly. But it works. + +Fixes #1277. + +Signed-off-by: Josh Poimboeuf + +Signed-off-by: hubin +--- + kpatch-build/kpatch-build | 343 +++++++++++++++++++++++++++++++------- + 1 file changed, 279 insertions(+), 64 deletions(-) + +diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build +index 511ef33..27a67ad 100755 +--- a/kpatch-build/kpatch-build ++++ b/kpatch-build/kpatch-build +@@ -438,90 +438,305 @@ find_special_section_data() { + save_env + return + } ++### ++# path of file, relative to dir ++# adapted from https://stackoverflow.com/a/24848739 ++relpath() { ++ local file="$1" ++ local dir="$2" ++ ++ local filedir ++ local common ++ local result ++ ++ filedir="$(dirname "$(readlink -f "$file")")" ++ common="$(readlink -f "$dir")" ++ ++ if [[ "$filedir" = "$common" ]]; then ++ basename "$file" ++ return ++ fi + +-filter_parent_obj() +-{ +- local dir="${1}" +- local file="${2}" ++ while [[ "${filedir#$common/}" = "$filedir" ]]; do ++ common="$(dirname "$common")" ++ result="../$result" ++ done + +- grep -v "\.mod\.cmd$" | grep -Fv "${dir}/.${file}.cmd" | while read input; do +- if [ "$(readlink -f $input)" != "$(readlink -f ${dir}/.${file}.cmd)" ];then +- echo $input; +- fi +- done ++ result="${result}${filedir#$common/}" ++ echo "${result}/$(basename "$file")" + } + +-find_parent_obj() { +- dir="$(dirname "$1")" +- absdir="$(readlink -f "$dir")" +- pwddir="$(readlink -f .)" +- pdir="${absdir#$pwddir/}" +- file="$(basename "$1")" +- grepname="${1%.o}" +- grepname="$grepname\\.o" +- if [[ "$DEEP_FIND" -eq 1 ]]; then +- num=0 +- if [[ -n "$last_deep_find" ]]; then +- parent="$(grep -lw "$grepname" "$last_deep_find"/.*.cmd | filter_parent_obj "${pdir}" "${file}" | head -n1)" +- num="$(grep -lw "$grepname" "$last_deep_find"/.*.cmd | filter_parent_obj "${pdir}" "${file}" | wc -l)" +- fi +- if [[ "$num" -eq 0 ]]; then +- parent="$(find . -name ".*.cmd" -print0 | xargs -0 grep -lw "$grepname" | filter_parent_obj "${pdir}" "${file}" | cut -c3- | head -n1)" +- num="$(find . -name ".*.cmd" -print0 | xargs -0 grep -lw "$grepname" | filter_parent_obj "${pdir}" "${file}" | wc -l)" +- [[ "$num" -eq 1 ]] && last_deep_find="$(dirname "$parent")" ++cmd_file_to_o_file() { ++ local parent="$1" ++ ++ # convert cmd file name to corresponding .o ++ parent_dir="$(dirname "$parent")" ++ parent_dir="${parent_dir#./}" ++ parent="$(basename "$parent")" ++ parent="${parent#.}" ++ parent="${parent%.cmd}" ++ parent="$parent_dir/$parent" ++ ++ [[ -f $parent ]] || die "can't find $parent associated with $1" ++ ++ echo "$parent" ++} ++ ++get_parent_from_parents() { ++ local parents=("$@") ++ ++ [[ ${#parents[@]} -eq 0 ]] && PARENT="" && return ++ [[ ${#parents[@]} -eq 1 ]] && PARENT="${parents[0]}" && return ++ ++ # multiple parents: ++ local parent ++ local mod_name="${parents[0]%.*}" ++ local mod_file ++ for parent in "${parents[@]}"; do ++ # for modules, there can be multiple matches. Some ++ # combination of foo.o, foo.mod, and foo.ko, depending ++ # on kernel version and whether the module is single or ++ # multi-object. Make sure a .mod and/or .ko exists, and no ++ # more than one .mod/.ko exists. ++ ++ [[ $parent = *.o ]] && continue ++ ++ if [[ ${parent%.*} != "$mod_name" ]]; then ++ mod_file="" ++ break + fi +- if [[ "$num" -eq 0 ]]; then +- parent="$(find $USERMODBUILDDIR -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | filter_parent_obj "$pdir" "${file}" | head -n1)" +- num="$(find $USERMODBUILDDIR -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | filter_parent_obj "$pdir" "${file}" | wc -l)" +- [[ "$num" -eq 1 ]] && last_deep_find="$(dirname "$parent")" ++ ++ if [[ $parent = *.mod || $parent = *.ko ]]; then ++ mod_file=$parent ++ continue + fi ++ ++ mod_file="" ++ break ++ done ++ ++ if [[ -n $mod_file ]]; then ++ PARENT="$mod_file" ++ return ++ fi ++ ++ ERROR_IF_DIFF="multiple parent matches for $file: ${parents[*]}" ++ PARENT="${parents[0]}" ++} ++ ++__find_parent_obj_in_dir() { ++ local file="$1" ++ local dir="$2" ++ ++ declare -a parents ++ ++ while IFS='' read -r parent; do ++ parent="$(cmd_file_to_o_file "$parent")" ++ [[ $parent -ef $file ]] && continue ++ parents+=("$parent") ++ done < <(grep -El "[ ]${file/./\\.}([ \)]|$)" "$dir"/.*.cmd) ++ ++ get_parent_from_parents "${parents[@]}" ++} ++ ++find_parent_obj_in_dir() { ++ local file="$1" ++ local dir="$2" ++ ++ # make sure the dir has .cmd files ++ if ! compgen -G "$dir"/.*.cmd > /dev/null; then ++ PARENT="" ++ return ++ fi ++ ++ # 5.19+: ../acp/acp_hw.o ++ __find_parent_obj_in_dir "$(relpath "$file" "$dir")" "$dir" ++ [[ -n $PARENT ]] && return ++ ++ # pre-5.19 (and 5.19+ single-object modules): ++ if [[ $file == $dir* ]]; then ++ # arch/x86/kernel/smp.o ++ __find_parent_obj_in_dir "$file" "$dir" + else +- parent="$(grep -lw "$grepname" "$dir"/.*.cmd | filter_parent_obj "${dir}" "${file}" | head -n1)" +- num="$(grep -lw "$grepname" "$dir"/.*.cmd | filter_parent_obj "${dir}" "${file}" | wc -l)" ++ # drivers/gpu/drm/amd/amdgpu/../acp/acp_hw.o ++ __find_parent_obj_in_dir "$dir"/"$(relpath "$file" "$dir")" "$dir" + fi ++} + +- [[ "$num" -eq 0 ]] && PARENT="" && return +- [[ "$num" -gt 1 ]] && ERROR_IF_DIFF="two parent matches for $1" ++find_parent_obj() { ++ local file="$1" ++ ++ # common case: look in same directory ++ find_parent_obj_in_dir "$file" "$(dirname "$file")" ++ [[ -n $PARENT ]] && return ++ ++ # if we previously had a successful deep find, try that dir first ++ if [[ -n "$LAST_DEEP_FIND_DIR" ]]; then ++ find_parent_obj_in_dir "$file" "$LAST_DEEP_FIND_DIR" ++ [[ -n "$PARENT" ]] && return ++ fi ++ ++ # prevent known deep finds ++ if [[ $file = drivers/gpu/drm/amd/* ]]; then ++ find_parent_obj_in_dir "$file" "drivers/gpu/drm/amd/amdgpu" ++ [[ -n "$PARENT" ]] && return ++ fi ++ if [[ $file = virt/kvm/* ]]; then ++ find_parent_obj_in_dir "$file" "arch/x86/kvm" ++ [[ -n "$PARENT" ]] && return ++ fi ++ if [[ $file = drivers/oprofile/* ]]; then ++ find_parent_obj_in_dir "$file" "arch/x86/oprofile" ++ [[ -n "$PARENT" ]] && return ++ fi ++ ++ # check higher-level dirs ++ local dir ++ dir="$(dirname "$file")" ++ while [[ ! $dir -ef . ]]; do ++ dir="$(dirname "$dir")" ++ find_parent_obj_in_dir "$file" "$dir" ++ [[ -n $PARENT ]] && return ++ done + +- dir="$(dirname "$parent")" +- PARENT="$(basename "$parent")" +- PARENT="${PARENT#.}" +- PARENT="${PARENT%.cmd}" +- [[ $dir != "." ]] && PARENT="$dir/$PARENT" +- [[ ! -e "$PARENT" ]] && die "ERROR: can't find parent $PARENT for $1" ++ # slow path: search the entire tree ("deep find") ++ echo 'doing "deep find" for parent object' ++ declare -a parents ++ while IFS= read -r -d '' dir; do ++ find_parent_obj_in_dir "$file" "$dir" ++ if [[ -n $PARENT ]]; then ++ parents+=("$PARENT") ++ LAST_DEEP_FIND_DIR="$dir" ++ fi ++ done < <(find . -type d -print0) ++ ++ get_parent_from_parents "${parents[@]}" + } + ++# find vmlinux or .ko associated with a .o file + find_kobj() { +- arg="$1" +- KOBJFILE="$arg" +- DEEP_FIND=0 ++ local file="$1" ++ ++ if [[ -n $OOT_MODULE ]]; then ++ KOBJFILE="$OOT_MODULE" ++ return ++ fi ++ ++ KOBJFILE="$file" + ERROR_IF_DIFF= + while true; do ++ case "$KOBJFILE" in ++ *.mod) ++ KOBJFILE=${PARENT/.mod/.ko} ++ [[ -e $KOBJFILE ]] || die "can't find .ko for $PARENT" ++ return ++ ;; ++ *.ko) ++ return ++ ;; ++ */built-in.o|\ ++ */built-in.a|\ ++ arch/x86/kernel/ebda.o|\ ++ arch/x86/kernel/head*.o|\ ++ arch/x86/kernel/platform-quirks.o|\ ++ arch/x86/lib/lib.a|\ ++ lib/lib.a) ++ KOBJFILE=vmlinux ++ return ++ ;; ++ esac ++ + find_parent_obj "$KOBJFILE" +- [[ -n "$PARENT" ]] && DEEP_FIND=0 +- if [[ -z "$PARENT" ]]; then +- [[ "$KOBJFILE" = *.ko ]] && return +- case "$KOBJFILE" in +- */built-in.o|\ +- */built-in.a|\ +- arch/x86/lib/lib.a|\ +- arch/x86/kernel/head*.o|\ +- arch/x86/kernel/ebda.o|\ +- arch/x86/kernel/platform-quirks.o|\ +- lib/lib.a) +- KOBJFILE=vmlinux +- return +- esac +- if [[ "$DEEP_FIND" -eq 0 ]]; then +- DEEP_FIND=1 +- continue; +- fi +- die "invalid ancestor $KOBJFILE for $arg" +- fi ++ [[ -z "$PARENT" ]] && die "invalid ancestor $KOBJFILE for $file" + KOBJFILE="$PARENT" + done + } + ++ ++filter_parent_obj() ++{ ++ local dir="${1}" ++ local file="${2}" ++ ++ grep -v "\.mod\.cmd$" | grep -Fv "${dir}/.${file}.cmd" | while read input; do ++ if [ "$(readlink -f $input)" != "$(readlink -f ${dir}/.${file}.cmd)" ];then ++ echo $input; ++ fi ++ done ++} ++ ++find_parent_obj() { ++ dir="$(dirname "$1")" ++ absdir="$(readlink -f "$dir")" ++ pwddir="$(readlink -f .)" ++ pdir="${absdir#$pwddir/}" ++ file="$(basename "$1")" ++ grepname="${1%.o}" ++ grepname="$grepname\\.o" ++ if [[ "$DEEP_FIND" -eq 1 ]]; then ++ num=0 ++ if [[ -n "$last_deep_find" ]]; then ++ parent="$(grep -lw "$grepname" "$last_deep_find"/.*.cmd | filter_parent_obj "${pdir}" "${file}" | head -n1)" ++ num="$(grep -lw "$grepname" "$last_deep_find"/.*.cmd | filter_parent_obj "${pdir}" "${file}" | wc -l)" ++ fi ++ if [[ "$num" -eq 0 ]]; then ++ parent="$(find . -name ".*.cmd" -print0 | xargs -0 grep -lw "$grepname" | filter_parent_obj "${pdir}" "${file}" | cut -c3- | head -n1)" ++ num="$(find . -name ".*.cmd" -print0 | xargs -0 grep -lw "$grepname" | filter_parent_obj "${pdir}" "${file}" | wc -l)" ++ [[ "$num" -eq 1 ]] && last_deep_find="$(dirname "$parent")" ++ fi ++ if [[ "$num" -eq 0 ]]; then ++ parent="$(find $USERMODBUILDDIR -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | filter_parent_obj "$pdir" "${file}" | head -n1)" ++ num="$(find $USERMODBUILDDIR -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | filter_parent_obj "$pdir" "${file}" | wc -l)" ++ [[ "$num" -eq 1 ]] && last_deep_find="$(dirname "$parent")" ++ fi ++ else ++ parent="$(grep -lw "$grepname" "$dir"/.*.cmd | filter_parent_obj "${dir}" "${file}" | head -n1)" ++ num="$(grep -lw "$grepname" "$dir"/.*.cmd | filter_parent_obj "${dir}" "${file}" | wc -l)" ++ fi ++ ++ [[ "$num" -eq 0 ]] && PARENT="" && return ++ [[ "$num" -gt 1 ]] && ERROR_IF_DIFF="two parent matches for $1" ++ ++ dir="$(dirname "$parent")" ++ PARENT="$(basename "$parent")" ++ PARENT="${PARENT#.}" ++ PARENT="${PARENT%.cmd}" ++ [[ $dir != "." ]] && PARENT="$dir/$PARENT" ++ [[ ! -e "$PARENT" ]] && die "ERROR: can't find parent $PARENT for $1" ++} ++ ++find_kobj() { ++ arg="$1" ++ KOBJFILE="$arg" ++ DEEP_FIND=0 ++ ERROR_IF_DIFF= ++ while true; do ++ find_parent_obj "$KOBJFILE" ++ [[ -n "$PARENT" ]] && DEEP_FIND=0 ++ if [[ -z "$PARENT" ]]; then ++ [[ "$KOBJFILE" = *.ko ]] && return ++ case "$KOBJFILE" in ++ */built-in.o|\ ++ */built-in.a|\ ++ arch/x86/lib/lib.a|\ ++ arch/x86/kernel/head*.o|\ ++ arch/x86/kernel/ebda.o|\ ++ arch/x86/kernel/platform-quirks.o|\ ++ lib/lib.a) ++ KOBJFILE=vmlinux ++ return ++ esac ++ if [[ "$DEEP_FIND" -eq 0 ]]; then ++ DEEP_FIND=1 ++ continue; ++ fi ++ die "invalid ancestor $KOBJFILE for $arg" ++ fi ++ KOBJFILE="$PARENT" ++ done ++} ++ ++ + # Only allow alphanumerics and '_' and '-' in the module name. Everything else + # is replaced with '-'. Also truncate to 55 chars so the full name + NUL + # terminator fits in the kernel's 56-byte module name array. +-- +2.41.0 + diff --git a/0046-kpatch-build_ignore_init_version-timestamp_o.patch b/0046-kpatch-build_ignore_init_version-timestamp_o.patch new file mode 100644 index 0000000..8e40ebd --- /dev/null +++ b/0046-kpatch-build_ignore_init_version-timestamp_o.patch @@ -0,0 +1,29 @@ +From 934b3b3c0c12be2435f8edbe484c2696dda93864 Mon Sep 17 00:00:00 2001 +From: Joe Lawrence +Date: Mon, 16 Jan 2023 09:33:55 -0500 +Subject: [PATCH] kpatch-build: ignore init/version-timestamp.o + +Kernel v6.1+ commit 2df8220cc511 ("kbuild: build init/built-in.a just +once") split init_uts_ns and linux_banner out to +init/version-timestamp.c from init/version.c + +Add init/version-timestamp.o to the list of object files that kpatch-cc +won't add to its changed_objs list. + +Signed-off-by: Joe Lawrence +--- + kpatch-build/kpatch-cc | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/kpatch-build/kpatch-cc b/kpatch-build/kpatch-cc +index 2a3d2644..17aae25b 100755 +--- a/kpatch-build/kpatch-cc ++++ b/kpatch-build/kpatch-cc +@@ -44,6 +44,7 @@ if [[ "$TOOLCHAINCMD" =~ ^(.*-)?gcc$ || "$TOOLCHAINCMD" =~ ^(.*-)?clang$ ]] ; th + arch/s390/kernel/vdso64/*|\ + drivers/firmware/efi/libstub/*|\ + init/version.o|\ ++ init/version-timestamp.o|\ + kernel/system_certificates.o|\ + lib/*|\ + tools/*|\ diff --git a/0047-lookup.c-maybe_discarded_sym-add-__pfx_-pattern.patch b/0047-lookup.c-maybe_discarded_sym-add-__pfx_-pattern.patch new file mode 100644 index 0000000..430efd0 --- /dev/null +++ b/0047-lookup.c-maybe_discarded_sym-add-__pfx_-pattern.patch @@ -0,0 +1,26 @@ +From 2c6fb366440a5e0e9767d02afe1a6561fece948c Mon Sep 17 00:00:00 2001 +From: chenziyang +Date: Sat, 16 Sep 2023 18:16:25 +0800 +Subject: [PATCH] lookup.c: maybe_discarded_sym() add __pfx_ pattern + +find_local_syms function has error because vmlinux.symtab does not contains "_pfx" symbols but version.o contains them, and local symbols cannot match. +So we add string compare of __pfx in maybe_discarded_sym function. +--- + kpatch-build/lookup.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/kpatch-build/lookup.c b/kpatch-build/lookup.c +index 4b1717a..d2d6e66 100644 +--- a/kpatch-build/lookup.c ++++ b/kpatch-build/lookup.c +@@ -85,6 +85,7 @@ static bool maybe_discarded_sym(const char *name) + !strncmp(name, "__brk_reservation_fn_", 21) || + !strncmp(name, "__func_stack_frame_non_standard_", 32) || + strstr(name, "__addressable_") || ++ strstr(name, "__pfx_") || + strstr(name, "__UNIQUE_ID_") || + !strncmp(name, ".L.str", 6)) + return true; +-- +2.41.0 + diff --git a/README.md b/README.md index 3e00e25..ee15d39 100644 --- a/README.md +++ b/README.md @@ -190,7 +190,13 @@ rpm -Uvh ~/rpmbuild/RPMS/noarch/kpatch*.rpm ``` ## 热补丁约束限制 - +### 23.09版本x86架构约束 +因为23.09的内核6.4.0版本x86架构新增了编译选项:CONFIG_X86_KERNEL_IBT, +造成编译出的内核ELF文件和5.10内核有差异,导致热补丁编译失败。为了规避该选项带来的影响,在x86架构编译热补丁时 +需要在/opt/patch_workspace/.config中将该选项修改为如下字段: +``` +#CONFIG_X86_KERNEL_IBT is not set +``` ### 不支持的函数修改行为 - 不支持修改函数参数或返回值类型或个数。 diff --git a/kpatch.spec b/kpatch.spec index 3e859dc..e60221a 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,10 @@ 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-kpatch-build-Fix-setlocalversion-issue-with-6.3-kernel.patch +Patch0045:0045-kpatch-build-support-Linux-5.19-.cmd-file-format.patch +Patch0046:0046-kpatch-build_ignore_init_version-timestamp_o.patch +Patch0047:0047-lookup.c-maybe_discarded_sym-add-__pfx_-pattern.patch BuildRequires: gcc elfutils-libelf-devel kernel-devel git Requires: bc make gcc patch bison flex openssl-devel @@ -116,6 +120,12 @@ popd %{_mandir}/man1/*.1.gz %changelog +* Sat Sep 16 2023 Chen Ziyang -1:0.9.7-5 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:backport upstream kpatch and use patch0047 to accommondate kernel 6.4.0 + * Tue Aug 1 2023 Bin Hu -1:0.9.7-4 - Type:enhancement - ID:NA -- Gitee From ec26776bb1cdfb477510ab074f4bc45603be3d9a Mon Sep 17 00:00:00 2001 From: chenziyang Date: Tue, 19 Sep 2023 21:23:33 +0800 Subject: [PATCH 2/3] backport upstream kpatch. Use patch0049 to fix kpatch-build fail on arm64 caused by upgrade kernel 6.4.0 --- ...-support-Linux-5.19-.cmd-file-format.patch | 127 ++------- ...ect-support-x86-NOP-padded-functions.patch | 264 ++++++++++++++++++ ...able_function_entry-so-most-of-funct.patch | 26 ++ kpatch.spec | 10 +- 4 files changed, 318 insertions(+), 109 deletions(-) create mode 100644 0048-create-diff-object-support-x86-NOP-padded-functions.patch create mode 100644 0049-arm64-open-patchable_function_entry-so-most-of-funct.patch diff --git a/0045-kpatch-build-support-Linux-5.19-.cmd-file-format.patch b/0045-kpatch-build-support-Linux-5.19-.cmd-file-format.patch index f16fdb7..339878e 100644 --- a/0045-kpatch-build-support-Linux-5.19-.cmd-file-format.patch +++ b/0045-kpatch-build-support-Linux-5.19-.cmd-file-format.patch @@ -18,14 +18,14 @@ Signed-off-by: Josh Poimboeuf Signed-off-by: hubin --- - kpatch-build/kpatch-build | 343 +++++++++++++++++++++++++++++++------- - 1 file changed, 279 insertions(+), 64 deletions(-) + kpatch-build/kpatch-build | 258 ++++++++++++++++++++++++++++---------- + 1 file changed, 194 insertions(+), 64 deletions(-) diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build -index 511ef33..27a67ad 100755 +index 511ef33..ca03807 100755 --- a/kpatch-build/kpatch-build +++ b/kpatch-build/kpatch-build -@@ -438,90 +438,305 @@ find_special_section_data() { +@@ -438,86 +438,216 @@ find_special_section_data() { save_env return } @@ -184,11 +184,9 @@ index 511ef33..27a67ad 100755 - num="$(grep -lw "$grepname" "$dir"/.*.cmd | filter_parent_obj "${dir}" "${file}" | wc -l)" + # drivers/gpu/drm/amd/amdgpu/../acp/acp_hw.o + __find_parent_obj_in_dir "$dir"/"$(relpath "$file" "$dir")" "$dir" - fi ++ fi +} - -- [[ "$num" -eq 0 ]] && PARENT="" && return -- [[ "$num" -gt 1 ]] && ERROR_IF_DIFF="two parent matches for $1" ++ +find_parent_obj() { + local file="$1" + @@ -214,8 +212,10 @@ index 511ef33..27a67ad 100755 + if [[ $file = drivers/oprofile/* ]]; then + find_parent_obj_in_dir "$file" "arch/x86/oprofile" + [[ -n "$PARENT" ]] && return -+ fi -+ + fi + +- [[ "$num" -eq 0 ]] && PARENT="" && return +- [[ "$num" -gt 1 ]] && ERROR_IF_DIFF="two parent matches for $1" + # check higher-level dirs + local dir + dir="$(dirname "$file")" @@ -224,13 +224,7 @@ index 511ef33..27a67ad 100755 + find_parent_obj_in_dir "$file" "$dir" + [[ -n $PARENT ]] && return + done - -- dir="$(dirname "$parent")" -- PARENT="$(basename "$parent")" -- PARENT="${PARENT#.}" -- PARENT="${PARENT%.cmd}" -- [[ $dir != "." ]] && PARENT="$dir/$PARENT" -- [[ ! -e "$PARENT" ]] && die "ERROR: can't find parent $PARENT for $1" ++ + # slow path: search the entire tree ("deep find") + echo 'doing "deep find" for parent object' + declare -a parents @@ -241,7 +235,13 @@ index 511ef33..27a67ad 100755 + LAST_DEEP_FIND_DIR="$dir" + fi + done < <(find . -type d -print0) -+ + +- dir="$(dirname "$parent")" +- PARENT="$(basename "$parent")" +- PARENT="${PARENT#.}" +- PARENT="${PARENT%.cmd}" +- [[ $dir != "." ]] && PARENT="$dir/$PARENT" +- [[ ! -e "$PARENT" ]] && die "ERROR: can't find parent $PARENT for $1" + get_parent_from_parents "${parents[@]}" } @@ -306,95 +306,6 @@ index 511ef33..27a67ad 100755 KOBJFILE="$PARENT" done } - -+ -+filter_parent_obj() -+{ -+ local dir="${1}" -+ local file="${2}" -+ -+ grep -v "\.mod\.cmd$" | grep -Fv "${dir}/.${file}.cmd" | while read input; do -+ if [ "$(readlink -f $input)" != "$(readlink -f ${dir}/.${file}.cmd)" ];then -+ echo $input; -+ fi -+ done -+} -+ -+find_parent_obj() { -+ dir="$(dirname "$1")" -+ absdir="$(readlink -f "$dir")" -+ pwddir="$(readlink -f .)" -+ pdir="${absdir#$pwddir/}" -+ file="$(basename "$1")" -+ grepname="${1%.o}" -+ grepname="$grepname\\.o" -+ if [[ "$DEEP_FIND" -eq 1 ]]; then -+ num=0 -+ if [[ -n "$last_deep_find" ]]; then -+ parent="$(grep -lw "$grepname" "$last_deep_find"/.*.cmd | filter_parent_obj "${pdir}" "${file}" | head -n1)" -+ num="$(grep -lw "$grepname" "$last_deep_find"/.*.cmd | filter_parent_obj "${pdir}" "${file}" | wc -l)" -+ fi -+ if [[ "$num" -eq 0 ]]; then -+ parent="$(find . -name ".*.cmd" -print0 | xargs -0 grep -lw "$grepname" | filter_parent_obj "${pdir}" "${file}" | cut -c3- | head -n1)" -+ num="$(find . -name ".*.cmd" -print0 | xargs -0 grep -lw "$grepname" | filter_parent_obj "${pdir}" "${file}" | wc -l)" -+ [[ "$num" -eq 1 ]] && last_deep_find="$(dirname "$parent")" -+ fi -+ if [[ "$num" -eq 0 ]]; then -+ parent="$(find $USERMODBUILDDIR -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | filter_parent_obj "$pdir" "${file}" | head -n1)" -+ num="$(find $USERMODBUILDDIR -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | filter_parent_obj "$pdir" "${file}" | wc -l)" -+ [[ "$num" -eq 1 ]] && last_deep_find="$(dirname "$parent")" -+ fi -+ else -+ parent="$(grep -lw "$grepname" "$dir"/.*.cmd | filter_parent_obj "${dir}" "${file}" | head -n1)" -+ num="$(grep -lw "$grepname" "$dir"/.*.cmd | filter_parent_obj "${dir}" "${file}" | wc -l)" -+ fi -+ -+ [[ "$num" -eq 0 ]] && PARENT="" && return -+ [[ "$num" -gt 1 ]] && ERROR_IF_DIFF="two parent matches for $1" -+ -+ dir="$(dirname "$parent")" -+ PARENT="$(basename "$parent")" -+ PARENT="${PARENT#.}" -+ PARENT="${PARENT%.cmd}" -+ [[ $dir != "." ]] && PARENT="$dir/$PARENT" -+ [[ ! -e "$PARENT" ]] && die "ERROR: can't find parent $PARENT for $1" -+} -+ -+find_kobj() { -+ arg="$1" -+ KOBJFILE="$arg" -+ DEEP_FIND=0 -+ ERROR_IF_DIFF= -+ while true; do -+ find_parent_obj "$KOBJFILE" -+ [[ -n "$PARENT" ]] && DEEP_FIND=0 -+ if [[ -z "$PARENT" ]]; then -+ [[ "$KOBJFILE" = *.ko ]] && return -+ case "$KOBJFILE" in -+ */built-in.o|\ -+ */built-in.a|\ -+ arch/x86/lib/lib.a|\ -+ arch/x86/kernel/head*.o|\ -+ arch/x86/kernel/ebda.o|\ -+ arch/x86/kernel/platform-quirks.o|\ -+ lib/lib.a) -+ KOBJFILE=vmlinux -+ return -+ esac -+ if [[ "$DEEP_FIND" -eq 0 ]]; then -+ DEEP_FIND=1 -+ continue; -+ fi -+ die "invalid ancestor $KOBJFILE for $arg" -+ fi -+ KOBJFILE="$PARENT" -+ done -+} -+ -+ - # Only allow alphanumerics and '_' and '-' in the module name. Everything else - # is replaced with '-'. Also truncate to 55 chars so the full name + NUL - # terminator fits in the kernel's 56-byte module name array. -- -2.41.0 +2.33.0 diff --git a/0048-create-diff-object-support-x86-NOP-padded-functions.patch b/0048-create-diff-object-support-x86-NOP-padded-functions.patch new file mode 100644 index 0000000..65d88b1 --- /dev/null +++ b/0048-create-diff-object-support-x86-NOP-padded-functions.patch @@ -0,0 +1,264 @@ +From 3e54c63b175b68cf48654c119e62bda398d0c018 Mon Sep 17 00:00:00 2001 +From: Joe Lawrence +Date: Mon, 16 Jan 2023 09:33:55 -0500 +Subject: [PATCH] create-diff-object: support x86 NOP-padded functions + +Kernel v6.2+ commit bea75b33895f ("x86/Kconfig: Introduce function +padding") added 16 bytes of NOP padding in front of each function. + +For objects built with --function-sections, this means that function +symbols no longer sit at the beginning of their respective ELF sections, +but 16 bytes offset. + +In the same release, kernel v6.2+ commit 9f2899fe36a6 ("objtool: Add +option to generate prefix symbols") adds ELF function symbols with +prefix "__pfx_" to indicate the start of a function, inclusive of +NOP-padding. + +For example: + + $ objdump -Dr -j.text.cmdline_proc_show fs/proc/cmdline.o + ... + Disassembly of section .text.cmdline_proc_show: + + 0000000000000000 <__pfx_cmdline_proc_show>: + 0: 90 nop + 1: 90 nop + 2: 90 nop + 3: 90 nop + 4: 90 nop + 5: 90 nop + 6: 90 nop + 7: 90 nop + 8: 90 nop + 9: 90 nop + a: 90 nop + b: 90 nop + c: 90 nop + d: 90 nop + e: 90 nop + f: 90 nop + + 0000000000000010 : + 10: e8 00 00 00 00 callq 15 + 11: R_X86_64_PLT32 __fentry__-0x4 + 15: 55 push %rbp + 16: 48 8b 35 00 00 00 00 mov 0x0(%rip),%rsi # 1d + 19: R_X86_64_PC32 saved_command_line-0x4 + 1d: 48 89 fd mov %rdi,%rbp + 20: e8 00 00 00 00 callq 25 + 21: R_X86_64_PLT32 seq_puts-0x4 + 25: 48 89 ef mov %rbp,%rdi + 28: be 0a 00 00 00 mov $0xa,%esi + 2d: e8 00 00 00 00 callq 32 + 2e: R_X86_64_PLT32 seq_putc-0x4 + 32: 31 c0 xor %eax,%eax + 34: 5d pop %rbp + 35: e9 00 00 00 00 jmpq 3a + 36: R_X86_64_PLT32 __x86_return_thunk-0x4 + +Kpatch-build needs to gracefully handle NOP-padding when it is present. +At the same time, it should include "__pfx_" symbols when +their respective functions change, but not treat prefix such functions +as first-class functions. + +This also adds support for CONFIG_CFI_CLANG, which also creates prefixed +symbols with the name "__cfi_". + +Signed-off-by: Joe Lawrence +Signed-off-by: Josh Poimboeuf +--- + kpatch-build/create-diff-object.c | 23 ++++++-- + kpatch-build/kpatch-elf.c | 92 +++++++++++++++++++++++++++++++ + kpatch-build/kpatch-elf.h | 2 + + 3 files changed, 111 insertions(+), 6 deletions(-) + +diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c +index 0754f7506..76ba867f9 100644 +--- a/kpatch-build/create-diff-object.c ++++ b/kpatch-build/create-diff-object.c +@@ -236,14 +236,21 @@ static struct rela *toc_rela(const struct rela *rela) + static void kpatch_bundle_symbols(struct kpatch_elf *kelf) + { + struct symbol *sym; ++ unsigned int expected_offset; + + list_for_each_entry(sym, &kelf->symbols, list) { + if (is_bundleable(sym)) { +- if (sym->sym.st_value != 0 && +- !is_gcc6_localentry_bundled_sym(kelf, sym)) { +- ERROR("symbol %s at offset %lu within section %s, expected 0", ++ if (sym->pfx) ++ expected_offset = 16; ++ else if (is_gcc6_localentry_bundled_sym(kelf, sym)) ++ expected_offset = 8; ++ else ++ expected_offset = 0; ++ ++ if (sym->sym.st_value != expected_offset) { ++ ERROR("symbol %s at offset %lu within section %s, expected %u", + sym->name, sym->sym.st_value, +- sym->sec->name); ++ sym->sec->name, expected_offset); + } + + sym->sec->sym = sym; +@@ -1913,6 +1920,8 @@ static int kpatch_include_changed_functions(struct kpatch_elf *kelf) + sym->type == STT_FUNC) { + changed_nr++; + kpatch_include_symbol(sym); ++ if (sym->pfx) ++ kpatch_include_symbol(sym->pfx); + } + + if (sym->type == STT_FILE) +@@ -1927,7 +1936,8 @@ static void kpatch_print_changes(struct kpatch_elf *kelf) + struct symbol *sym; + + list_for_each_entry(sym, &kelf->symbols, list) { +- if (!sym->include || !sym->sec || sym->type != STT_FUNC || sym->parent) ++ if (!sym->include || !sym->sec || sym->type != STT_FUNC || ++ sym->parent || sym->is_pfx) + continue; + if (sym->status == NEW) + log_normal("new function: %s\n", sym->name); +@@ -3922,7 +3932,8 @@ static void kpatch_find_func_profiling_calls(struct kpatch_elf *kelf) + struct rela *rela; + unsigned char *insn; + list_for_each_entry(sym, &kelf->symbols, list) { +- if (sym->type != STT_FUNC || !sym->sec || !sym->sec->rela) ++ if (sym->type != STT_FUNC || sym->is_pfx || ++ !sym->sec || !sym->sec->rela) + continue; + + switch(kelf->arch) { +diff --git a/kpatch-build/kpatch-elf.c b/kpatch-build/kpatch-elf.c +index 213ff5f3b..4fb985c19 100644 +--- a/kpatch-build/kpatch-elf.c ++++ b/kpatch-build/kpatch-elf.c +@@ -397,6 +397,97 @@ static void kpatch_create_section_list(struct kpatch_elf *kelf) + ERROR("expected NULL"); + } + ++/* ++ * Some x86 kernels have NOP function padding [1] for which objtool [2] ++ * adds ELF function symbols with prefix "__pfx_" to indicate the start ++ * of a function, inclusive of NOP-padding. Find the prefix symbols and ++ * link them to their corresponding function symbols at an expected ++ * offset. ++ * ++ * A few examples: ++ * ++ * Value Size Type Bind Vis Ndx Name ++ * (fork.o, simple case) ++ * 0000000000000000 0 SECTION LOCAL DEFAULT 31 .text.get_task_mm ++ * 0000000000000000 16 FUNC GLOBAL DEFAULT 31 __pfx_get_task_mm ++ * 0000000000000010 91 FUNC GLOBAL DEFAULT 31 get_task_mm ++ * ++ * (fork.o, multiple function aliases) ++ * 0000000000000000 0 SECTION LOCAL DEFAULT 190 .text.__do_sys_fork ++ * 0000000000000000 16 FUNC GLOBAL DEFAULT 190 __pfx___x64_sys_fork ++ * 0000000000000010 49 FUNC LOCAL DEFAULT 190 __do_sys_fork ++ * 0000000000000010 49 FUNC GLOBAL DEFAULT 190 __ia32_sys_fork ++ * 0000000000000010 49 FUNC GLOBAL DEFAULT 190 __x64_sys_fork ++ * ++ * (fork.o multiple functions in one section) ++ * 0000000000000000 0 SECTION LOCAL DEFAULT 59 .init.text ++ * 0000000000000000 16 FUNC LOCAL DEFAULT 59 __pfx_coredump_filter_setup ++ * 0000000000000010 40 FUNC LOCAL DEFAULT 59 coredump_filter_setup ++ * 0000000000000038 16 FUNC WEAK DEFAULT 59 __pfx_arch_task_cache_init ++ * 0000000000000048 10 FUNC WEAK DEFAULT 59 arch_task_cache_init ++ * 0000000000000052 16 FUNC GLOBAL DEFAULT 59 __pfx_fork_init ++ * 0000000000000062 357 FUNC GLOBAL DEFAULT 59 fork_init ++ * 00000000000001c7 16 FUNC GLOBAL DEFAULT 59 __pfx_fork_idle ++ * 00000000000001d7 214 FUNC GLOBAL DEFAULT 59 fork_idle ++ * 00000000000002ad 16 FUNC GLOBAL DEFAULT 59 __pfx_mm_cache_init ++ * 00000000000002bd 72 FUNC GLOBAL DEFAULT 59 mm_cache_init ++ * 0000000000000305 16 FUNC GLOBAL DEFAULT 59 __pfx_proc_caches_init ++ * 0000000000000315 192 FUNC GLOBAL DEFAULT 59 proc_caches_init ++ * ++ * (fork.o, function without nop padding / __pfx_ symbol) ++ * 0000000000000000 0 SECTION LOCAL DEFAULT 99 .text.unlikely.__mmdrop ++ * 0000000000000000 48 FUNC LOCAL DEFAULT 99 __mmdrop.cold ++ * ++ * (kpatch-build generated tmp.ko, multple functions in one section, no __pfx_ symbols) ++ * 0000000000000000 0 SECTION LOCAL DEFAULT 10 .text.unlikely.callback_info.isra.0 ++ * 0000000000000010 65 FUNC LOCAL DEFAULT 10 callback_info.isra.0 ++ * 0000000000000061 54 FUNC LOCAL DEFAULT 10 callback_info.isra.0 ++ * 00000000000000a7 54 FUNC LOCAL DEFAULT 10 callback_info.isra.0 ++ * ++ * CONFIG_CFI_CLANG uses something very similar, except the symbol is created ++ * by the compiler and its prefix is "__cfi_". ++ * ++ * [1] bea75b33895f ("x86/Kconfig: Introduce function padding") ++ * [2] 9f2899fe36a6 ("objtool: Add option to generate prefix symbols") ++ */ ++static void kpatch_link_prefixed_functions(struct kpatch_elf *kelf) ++{ ++ struct symbol *func, *pfx; ++ bool found; ++ ++ if (kelf->arch != X86_64) ++ return; ++ ++ list_for_each_entry(pfx, &kelf->symbols, list) { ++ if (!pfx->name || pfx->type != STT_FUNC) ++ continue; ++ ++ if (strncmp(pfx->name, "__pfx_", 6) && ++ strncmp(pfx->name, "__cfi_", 6)) ++ continue; ++ ++ found = false; ++ ++ list_for_each_entry(func, &kelf->symbols, list) { ++ if (func->type == STT_FUNC && func->sec == pfx->sec && ++ func->sym.st_value == pfx->sym.st_value + 16) { ++ ++ /* ++ * If a func has aliases, it's possible for ++ * multiple functions to have the same 'pfx'. ++ */ ++ ++ pfx->is_pfx = true; ++ func->pfx = pfx; ++ found = true; ++ } ++ } ++ ++ if (!found) ++ ERROR("missing func for %s", pfx->name); ++ } ++} ++ + static void kpatch_create_symbol_list(struct kpatch_elf *kelf) + { + struct section *symtab; +@@ -459,6 +550,7 @@ static void kpatch_create_symbol_list(struct kpatch_elf *kelf) + log_debug("\n"); + } + ++ kpatch_link_prefixed_functions(kelf); + } + + struct kpatch_elf *kpatch_elf_open(const char *name) +diff --git a/kpatch-build/kpatch-elf.h b/kpatch-build/kpatch-elf.h +index cd2900cf4..956c1c2ce 100644 +--- a/kpatch-build/kpatch-elf.h ++++ b/kpatch-build/kpatch-elf.h +@@ -77,6 +77,7 @@ struct symbol { + struct list_head list; + struct symbol *twin; + struct symbol *parent; ++ struct symbol *pfx; + struct list_head children; + struct list_head subfunction_node; + struct section *sec; +@@ -91,6 +92,7 @@ struct symbol { + enum symbol_strip strip; /* used in the output elf */ + }; + int has_func_profiling; ++ bool is_pfx; + }; + + struct rela { diff --git a/0049-arm64-open-patchable_function_entry-so-most-of-funct.patch b/0049-arm64-open-patchable_function_entry-so-most-of-funct.patch new file mode 100644 index 0000000..ab44302 --- /dev/null +++ b/0049-arm64-open-patchable_function_entry-so-most-of-funct.patch @@ -0,0 +1,26 @@ +From 277eb06c8522b206a5482eaaa2bd59a04bb7e4c6 Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Tue, 19 Sep 2023 20:36:49 +0800 +Subject: [PATCH] arm64 open patchable_function_entry so most of function + symbols' st_vale is 8 + +--- + kpatch-build/create-diff-object.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c +index bc71a82..ee2df49 100644 +--- a/kpatch-build/create-diff-object.c ++++ b/kpatch-build/create-diff-object.c +@@ -240,7 +240,7 @@ static void kpatch_bundle_symbols(struct kpatch_elf *kelf) + if (is_bundleable(sym)) { + if (sym->pfx) + expected_offset = 16; +- else if (is_gcc6_localentry_bundled_sym(kelf, sym)) ++ else if (is_gcc6_localentry_bundled_sym(kelf, sym) || kelf->arch == ARM64) + expected_offset = 8; + else + expected_offset = 0; +-- +2.33.0 + diff --git a/kpatch.spec b/kpatch.spec index e60221a..a327241 100644 --- a/kpatch.spec +++ b/kpatch.spec @@ -1,7 +1,7 @@ Name: kpatch Epoch: 1 Version: 0.9.7 -Release: 5 +Release: 6 Summary: A Linux dynamic kernel patching infrastructure License: GPLv2 @@ -60,6 +60,8 @@ Patch0044:0044-kpatch-build-Fix-setlocalversion-issue-with-6.3-kernel.patch Patch0045:0045-kpatch-build-support-Linux-5.19-.cmd-file-format.patch Patch0046:0046-kpatch-build_ignore_init_version-timestamp_o.patch Patch0047:0047-lookup.c-maybe_discarded_sym-add-__pfx_-pattern.patch +Patch0048:0048-create-diff-object-support-x86-NOP-padded-functions.patch +Patch0049:0049-arm64-open-patchable_function_entry-so-most-of-funct.patch BuildRequires: gcc elfutils-libelf-devel kernel-devel git Requires: bc make gcc patch bison flex openssl-devel @@ -120,6 +122,12 @@ popd %{_mandir}/man1/*.1.gz %changelog +* Tue Sep 19 2023 Chen Ziyang -1:0.9.7-6 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:backport upstream kpatch. Use patch0048 to fix kpatch-build fail on arm64 caused by upgrade kernel 6.4.0 + * Sat Sep 16 2023 Chen Ziyang -1:0.9.7-5 - Type:bugfix - ID:NA -- Gitee From 16f14e218912e8821b07a45b7c65f0135c84b9cc Mon Sep 17 00:00:00 2001 From: chenziyang Date: Thu, 21 Sep 2023 21:46:17 +0800 Subject: [PATCH 3/3] backport upstream patch to fix x86 kpatch build fail add require package dwarves to ensure kernel .config do not change after kpatch-build --- ...-object-support-.call_sites-sections.patch | 46 +++++++++++++++++++ README.md | 2 +- kpatch.spec | 12 ++++- make_compile_env.sh | 2 +- 4 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 0050-backport-create-diff-object-support-.call_sites-sections.patch diff --git a/0050-backport-create-diff-object-support-.call_sites-sections.patch b/0050-backport-create-diff-object-support-.call_sites-sections.patch new file mode 100644 index 0000000..23a8b6f --- /dev/null +++ b/0050-backport-create-diff-object-support-.call_sites-sections.patch @@ -0,0 +1,46 @@ +From 6b78bd5c6723170b0affde59fb715d3216b8d502 Mon Sep 17 00:00:00 2001 +From: Joe Lawrence +Date: Mon, 16 Jan 2023 09:33:55 -0500 +Subject: [PATCH] create-diff-object: support .call_sites sections + +Kernel v6.2+ commits 00abd3840812 ("objtool: Add .call_sites section") +and e81dc127ef69 ("x86/callthunks: Add call patching for call depth +tracking") added .call_sites sections to object files. These are filled +with an array of s32 values. + +Signed-off-by: Joe Lawrence +--- + kpatch-build/create-diff-object.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c +index ee2df49..9351bc1 100644 +--- a/kpatch-build/create-diff-object.c ++++ b/kpatch-build/create-diff-object.c +@@ -2238,6 +2238,11 @@ static int static_call_sites_group_size(struct kpatch_elf *kelf, int offset) + return size; + } + ++static int call_sites_group_size(struct kpatch_elf *kelf, int offset) ++{ ++ return 4; ++} ++ + static int retpoline_sites_group_size(struct kpatch_elf *kelf, int offset) + { + return 4; +@@ -2380,6 +2385,11 @@ static struct special_section special_sections[] = { + .arch = X86_64 | ARM64, + .group_size = static_call_sites_group_size, + }, ++ { ++ .name = ".call_sites", ++ .arch = X86_64, ++ .group_size = call_sites_group_size, ++ }, + { + .name = ".retpoline_sites", + .arch = X86_64 | ARM64, +-- +2.33.0 + diff --git a/README.md b/README.md index ee15d39..b687c77 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ https://github.com/dynup/kpatch 安装依赖软件包 ```bash -yum install -y make gcc patch bison flex openssl-devel kpatch kpatch-runtime elfutils-libelf-devel +yum install -y make gcc patch bison flex openssl-devel kpatch kpatch-runtime elfutils-libelf-devel dwarves ``` 安装当前内核源码和开发包 diff --git a/kpatch.spec b/kpatch.spec index a327241..45961e7 100644 --- a/kpatch.spec +++ b/kpatch.spec @@ -1,7 +1,7 @@ Name: kpatch Epoch: 1 Version: 0.9.7 -Release: 6 +Release: 7 Summary: A Linux dynamic kernel patching infrastructure License: GPLv2 @@ -62,9 +62,10 @@ Patch0046:0046-kpatch-build_ignore_init_version-timestamp_o.patch Patch0047:0047-lookup.c-maybe_discarded_sym-add-__pfx_-pattern.patch Patch0048:0048-create-diff-object-support-x86-NOP-padded-functions.patch Patch0049:0049-arm64-open-patchable_function_entry-so-most-of-funct.patch +Patch0050:0050-backport-create-diff-object-support-.call_sites-sections.patch BuildRequires: gcc elfutils-libelf-devel kernel-devel git -Requires: bc make gcc patch bison flex openssl-devel +Requires: bc make gcc patch bison flex openssl-devel dwarves Recommends: %{name}-help = %{version}-%{release} %description @@ -122,6 +123,13 @@ popd %{_mandir}/man1/*.1.gz %changelog +* Fri Sep 22 2023 Chen Ziyang -1:0.9.7-7 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:backport upstream kpatch fix kpatch-build fail (unsupport change of call_sites) on x86_64 + Add require dwarves package because it can ensure .config in source directory consistent with kernel config in /boot dir + * Tue Sep 19 2023 Chen Ziyang -1:0.9.7-6 - Type:bugfix - ID:NA diff --git a/make_compile_env.sh b/make_compile_env.sh index 416c02f..ea46160 100644 --- a/make_compile_env.sh +++ b/make_compile_env.sh @@ -1,6 +1,6 @@ #!/bin/bash rm -rf kpatch_compile_env -yum install -y strace vim git rpm-build bc elfutils-libelf-devel gdb-headless make gcc patch bison flex openssl-devel kernel-source-`uname -r` kernel-debuginfo-`uname -r` kernel-devel-`uname -r` --installroot=`pwd`/kpatch_compile_env/ +yum install -y strace vim git rpm-build bc elfutils-libelf-devel gdb-headless make gcc patch bison flex openssl-devel dwarves kernel-source-`uname -r` kernel-debuginfo-`uname -r` kernel-devel-`uname -r` --installroot=`pwd`/kpatch_compile_env/ mkdir -p kpatch_compile_env/kpatch /bin/cp * kpatch_compile_env/kpatch/ cat > kpatch_compile_env/installkpatch.sh <