sync code to openeuler

sync latest code to openeuler

Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
This commit is contained in:
Zhipeng Xie 2019-12-30 15:59:18 +08:00
parent 873089dd88
commit 428b311440
36 changed files with 5002 additions and 39 deletions

View File

@ -0,0 +1,35 @@
From 722d27f6bdd4fa012e08db784bf9bb93bb75be2c Mon Sep 17 00:00:00 2001
From: Artem Savkov <asavkov@redhat.com>
Date: Tue, 16 Oct 2018 16:05:01 +0200
Subject: [PATCH] Add "__addressable_" to maybe_discarded_sym().
Starting with 1b1eeca7e4c1 "init: allow initcall tables to be emitted using
relative references" [1] __init functions are generating an "__addressable_"
symbol in a ".discarded.addressable" section so it does not show up in final
vmlinux triggering find_local_syms failures. Add "_addressable_" to the list
in maybe_discarded_sym().
[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=1b1eeca7e4c19fa76d409d4c7b338dba21f2df45
Signed-off-by: Artem Savkov <asavkov@redhat.com>
---
kpatch-build/lookup.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/kpatch-build/lookup.c b/kpatch-build/lookup.c
index b88dc59..7c8e635 100644
--- a/kpatch-build/lookup.c
+++ b/kpatch-build/lookup.c
@@ -80,7 +80,8 @@ static int maybe_discarded_sym(const char *name)
*/
if (!strncmp(name, "__exitcall_", 11) ||
!strncmp(name, "__brk_reservation_fn_", 21) ||
- !strncmp(name, "__func_stack_frame_non_standard_", 32))
+ !strncmp(name, "__func_stack_frame_non_standard_", 32) ||
+ !strncmp(name, "__addressable_", 14))
return 1;
return 0;
--
1.7.12.4

View File

@ -0,0 +1,36 @@
From 17a97b48bcf0d486007b746c48321bab6dedb2d8 Mon Sep 17 00:00:00 2001
From: Artem Savkov <asavkov@redhat.com>
Date: Wed, 14 Nov 2018 15:09:34 +0100
Subject: [PATCH] kmod/patch: fix patch linking with 4.20
4.20 includes commit 69ea912fda74 "kbuild: remove unneeded link_multi_deps"
which changes kbuild so that only '.o' files are given to ld as targets
for linking, leaving out our linker script. Even before this commit we
were still doing this wrong and were succeeding just because ld is smart
enough to detect the script, it even throws a warning:
ld: warning: kpatch.lds contains output sections; did you forget -T?
The right thing to do is to add the script to ldflags either through
kbuilds 'ldflags-y' or by adding it to LDFLAGS/KPATCH_LDFLAGS directly.
Signed-off-by: Artem Savkov <asavkov@redhat.com>
---
kmod/patch/Makefile | 1 +
1 file changed, 1 insertion(+)
diff --git a/kmod/patch/Makefile b/kmod/patch/Makefile
index 96d1fca..7ba0820 100644
--- a/kmod/patch/Makefile
+++ b/kmod/patch/Makefile
@@ -11,6 +11,7 @@ KBUILD_CFLAGS_MODULE += -mcmodel=large
endif
obj-m += $(KPATCH_NAME).o
+ldflags-y += -T $(src)/kpatch.lds
$(KPATCH_NAME)-objs += patch-hook.o kpatch.lds output.o
--
1.7.12.4

View File

@ -0,0 +1,42 @@
From b2f40b03ce1778c7e97586e4111d22d3b28b3330 Mon Sep 17 00:00:00 2001
From: Artem Savkov <asavkov@redhat.com>
Date: Fri, 7 Dec 2018 16:46:08 +0100
Subject: [PATCH] kmod/patch: more linking fixes
While adding proper linker script option my previous patch left the
linker script in the list of source files (on pre-4.20 kernels) for
ld somehow breaking kpatch callback sections. For this to work
properly kpatch.lds needs to be added to 'extra-y' instead of objs. And
for kbuild to process this option properly we need to call make without
the .ko target, i.e. let kbuild decide what to build.
Fixes: 17a97b4 ("kmod/patch: fix patch linking with 4.20")
Signed-off-by: Artem Savkov <asavkov@redhat.com>
---
kmod/patch/Makefile | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/kmod/patch/Makefile b/kmod/patch/Makefile
index 7ba0820..e017b17 100644
--- a/kmod/patch/Makefile
+++ b/kmod/patch/Makefile
@@ -12,13 +12,14 @@ endif
obj-m += $(KPATCH_NAME).o
ldflags-y += -T $(src)/kpatch.lds
+extra-y := kpatch.lds
-$(KPATCH_NAME)-objs += patch-hook.o kpatch.lds output.o
+$(KPATCH_NAME)-objs += patch-hook.o output.o
all: $(KPATCH_NAME).ko
$(KPATCH_NAME).ko:
- $(KPATCH_MAKE) $(KPATCH_NAME).ko
+ $(KPATCH_MAKE)
patch-hook.o: patch-hook.c kpatch-patch-hook.c livepatch-patch-hook.c
$(KPATCH_MAKE) patch-hook.o
--
1.7.12.4

View File

@ -0,0 +1,75 @@
From 942cc3ace7edb7c15f40f931dd6f47a934b9fc77 Mon Sep 17 00:00:00 2001
From: Artem Savkov <asavkov@redhat.com>
Date: Tue, 12 Jun 2018 17:33:17 +0200
Subject: [PATCH] create-diff-object: allow changing subsections
gcc8 can place functions to .text.unlikely and .text.hot subsections
during optimizations. Allow symbols to change subsections instead of
failing.
Signed-off-by: Artem Savkov <asavkov@redhat.com>
backport from:
https://github.com/jpoimboe/kpatch/commit/35cc6ff0162fc8008c4c639fdfcabd61b38a982f
---
kpatch-build/create-diff-object.c | 28 ++++++++++++++++++++++++++--
1 file changed, 26 insertions(+), 2 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 2ddd00d..61ce74f 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -68,6 +68,12 @@
char *childobj;
+enum subsection {
+ SUBSECTION_NORMAL,
+ SUBSECTION_HOT,
+ SUBSECTION_UNLIKELY
+};
+
enum loglevel loglevel = NORMAL;
#ifndef EM_X86_64
@@ -708,6 +714,22 @@ static void kpatch_compare_sections(struct list_head *seclist)
}
}
+static enum subsection kpatch_subsection_type(struct section *sec)
+{
+ if (!strncmp(sec->name, ".text.unlikely.", 15))
+ return SUBSECTION_UNLIKELY;
+
+ if (!strncmp(sec->name, ".text.hot.", 10))
+ return SUBSECTION_HOT;
+
+ return SUBSECTION_NORMAL;
+}
+
+static int kpatch_subsection_changed(struct section *sec1, struct section *sec2)
+{
+ return kpatch_subsection_type(sec1) != kpatch_subsection_type(sec2);
+}
+
static void kpatch_compare_correlated_symbol(struct symbol *sym)
{
struct symbol *sym1 = sym, *sym2 = sym->twin;
@@ -720,10 +742,12 @@ static void kpatch_compare_correlated_symbol(struct symbol *sym)
/*
* If two symbols are correlated but their sections are not, then the
* symbol has changed sections. This is only allowed if the symbol is
- * moving out of an ignored section.
++ * moving out of an ignored section, or moving between normal/hot/unlikely
++ * subsections.
*/
if (sym1->sec && sym2->sec && sym1->sec->twin != sym2->sec) {
- if (sym2->sec->twin && sym2->sec->twin->ignore)
+ if ((sym2->sec->twin && sym2->sec->twin->ignore) ||
+ kpatch_subsection_changed(sym1->sec, sym2->sec))
sym->status = CHANGED;
else if (sym1->name[0] == '$') /* reserved symbols in aarch64 */
log_debug("maping symbols: %s", sym1->name); /* do nothing just ignogre */
--
2.19.1

View File

@ -0,0 +1,34 @@
From ee167e43252bdb9e84cbefcd8b6fe767c9dc768f Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:24:15 +0000
Subject: [PATCH 1001/1015] livepatch-patch-hook: don't active patch when
insmod
we want to active patch after loading the patch.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kmod/patch/livepatch-patch-hook.c | 7 -------
1 files changed, 0 insertions(+), 7 deletions(-)
diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c
index 7a587a3..e59a377 100644
--- a/kmod/patch/livepatch-patch-hook.c
+++ b/kmod/patch/livepatch-patch-hook.c
@@ -443,13 +443,6 @@ static int __init patch_init(void)
return ret;
}
- ret = klp_enable_patch(lpatch);
- if (ret) {
- WARN_ON(klp_unregister_patch(lpatch));
- patch_free_livepatch(lpatch);
- return ret;
- }
-
return 0;
out:
patch_free_livepatch(lpatch);
--
1.7.5.4

View File

@ -0,0 +1,208 @@
From c27f1093cd47c48e2f403c4ffb29bf066ce0bea5 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:24:24 +0000
Subject: [PATCH 1002/1015] kpatch-build: support third party module make
hotpatch
support out of tree module to make hotpatch.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/kpatch-build | 76 ++++++++++++++++++++++++++++++++++++---------
kpatch-build/kpatch-gcc | 5 +++
2 files changed, 66 insertions(+), 15 deletions(-)
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index a76913f..ccef86d 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -102,7 +102,11 @@ remove_patches() {
for (( ; APPLIED_PATCHES>0; APPLIED_PATCHES-- )); do
idx=$(( APPLIED_PATCHES - 1))
patch="${PATCH_LIST[$idx]}"
- patch -p1 -R -d "$SRCDIR" < "$patch" &> /dev/null
+ if [ -n "$USERMODDIR" ];then
+ patch -p1 -R -d "$USERMODDIR" < "$patch" &> /dev/null
+ else
+ patch -p1 -R -d "$SRCDIR" < "$patch" &> /dev/null
+ fi
done
# If $SRCDIR was a git repo, make sure git actually sees that
@@ -318,8 +322,8 @@ find_parent_obj() {
num="$(grep -l "$grepname" "$last_deep_find"/.*.cmd | grep -Fvc "$pdir/.${file}.cmd")"
fi
if [[ "$num" -eq 0 ]]; then
- parent="$(find ./* -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fv "$pdir/.${file}.cmd" | cut -c3- | head -n1)"
- num="$(find ./* -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fvc "$pdir/.${file}.cmd")"
+ parent="$(find . -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fv "$pdir/.${file}.cmd" | cut -c3- | head -n1)"
+ num="$(find . -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fvc "$pdir/.${file}.cmd")"
[[ "$num" -eq 1 ]] && last_deep_find="$(dirname "$parent")"
fi
else
@@ -335,6 +339,9 @@ find_parent_obj() {
PARENT="${PARENT#.}"
PARENT="${PARENT%.cmd}"
PARENT="$dir/$PARENT"
+ if [ -n "$USERMODDIR" ];then
+ PARENT="$(readlink -f "$PARENT")"
+ fi
[[ ! -e "$PARENT" ]] && die "ERROR: can't find parent $PARENT for $1"
}
@@ -397,7 +404,7 @@ usage() {
echo " (not recommended)" >&2
}
-options="$(getopt -o ha:r:s:c:v:j:t:n:o:d -l "help,archversion:,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,debug,skip-gcc-check,skip-cleanup" -- "$@")" || die "getopt failed"
+options="$(getopt -o ha:r:s:c:v:j:t:n:o:dm:b: -l "help,archversion:,sourcerpm:,sourcedir:,config:,vmlinux:,jobs:,target:,name:,output:,debug,skip-gcc-check,skip-cleanup,moduledir,builddir" -- "$@")" || die "getopt failed"
eval set -- "$options"
@@ -463,6 +470,16 @@ while [[ $# -gt 0 ]]; do
echo "WARNING: Skipping gcc version matching check (not recommended)"
SKIPGCCCHECK=1
;;
+ -m|--moduledir)
+ USERMODDIR=$(readlink -f "$2")
+ shift
+ [[ ! -d "$USERMODDIR" ]] && die "module dir $USERMODDIR not found"
+ ;;
+ -b|--builddir)
+ BUILDDIR=$(readlink -f "$2")
+ shift
+ [[ ! -d "$BUILDDIR" ]] && die "kernel develop dir $BUILDDIR not found"
+ ;;
*)
[[ "$1" = "--" ]] && shift && continue
[[ ! -f "$1" ]] && die "patch file '$1' not found"
@@ -528,7 +545,7 @@ if [[ "$ARCHVERSION" =~ - ]]; then
fi
[[ "$ARCHVERSION" =~ .el7a. ]] && ALT="-alt"
-[[ -z "$TARGETS" ]] && TARGETS="vmlinux modules"
+[[ -z "$USERMODDIR" ]] && [[ -z "$TARGETS" ]] && TARGETS="vmlinux modules"
# Don't check external file.
# shellcheck disable=SC1091
@@ -691,7 +708,11 @@ fi
grep -q "CONFIG_DEBUG_INFO_SPLIT=y" "$CONFIGFILE" && die "kernel option 'CONFIG_DEBUG_INFO_SPLIT' not supported"
echo "Testing patch file(s)"
-cd "$SRCDIR" || die
+if [ -z "$USERMODDIR" ];then
+ cd "$SRCDIR" || die
+else
+ cd $USERMODDIR || die
+fi
apply_patches
remove_patches
@@ -709,15 +730,23 @@ find_special_section_data
if [[ $DEBUG -ge 4 ]]; then
export KPATCH_GCC_DEBUG=1
fi
-
-echo "Building original kernel"
-./scripts/setlocalversion --save-scmversion || die
+if [ -z "$USERMODDIR" ];then
+ echo "Building original kernel"
+ ./scripts/setlocalversion --save-scmversion || die
+else
+ echo "Building original module"
+fi
unset KPATCH_GCC_TEMPDIR
# $TARGETS used as list, no quotes.
# shellcheck disable=SC2086
CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make "-j$CPUS" $TARGETS 2>&1 | logger || die
-echo "Building patched kernel"
+sleep 1
+if [ -z "$USERMODDIR" ];then
+ echo "Building patched kernel"
+else
+ echo "Building patched module"
+fi
apply_patches
mkdir -p "$TEMPDIR/orig" "$TEMPDIR/patched"
KPATCH_GCC_TEMPDIR="$TEMPDIR"
@@ -739,14 +768,22 @@ if [[ ! -e "$TEMPDIR/changed_objs" ]]; then
die "no changed objects found"
fi
-grep -q vmlinux "$SRCDIR/Module.symvers" || die "truncated $SRCDIR/Module.symvers file"
+SYMVERS="$SRCDIR/Module.symvers"
+if [ ! -f "$SYMVERS" -a -n "$BUILDDIR" ];then
+ SYMVERS="$BUILDDIR/Module.symvers"
+fi
+grep -q vmlinux "$SYMVERS" || die "truncated $SYMVERS file"
# Read as words, no quotes.
# shellcheck disable=SC2013
for i in $(cat "$TEMPDIR/changed_objs")
do
mkdir -p "$TEMPDIR/patched/$(dirname "$i")" || die
- cp -f "$SRCDIR/$i" "$TEMPDIR/patched/$i" || die
+ if [ -z "$USERMODDIR" ];then
+ cp -f "$SRCDIR/$i" "$TEMPDIR/patched/$i" || die
+ else
+ cp -f "$i" "$TEMPDIR/patched/$i" || die
+ fi
done
echo "Extracting new and modified ELF sections"
@@ -788,7 +825,11 @@ for i in $FILES; do
[[ "$i" = usr/initramfs_data.o ]] && continue
mkdir -p "output/$(dirname "$i")"
- cd "$SRCDIR" || die
+ if [ -z "$USERMODDIR" ];then
+ cd "$SRCDIR" || die
+ else
+ cd $USERMODDIR || die
+ fi
find_kobj "$i"
cd "$TEMPDIR" || die
if [[ -e "orig/$i" ]]; then
@@ -808,7 +849,7 @@ for i in $FILES; do
# create-diff-object orig.o patched.o parent-name parent-symtab
# Module.symvers patch-mod-name output.o
"$TOOLSDIR"/create-diff-object "orig/$i" "patched/$i" "$KOBJFILE_NAME" \
- "$SYMTAB" "$SRCDIR/Module.symvers" "${MODNAME//-/_}" \
+ "$SYMTAB" "$SYMVERS" "${MODNAME//-/_}" \
"output/$i" 2>&1 | logger 1
check_pipe_status create-diff-object
# create-diff-object returns 3 if no functional change is found
@@ -871,7 +912,12 @@ fi
cd "$TEMPDIR/patch" || die
-KPATCH_BUILD="$SRCDIR" KPATCH_NAME="$MODNAME" \
+if [ -z "$BUILDDIR" ];then
+ KPATCH_BUILDIR="$SRCDIR"
+else
+ KPATCH_BUILDIR="$BUILDDIR"
+fi
+KPATCH_BUILD="$KPATCH_BUILDIR" KPATCH_NAME="$MODNAME" \
KBUILD_EXTRA_SYMBOLS="$KBUILD_EXTRA_SYMBOLS" \
KPATCH_LDFLAGS="$KPATCH_LDFLAGS" \
make 2>&1 | logger || die
diff --git a/kpatch-build/kpatch-gcc b/kpatch-build/kpatch-gcc
index 2d56da1..21f7e2e 100755
--- a/kpatch-build/kpatch-gcc
+++ b/kpatch-build/kpatch-gcc
@@ -23,6 +23,11 @@ if [[ "$TOOLCHAINCMD" = "gcc" ]] ; then
[[ "$obj" = */.tmp_mc_*.o ]] && break;
[[ "$obj" = */.tmp_*.o ]] && obj="${obj/.tmp_/}"
+
+ if [[ $obj =~ \/\.[0-9]+\.o ]]; then
+ break;
+ fi
+
case "$obj" in
*.mod.o|\
*built-in.o|\
--
1.7.5.4

View File

@ -0,0 +1,92 @@
From 214de7459555f3f0461cf4127c55f727ccf473d1 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:24:30 +0000
Subject: [PATCH 1003/1015] kpatch-build: support makefile not in third party
module source directory
support makefile not in third party module source directory.
for example:
testmod/build/Makefile
testmod/src/test.c
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/kpatch-build | 32 +++++++++++++++++++++++++++-----
1 files changed, 27 insertions(+), 5 deletions(-)
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index ccef86d..93a0589 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -311,7 +311,10 @@ find_parent_obj() {
dir="$(dirname "$1")"
absdir="$(readlink -f "$dir")"
pwddir="$(readlink -f .)"
- pdir="${absdir#$pwddir/}"
+ pdir="."
+ if [ "$absdir" != "$pwddir" ];then
+ pdir="${absdir#$pwddir/}"
+ fi
file="$(basename "$1")"
grepname="${1%.o}"
grepname="$grepname\\.o"
@@ -326,6 +329,11 @@ find_parent_obj() {
num="$(find . -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fvc "$pdir/.${file}.cmd")"
[[ "$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" | grep -Fv "$pdir/.${file}.cmd" | head -n1)"
+ num="$(find $USERMODBUILDDIR -name ".*.cmd" -print0 | xargs -0 grep -l "$grepname" | grep -Fvc "$pdir/.${file}.cmd")"
+ [[ "$num" -eq 1 ]] && last_deep_find="$(dirname "$parent")"
+ fi
else
parent="$(grep -l "$grepname" "$dir"/.*.cmd | grep -Fv "$dir/.${file}.cmd" | head -n1)"
num="$(grep -l "$grepname" "$dir"/.*.cmd | grep -Fvc "$dir/.${file}.cmd")"
@@ -730,16 +738,24 @@ find_special_section_data
if [[ $DEBUG -ge 4 ]]; then
export KPATCH_GCC_DEBUG=1
fi
+if [ -z "$USERMODBUILDDIR" ];then
+ USERMODBUILDDIR=$USERMODDIR;
+fi
if [ -z "$USERMODDIR" ];then
echo "Building original kernel"
./scripts/setlocalversion --save-scmversion || die
else
echo "Building original module"
+ [[ -e $USERMODDIR/Module.symvers ]] && cp -f $USERMODDIR/Module.symvers $TEMPDIR/patch/
fi
unset KPATCH_GCC_TEMPDIR
# $TARGETS used as list, no quotes.
# shellcheck disable=SC2086
-CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make "-j$CPUS" $TARGETS 2>&1 | logger || die
+if [ -z "$USERMODDIR" ];then
+ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make "-j$CPUS" $TARGETS 2>&1 | logger || die
+else
+ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make -C "$USERMODBUILDDIR" M="$USERMODBUILDDIR" "-j$CPUS" $USERMODFLAGS $TARGETS 2>&1 | logger || die
+fi
sleep 1
if [ -z "$USERMODDIR" ];then
@@ -753,9 +769,15 @@ KPATCH_GCC_TEMPDIR="$TEMPDIR"
export KPATCH_GCC_TEMPDIR
# $TARGETS used as list, no quotes.
# shellcheck disable=SC2086
-CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \
- KBUILD_MODPOST_WARN=1 \
- make "-j$CPUS" $TARGETS 2>&1 | logger || die
+if [ -z "$USERMODDIR" ];then
+ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \
+ KBUILD_MODPOST_WARN=1 \
+ make "-j$CPUS" $TARGETS 2>&1 | logger || die
+else
+ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \
+ KBUILD_MODPOST_WARN=1 \
+ make -C "$USERMODBUILDDIR" M="$USERMODBUILDDIR" "-j$CPUS" $USERMODFLAGS $TARGETS 2>&1 | logger || die
+fi
# source.c:(.section+0xFF): undefined reference to `symbol'
grep "undefined reference" "$LOGFILE" | sed -r "s/^.*\`(.*)'$/\\1/" \
--
1.7.5.4

View File

@ -0,0 +1,56 @@
From fc6b9c5b1b3eb5d59186fe35cc90d3c06b07c537 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:24:36 +0000
Subject: [PATCH 1004/1015] create-diff-object: new static var should be
included
Before this patch, only global variables(no referenced) will be
included by kpatch-build. But some macros put some static varibles
in the object file, and no function references it, so they won't
be included by kpatch-build. Because they are changed, the kpatch
will report an error.
This patch includes all new static variables, and this method won't
cause a problem even the new static variables are in unbundled section.
Signed-off-by: Zhou Chengming <zhouchengming1@huawei.com>
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/create-diff-object.c | 15 +++++++++++++++
1 files changed, 15 insertions(+), 0 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index d242d01..6e23295 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -1536,6 +1536,20 @@ static void kpatch_include_force_elements(struct kpatch_elf *kelf)
sym->include = 0;
}
+int kpatch_include_new_static_var(struct kpatch_elf *kelf)
+{
+ struct symbol *sym;
+
+ list_for_each_entry(sym, &kelf->symbols, list) {
+ if (sym->status == NEW &&
+ sym->type == STT_OBJECT &&
+ sym->bind == STB_LOCAL)
+ kpatch_include_symbol(sym);
+ }
+
+ return 0;
+}
+
static int kpatch_include_new_globals(struct kpatch_elf *kelf)
{
struct symbol *sym;
@@ -3211,6 +3225,7 @@ int main(int argc, char *argv[])
callbacks_exist = kpatch_include_callback_elements(kelf_patched);
kpatch_include_force_elements(kelf_patched);
new_globals_exist = kpatch_include_new_globals(kelf_patched);
+ kpatch_include_new_static_var(kelf_patched);
kpatch_print_changes(kelf_patched);
kpatch_dump_kelf(kelf_patched);
--
1.7.5.4

View File

@ -0,0 +1,32 @@
From 858cc1f1ef2565d6ffa539550fc13af7e62863e4 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:24:42 +0000
Subject: [PATCH 1005/1015] livepatch, fix: use THIS modname as the name of
ddebug_table
We just want a unique name for every module, so put a _ddebug in
this file as the first of _ddebug array. Then remove path will work
correctly, use the mod->name.
Suggested-by: Li Bin <huawei.libin@huawei.com>
Signed-off-by: Zhou Chengming <zhouchengming1@huawei.com>
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kmod/patch/livepatch-patch-hook.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c
index e59a377..2c0cadd 100644
--- a/kmod/patch/livepatch-patch-hook.c
+++ b/kmod/patch/livepatch-patch-hook.c
@@ -452,6 +452,7 @@ out:
static void __exit patch_exit(void)
{
+ pr_debug("make THIS modname first\n");
WARN_ON(klp_unregister_patch(lpatch));
}
--
1.7.5.4

View File

@ -0,0 +1,50 @@
From 2f95a0fa6214a97f60a0d5ba4dc0cda152d5c7d4 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:24:51 +0000
Subject: [PATCH 1006/1015] create-diff-object: fix correlate static local
variables for __param section
kpatch-build correlate fail when no sections reference
static local variables in __param section, so the static
local variables are incorrectly recognized as a new symbol
and include a incomplete __param section into the patch.
The kernel oops when meet the incomplete __param section.
[ 625.961330] Call Trace:
[ 625.963279] [<ffffffff9b2a0c27>] ? kernfs_name_hash+0x17/0xd0
[ 625.965213] [<ffffffff9b2a219f>] kernfs_add_one+0x8f/0x150
[ 625.967120] [<ffffffff9b2a3a1e>] __kernfs_create_file+0x7e/0xa0
[ 625.969038] [<ffffffff9b2a44db>] sysfs_add_file_mode_ns+0x9b/0x160
[ 625.970912] [<ffffffff9b2a5231>] internal_create_group+0xd1/0x250
[ 625.972755] [<ffffffff9b0b8629>] ? add_sysfs_param.isra.3+0x89/0x280
[ 625.975274] [<ffffffff9b2a53c3>] sysfs_create_group+0x13/0x20
[ 625.977108] [<ffffffff9b0b8f24>] module_param_sysfs_setup+0x94/0xd0
[ 625.978899] [<ffffffff9b10f4e2>] load_module+0x2392/0x2bc0
[ 625.980693] [<ffffffff9b376a70>] ? ddebug_proc_write+0xf0/0xf0
[ 625.982448] [<ffffffff9b10b4b3>] ?
copy_module_from_fd.isra.43+0x53/0x150
[ 625.984187] [<ffffffff9b10fec6>] SyS_finit_module+0xa6/0xd0
[ 625.985926] [<ffffffff9b71f7d5>] system_call_fastpath+0x1c/0x21
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/create-diff-object.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 6e23295..bd7dd37 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -925,6 +925,10 @@ static int kpatch_is_normal_static_local(struct symbol *sym)
if (is_special_static(sym))
return 0;
+ if (!strncmp(sym->name, "__param_", strlen("__param_")) &&
+ !strncmp(sym->sec->name, "__param", strlen("__param")))
+ return 0;
+
return 1;
}
--
1.7.5.4

View File

@ -0,0 +1,31 @@
From 0a92ec9f158340501151bf350050597414affece Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:24:58 +0000
Subject: [PATCH 1007/1015] create-diff-object: don't create dynamic reloc for
symbol exported by patch itself
when a patch export a new function, ___kcrctab+xxx has a reloc,
use origin reloc to get right symbol version.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/create-diff-object.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index bd7dd37..349e483 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -2808,6 +2808,9 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
if (!strcmp(sym_objname, "vmlinux"))
continue;
+ if (!strcmp(sym_objname, pmod_name))
+ continue;
+
external = 1;
}
}
--
1.7.5.4

View File

@ -0,0 +1,45 @@
From aaaec2d292b7e1d07c35e07ba92917ee05a4a141 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:25:03 +0000
Subject: [PATCH 1008/1015] livepatch-patch-hook: support force enable/disable
function
we use immediate to indicate patch which bypass stack check.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kmod/patch/livepatch-patch-hook.c | 11 +++++++++++
1 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c
index 2c0cadd..625ffbd 100644
--- a/kmod/patch/livepatch-patch-hook.c
+++ b/kmod/patch/livepatch-patch-hook.c
@@ -228,6 +228,16 @@ extern struct kpatch_pre_patch_callback __kpatch_callbacks_pre_patch[], __kpatch
extern struct kpatch_post_patch_callback __kpatch_callbacks_post_patch[], __kpatch_callbacks_post_patch_end[];
extern struct kpatch_pre_unpatch_callback __kpatch_callbacks_pre_unpatch[], __kpatch_callbacks_pre_unpatch_end[];
extern struct kpatch_post_unpatch_callback __kpatch_callbacks_post_unpatch[], __kpatch_callbacks_post_unpatch_end[];
+extern unsigned long __kpatch_force_funcs[], __kpatch_force_funcs_end[];
+
+static int patch_is_func_forced(unsigned long addr)
+{
+ unsigned long *a;
+ for (a = __kpatch_force_funcs; a < __kpatch_force_funcs_end; a++)
+ if (*a == addr)
+ return 1;
+ return 0;
+}
#ifdef HAVE_CALLBACKS
static int add_callbacks_to_patch_objects(void)
@@ -393,6 +403,7 @@ static int __init patch_init(void)
lfunc = &lfuncs[j];
lfunc->old_name = func->kfunc->name;
lfunc->new_func = (void *)func->kfunc->new_addr;
+ lfunc->immediate = patch_is_func_forced(lfunc->new_func);
#ifdef HAVE_SYMPOS
lfunc->old_sympos = func->kfunc->sympos;
#else
--
1.7.5.4

View File

@ -0,0 +1,349 @@
From e91d2d2c6778275b16249f7e9d7439018fed70fe Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:25:08 +0000
Subject: [PATCH 1009/1015] kmod/kpatch-build: support build patch for
old kernels
Forward compatible for old kernels
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kmod/patch/kpatch-macros.h | 48 ++++++++++++++
kmod/patch/kpatch-patch.h | 4 +
kmod/patch/kpatch.lds.S | 12 ++++
kmod/patch/livepatch-patch-hook.c | 124 +++++++++++++++++++++++++++++++++++++
kpatch-build/create-diff-object.c | 8 +++
5 files changed, 196 insertions(+), 0 deletions(-)
diff --git a/kmod/patch/kpatch-macros.h b/kmod/patch/kpatch-macros.h
index a60a267..569a18d 100644
--- a/kmod/patch/kpatch-macros.h
+++ b/kmod/patch/kpatch-macros.h
@@ -133,4 +133,52 @@ struct kpatch_post_unpatch_callback {
printk(_fmt, ## __VA_ARGS__); \
})
+typedef void (*kpatch_loadcall_t)(void);
+typedef void (*kpatch_unloadcall_t)(void);
+
+struct kpatch_load {
+ kpatch_loadcall_t fn;
+ char *objname; /* filled in by create-diff-object */
+};
+
+struct kpatch_unload {
+ kpatch_unloadcall_t fn;
+ char *objname; /* filled in by create-diff-object */
+};
+
+/*
+ * KPATCH_LOAD_HOOK macro
+ *
+ * The first line only ensures that the hook being registered has the required
+ * function signature. If not, there is compile error on this line.
+ *
+ * The section line declares a struct kpatch_load to be allocated in a new
+ * .kpatch.hook.load section. This kpatch_load_data symbol is later stripped
+ * by create-diff-object so that it can be declared in multiple objects that
+ * are later linked together, avoiding global symbol collision. Since multiple
+ * hooks can be registered, the .kpatch.hook.load section is a table of struct
+ * kpatch_load elements that will be executed in series by the kpatch core
+ * module at load time, assuming the kernel object (module) is currently
+ * loaded; otherwise, the hook is called when module to be patched is loaded
+ * via the module load notifier.
+ */
+#define KPATCH_LOAD_HOOK(_fn) \
+ static inline kpatch_loadcall_t __loadtest(void) { return _fn; } \
+ struct kpatch_load kpatch_load_data __section(.kpatch.hooks.load) = { \
+ .fn = _fn, \
+ .objname = NULL \
+ };
+
+/*
+ * KPATCH_UNLOAD_HOOK macro
+ *
+ * Same as LOAD hook with s/load/unload/
+ */
+#define KPATCH_UNLOAD_HOOK(_fn) \
+ static inline kpatch_unloadcall_t __unloadtest(void) { return _fn; } \
+ struct kpatch_unload kpatch_unload_data __section(.kpatch.hooks.unload) = { \
+ .fn = _fn, \
+ .objname = NULL \
+ };
+
#endif /* __KPATCH_MACROS_H_ */
diff --git a/kmod/patch/kpatch-patch.h b/kmod/patch/kpatch-patch.h
index 917ea32..4d47d30 100644
--- a/kmod/patch/kpatch-patch.h
+++ b/kmod/patch/kpatch-patch.h
@@ -59,5 +59,9 @@ struct kpatch_post_unpatch_callback {
void (*callback)(void *obj);
char *objname;
};
+struct kpatch_patch_hook {
+ void (*hook)(void);
+ char *objname;
+};
#endif /* _KPATCH_PATCH_H_ */
diff --git a/kmod/patch/kpatch.lds.S b/kmod/patch/kpatch.lds.S
index bc5de82..e3c4e97 100644
--- a/kmod/patch/kpatch.lds.S
+++ b/kmod/patch/kpatch.lds.S
@@ -47,4 +47,16 @@ SECTIONS
__kpatch_force_funcs_end = . ;
QUAD(0);
}
+ .kpatch.hooks.load : {
+ __kpatch_hooks_load = . ;
+ *(.kpatch.hooks.load)
+ __kpatch_hooks_load_end = . ;
+ QUAD(0);
+ }
+ .kpatch.hooks.unload : {
+ __kpatch_hooks_unload = . ;
+ *(.kpatch.hooks.unload)
+ __kpatch_hooks_unload_end = . ;
+ QUAD(0);
+ }
}
diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c
index 625ffbd..8f7d044 100644
--- a/kmod/patch/livepatch-patch-hook.c
+++ b/kmod/patch/livepatch-patch-hook.c
@@ -64,6 +64,15 @@
# define HAVE_CALLBACKS
#endif
+#ifdef EULER_RELEASE_CODE
+# if EULER_RELEASE_CODE <= EULER_RELEASE_VERSION(2, 3)
+# undef HAVE_SYMPOS
+# undef HAVE_IMMEDIATE
+# undef HAVE_ELF_RELOCS
+# define HAVE_LOADHOOKS
+# endif
+#endif
+
/*
* There are quite a few similar structures at play in this file:
* - livepatch.h structs prefixed with klp_*
@@ -95,6 +104,11 @@ struct patch_object {
#endif
const char *name;
int funcs_nr, relocs_nr;
+#ifdef HAVE_LOADHOOKS
+ struct list_head hooks_load;
+ struct list_head hooks_unload;
+ int hooks_load_nr, hooks_unload_nr;
+#endif
};
struct patch_func {
@@ -107,6 +121,13 @@ struct patch_reloc {
struct kpatch_patch_dynrela *kdynrela;
};
+#ifdef HAVE_LOADHOOKS
+struct patch_hook {
+ struct list_head list;
+ struct kpatch_patch_hook *khook;
+};
+#endif
+
static struct patch_object *patch_alloc_new_object(const char *name)
{
struct patch_object *object;
@@ -118,6 +139,10 @@ static struct patch_object *patch_alloc_new_object(const char *name)
#ifndef HAVE_ELF_RELOCS
INIT_LIST_HEAD(&object->relocs);
#endif
+#ifdef HAVE_LOADHOOKS
+ INIT_LIST_HEAD(&object->hooks_load);
+ INIT_LIST_HEAD(&object->hooks_unload);
+#endif
if (strcmp(name, "vmlinux"))
object->name = name;
list_add(&object->list, &patch_objects);
@@ -180,6 +205,37 @@ static int patch_add_reloc_to_object(struct kpatch_patch_dynrela *kdynrela)
}
#endif
+#ifdef HAVE_LOADHOOKS
+static int patch_add_hook_to_object(struct kpatch_patch_hook *khook, bool load)
+{
+ struct patch_hook *hook;
+ struct patch_object *object;
+
+ hook = kzalloc(sizeof(*hook), GFP_KERNEL);
+ if (!hook)
+ return -ENOMEM;
+ INIT_LIST_HEAD(&hook->list);
+ hook->khook = khook;
+
+ object = patch_find_object_by_name(khook->objname);
+ if (!object) {
+ kfree(hook);
+ return -ENOMEM;
+ }
+
+ if (load) {
+ list_add(&hook->list, &object->hooks_load);
+ object->hooks_load_nr++;
+ }
+ else {
+ list_add(&hook->list, &object->hooks_unload);
+ object->hooks_unload_nr++;
+ }
+
+ return 0;
+}
+#endif
+
static void patch_free_scaffold(void) {
struct patch_func *func, *safefunc;
struct patch_object *object, *safeobject;
@@ -217,6 +273,12 @@ static void patch_free_livepatch(struct klp_patch *patch)
if (object->relocs)
kfree(object->relocs);
#endif
+#ifdef HAVE_LOADHOOKS
+ if (object->hooks_load)
+ kfree(object->hooks_load);
+ if (object->hooks_unload)
+ kfree(object->hooks_unload);
+#endif
}
if (patch->objs)
kfree(patch->objs);
@@ -228,6 +290,10 @@ extern struct kpatch_pre_patch_callback __kpatch_callbacks_pre_patch[], __kpatch
extern struct kpatch_post_patch_callback __kpatch_callbacks_post_patch[], __kpatch_callbacks_post_patch_end[];
extern struct kpatch_pre_unpatch_callback __kpatch_callbacks_pre_unpatch[], __kpatch_callbacks_pre_unpatch_end[];
extern struct kpatch_post_unpatch_callback __kpatch_callbacks_post_unpatch[], __kpatch_callbacks_post_unpatch_end[];
+#ifdef HAVE_LOADHOOKS
+extern struct kpatch_patch_hook __kpatch_hooks_load[], __kpatch_hooks_load_end[];
+extern struct kpatch_patch_hook __kpatch_hooks_unload[], __kpatch_hooks_unload_end[];
+#endif
extern unsigned long __kpatch_force_funcs[], __kpatch_force_funcs_end[];
static int patch_is_func_forced(unsigned long addr)
@@ -347,6 +413,11 @@ static int __init patch_init(void)
struct patch_reloc *reloc;
struct klp_reloc *lrelocs, *lreloc;
#endif
+#ifdef HAVE_LOADHOOKS
+ struct patch_hook *hook;
+ struct kpatch_patch_hook *khook_load, *khook_unload;
+ struct klp_hook *lhooks_load, *lhooks_unload, *lhook;
+#endif
/* organize functions and relocs by object in scaffold */
for (kfunc = __kpatch_funcs;
@@ -371,6 +442,24 @@ static int __init patch_init(void)
if (ret)
goto out;
+#ifdef HAVE_LOADHOOKS
+ for (khook_load = __kpatch_hooks_load;
+ khook_load != __kpatch_hooks_load_end;
+ khook_load++) {
+ ret = patch_add_hook_to_object(khook_load, true);
+ if (ret)
+ goto out;
+ }
+
+ for (khook_unload = __kpatch_hooks_unload;
+ khook_unload != __kpatch_hooks_unload_end;
+ khook_unload++) {
+ ret = patch_add_hook_to_object(khook_unload, false);
+ if (ret)
+ goto out;
+ }
+#endif
+
/* past this point, only possible return code is -ENOMEM */
ret = -ENOMEM;
@@ -403,12 +492,21 @@ static int __init patch_init(void)
lfunc = &lfuncs[j];
lfunc->old_name = func->kfunc->name;
lfunc->new_func = (void *)func->kfunc->new_addr;
+#if defined(HAVE_IMMEDIATE)
lfunc->immediate = patch_is_func_forced(lfunc->new_func);
+#endif
#ifdef HAVE_SYMPOS
lfunc->old_sympos = func->kfunc->sympos;
#else
lfunc->old_addr = func->kfunc->old_addr;
#endif
+#ifdef EULER_RELEASE_CODE
+# if EULER_RELEASE_CODE <= EULER_RELEASE_VERSION(2, 3)
+ lfunc->old_size = func->kfunc->old_size;
+ lfunc->new_size = func->kfunc->new_size;
+ lfunc->force = patch_is_func_forced(func->kfunc->new_addr);
+# endif
+#endif
j++;
}
@@ -439,6 +537,32 @@ static int __init patch_init(void)
lobject->callbacks = object->callbacks;
#endif
+#ifdef HAVE_LOADHOOKS
+ lhooks_load = kzalloc(sizeof(struct klp_hook) *
+ (object->hooks_load_nr+1), GFP_KERNEL);
+ if (!lhooks_load)
+ goto out;
+ lobject->hooks_load = lhooks_load;
+ j = 0;
+ list_for_each_entry(hook, &object->hooks_load, list) {
+ lhook = &lhooks_load[j];
+ lhook->hook = hook->khook->hook;
+ j++;
+ }
+
+ lhooks_unload = kzalloc(sizeof(struct klp_hook) *
+ (object->hooks_unload_nr+1), GFP_KERNEL);
+ if (!lhooks_unload)
+ goto out;
+ lobject->hooks_unload = lhooks_unload;
+ j = 0;
+ list_for_each_entry(hook, &object->hooks_unload, list) {
+ lhook = &lhooks_unload[j];
+ lhook->hook = hook->khook->hook;
+ j++;
+ }
+#endif
+
i++;
}
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 349e483..ed96758 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -1463,6 +1463,10 @@ static int kpatch_include_callback_elements(struct kpatch_elf *kelf)
".rela.kpatch.callbacks.post_patch",
".rela.kpatch.callbacks.pre_unpatch",
".rela.kpatch.callbacks.post_unpatch",
+ ".kpatch.hooks.load",
+ ".kpatch.hooks.unload",
+ ".rela.kpatch.hooks.load",
+ ".rela.kpatch.hooks.unload",
NULL,
};
char **callback_section;
@@ -2921,6 +2925,10 @@ static void kpatch_create_callbacks_objname_rela(struct kpatch_elf *kelf, char *
.offset = offsetof(struct kpatch_pre_unpatch_callback, objname) },
{ .name = ".rela.kpatch.callbacks.post_unpatch",
.offset = offsetof(struct kpatch_post_patch_callback, objname) },
+ { .name = ".rela.kpatch.hooks.load",
+ .offset = offsetof(struct kpatch_patch_hook, objname) },
+ { .name = ".rela.kpatch.hooks.unload",
+ .offset = offsetof(struct kpatch_patch_hook, objname) },
{ .name = NULL, .offset = 0 },
};
struct callback *callbackp;
--
1.7.5.4

View File

@ -0,0 +1,480 @@
From be8e5ce9541fc230131be230bd0646c473427895 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:25:20 +0000
Subject: [PATCH 1010/1015] kmod/kpatch-build: support cross compile hotpatch
for aarch64
use R_AARCH64_ABS64 for aarch64, function_ptr_rela and
kpatch_line_macro_change_only are left to implement later.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kmod/patch/livepatch-patch-hook.c | 16 +++---
kpatch-build/create-diff-object.c | 98 ++++++++++++++++++++++++++++++----
kpatch-build/create-kpatch-module.c | 24 ++++++++-
kpatch-build/kpatch-build | 42 ++++++++++++---
kpatch-build/kpatch-gcc | 4 +-
5 files changed, 152 insertions(+), 32 deletions(-)
diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c
index 8f7d044..ee3b2b9 100644
--- a/kmod/patch/livepatch-patch-hook.c
+++ b/kmod/patch/livepatch-patch-hook.c
@@ -66,13 +66,17 @@
#ifdef EULER_RELEASE_CODE
# if EULER_RELEASE_CODE <= EULER_RELEASE_VERSION(2, 3)
-# undef HAVE_SYMPOS
-# undef HAVE_IMMEDIATE
-# undef HAVE_ELF_RELOCS
-# define HAVE_LOADHOOKS
+# define __HULK__
# endif
#endif
+#ifdef __HULK__
+# undef HAVE_SYMPOS
+# undef HAVE_IMMEDIATE
+# undef HAVE_ELF_RELOCS
+# define HAVE_LOADHOOKS
+#endif
+
/*
* There are quite a few similar structures at play in this file:
* - livepatch.h structs prefixed with klp_*
@@ -500,12 +504,10 @@ static int __init patch_init(void)
#else
lfunc->old_addr = func->kfunc->old_addr;
#endif
-#ifdef EULER_RELEASE_CODE
-# if EULER_RELEASE_CODE <= EULER_RELEASE_VERSION(2, 3)
+#ifdef __HULK__
lfunc->old_size = func->kfunc->old_size;
lfunc->new_size = func->kfunc->new_size;
lfunc->force = patch_is_func_forced(func->kfunc->new_addr);
-# endif
#endif
j++;
}
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index ed96758..b8d3bb4 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -70,6 +70,31 @@ char *childobj;
enum loglevel loglevel = NORMAL;
+#ifndef EM_X86_64
+#define EM_X86_64 62
+#endif
+
+#ifndef EM_AARCH64
+#define EM_AARCH64 183
+#endif
+
+#ifndef R_AARCH64_ABS64
+#define R_AARCH64_NONE 0
+#define R_AARCH64_ABS64 257
+#define R_AARCH64_CALL26 283
+#endif
+
+static unsigned int arch;
+static unsigned int absolute_rela_type;
+
+static unsigned int arch_of_elf(Elf *elf)
+{
+ GElf_Ehdr eh;
+ if (!gelf_getehdr(elf, &eh))
+ ERROR("gelf_getehdr");
+ return eh.e_machine;
+}
+
/*******************
* Data structures
* ****************/
@@ -635,6 +660,8 @@ static void kpatch_compare_correlated_symbol(struct symbol *sym)
if (sym1->sec && sym2->sec && sym1->sec->twin != sym2->sec) {
if (sym2->sec->twin && sym2->sec->twin->ignore)
sym->status = CHANGED;
+ else if (sym1->name[0] == '$') /* reserved symbols in aarch64 */
+ log_debug("maping symbols: %s", sym1->name); /* do nothing just ignogre */
else
DIFF_FATAL("symbol changed sections: %s", sym1->name);
}
@@ -2294,7 +2321,7 @@ static void kpatch_create_kpatch_arch_section(struct kpatch_elf *kelf, char *obj
/* entries[index].sec */
ALLOC_LINK(rela, &karch_sec->rela->relas);
rela->sym = sec->secsym;
- rela->type = ABSOLUTE_RELA_TYPE;
+ rela->type = absolute_rela_type;
rela->addend = 0;
rela->offset = index * sizeof(*entries) + \
offsetof(struct kpatch_arch, sec);
@@ -2302,7 +2329,7 @@ static void kpatch_create_kpatch_arch_section(struct kpatch_elf *kelf, char *obj
/* entries[index].objname */
ALLOC_LINK(rela, &karch_sec->rela->relas);
rela->sym = strsym;
- rela->type = ABSOLUTE_RELA_TYPE;
+ rela->type = absolute_rela_type;
rela->addend = offset_of_string(&kelf->strings, objname);
rela->offset = index * sizeof(*entries) + \
offsetof(struct kpatch_arch, objname);
@@ -2500,7 +2527,7 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
*/
ALLOC_LINK(rela, &relasec->relas);
rela->sym = sym;
- rela->type = ABSOLUTE_RELA_TYPE;
+ rela->type = absolute_rela_type;
rela->addend = 0;
rela->offset = index * sizeof(*funcs);
@@ -2510,7 +2537,7 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
*/
ALLOC_LINK(rela, &relasec->relas);
rela->sym = strsym;
- rela->type = ABSOLUTE_RELA_TYPE;
+ rela->type = absolute_rela_type;
rela->addend = offset_of_string(&kelf->strings, sym->name);
rela->offset = index * sizeof(*funcs) +
offsetof(struct kpatch_patch_func, name);
@@ -2521,7 +2548,7 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
*/
ALLOC_LINK(rela, &relasec->relas);
rela->sym = strsym;
- rela->type = ABSOLUTE_RELA_TYPE;
+ rela->type = absolute_rela_type;
rela->addend = objname_offset;
rela->offset = index * sizeof(*funcs) +
offsetof(struct kpatch_patch_func,objname);
@@ -2834,7 +2861,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
/* add rela to fill in ksyms[index].name field */
ALLOC_LINK(rela2, &ksym_sec->rela->relas);
rela2->sym = strsym;
- rela2->type = ABSOLUTE_RELA_TYPE;
+ rela2->type = absolute_rela_type;
rela2->addend = offset_of_string(&kelf->strings, rela->sym->name);
rela2->offset = index * sizeof(*ksyms) + \
offsetof(struct kpatch_symbol, name);
@@ -2842,7 +2869,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
/* add rela to fill in ksyms[index].objname field */
ALLOC_LINK(rela2, &ksym_sec->rela->relas);
rela2->sym = strsym;
- rela2->type = ABSOLUTE_RELA_TYPE;
+ rela2->type = absolute_rela_type;
rela2->addend = offset_of_string(&kelf->strings, sym_objname);
rela2->offset = index * sizeof(*ksyms) + \
offsetof(struct kpatch_symbol, objname);
@@ -2863,7 +2890,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
ERROR("can't create dynrela for section %s (symbol %s): no bundled or section symbol",
sec->name, rela->sym->name);
- rela2->type = ABSOLUTE_RELA_TYPE;
+ rela2->type = absolute_rela_type;
rela2->addend = rela->offset;
rela2->offset = index * sizeof(*krelas) + \
offsetof(struct kpatch_relocation, dest);
@@ -2871,7 +2898,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
/* add rela to fill in krelas[index].objname field */
ALLOC_LINK(rela2, &krela_sec->rela->relas);
rela2->sym = strsym;
- rela2->type = ABSOLUTE_RELA_TYPE;
+ rela2->type = absolute_rela_type;
rela2->addend = offset_of_string(&kelf->strings, objname);
rela2->offset = index * sizeof(*krelas) + \
offsetof(struct kpatch_relocation, objname);
@@ -2879,7 +2906,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
/* add rela to fill in krelas[index].ksym field */
ALLOC_LINK(rela2, &krela_sec->rela->relas);
rela2->sym = ksym_sec_sym;
- rela2->type = ABSOLUTE_RELA_TYPE;
+ rela2->type = absolute_rela_type;
rela2->addend = index * sizeof(*ksyms);
rela2->offset = index * sizeof(*krelas) + \
offsetof(struct kpatch_relocation, ksym);
@@ -2946,7 +2973,7 @@ static void kpatch_create_callbacks_objname_rela(struct kpatch_elf *kelf, char *
if (!strcmp(callbackp->name, sec->name)) {
ALLOC_LINK(rela, &sec->relas);
rela->sym = strsym;
- rela->type = ABSOLUTE_RELA_TYPE;
+ rela->type = absolute_rela_type;
rela->addend = objname_offset;
rela->offset = callbackp->offset;
break;
@@ -3000,6 +3027,7 @@ static void kpatch_create_mcount_sections(struct kpatch_elf *kelf)
/* add rela in .rela__mcount_loc to fill in function pointer */
ALLOC_LINK(rela, &relasec->relas);
rela->sym = sym;
+ if (arch == EM_X86_64) {
rela->type = R_X86_64_64;
rela->addend = 0;
rela->offset = index * sizeof(*funcs);
@@ -3024,6 +3052,37 @@ static void kpatch_create_mcount_sections(struct kpatch_elf *kelf)
rela = list_first_entry(&sym->sec->rela->relas, struct rela,
list);
rela->type = R_X86_64_PC32;
+ } else if (arch == EM_AARCH64) {
+ unsigned int *insnp;
+ rela->type = R_AARCH64_ABS64;
+ /* bl <__fentry__> is the second insn */
+ rela->addend = 4;
+ rela->offset = index * sizeof(*funcs);
+
+ newdata = malloc(sym->sec->data->d_size);
+ memcpy(newdata, sym->sec->data->d_buf, sym->sec->data->d_size);
+ sym->sec->data->d_buf = newdata;
+ insnp = newdata;
+
+ /*
+ * mov x9, x30
+ * nop //function in .text.<func>, so it be replaced with nop by recordmcount
+ * mov x30, x9
+ */
+ if (insnp[0] != 0xaa1e03e9 || insnp[1] != 0xd503201f || insnp[2] != 0xaa0903fe)
+ ERROR("%s: unexpected instruction at the start of the function",
+ sym->name);
+
+ /* change the nop to bl __fentry__ */
+ insnp[1] = 0x94000000;
+ rela = list_first_entry(&sym->sec->rela->relas, struct rela,
+ list);
+ rela->type = R_AARCH64_CALL26;
+ rela->offset = 4;
+
+ } else {
+ ERROR("unsupport arch %d\n", arch);
+ }
index++;
}
@@ -3168,6 +3227,7 @@ int main(int argc, char *argv[])
char *hint = NULL, *orig_obj, *patched_obj, *parent_name;
char *parent_symtab, *mod_symvers, *patch_name, *output_obj;
struct sym_compare_type *base_locals;
+ char *gcc_add_option, *mlongcall;
arguments.debug = 0;
argp_parse (&argp, argc, argv, 0, NULL, &arguments);
@@ -3188,6 +3248,13 @@ int main(int argc, char *argv[])
kelf_base = kpatch_elf_open(orig_obj);
kelf_patched = kpatch_elf_open(patched_obj);
+ arch = arch_of_elf(kelf_base->elf);
+ if (arch == EM_X86_64)
+ absolute_rela_type = R_X86_64_64;
+ else if (arch == EM_AARCH64)
+ absolute_rela_type = R_AARCH64_ABS64;
+ else
+ ERROR("only arch x86_64 and arm64 be supported\n");
kpatch_bundle_symbols(kelf_base);
kpatch_bundle_symbols(kelf_patched);
@@ -3276,7 +3343,14 @@ int main(int argc, char *argv[])
kpatch_create_callbacks_objname_rela(kelf_out, parent_name);
kpatch_build_strings_section_data(kelf_out);
- kpatch_create_mcount_sections(kelf_out);
+ gcc_add_option = getenv("GCC_ADD_OPTION");
+ printf("gcc add option :%s\n", gcc_add_option);
+ mlongcall = strstr(gcc_add_option, "-mlong-calls");
+ if (arch == EM_AARCH64 && mlongcall) {
+ printf("-mlong-calls found, no need to create mcount section\n");
+ } else {
+ kpatch_create_mcount_sections(kelf_out);
+ }
/*
* At this point, the set of output sections and symbols is
diff --git a/kpatch-build/create-kpatch-module.c b/kpatch-build/create-kpatch-module.c
index 67b16b0..9f1c3b9 100644
--- a/kpatch-build/create-kpatch-module.c
+++ b/kpatch-build/create-kpatch-module.c
@@ -31,6 +31,17 @@
char *childobj;
enum loglevel loglevel = NORMAL;
+static unsigned int arch;
+static unsigned int absolute_rela_type;
+
+static unsigned int arch_of_elf(Elf *elf)
+{
+ GElf_Ehdr eh;
+ if (!gelf_getehdr(elf, &eh))
+ ERROR("gelf_getehdr");
+ return eh.e_machine;
+}
+
/*
* Create .kpatch.dynrelas from .kpatch.relocations and .kpatch.symbols sections
*
@@ -102,14 +113,14 @@ static void create_dynamic_rela_sections(struct kpatch_elf *kelf, struct section
/* dest */
ALLOC_LINK(rela, &dynsec->rela->relas);
rela->sym = sym;
- rela->type = R_X86_64_64;
+ rela->type = absolute_rela_type;
rela->addend = dest_offset;
rela->offset = index * sizeof(*dynrelas);
/* name */
ALLOC_LINK(rela, &dynsec->rela->relas);
rela->sym = strsec->secsym;
- rela->type = R_X86_64_64;
+ rela->type = absolute_rela_type;
rela->addend = name_offset;
rela->offset = index * sizeof(*dynrelas) + \
offsetof(struct kpatch_patch_dynrela, name);
@@ -117,7 +128,7 @@ static void create_dynamic_rela_sections(struct kpatch_elf *kelf, struct section
/* objname */
ALLOC_LINK(rela, &dynsec->rela->relas);
rela->sym = strsec->secsym;
- rela->type = R_X86_64_64;
+ rela->type = absolute_rela_type;
rela->addend = objname_offset;
rela->offset = index * sizeof(*dynrelas) + \
offsetof(struct kpatch_patch_dynrela, objname);
@@ -200,6 +211,13 @@ int main(int argc, char *argv[])
childobj = basename(arguments.args[0]);
kelf = kpatch_elf_open(arguments.args[0]);
+ arch = arch_of_elf(kelf->elf);
+ if (arch == EM_X86_64)
+ absolute_rela_type = R_X86_64_64;
+ else if (arch == EM_AARCH64)
+ absolute_rela_type = R_AARCH64_ABS64;
+ else
+ ERROR("only arch x86_64 and arm64 be supported\n");
/*
* Sanity checks:
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index 93a0589..017604c 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -384,6 +384,27 @@ find_kobj() {
done
}
+arch_export() {
+ E_MACHINE=$(od -An -j18 -N2 -d $VMLINUX)
+ if [[ $E_MACHINE -eq 62 ]]; then
+ export ARCH=x86_64
+ export ARCH_COMPILE=
+ export ENDIAN=little
+ export GCC_ADD_OPTION=
+ elif [[ $E_MACHINE -eq 183 ]]; then
+ export ARCH=arm64
+ export ARCH_COMPILE=aarch64-linux-gnu-
+ export ENDIAN=little
+ if grep "\-mlong-calls" $SRCDIR/Makefile > /dev/null; then
+ export GCC_ADD_OPTION="-fno-section-anchors -mlong-calls"
+ else
+ export GCC_ADD_OPTION="-fno-section-anchors"
+ fi
+ else
+ die "only support arm64 or x86_64 architecture"
+ fi
+}
+
# Only allow alphanumerics and '_' and '-' in the module name. Everything else
# is replaced with '-'. Also truncate to 48 chars so the full name fits in the
# kernel's 56-byte module name array.
@@ -725,12 +746,12 @@ apply_patches
remove_patches
cp -LR "$DATADIR/patch" "$TEMPDIR" || die
-
+arch_export
if [[ "$ARCH" = "ppc64le" ]]; then
ARCH_KCFLAGS="-mcmodel=large -fplugin=$PLUGINDIR/ppc64le-plugin.so"
fi
-export KCFLAGS="-I$DATADIR/patch -ffunction-sections -fdata-sections $ARCH_KCFLAGS"
+export KCFLAGS="-I$DATADIR/patch -ffunction-sections -fdata-sections $ARCH_KCFLAGS ${GCC_ADD_OPTION}"
echo "Reading special section data"
find_special_section_data
@@ -752,9 +773,9 @@ unset KPATCH_GCC_TEMPDIR
# $TARGETS used as list, no quotes.
# shellcheck disable=SC2086
if [ -z "$USERMODDIR" ];then
- CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make "-j$CPUS" $TARGETS 2>&1 | logger || die
+ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc $ARCH_COMPILE" make "-j$CPUS" $TARGETS 2>&1 | logger || die
else
- CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " make -C "$USERMODBUILDDIR" M="$USERMODBUILDDIR" "-j$CPUS" $USERMODFLAGS $TARGETS 2>&1 | logger || die
+ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc $ARCH_COMPILE" make -C "$USERMODBUILDDIR" M="$USERMODBUILDDIR" "-j$CPUS" $USERMODFLAGS $TARGETS 2>&1 | logger || die
fi
sleep 1
@@ -770,11 +791,11 @@ export KPATCH_GCC_TEMPDIR
# $TARGETS used as list, no quotes.
# shellcheck disable=SC2086
if [ -z "$USERMODDIR" ];then
- CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \
+ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc $ARCH_COMPILE" \
KBUILD_MODPOST_WARN=1 \
make "-j$CPUS" $TARGETS 2>&1 | logger || die
else
- CROSS_COMPILE="$TOOLSDIR/kpatch-gcc " \
+ CROSS_COMPILE="$TOOLSDIR/kpatch-gcc $ARCH_COMPILE" \
KBUILD_MODPOST_WARN=1 \
make -C "$USERMODBUILDDIR" M="$USERMODBUILDDIR" "-j$CPUS" $USERMODFLAGS $TARGETS 2>&1 | logger || die
fi
@@ -907,6 +928,10 @@ if "$KPATCH_MODULE"; then
export KCPPFLAGS="-D__KPATCH_MODULE__"
fi
+if grep "hulk" $SRCDIR/Makefile > /dev/null; then
+ export KCPPFLAGS="-D__HULK__ $KCPPFLAGS"
+fi
+
echo "Building patch module: $MODNAME.ko"
if [[ -z "$USERSRCDIR" ]] && [[ "$DISTRO" = ubuntu ]]; then
@@ -919,12 +944,12 @@ fi
cd "$TEMPDIR/output" || die
# $KPATCH_LDFLAGS and result of find used as list, no quotes.
# shellcheck disable=SC2086,SC2046
-ld -r $KPATCH_LDFLAGS -o ../patch/tmp_output.o $(find . -name "*.o") 2>&1 | logger || die
+${ARCH_COMPILE}ld -r $KPATCH_LDFLAGS -o ../patch/tmp_output.o $(find . -name "*.o") 2>&1 | logger || die
if "$KPATCH_MODULE"; then
# Add .kpatch.checksum for kpatch script
md5sum ../patch/tmp_output.o | awk '{printf "%s\0", $1}' > checksum.tmp || die
- objcopy --add-section .kpatch.checksum=checksum.tmp --set-section-flags .kpatch.checksum=alloc,load,contents,readonly ../patch/tmp_output.o || die
+ ${ARCH_COMPILE}objcopy --add-section .kpatch.checksum=checksum.tmp --set-section-flags .kpatch.checksum=alloc,load,contents,readonly ../patch/tmp_output.o || die
rm -f checksum.tmp
"$TOOLSDIR"/create-kpatch-module "$TEMPDIR"/patch/tmp_output.o "$TEMPDIR"/patch/output.o 2>&1 | logger 1
check_pipe_status create-kpatch-module
@@ -942,6 +967,7 @@ fi
KPATCH_BUILD="$KPATCH_BUILDIR" KPATCH_NAME="$MODNAME" \
KBUILD_EXTRA_SYMBOLS="$KBUILD_EXTRA_SYMBOLS" \
KPATCH_LDFLAGS="$KPATCH_LDFLAGS" \
+CROSS_COMPILE="$ARCH_COMPILE" \
make 2>&1 | logger || die
if ! "$KPATCH_MODULE"; then
diff --git a/kpatch-build/kpatch-gcc b/kpatch-build/kpatch-gcc
index 21f7e2e..be18847 100755
--- a/kpatch-build/kpatch-gcc
+++ b/kpatch-build/kpatch-gcc
@@ -13,7 +13,7 @@ fi
declare -a args=("$@")
-if [[ "$TOOLCHAINCMD" = "gcc" ]] ; then
+if [[ "$TOOLCHAINCMD" = ${ARCH_COMPILE}gcc ]] ; then
while [ "$#" -gt 0 ]; do
if [ "$1" = "-o" ]; then
obj="$2"
@@ -64,7 +64,7 @@ if [[ "$TOOLCHAINCMD" = "gcc" ]] ; then
fi
shift
done
-elif [[ "$TOOLCHAINCMD" = "ld" ]] ; then
+elif [[ "$TOOLCHAINCMD" = ${ARCH_COMPILE}ld ]] ; then
while [ "$#" -gt 0 ]; do
if [ "$1" = "-o" ]; then
obj="$2"
--
1.7.5.4

View File

@ -0,0 +1,48 @@
From 868a6e4462bebcffa4bf6beea02262823e7dc3a3 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:25:33 +0000
Subject: [PATCH] kpatch-build: use .klp.rela in euleros 7.5 kernel
use .klp.rela in euleros 7.5 kernel
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/kpatch-build | 13 +++++++++++--
1 files changed, 11 insertions(+), 2 deletions(-)
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index fb14850..5a70a44 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -157,6 +157,15 @@ is_rhel() {
[[ $1 =~ \.el[78]\. ]]
}
+is_euleros_klp() {
+ if [[ "$1" =~ ^3.10.0-862 ]] ;then
+ if [ $ID == "euleros" ];then
+ return 0;
+ fi
+ fi
+ return 1;
+}
+
find_dirs() {
if [[ -e "$SCRIPTDIR/create-diff-object" ]]; then
# git repo
@@ -708,10 +717,10 @@ KPATCH_MODULE=true
grep -q "CONFIG_DEBUG_INFO=y" "$CONFIGFILE" || die "kernel doesn't have 'CONFIG_DEBUG_INFO' enabled"
if grep -q "CONFIG_LIVEPATCH=y" "$CONFIGFILE"; then
# The kernel supports livepatch.
- if version_gte "${ARCHVERSION//-*/}" 4.7.0 || is_rhel "$ARCHVERSION"; then
+ if version_gte "${ARCHVERSION//-*/}" 4.7.0 || is_rhel "$ARCHVERSION" || is_euleros_klp "$ARCHVERSION"; then
# Use new .klp.rela. sections
KPATCH_MODULE=false
- if version_gte "${ARCHVERSION//-*/}" 4.9.0 || is_rhel "$ARCHVERSION"; then
+ if version_gte "${ARCHVERSION//-*/}" 4.9.0 || is_rhel "$ARCHVERSION" || is_euleros_klp "$ARCHVERSION"; then
KPATCH_LDFLAGS="--unique=.parainstructions --unique=.altinstructions"
fi
fi
--
1.7.5.4

View File

@ -0,0 +1,68 @@
From 78a13a6091a0d4b1a45fe8f378892a64dece7202 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:25:38 +0000
Subject: [PATCH 1012/1015] create-diff-object: create dynamic relocs for
changed functions in this object
Currently, we only create dynamic relocs for changed functions of
other objects, but not this object. It will cause a problem like:
original: funcA and funcB (funcA calls funcB)
patch-1: funcA-1 and funcB-1 (funcA-1 calls funcB-1)
patch-2: funcB-2 (funcA-1 should call funcB-2)
But as we don't create dynamic relocs for funcA-1, it will call
funcB-1 directly (not by jumping from funcB). So the new funcB-2
will not get called. This patch will create dynamic relocs for
all the changed functions, including changed ones in this object.
Reported-by: Xie Zhipeng <xiezhipeng1@huawei.com>
Tested-by: Zhou Chengming <zhouchengming1@huawei.com>
Signed-off-by: Zhou Chengming <zhouchengming1@huawei.com>
Signed-off-by: Li Bin <huawei.libin@huawei.com>
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/create-diff-object.c | 20 ++++++++++++++++----
1 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index b8d3bb4..4fb27da 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -2684,6 +2684,14 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
*/
if (may_need_dynrela(rela))
toc_rela(rela)->need_dynrela = 1;
+ if (rela->sym->sec) {
+ if (rela->sym->type == STT_FUNC &&
+ rela->sym->status == CHANGED &&
+ rela->sym->sec != sec->base &&
+ sec->base->sym &&
+ sec->base->sym->type == STT_FUNC)
+ toc_rela(rela)->need_dynrela = 1;
+ }
}
}
@@ -2765,10 +2773,14 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
/* An unchanged local symbol */
ret = lookup_local_symbol(table,
rela->sym->name, &result);
- if (ret)
- ERROR("lookup_local_symbol %s needed for %s",
- rela->sym->name, sec->base->name);
-
+ if (ret) {
+ /* maybe it is a global symbol converted in kpatch_create_patches_sections*/
+ ret = lookup_global_symbol(table,
+ rela->sym->name, &result);
+ if (ret)
+ ERROR("lookup_local_symbol %s needed for %s",
+ rela->sym->name, sec->base->name);
+ }
}
else if (vmlinux) {
/*
--
1.7.5.4

View File

@ -0,0 +1,365 @@
From 1eaabfe01cfae870abd45bfa470caa144f34e74c Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:25:45 +0000
Subject: [PATCH 1013/1015] kmod/kpatch-build: fix duplicate symbol relocation
for hulk kernel
hulk kernel fix it by find a uniq symbol(ref_name) and
use ref_offset to find the duplicate symbol
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kmod/patch/kpatch-patch.h | 4 ++
kmod/patch/livepatch-patch-hook.c | 6 ++
kpatch-build/create-diff-object.c | 44 +++++++++++++++++-
kpatch-build/create-kpatch-module.c | 23 +++++++++-
kpatch-build/kpatch-build | 12 +++++
kpatch-build/kpatch-intermediate.h | 2 +
kpatch-build/lookup.c | 87 ++++++++++++++++++++++++++++++++++-
kpatch-build/lookup.h | 8 +++
8 files changed, 183 insertions(+), 3 deletions(-)
diff --git a/kmod/patch/kpatch-patch.h b/kmod/patch/kpatch-patch.h
index 4d47d30..2eacb37 100644
--- a/kmod/patch/kpatch-patch.h
+++ b/kmod/patch/kpatch-patch.h
@@ -30,6 +30,8 @@ struct kpatch_patch_func {
unsigned long sympos;
char *name;
char *objname;
+ char *ref_name;
+ long ref_offset;
};
struct kpatch_patch_dynrela {
@@ -41,6 +43,8 @@ struct kpatch_patch_dynrela {
char *objname;
int external;
int addend;
+ char *ref_name;
+ long ref_offset;
};
struct kpatch_pre_patch_callback {
diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c
index ee3b2b9..fefc068 100644
--- a/kmod/patch/livepatch-patch-hook.c
+++ b/kmod/patch/livepatch-patch-hook.c
@@ -508,6 +508,8 @@ static int __init patch_init(void)
lfunc->old_size = func->kfunc->old_size;
lfunc->new_size = func->kfunc->new_size;
lfunc->force = patch_is_func_forced(func->kfunc->new_addr);
+ lfunc->ref_name= func->kfunc->ref_name;
+ lfunc->ref_offset = func->kfunc->ref_offset;
#endif
j++;
}
@@ -531,6 +533,10 @@ static int __init patch_init(void)
lreloc->name = reloc->kdynrela->name;
lreloc->addend = reloc->kdynrela->addend;
lreloc->external = reloc->kdynrela->external;
+#ifdef __HULK__
+ lreloc->ref_name = reloc->kdynrela->ref_name;
+ lreloc->ref_offset = reloc->kdynrela->ref_offset;
+#endif
j++;
}
#endif /* HAVE_ELF_RELOCS */
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 4fb27da..e72f6dd 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -2519,6 +2519,29 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
funcs[index].old_size = result.size;
funcs[index].new_size = sym->sym.st_size;
funcs[index].sympos = result.pos;
+ if (lookup_is_duplicate_symbol(table, sym->name)) {
+ struct lookup_refsym refsym;
+ long offset;
+
+ if (lookup_ref_symbol(table, sym->name, &refsym))
+ ERROR("unresolvable ambiguity on symbol %s\n", sym->name);
+
+ offset = (long)result.value - (long)refsym.value;
+ funcs[index].ref_offset = offset;
+
+ /*
+ * Add a relocation that will populate
+ * the funcs[index].ref_name field.
+ */
+ ALLOC_LINK(rela, &relasec->relas);
+ rela->sym = strsym;
+ rela->type = absolute_rela_type;
+ rela->addend = offset_of_string(&kelf->strings, refsym.name);
+ rela->offset = index * sizeof(*funcs) +
+ offsetof(struct kpatch_patch_func, ref_name);
+
+ }
+
/*
* Add a relocation that will populate
@@ -2653,6 +2676,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
struct lookup_result result;
char *sym_objname;
int ret, vmlinux, external;
+ long ref_offset;
vmlinux = !strcmp(objname, "vmlinux");
@@ -2860,12 +2884,29 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
log_debug("lookup for %s @ 0x%016lx len %lu\n",
rela->sym->name, result.value, result.size);
+ ref_offset = 0;
/* Fill in ksyms[index] */
if (vmlinux)
ksyms[index].src = result.value;
- else
+ else {
/* for modules, src is discovered at runtime */
ksyms[index].src = 0;
+ if (lookup_is_duplicate_symbol(table, rela->sym->name)) {
+ struct lookup_refsym refsym;
+
+ if (lookup_ref_symbol(table, rela->sym->name, &refsym))
+ ERROR("unresolvable ambiguity on symbol %s\n", rela->sym->name);
+
+ ref_offset = (long)result.value - (long)refsym.value;
+ /* add rela to fill in ref_name field */
+ ALLOC_LINK(rela2, &krela_sec->rela->relas);
+ rela2->sym = strsym;
+ rela2->type = absolute_rela_type;
+ rela2->addend = offset_of_string(&kelf->strings, refsym.name);
+ rela2->offset = index * sizeof(*krelas) +
+ offsetof(struct kpatch_relocation, ref_name);
+ }
+ }
ksyms[index].pos = result.pos;
ksyms[index].type = rela->sym->type;
ksyms[index].bind = rela->sym->bind;
@@ -2893,6 +2934,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
krelas[index].addend = rela->addend;
krelas[index].type = rela->type;
krelas[index].external = external;
+ krelas[index].ref_offset = ref_offset;
/* add rela to fill in krelas[index].dest field */
ALLOC_LINK(rela2, &krela_sec->rela->relas);
diff --git a/kpatch-build/create-kpatch-module.c b/kpatch-build/create-kpatch-module.c
index 9f1c3b9..8292dc8 100644
--- a/kpatch-build/create-kpatch-module.c
+++ b/kpatch-build/create-kpatch-module.c
@@ -57,7 +57,7 @@ static void create_dynamic_rela_sections(struct kpatch_elf *kelf, struct section
struct section *dynsec;
struct symbol *sym;
struct rela *rela;
- int index, nr, offset, dest_offset, objname_offset, name_offset;
+ int index, nr, offset, dest_offset, objname_offset, name_offset, ref_name_offset;
ksyms = ksymsec->data->d_buf;
krelas = krelasec->data->d_buf;
@@ -109,6 +109,27 @@ static void create_dynamic_rela_sections(struct kpatch_elf *kelf, struct section
dynrelas[index].type = krelas[index].type;
dynrelas[index].external = krelas[index].external;
dynrelas[index].sympos = ksym->pos;
+ dynrelas[index].ref_name = krelas[index].ref_name;
+ dynrelas[index].ref_offset = krelas[index].ref_offset;
+
+ if (dynrelas[index].ref_offset)
+ {
+ /* Get objname offset */
+ rela = find_rela_by_offset(krelasec->rela,
+ index * sizeof(*krelas) + offsetof(struct kpatch_relocation, ref_name));
+ if (!rela) {
+ ERROR("find_rela_by_offset");
+ }
+ ref_name_offset = rela->addend;
+ /* ref_name */
+ ALLOC_LINK(rela, &dynsec->rela->relas);
+ rela->sym = strsec->secsym;
+ rela->type = absolute_rela_type;
+ rela->addend = ref_name_offset;
+ rela->offset = index * sizeof(*dynrelas) + \
+ offsetof(struct kpatch_patch_dynrela, ref_name);
+
+ }
/* dest */
ALLOC_LINK(rela, &dynsec->rela->relas);
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index 9c40612..80b9607 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -894,6 +894,18 @@ for i in $FILES; do
KOBJFILE_NAME="${KOBJFILE_NAME/-/_}"
KOBJFILE_PATH="${TEMPDIR}/module/$KOBJFILE"
SYMTAB="${KOBJFILE_PATH}.symtab"
+ unset KCFLAGS
+ remove_patches
+ if [ -z "$USERMODDIR" ];then
+ cd "$SRCDIR" || die
+ CROSS_COMPILE="$ARCH_COMPILE" make "-j$CPUS" ${KOBJFILE} 2>&1 | logger || die
+ else
+ cd "$USERMODDIR"
+ CROSS_COMPILE="$ARCH_COMPILE" make -C "$USERMODBUILDDIR" M="$USERMODBUILDDIR" "-j$CPUS" $USERMODFLAGS $TARGETS 2>&1 | logger || die
+ fi
+ cp ${KOBJFILE} ${KOBJFILE_PATH}
+ apply_patches
+ cd "$TEMPDIR" || die
fi
eu-readelf -s "$KOBJFILE_PATH" > "$SYMTAB"
diff --git a/kpatch-build/kpatch-intermediate.h b/kpatch-build/kpatch-intermediate.h
index 3dea775..59deed0 100644
--- a/kpatch-build/kpatch-intermediate.h
+++ b/kpatch-build/kpatch-intermediate.h
@@ -39,6 +39,8 @@ struct kpatch_relocation {
int external;
char *objname; /* object to which this rela applies to */
struct kpatch_symbol *ksym;
+ char *ref_name;
+ long ref_offset;
};
struct kpatch_arch {
diff --git a/kpatch-build/lookup.c b/kpatch-build/lookup.c
index d08c10b..e4677db 100644
--- a/kpatch-build/lookup.c
+++ b/kpatch-build/lookup.c
@@ -44,6 +44,7 @@ struct object_symbol {
unsigned long size;
char *name;
int type, bind;
+ int sec_index;
};
struct export_symbol {
@@ -229,6 +230,7 @@ static void symtab_read(struct lookup_table *table, char *path)
table->obj_syms[i].value = value;
table->obj_syms[i].size = size;
table->obj_syms[i].name = strdup(name);
+ table->obj_syms[i].sec_index = atoi(ndx);
if (!strcmp(bind, "LOCAL")) {
table->obj_syms[i].bind = STB_LOCAL;
@@ -425,7 +427,90 @@ char *lookup_exported_symbol_objname(struct lookup_table *table, char *name)
return match->objname;
return NULL;
- }
+}
+
+int lookup_is_duplicate_symbol(struct lookup_table *table, char *name)
+{
+ struct object_symbol *sym;
+ int i, count = 0;
+
+ for_each_obj_symbol(i, sym, table)
+ if (!strcmp(sym->name, name)) {
+ count++;
+ if (count > 1)
+ return 1;
+ }
+
+ return 0;
+}
+
+struct object_symbol *lookup_find_symbol_by_name(struct lookup_table *table, char *name)
+{
+ struct object_symbol *sym;
+ unsigned long pos = 0;
+ int i, match = 0, in_file = 0;
+
+ if (!table->local_syms)
+ return NULL;
+
+ for_each_obj_symbol(i, sym, table) {
+ if (sym->bind == STB_LOCAL && !strcmp(sym->name, name))
+ pos++;
+
+ if (table->local_syms == sym) {
+ in_file = 1;
+ continue;
+ }
+
+ if (!in_file)
+ continue;
+
+ if (sym->type == STT_FILE)
+ break;
+
+ if (sym->bind == STB_LOCAL && !strcmp(sym->name, name)) {
+ match = 1;
+ break;
+ }
+ }
+
+ if (!match) {
+ for_each_obj_symbol(i, sym, table) {
+ if ((sym->bind == STB_GLOBAL || sym->bind == STB_WEAK) &&
+ !strcmp(sym->name, name)) {
+ return sym;
+ }
+ }
+ return NULL;
+ }
+
+ return sym;
+}
+
+int lookup_ref_symbol(struct lookup_table *table, char *name,
+ struct lookup_refsym *refsym)
+{
+ struct object_symbol *orig_sym, *sym;
+ int i;
+
+ orig_sym = lookup_find_symbol_by_name(table, name);
+ if (!orig_sym)
+ ERROR("lookup_ref_symbol");
+ memset(refsym, 0, sizeof(*refsym));
+ for_each_obj_symbol(i, sym, table) {
+ if (!strcmp(sym->name, name) || sym->type == STT_FILE ||
+ sym->sec_index != orig_sym->sec_index)
+ continue;
+
+ if (!lookup_is_duplicate_symbol(table, sym->name)) {
+ refsym->name = sym->name;
+ refsym->value = sym->value;
+ return 0;
+ }
+ }
+
+ return 1;
+}
#if 0 /* for local testing */
static void find_this(struct lookup_table *table, char *sym, char *hint)
diff --git a/kpatch-build/lookup.h b/kpatch-build/lookup.h
index 420d0f0..5ad9241 100644
--- a/kpatch-build/lookup.h
+++ b/kpatch-build/lookup.h
@@ -14,6 +14,11 @@ struct sym_compare_type {
int type;
};
+struct lookup_refsym {
+ char *name;
+ unsigned long value;
+};
+
struct lookup_table *lookup_open(char *symtab_path, char *symvers_path,
char *hint, struct sym_compare_type *locals);
void lookup_close(struct lookup_table *table);
@@ -23,5 +28,8 @@ int lookup_global_symbol(struct lookup_table *table, char *name,
struct lookup_result *result);
int lookup_is_exported_symbol(struct lookup_table *table, char *name);
char *lookup_exported_symbol_objname(struct lookup_table *table, char *name);
+int lookup_is_duplicate_symbol(struct lookup_table *table, char *name);
+int lookup_ref_symbol(struct lookup_table *table, char *name,
+ struct lookup_refsym *refsym);
#endif /* _LOOKUP_H_ */
--
1.7.5.4

View File

@ -0,0 +1,31 @@
From 83ecafcda5326baceeb68fba90dc13083ff48fe6 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:25:50 +0000
Subject: [PATCH 1014/1015] create-diff-object: add dynamic reloction for
function pointer on aarch64
implement function_ptr_rela for aarch64.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/create-diff-object.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index e72f6dd..f8f3e15 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -2628,7 +2628,9 @@ static int function_ptr_rela(const struct rela *rela)
rela_toc->addend == (int)rela_toc->sym->sym.st_value &&
(rela->type == R_X86_64_32S ||
rela->type == R_PPC64_TOC16_HA ||
- rela->type == R_PPC64_TOC16_LO_DS));
+ rela->type == R_PPC64_TOC16_LO_DS ||
+ rela->type == R_AARCH64_ADR_PREL_PG_HI21 ||
+ rela->type == R_AARCH64_ADD_ABS_LO12_NC));
}
static int may_need_dynrela(const struct rela *rela)
--
1.7.5.4

View File

@ -0,0 +1,106 @@
From d1bbff5da464148e5d277b601a31d7872b4e376b Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 2 Nov 2018 17:26:00 +0000
Subject: [PATCH 1015/1015] create-diff-object: exclude line only change for
arm64
exclude line only change for arm64 by compare mov instruction
except immediate part.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/create-diff-object.c | 71 ++++++++++++++++++++++++++++++++++++-
1 files changed, 70 insertions(+), 1 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index f8f3e15..12d8bd6 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -609,6 +609,68 @@ static int kpatch_line_macro_change_only(struct section *sec)
return 0;
}
#endif
+#define ARM64_INSTR_LEN 4
+static int arm64_kpatch_line_macro_change_only(struct section *sec)
+{
+ unsigned long start1, start2, size, offset;
+ struct rela *rela;
+ int lineonly = 0, found;
+ unsigned int mov_imm_mask = ((1<<16) - 1)<<5;
+
+ if (sec->status != CHANGED ||
+ is_rela_section(sec) ||
+ !is_text_section(sec) ||
+ sec->sh.sh_size != sec->twin->sh.sh_size ||
+ !sec->rela ||
+ sec->rela->status != SAME)
+ return 0;
+
+ start1 = (unsigned long)sec->twin->data->d_buf;
+ start2 = (unsigned long)sec->data->d_buf;
+ size = sec->sh.sh_size;
+ for (offset = 0; offset < size; offset += ARM64_INSTR_LEN) {
+ if (!memcmp((void *)start1 + offset, (void *)start2 + offset,
+ ARM64_INSTR_LEN))
+ continue;
+
+ /* verify it's a mov immediate to w1 */
+ if ((*(int *)(start1 + offset) & ~mov_imm_mask) !=
+ (*(int *)(start2 + offset) & ~mov_imm_mask))
+ return 0;
+
+ found = 0;
+ list_for_each_entry(rela, &sec->rela->relas, list) {
+ if (rela->offset < offset + ARM64_INSTR_LEN)
+ continue;
+ if (rela->string)
+ continue;
+ if (!strncmp(rela->sym->name, "__warned.", 9))
+ continue;
+ if (!strncmp(rela->sym->name, "warn_slowpath_", 14) ||
+ (!strcmp(rela->sym->name, "__warn_printk")) ||
+ (!strcmp(rela->sym->name, "__might_sleep")) ||
+ (!strcmp(rela->sym->name, "___might_sleep")) ||
+ (!strcmp(rela->sym->name, "__might_fault")) ||
+ (!strcmp(rela->sym->name, "printk")) ||
+ (!strcmp(rela->sym->name, "lockdep_rcu_suspicious"))) {
+ found = 1;
+ break;
+ }
+ return 0;
+ }
+ if (!found)
+ return 0;
+
+ lineonly = 1;
+ }
+
+ if (!lineonly)
+ ERROR("no instruction changes detected for changed section %s",
+ sec->name);
+
+ return 1;
+}
+
static void kpatch_compare_sections(struct list_head *seclist)
{
@@ -624,7 +686,14 @@ static void kpatch_compare_sections(struct list_head *seclist)
/* exclude WARN-only, might_sleep changes */
list_for_each_entry(sec, seclist, list) {
- if (kpatch_line_macro_change_only(sec)) {
+ int line_only;
+ if (arch == EM_X86_64)
+ line_only = kpatch_line_macro_change_only(sec);
+ else if (arch == EM_AARCH64)
+ line_only = arm64_kpatch_line_macro_change_only(sec);
+ else
+ line_only = 0;
+ if (line_only) {
log_debug("reverting macro / line number section %s status to SAME\n",
sec->name);
sec->status = SAME;
--
1.7.5.4

View File

@ -0,0 +1,31 @@
From dc771a1789ea3769777228f792f0902f8b0566ba Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Thu, 22 Nov 2018 21:06:32 +0000
Subject: [PATCH] kpatch-build: include secsym in kpatch_mark_ignored_sections
kpatch_mark_ignored_sections include .rodata.str1.1 section but does
not include its section symbol, causing its section symbol can not be
included any more in kpatch_include_standard_elements. After the
section symbol is freed in kpatch_elf_teardown, we got a segmentation
fault in kpatch_create_intermediate_sections.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/create-diff-object.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 2e54960..97ae0d4 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -2285,6 +2285,7 @@ static void kpatch_mark_ignored_sections(struct kpatch_elf *kelf)
* from the section data comparison, but this is a simpler way.
*/
strsec->include = 1;
+ strsec->secsym->include = 1;
name = strsec->data->d_buf + rela->addend;
ignoresec = find_section_by_name(&kelf->sections, name);
if (!ignoresec)
--
1.7.5.4

View File

@ -0,0 +1,124 @@
From 50782f658313574a530f80d2f4b78fe23488c6c2 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Thu, 20 Dec 2018 04:55:38 +0000
Subject: [PATCH] support compile kpatch on aarch64
delete __x86_64__ to support compile kpatch on aarch64.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/Makefile | 3 +++
kpatch-build/create-diff-object.c | 16 +---------------
2 files changed, 4 insertions(+), 15 deletions(-)
diff --git a/kpatch-build/Makefile b/kpatch-build/Makefile
index 232b336..974e0f2 100644
--- a/kpatch-build/Makefile
+++ b/kpatch-build/Makefile
@@ -12,6 +12,9 @@ SOURCES = create-diff-object.c kpatch-elf.c \
ifeq ($(ARCH),x86_64)
SOURCES += insn/insn.c insn/inat.c
INSN = insn/insn.o insn/inat.o
+else ifeq ($(ARCH),aarch64)
+SOURCES += insn/insn.c insn/inat.c
+INSN = insn/insn.o insn/inat.o
else ifeq ($(ARCH),ppc64le)
SOURCES += gcc-plugins/ppc64le-plugin.c
PLUGIN = gcc-plugins/ppc64le-plugin.so
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 97ae0d4..80a76a9 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -426,7 +426,6 @@ out:
log_debug("section %s has changed\n", sec->name);
}
-#ifdef __x86_64__
/*
* Determine if a section has changed only due to a WARN* or might_sleep
* macro call's embedding of the line number into an instruction operand.
@@ -537,7 +536,7 @@ static int kpatch_line_macro_change_only(struct section *sec)
return 1;
}
-#elif __powerpc64__
+#if __powerpc64__
#define PPC_INSTR_LEN 4
#define PPC_RA_OFFSET 16
@@ -603,11 +602,6 @@ static int kpatch_line_macro_change_only(struct section *sec)
return 1;
}
-#else
-static int kpatch_line_macro_change_only(struct section *sec)
-{
- return 0;
-}
#endif
#define ARM64_INSTR_LEN 4
static int arm64_kpatch_line_macro_change_only(struct section *sec)
@@ -1248,7 +1242,6 @@ static void kpatch_compare_correlated_elements(struct kpatch_elf *kelf)
kpatch_compare_symbols(&kelf->symbols);
}
-#ifdef __x86_64__
static void rela_insn(struct section *sec, struct rela *rela, struct insn *insn)
{
unsigned long insn_addr, start, end, rela_addr;
@@ -1267,7 +1260,6 @@ static void rela_insn(struct section *sec, struct rela *rela, struct insn *insn)
return;
}
}
-#endif
/*
* Mangle the relas a little. The compiler will sometimes use section symbols
@@ -1810,7 +1802,6 @@ static int ex_table_group_size(struct kpatch_elf *kelf, int offset)
return size;
}
-#ifdef __x86_64__
static int parainstructions_group_size(struct kpatch_elf *kelf, int offset)
{
static int size = 0;
@@ -1845,7 +1836,6 @@ static int smp_locks_group_size(struct kpatch_elf *kelf, int offset)
{
return 4;
}
-#endif
#ifdef __powerpc64__
static int fixup_entry_group_size(struct kpatch_elf *kelf, int offset)
{
@@ -1921,7 +1911,6 @@ static struct special_section special_sections[] = {
.name = "__bug_table",
.group_size = bug_table_group_size,
},
-#ifdef __x86_64__
{
.name = ".smp_locks",
.group_size = smp_locks_group_size,
@@ -1930,7 +1919,6 @@ static struct special_section special_sections[] = {
.name = ".parainstructions",
.group_size = parainstructions_group_size,
},
-#endif
{
.name = ".fixup",
.group_size = fixup_group_size,
@@ -1939,12 +1927,10 @@ static struct special_section special_sections[] = {
.name = "__ex_table", /* must come after .fixup */
.group_size = ex_table_group_size,
},
-#ifdef __x86_64__
{
.name = ".altinstructions",
.group_size = altinstructions_group_size,
},
-#endif
#ifdef __powerpc64__
{
.name = "__ftr_fixup",
--
2.19.1

View File

@ -0,0 +1,828 @@
From 9d590b5b9fb59c1cd52221feeef2794eb3333571 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Thu, 8 Nov 2018 15:12:06 +0000
Subject: [PATCH] support c plus kernel module
support GNU_UNIQUE type symbols.
support .group section corelation.
support symbol name longger than 128 bytes.
fix object size changed error for __FUNCTION__.xxx.
ignore compile warning for third party modules.
support functions have no fentry call.
support all function force enable/disable
fix sym replacing error for aarch64
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kmod/patch/livepatch-patch-hook.c | 8 ++
kpatch-build/create-diff-object.c | 161 ++++++++++++++++++++++++-----------
kpatch-build/create-klp-module.c | 27 +++++-
kpatch-build/create-kpatch-module.c | 15 +--
kpatch-build/kpatch-build | 7 ++-
kpatch-build/kpatch-elf.c | 8 ++-
kpatch-build/kpatch-gcc | 2 +-
kpatch-build/lookup.c | 125 +++++++++++++++++++++++++--
kpatch-build/lookup.h | 14 ++-
9 files changed, 287 insertions(+), 80 deletions(-)
diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c
index fefc068..ce1c955 100644
--- a/kmod/patch/livepatch-patch-hook.c
+++ b/kmod/patch/livepatch-patch-hook.c
@@ -497,8 +497,12 @@ static int __init patch_init(void)
lfunc->old_name = func->kfunc->name;
lfunc->new_func = (void *)func->kfunc->new_addr;
#if defined(HAVE_IMMEDIATE)
+#ifdef __ALL_FORCE__
+ lfunc->immediate = 1;
+#else
lfunc->immediate = patch_is_func_forced(lfunc->new_func);
#endif
+#endif
#ifdef HAVE_SYMPOS
lfunc->old_sympos = func->kfunc->sympos;
#else
@@ -507,7 +511,11 @@ static int __init patch_init(void)
#ifdef __HULK__
lfunc->old_size = func->kfunc->old_size;
lfunc->new_size = func->kfunc->new_size;
+#ifdef __ALL_FORCE__
+ lfunc->force = 1;
+#else
lfunc->force = patch_is_func_forced(func->kfunc->new_addr);
+#endif
lfunc->ref_name= func->kfunc->ref_name;
lfunc->ref_offset = func->kfunc->ref_offset;
#endif
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index 97ae0d4..8bb650d 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -224,6 +224,7 @@ static int is_special_static(struct symbol *sym)
"__func__.",
"_rs.",
"CSWTCH.",
+ "__FUNCTION__.",
NULL,
};
char **prefix;
@@ -386,7 +387,7 @@ static void kpatch_compare_correlated_nonrela_section(struct section *sec)
{
struct section *sec1 = sec, *sec2 = sec->twin;
- if (sec1->sh.sh_type != SHT_NOBITS &&
+ if (sec1->sh.sh_type != SHT_NOBITS && sec1->sh.sh_type != SHT_GROUP &&
memcmp(sec1->data->d_buf, sec2->data->d_buf, sec1->data->d_size))
sec->status = CHANGED;
else
@@ -400,8 +401,9 @@ static void kpatch_compare_correlated_section(struct section *sec)
/* Compare section headers (must match or fatal) */
if (sec1->sh.sh_type != sec2->sh.sh_type ||
sec1->sh.sh_flags != sec2->sh.sh_flags ||
- sec1->sh.sh_addralign != sec2->sh.sh_addralign ||
- sec1->sh.sh_entsize != sec2->sh.sh_entsize)
+ sec1->sh.sh_entsize != sec2->sh.sh_entsize ||
+ (sec1->sh.sh_addralign != sec2->sh.sh_addralign &&
+ strcmp(sec1->name, ".rodata")))
DIFF_FATAL("%s section header details differ", sec1->name);
/* Short circuit for mcount sections, we rebuild regardless */
@@ -763,6 +765,33 @@ static void kpatch_compare_symbols(struct list_head *symlist)
}
}
+static int kpatch_correlate_group_section(struct list_head *seclist1, struct list_head *seclist2, struct section *sec1, struct section *sec2)
+{
+ unsigned int *data1, *end1, *data2;
+ struct section *isec1, *isec2;
+
+ if (sec1->data->d_size != sec2->data->d_size)
+ return 1;
+ data1 = sec1->data->d_buf;
+ data2 = sec2->data->d_buf;
+ end1 = sec1->data->d_buf + sec1->data->d_size;
+ data1++;
+ data2++;
+ while (data1 < end1) {
+ isec1 = find_section_by_index(seclist1, *data1);
+ if (!isec1)
+ ERROR("group section not found");
+ isec2 = find_section_by_index(seclist2, *data2);
+ if (!isec2)
+ ERROR("group section not found");
+ if (strcmp(isec1->name, isec2->name))
+ return 1;
+ data1++;
+ data2++;
+ }
+ return 0;
+}
+
static void kpatch_correlate_sections(struct list_head *seclist1, struct list_head *seclist2)
{
struct section *sec1, *sec2;
@@ -777,15 +806,18 @@ static void kpatch_correlate_sections(struct list_head *seclist1, struct list_he
sec1->secsym))
continue;
- /*
- * Group sections must match exactly to be correlated.
- * Changed group sections are currently not supported.
- */
+ /* Group section的格式为
+ * flag
+ * section index
+ * section index
+ * ...
+ *
+ * 当C++代码发生修改时section index可能会发生变化
+ * 这时候我们就比对一下section index所对应的section的
+ * name如果相同我们就认为这两个group是SAME
+ * */
if (sec1->sh.sh_type == SHT_GROUP) {
- if (sec1->data->d_size != sec2->data->d_size)
- continue;
- if (memcmp(sec1->data->d_buf, sec2->data->d_buf,
- sec1->data->d_size))
+ if(kpatch_correlate_group_section(seclist1, seclist2, sec1, sec2))
continue;
}
sec1->twin = sec2;
@@ -1308,17 +1340,21 @@ static void kpatch_replace_sections_syms(struct kpatch_elf *kelf)
#ifdef __powerpc64__
add_off = 0;
#else
- if (rela->type == R_X86_64_PC32) {
- struct insn insn;
- rela_insn(sec, rela, &insn);
- add_off = (long)insn.next_byte -
- (long)sec->base->data->d_buf -
- rela->offset;
- } else if (rela->type == R_X86_64_64 ||
- rela->type == R_X86_64_32S)
- add_off = 0;
- else
- continue;
+ add_off = 0;
+ if (arch == EM_X86_64) {
+ if (rela->type == R_X86_64_PC32) {
+ struct insn insn;
+ rela_insn(sec, rela, &insn);
+ add_off = (long)insn.next_byte -
+ (long)sec->base->data->d_buf -
+ rela->offset;
+ } else if (rela->type == R_X86_64_64 ||
+ rela->type == R_X86_64_32S)
+ add_off = 0;
+ else
+ continue;
+ }
+ /* add_off is always equal to 0 on arm64 */
#endif
/*
@@ -1421,17 +1457,6 @@ static void kpatch_verify_patchability(struct kpatch_elf *kelf)
errs++;
}
- if (sec->status != SAME && sec->grouped) {
- log_normal("changed section %s is part of a section group\n",
- sec->name);
- errs++;
- }
-
- if (sec->sh.sh_type == SHT_GROUP && sec->status == NEW) {
- log_normal("new/changed group sections are not supported\n");
- errs++;
- }
-
/*
* ensure we aren't including .data.* or .bss.*
* (.data.unlikely and .data.once is ok b/c it only has __warned vars)
@@ -1458,6 +1483,7 @@ static void kpatch_include_section(struct section *sec)
/* Include the section and its section symbol */
if (sec->include)
return;
+
sec->include = 1;
if (sec->secsym)
sec->secsym->include = 1;
@@ -1640,7 +1666,7 @@ static void kpatch_include_force_elements(struct kpatch_elf *kelf)
sym->include = 0;
}
-int kpatch_include_new_static_var(struct kpatch_elf *kelf)
+static int kpatch_include_new_static_var(struct kpatch_elf *kelf)
{
struct symbol *sym;
@@ -2253,6 +2279,23 @@ static void kpatch_include_debug_sections(struct kpatch_elf *kelf)
}
}
+static void kpatch_ignore_debug_sections(struct kpatch_elf *kelf)
+{
+ struct section *sec;
+
+ /* include all .debug_* sections */
+ list_for_each_entry(sec, &kelf->sections, list) {
+ if (is_debug_section(sec)) {
+ sec->include = 0;
+ sec->status = SAME;
+ if (!is_rela_section(sec)) {
+ sec->secsym->include = 0;
+ sec->secsym->status = SAME;
+ }
+ }
+ }
+}
+
static void kpatch_mark_ignored_sections(struct kpatch_elf *kelf)
{
struct section *sec, *strsec, *ignoresec;
@@ -2589,14 +2632,13 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
funcs[index].old_size = result.size;
funcs[index].new_size = sym->sym.st_size;
funcs[index].sympos = result.pos;
- if (lookup_is_duplicate_symbol(table, sym->name)) {
+ if (lookup_is_duplicate_symbol(table, sym->name, objname, result.pos)) {
struct lookup_refsym refsym;
long offset;
- if (lookup_ref_symbol(table, sym->name, &refsym))
+ if (lookup_ref_symbol_offset(table, sym->name, &refsym, objname, &offset))
ERROR("unresolvable ambiguity on symbol %s\n", sym->name);
- offset = (long)result.value - (long)refsym.value;
funcs[index].ref_offset = offset;
/*
@@ -2631,7 +2673,7 @@ static void kpatch_create_patches_sections(struct kpatch_elf *kelf,
ALLOC_LINK(rela, &relasec->relas);
rela->sym = strsym;
rela->type = absolute_rela_type;
- rela->addend = offset_of_string(&kelf->strings, sym->name);
+ rela->addend = offset_of_string(&kelf->strings, strndup(sym->name, KSYM_NAME_LEN-1));
rela->offset = index * sizeof(*funcs) +
offsetof(struct kpatch_patch_func, name);
@@ -2780,13 +2822,14 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
*/
if (may_need_dynrela(rela))
toc_rela(rela)->need_dynrela = 1;
+
if (rela->sym->sec) {
if (rela->sym->type == STT_FUNC &&
- rela->sym->status == CHANGED &&
- rela->sym->sec != sec->base &&
- sec->base->sym &&
- sec->base->sym->type == STT_FUNC)
- toc_rela(rela)->need_dynrela = 1;
+ rela->sym->status == CHANGED &&
+ rela->sym->sec != sec->base &&
+ sec->base->sym &&
+ sec->base->sym->type == STT_FUNC)
+ toc_rela(rela)->need_dynrela = 1;
}
}
}
@@ -2820,6 +2863,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
if (!strcmp(sec->name, ".rela.kpatch.funcs") ||
!strcmp(sec->name, ".rela.kpatch.dynrelas"))
continue;
+
list_for_each_entry_safe(rela, safe, &sec->relas, list) {
if (!rela->need_dynrela)
continue;
@@ -2963,13 +3007,12 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
else {
/* for modules, src is discovered at runtime */
ksyms[index].src = 0;
- if (lookup_is_duplicate_symbol(table, rela->sym->name)) {
+ if (lookup_is_duplicate_symbol(table, rela->sym->name, objname, result.pos)) {
struct lookup_refsym refsym;
- if (lookup_ref_symbol(table, rela->sym->name, &refsym))
+ if (lookup_ref_symbol_offset(table, rela->sym->name, &refsym, objname, &ref_offset))
ERROR("unresolvable ambiguity on symbol %s\n", rela->sym->name);
- ref_offset = (long)result.value - (long)refsym.value;
/* add rela to fill in ref_name field */
ALLOC_LINK(rela2, &krela_sec->rela->relas);
rela2->sym = strsym;
@@ -2987,7 +3030,7 @@ static void kpatch_create_intermediate_sections(struct kpatch_elf *kelf,
ALLOC_LINK(rela2, &ksym_sec->rela->relas);
rela2->sym = strsym;
rela2->type = absolute_rela_type;
- rela2->addend = offset_of_string(&kelf->strings, rela->sym->name);
+ rela2->addend = offset_of_string(&kelf->strings, strndup(rela->sym->name, KSYM_NAME_LEN-1));
rela2->offset = index * sizeof(*ksyms) + \
offsetof(struct kpatch_symbol, name);
@@ -3163,6 +3206,9 @@ static void kpatch_create_mcount_sections(struct kpatch_elf *kelf)
* __fentry__" so that ftrace will be happy.
*/
newdata = malloc(sym->sec->data->d_size);
+ if (!newdata)
+ ERROR("malloc");
+
memcpy(newdata, sym->sec->data->d_buf, sym->sec->data->d_size);
sym->sec->data->d_buf = newdata;
insn = newdata;
@@ -3186,6 +3232,8 @@ static void kpatch_create_mcount_sections(struct kpatch_elf *kelf)
rela->offset = index * sizeof(*funcs);
newdata = malloc(sym->sec->data->d_size);
+ if (!newdata)
+ ERROR("malloc");
memcpy(newdata, sym->sec->data->d_buf, sym->sec->data->d_size);
sym->sec->data->d_buf = newdata;
insnp = newdata;
@@ -3354,6 +3402,8 @@ int main(int argc, char *argv[])
char *parent_symtab, *mod_symvers, *patch_name, *output_obj;
struct sym_compare_type *base_locals;
char *gcc_add_option, *mlongcall;
+ char *no_profiling_calls;
+ char *kallsyms;
arguments.debug = 0;
argp_parse (&argp, argc, argv, 0, NULL, &arguments);
@@ -3400,9 +3450,12 @@ int main(int argc, char *argv[])
return EXIT_STATUS_NO_CHANGE;
}
+ kallsyms = getenv("KALLSYMS");
+ if (kallsyms)
+ log_debug("kallsyms file:%s\n", kallsyms);
/* create symbol lookup table */
base_locals = kpatch_elf_locals(kelf_base);
- lookup = lookup_open(parent_symtab, mod_symvers, hint, base_locals);
+ lookup = lookup_open(parent_symtab, mod_symvers, hint, base_locals, kallsyms);
free(base_locals);
kpatch_mark_grouped_sections(kelf_patched);
@@ -3420,7 +3473,12 @@ int main(int argc, char *argv[])
*/
kpatch_mark_ignored_sections(kelf_patched);
kpatch_compare_correlated_elements(kelf_patched);
- kpatch_check_func_profiling_calls(kelf_patched);
+
+ no_profiling_calls = getenv("NO_PROFILING_CALLS");
+ if (!no_profiling_calls)
+ kpatch_check_func_profiling_calls(kelf_patched);
+ else
+ log_debug("NO_PROFILING_CALLS set\n");
kpatch_elf_teardown(kelf_base);
kpatch_elf_free(kelf_base);
@@ -3430,6 +3488,7 @@ int main(int argc, char *argv[])
kpatch_include_standard_elements(kelf_patched);
num_changed = kpatch_include_changed_functions(kelf_patched);
kpatch_include_debug_sections(kelf_patched);
+ kpatch_ignore_debug_sections(kelf_patched);
callbacks_exist = kpatch_include_callback_elements(kelf_patched);
kpatch_include_force_elements(kelf_patched);
new_globals_exist = kpatch_include_new_globals(kelf_patched);
@@ -3470,10 +3529,10 @@ int main(int argc, char *argv[])
kpatch_build_strings_section_data(kelf_out);
gcc_add_option = getenv("GCC_ADD_OPTION");
- printf("gcc add option :%s\n", gcc_add_option);
+ log_debug("gcc add option :%s\n", gcc_add_option);
mlongcall = strstr(gcc_add_option, "-mlong-calls");
if (arch == EM_AARCH64 && mlongcall) {
- printf("-mlong-calls found, no need to create mcount section\n");
+ log_debug("-mlong-calls found, no need to create mcount section\n");
} else {
kpatch_create_mcount_sections(kelf_out);
}
diff --git a/kpatch-build/create-klp-module.c b/kpatch-build/create-klp-module.c
index 253704b..7a72afd 100644
--- a/kpatch-build/create-klp-module.c
+++ b/kpatch-build/create-klp-module.c
@@ -38,7 +38,9 @@ enum loglevel loglevel = NORMAL;
*/
static struct symbol *find_or_add_ksym_to_symbols(struct kpatch_elf *kelf,
struct section *ksymsec,
- char *strings, int offset)
+ char *strings, int offset,
+ char *ref_name,
+ long ref_offset)
{
struct kpatch_symbol *ksyms, *ksym;
struct symbol *sym;
@@ -71,9 +73,14 @@ static struct symbol *find_or_add_ksym_to_symbols(struct kpatch_elf *kelf,
if (!objname)
ERROR("strdup");
- snprintf(pos, 32, "%lu", ksym->pos);
/* .klp.sym.objname.name,pos */
- snprintf(buf, 256, KLP_SYM_PREFIX "%s.%s,%s", objname, name, pos);
+ if (!ref_name) {
+ snprintf(pos, 32, "%lu", ksym->pos);
+ snprintf(buf, 256, KLP_SYM_PREFIX "%s.%s,%s", objname, name, pos);
+ } else {
+ snprintf(pos, 32, "%ld", ref_offset);
+ snprintf(buf, 256, KLP_SYM_PREFIX "%s-%s,%s", objname, ref_name, pos);
+ }
/* Look for an already allocated symbol */
list_for_each_entry(sym, &kelf->symbols, list) {
@@ -180,6 +187,7 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section
struct rela *rela;
char *objname;
int nr, index, offset, dest_off;
+ char *ref_name;
krelas = krelasec->data->d_buf;
nr = krelasec->data->d_size / sizeof(*krelas);
@@ -206,6 +214,17 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section
if (!objname)
ERROR("strdup");
+ /* Get the unique ref_name */
+ rela = find_rela_by_offset(krelasec->rela,
+ offset + offsetof(struct kpatch_relocation, ref_name));
+ if (!rela)
+ ref_name = NULL;
+ else {
+ ref_name = strdup(strings + rela->addend);
+ if (!ref_name)
+ ERROR("strdup");
+ }
+
/* Get the .kpatch.symbol entry for the rela src */
rela = find_rela_by_offset(krelasec->rela,
offset + offsetof(struct kpatch_relocation, ksym));
@@ -213,7 +232,7 @@ static void create_klp_relasecs_and_syms(struct kpatch_elf *kelf, struct section
ERROR("find_rela_by_offset");
/* Create (or find) a klp symbol from the rela src entry */
- sym = find_or_add_ksym_to_symbols(kelf, ksymsec, strings, rela->addend);
+ sym = find_or_add_ksym_to_symbols(kelf, ksymsec, strings, rela->addend, ref_name, krelas[index].ref_offset);
if (!sym)
ERROR("error finding or adding ksym to symtab");
diff --git a/kpatch-build/create-kpatch-module.c b/kpatch-build/create-kpatch-module.c
index 8292dc8..3e24b3a 100644
--- a/kpatch-build/create-kpatch-module.c
+++ b/kpatch-build/create-kpatch-module.c
@@ -112,14 +112,10 @@ static void create_dynamic_rela_sections(struct kpatch_elf *kelf, struct section
dynrelas[index].ref_name = krelas[index].ref_name;
dynrelas[index].ref_offset = krelas[index].ref_offset;
- if (dynrelas[index].ref_offset)
- {
- /* Get objname offset */
- rela = find_rela_by_offset(krelasec->rela,
- index * sizeof(*krelas) + offsetof(struct kpatch_relocation, ref_name));
- if (!rela) {
- ERROR("find_rela_by_offset");
- }
+ /* Get ref_name offset */
+ rela = find_rela_by_offset(krelasec->rela,
+ index * sizeof(*krelas) + offsetof(struct kpatch_relocation, ref_name));
+ if (rela) {
ref_name_offset = rela->addend;
/* ref_name */
ALLOC_LINK(rela, &dynsec->rela->relas);
@@ -128,9 +124,8 @@ static void create_dynamic_rela_sections(struct kpatch_elf *kelf, struct section
rela->addend = ref_name_offset;
rela->offset = index * sizeof(*dynrelas) + \
offsetof(struct kpatch_patch_dynrela, ref_name);
-
}
-
+
/* dest */
ALLOC_LINK(rela, &dynsec->rela->relas);
rela->sym = sym;
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index 81a6a44..a860f12 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -953,6 +953,10 @@ if grep "hulk" $SRCDIR/Makefile > /dev/null; then
export KCPPFLAGS="-D__HULK__ $KCPPFLAGS"
fi
+if [[ -n "$NO_STACK_CHECK" ]];then
+ export KCPPFLAGS="-D__ALL_FORCE__ $KCPPFLAGS"
+fi
+
echo "Building patch module: $MODNAME.ko"
if [[ -z "$USERSRCDIR" ]] && [[ "$DISTRO" = ubuntu ]]; then
@@ -990,6 +994,7 @@ KBUILD_EXTRA_SYMBOLS="$KBUILD_EXTRA_SYMBOLS" \
KPATCH_LDFLAGS="$KPATCH_LDFLAGS" \
CROSS_COMPILE="$ARCH_COMPILE" \
make 2>&1 | logger || die
+${ARCH_COMPILE}strip -g "$TEMPDIR/patch/$MODNAME.ko"
if ! "$KPATCH_MODULE"; then
if [[ -z "$KPATCH_LDFLAGS" ]]; then
@@ -1019,7 +1024,7 @@ fi
# column containing lines unique to first file.
UNDEFINED=$(comm -23 <(sort -u "${TEMPDIR}"/undefined_references) \
<(sort -u "${TEMPDIR}"/new_symbols) | tr '\n' ' ')
-[[ ! -z "$UNDEFINED" ]] && die "Undefined symbols: $UNDEFINED"
+[[ -z "$USERMODDIR" ]] && [[ ! -z "$UNDEFINED" ]] && die "Undefined symbols: $UNDEFINED"
cp -f "$TEMPDIR/patch/$MODNAME.ko" "$BASE" || die
diff --git a/kpatch-build/kpatch-elf.c b/kpatch-build/kpatch-elf.c
index fcb7161..0794031 100644
--- a/kpatch-build/kpatch-elf.c
+++ b/kpatch-build/kpatch-elf.c
@@ -700,8 +700,14 @@ void kpatch_reindex_elements(struct kpatch_elf *kelf)
unsigned int index;
index = 1; /* elf write function handles NULL section 0 */
- list_for_each_entry(sec, &kelf->sections, list)
+ list_for_each_entry(sec, &kelf->sections, list) {
sec->index = index++;
+ /*
+ * since we exclude .group section, we clear SHF_GROUP
+ * for every section in case of link error.
+ * */
+ sec->sh.sh_flags &= (~SHF_GROUP);
+ }
index = 0;
list_for_each_entry(sym, &kelf->symbols, list) {
diff --git a/kpatch-build/kpatch-gcc b/kpatch-build/kpatch-gcc
index be18847..d36e67b 100755
--- a/kpatch-build/kpatch-gcc
+++ b/kpatch-build/kpatch-gcc
@@ -13,7 +13,7 @@ fi
declare -a args=("$@")
-if [[ "$TOOLCHAINCMD" = ${ARCH_COMPILE}gcc ]] ; then
+if [[ "$TOOLCHAINCMD" = ${ARCH_COMPILE}gcc || "$TOOLCHAINCMD" = ${ARCH_COMPILE}g++ ]] ; then
while [ "$#" -gt 0 ]; do
if [ "$1" = "-o" ]; then
obj="$2"
diff --git a/kpatch-build/lookup.c b/kpatch-build/lookup.c
index e4677db..2a728f6 100644
--- a/kpatch-build/lookup.c
+++ b/kpatch-build/lookup.c
@@ -45,6 +45,7 @@ struct object_symbol {
char *name;
int type, bind;
int sec_index;
+ unsigned long kaddr;
};
struct export_symbol {
@@ -238,6 +239,8 @@ static void symtab_read(struct lookup_table *table, char *path)
table->obj_syms[i].bind = STB_GLOBAL;
} else if (!strcmp(bind, "WEAK")) {
table->obj_syms[i].bind = STB_WEAK;
+ } else if (!strcmp(bind, "GNU_UNIQUE")) {
+ table->obj_syms[i].bind = STB_GNU_UNIQUE;
} else {
ERROR("unknown symbol bind %s", bind);
}
@@ -263,6 +266,56 @@ static void symtab_read(struct lookup_table *table, char *path)
fclose(file);
}
+static void ksymtab_read(struct lookup_table *table, char *path)
+{
+ FILE *file;
+ struct object_symbol *sym, *sym1, *sym2;
+ unsigned long value;
+ int i, j, idx;
+ char line[256], name[256], type[256], mod[256];
+ idx = 0;
+
+ if ((file = fopen(path, "r")) == NULL)
+ ERROR("fopen");
+
+ while (fgets(line, 256, file)) {
+ if (sscanf(line, "%lx %s %s [%s]\n",
+ &value, type, name, mod) != 4)
+ continue;
+
+ if (name[0] == '$')
+ continue;
+
+ i = idx;
+ for_each_obj_symbol_continue(i, sym, table) {
+ if (!strncmp(sym->name, name, KSYM_NAME_LEN-1)) {
+ sym->kaddr = value;
+ idx = i + 1;
+ break;
+ }
+ }
+ }
+
+ for_each_obj_symbol(i, sym1, table) {
+ if (sym1->kaddr == 0)
+ continue;
+ for_each_obj_symbol(j, sym2, table) {
+ if (sym2->kaddr == 0)
+ continue;
+ if (sym1 == sym2)
+ continue;
+ if (sym1->sec_index != sym2->sec_index)
+ continue;
+ if ((long)sym1->value - (long)sym2->value ==
+ (long)sym1->kaddr - (long)sym2->kaddr)
+ continue;
+
+ ERROR("base mismatch(symbol offset)");
+ }
+ }
+ fclose(file);
+}
+
static void symvers_read(struct lookup_table *table, char *path)
{
FILE *file;
@@ -306,7 +359,8 @@ static void symvers_read(struct lookup_table *table, char *path)
}
struct lookup_table *lookup_open(char *symtab_path, char *symvers_path,
- char *hint, struct sym_compare_type *locals)
+ char *hint, struct sym_compare_type *locals,
+ char *kallsyms)
{
struct lookup_table *table;
@@ -317,6 +371,8 @@ struct lookup_table *lookup_open(char *symtab_path, char *symvers_path,
symtab_read(table, symtab_path);
symvers_read(table, symvers_path);
+ if (kallsyms)
+ ksymtab_read(table, kallsyms);
find_local_syms(table, hint, locals);
return table;
@@ -343,6 +399,15 @@ int lookup_local_symbol(struct lookup_table *table, char *name,
for_each_obj_symbol(i, sym, table) {
if (sym->bind == STB_LOCAL && !strcmp(sym->name, name))
pos++;
+ else {
+ /* symbol name longer than KSYM_NAME_LEN will be truncated
+ * by kernel, so we can not find it using its original
+ * name. we need to add pos for symbols which have same
+ * KSYM_NAME_LEN-1 long prefix.*/
+ if (strlen(name) >= KSYM_NAME_LEN-1 &&
+ !strncmp(sym->name, name, KSYM_NAME_LEN-1))
+ pos++;
+ }
if (table->local_syms == sym) {
in_file = 1;
@@ -374,15 +439,25 @@ int lookup_global_symbol(struct lookup_table *table, char *name,
struct lookup_result *result)
{
struct object_symbol *sym;
+ unsigned long pos = 0;
int i;
memset(result, 0, sizeof(*result));
for_each_obj_symbol(i, sym, table) {
- if ((sym->bind == STB_GLOBAL || sym->bind == STB_WEAK) &&
+ /* symbol name longer than KSYM_NAME_LEN will be truncated
+ * by kernel, so we can not find it using its original
+ * name. we need to add pos for symbols which have same
+ * KSYM_NAME_LEN-1 long prefix.*/
+ if (strlen(name) >= KSYM_NAME_LEN-1 &&
+ !strncmp(sym->name, name, KSYM_NAME_LEN-1))
+ pos++;
+
+ if ((sym->bind == STB_GLOBAL || sym->bind == STB_WEAK
+ || sym->bind == STB_GNU_UNIQUE) &&
!strcmp(sym->name, name)) {
result->value = sym->value;
result->size = sym->size;
- result->pos = 0; /* always 0 for global symbols */
+ result->pos = pos;
return 0;
}
}
@@ -429,10 +504,12 @@ char *lookup_exported_symbol_objname(struct lookup_table *table, char *name)
return NULL;
}
-int lookup_is_duplicate_symbol(struct lookup_table *table, char *name)
+int lookup_is_duplicate_symbol(struct lookup_table *table, char *name,
+ char *objname, unsigned long pos)
{
struct object_symbol *sym;
int i, count = 0;
+ char posstr[32], buf[256];
for_each_obj_symbol(i, sym, table)
if (!strcmp(sym->name, name)) {
@@ -441,6 +518,17 @@ int lookup_is_duplicate_symbol(struct lookup_table *table, char *name)
return 1;
}
+ /* symbol name longer than KSYM_NAME_LEN will be truncated
+ * by kernel, so we can not find it using its original
+ * name. Here, we consider these long name symbol as duplicated
+ * symbols. since create_klp_module will create symbol name
+ * format like .klp.sym.objname.symbol,pos, so we consider name
+ * length longer than KSYM_NAME_LEN-1 bytes as duplicated symbol*/
+ snprintf(posstr, 32, "%lu", pos);
+ snprintf(buf, 256, KLP_SYM_PREFIX "%s.%s,%s", objname, name, posstr);
+ if (strlen(buf) >= KSYM_NAME_LEN-1)
+ return 1;
+
return 0;
}
@@ -487,24 +575,45 @@ struct object_symbol *lookup_find_symbol_by_name(struct lookup_table *table, cha
return sym;
}
-int lookup_ref_symbol(struct lookup_table *table, char *name,
- struct lookup_refsym *refsym)
+int lookup_ref_symbol_offset(struct lookup_table *table, char *name,
+ struct lookup_refsym *refsym,
+ char *objname, long *offset)
{
struct object_symbol *orig_sym, *sym;
int i;
orig_sym = lookup_find_symbol_by_name(table, name);
if (!orig_sym)
- ERROR("lookup_ref_symbol");
+ ERROR("lookup_ref_symbol_offset");
memset(refsym, 0, sizeof(*refsym));
+
+ /*find a unique symbol in the same section first*/
for_each_obj_symbol(i, sym, table) {
if (!strcmp(sym->name, name) || sym->type == STT_FILE ||
sym->sec_index != orig_sym->sec_index)
continue;
- if (!lookup_is_duplicate_symbol(table, sym->name)) {
+ if (!lookup_is_duplicate_symbol(table, sym->name, objname, 1)) {
refsym->name = sym->name;
refsym->value = sym->value;
+ *offset = (long)orig_sym->value - (long)sym->value;
+ return 0;
+ }
+ }
+
+ if (orig_sym->kaddr == 0)
+ return 1;
+
+ /*find a unique symbol has kaddr*/
+ for_each_obj_symbol(i, sym, table) {
+ if (!strcmp(sym->name, name) || sym->type == STT_FILE ||
+ sym->kaddr == 0)
+ continue;
+
+ if (!lookup_is_duplicate_symbol(table, sym->name, objname, 1)) {
+ refsym->name = sym->name;
+ refsym->value = 0;
+ *offset = (long)orig_sym->kaddr - (long)sym->kaddr;
return 0;
}
}
diff --git a/kpatch-build/lookup.h b/kpatch-build/lookup.h
index 5ad9241..00b6ccc 100644
--- a/kpatch-build/lookup.h
+++ b/kpatch-build/lookup.h
@@ -1,6 +1,9 @@
#ifndef _LOOKUP_H_
#define _LOOKUP_H_
+#include "kpatch-elf.h"
+#define KSYM_NAME_LEN 128
+
struct lookup_table;
struct lookup_result {
@@ -20,7 +23,8 @@ struct lookup_refsym {
};
struct lookup_table *lookup_open(char *symtab_path, char *symvers_path,
- char *hint, struct sym_compare_type *locals);
+ char *hint, struct sym_compare_type *locals,
+ char *kallsyms);
void lookup_close(struct lookup_table *table);
int lookup_local_symbol(struct lookup_table *table, char *name,
struct lookup_result *result);
@@ -28,8 +32,10 @@ int lookup_global_symbol(struct lookup_table *table, char *name,
struct lookup_result *result);
int lookup_is_exported_symbol(struct lookup_table *table, char *name);
char *lookup_exported_symbol_objname(struct lookup_table *table, char *name);
-int lookup_is_duplicate_symbol(struct lookup_table *table, char *name);
-int lookup_ref_symbol(struct lookup_table *table, char *name,
- struct lookup_refsym *refsym);
+int lookup_is_duplicate_symbol(struct lookup_table *table, char *name,
+ char *objname, unsigned long pos);
+int lookup_ref_symbol_offset(struct lookup_table *table, char *name,
+ struct lookup_refsym *refsym, char *objname,
+ long *offset);
#endif /* _LOOKUP_H_ */
--
1.7.5.4

View File

@ -0,0 +1,28 @@
From e617351fafaf7504a531fd00a49994653e59a737 Mon Sep 17 00:00:00 2001
From: Zhiyu Hu <huzhiyu1@huawei.com>
Date: Fri, 28 Dec 2018 07:06:38 +0000
Subject: [PATCH] fix rodata.str problem
fix some rodata.str problem
Signed-off-by: Zhiyu Hu <huzhiyu1@huawei.com>
---
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 d2e6aee..f075671 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -1552,7 +1552,7 @@ static void kpatch_include_standard_elements(struct kpatch_elf *kelf)
!strcmp(sec->name, ".toc") ||
!strcmp(sec->name, ".rodata") ||
(!strncmp(sec->name, ".rodata.", 8) &&
- strstr(sec->name, ".str1."))) {
+ strstr(sec->name, ".str"))) {
kpatch_include_section(sec);
}
}
--
1.8.3.1

View File

@ -0,0 +1,28 @@
From f221fbe8ff0c22b61aaf42687f5ece04f10ec403 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Thu, 17 Jan 2019 20:50:25 +0000
Subject: [PATCH] kpatch-build: adapt for ksymtab in 4.19 kernel
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/create-diff-object.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/kpatch-build/create-diff-object.c b/kpatch-build/create-diff-object.c
index f075671..2ddd00d 100644
--- a/kpatch-build/create-diff-object.c
+++ b/kpatch-build/create-diff-object.c
@@ -1664,8 +1664,8 @@ static int kpatch_include_new_static_var(struct kpatch_elf *kelf)
list_for_each_entry(sym, &kelf->symbols, list) {
if (sym->status == NEW &&
- sym->type == STT_OBJECT &&
- sym->bind == STB_LOCAL)
+ sym->bind == STB_LOCAL &&
+ (sym->type == STT_OBJECT || (sym->type == STT_NOTYPE && sym->name[0] != '$')))
kpatch_include_symbol(sym);
}
--
1.7.5.4

View File

@ -0,0 +1,91 @@
From 6b7ff79bb40a7dbb28e6aba320e4ac075e4c182d Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Fri, 18 Jan 2019 00:07:02 +0000
Subject: [PATCH] support force enable/disable for kernel 4.19
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kmod/patch/livepatch-patch-hook.c | 7 +++++--
kpatch-build/kpatch-build | 12 ++++++++++--
2 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/kmod/patch/livepatch-patch-hook.c b/kmod/patch/livepatch-patch-hook.c
index ce1c955..919dfc7 100644
--- a/kmod/patch/livepatch-patch-hook.c
+++ b/kmod/patch/livepatch-patch-hook.c
@@ -511,14 +511,17 @@ static int __init patch_init(void)
#ifdef __HULK__
lfunc->old_size = func->kfunc->old_size;
lfunc->new_size = func->kfunc->new_size;
+ lfunc->ref_name= func->kfunc->ref_name;
+ lfunc->ref_offset = func->kfunc->ref_offset;
+#endif
+#if defined(__HULK__) || defined(__KLP_SUPPORT_FORCE__)
#ifdef __ALL_FORCE__
lfunc->force = 1;
#else
lfunc->force = patch_is_func_forced(func->kfunc->new_addr);
#endif
- lfunc->ref_name= func->kfunc->ref_name;
- lfunc->ref_offset = func->kfunc->ref_offset;
#endif
+
j++;
}
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index a860f12..c227b44 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -279,7 +279,7 @@ find_special_section_data() {
# shellcheck disable=SC2086
SPECIAL_VARS="$(readelf -wi "$VMLINUX" |
gawk --non-decimal-data $AWK_OPTIONS '
- BEGIN { a = b = p = e = o = 0 }
+ BEGIN { a = b = p = e = o = f = 0 }
# Set state if name matches
a == 0 && /DW_AT_name.* alt_instr[[:space:]]*$/ {a = 1; next}
@@ -287,6 +287,7 @@ find_special_section_data() {
p == 0 && /DW_AT_name.* paravirt_patch_site[[:space:]]*$/ {p = 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}
+ f == 0 && /DW_AT_name.* klp_func[[:space:]]*$/ {f = 1; next}
# Reset state unless this abbrev describes the struct size
a == 1 && !/DW_AT_byte_size/ { a = 0; next }
@@ -294,6 +295,8 @@ find_special_section_data() {
p == 1 && !/DW_AT_byte_size/ { p = 0; next }
e == 1 && !/DW_AT_byte_size/ { e = 0; next }
o == 1 && !/DW_AT_byte_size/ { o = 0; next }
+ f == 1 && /DW_TAG_structure_type/ { f = 3; next }
+ f == 1 && /DW_AT_name.* force[[:space:]]*$/ {f = 2; next}
# Now that we know the size, stop parsing for it
a == 1 {printf("export ALT_STRUCT_SIZE=%d\n", $4); a = 2}
@@ -301,9 +304,10 @@ find_special_section_data() {
p == 1 {printf("export PARA_STRUCT_SIZE=%d\n", $4); p = 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}
+ f == 2 {printf("export KLP_SUPPORT_FORCE=y\n"); f = 3}
# Bail out once we have everything
- a == 2 && b == 2 && (p == 2 || skip_p) && e == 2 && (o == 2 || skip_o) {exit}')"
+ a == 2 && b == 2 && (p == 2 || skip_p) && e == 2 && (o == 2 || skip_o) && f == 3 {exit}')"
[[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS"
@@ -957,6 +961,10 @@ if [[ -n "$NO_STACK_CHECK" ]];then
export KCPPFLAGS="-D__ALL_FORCE__ $KCPPFLAGS"
fi
+if [[ -n "$KLP_SUPPORT_FORCE" ]];then
+ export KCPPFLAGS="-D__KLP_SUPPORT_FORCE__ $KCPPFLAGS"
+fi
+
echo "Building patch module: $MODNAME.ko"
if [[ -z "$USERSRCDIR" ]] && [[ "$DISTRO" = ubuntu ]]; then
--
1.7.5.4

View File

@ -0,0 +1,118 @@
From 87203483495fec8ad1394def83fa884a96b711ec Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Thu, 14 Feb 2019 14:21:20 +0000
Subject: [PATCH] kpatch-build: adapt for native compile_env
we check vmlinux to determine if klp_func and klp_object
have some members and set flag for livepatch-patch-hook.c.
support arm64 native compile enviroment.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/kpatch-build | 46 ++++++++++++++++++++++++++++++++++----------
1 files changed, 35 insertions(+), 11 deletions(-)
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index c227b44..18f79d4 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -279,7 +279,7 @@ find_special_section_data() {
# shellcheck disable=SC2086
SPECIAL_VARS="$(readelf -wi "$VMLINUX" |
gawk --non-decimal-data $AWK_OPTIONS '
- BEGIN { a = b = p = e = o = f = 0 }
+ BEGIN { a = b = p = e = o = c = f = s = i = r = j = h = 0 }
# Set state if name matches
a == 0 && /DW_AT_name.* alt_instr[[:space:]]*$/ {a = 1; next}
@@ -287,7 +287,8 @@ find_special_section_data() {
p == 0 && /DW_AT_name.* paravirt_patch_site[[:space:]]*$/ {p = 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}
- f == 0 && /DW_AT_name.* klp_func[[:space:]]*$/ {f = 1; next}
+ c == 0 && /DW_AT_name.* klp_func[[:space:]]*$/ {c = 1; next}
+ j == 0 && /DW_AT_name.* klp_object[[:space:]]*$/ {j = 1; next}
# Reset state unless this abbrev describes the struct size
a == 1 && !/DW_AT_byte_size/ { a = 0; next }
@@ -295,8 +296,13 @@ find_special_section_data() {
p == 1 && !/DW_AT_byte_size/ { p = 0; next }
e == 1 && !/DW_AT_byte_size/ { e = 0; next }
o == 1 && !/DW_AT_byte_size/ { o = 0; next }
- f == 1 && /DW_TAG_structure_type/ { f = 3; next }
- f == 1 && /DW_AT_name.* force[[:space:]]*$/ {f = 2; next}
+ c == 1 && /DW_TAG_structure_type/ { c = 3; next }
+ j == 1 && /DW_TAG_structure_type/ { j = 3; next }
+ c == 1 && /DW_AT_name.* force[[:space:]]*$/ {f = 2; next}
+ c == 1 && /DW_AT_name.* old_sympos[[:space:]]*$/ {s = 2; next}
+ i == 1 && /DW_AT_name.* immediate[[:space:]]*$/ {i = 2; next}
+ j == 1 && /DW_AT_name.* relocs[[:space:]]*$/ {r = 2; next}
+ j == 1 && /DW_AT_name.* hooks_load[[:space:]]*$/ {h = 2; next}
# Now that we know the size, stop parsing for it
a == 1 {printf("export ALT_STRUCT_SIZE=%d\n", $4); a = 2}
@@ -304,10 +310,14 @@ find_special_section_data() {
p == 1 {printf("export PARA_STRUCT_SIZE=%d\n", $4); p = 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}
- f == 2 {printf("export KLP_SUPPORT_FORCE=y\n"); f = 3}
+ f == 2 {printf("export KLP_SUPPORT_FORCE=y\n"); f = 3}
+ s == 2 {printf("export KLP_SUPPORT_OLD_SYMPOS=y\n"); s = 3}
+ i == 2 {printf("export KLP_SUPPORT_IMMEDIATE=y\n"); i = 3}
+ r == 2 {printf("export KLP_SUPPORT_RELOCS=y\n"); r = 3}
+ h == 2 {printf("export KLP_SUPPORT_LOADHOOKS=y\n"); h = 3}
# Bail out once we have everything
- a == 2 && b == 2 && (p == 2 || skip_p) && e == 2 && (o == 2 || skip_o) && f == 3 {exit}')"
+ a == 2 && b == 2 && (p == 2 || skip_p) && e == 2 && (o == 2 || skip_o) && c == 3 && j == 3 {exit}')"
[[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS"
@@ -406,7 +416,9 @@ arch_export() {
export GCC_ADD_OPTION=
elif [[ $E_MACHINE -eq 183 ]]; then
export ARCH=arm64
- export ARCH_COMPILE=aarch64-linux-gnu-
+ if [ $(arch) != "aarch64" ]; then
+ export ARCH_COMPILE=aarch64-linux-gnu-
+ fi
export ENDIAN=little
if grep "\-mlong-calls" $SRCDIR/Makefile > /dev/null; then
export GCC_ADD_OPTION="-fno-section-anchors -mlong-calls"
@@ -953,10 +965,6 @@ if "$KPATCH_MODULE"; then
export KCPPFLAGS="-D__KPATCH_MODULE__"
fi
-if grep "hulk" $SRCDIR/Makefile > /dev/null; then
- export KCPPFLAGS="-D__HULK__ $KCPPFLAGS"
-fi
-
if [[ -n "$NO_STACK_CHECK" ]];then
export KCPPFLAGS="-D__ALL_FORCE__ $KCPPFLAGS"
fi
@@ -965,6 +973,22 @@ if [[ -n "$KLP_SUPPORT_FORCE" ]];then
export KCPPFLAGS="-D__KLP_SUPPORT_FORCE__ $KCPPFLAGS"
fi
+if [[ -n "$KLP_SUPPORT_OLD_SYMPOS" ]];then
+ export KCPPFLAGS="-DHAVE_SYMPOS $KCPPFLAGS"
+fi
+
+if [[ -n "$KLP_SUPPORT_IMMEDIATE" ]];then
+ export KCPPFLAGS="-DHAVE_IMMEDIATE $KCPPFLAGS"
+fi
+
+if [[ -n "$KLP_SUPPORT_RELOCS" ]];then
+ export KCPPFLAGS="-DHAVE_ELF_RELOCS $KCPPFLAGS"
+fi
+
+if [[ -n "$KLP_SUPPORT_LOADHOOKS" ]];then
+ export KCPPFLAGS="-DHAVE_LOADHOOKS $KCPPFLAGS"
+fi
+
echo "Building patch module: $MODNAME.ko"
if [[ -z "$USERSRCDIR" ]] && [[ "$DISTRO" = ubuntu ]]; then
--
1.7.5.4

View File

@ -0,0 +1,96 @@
From d53b2d1f87f5e891ba8f6945765134da9ee2d29d Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Thu, 7 Mar 2019 14:38:15 +0000
Subject: [PATCH] add find_special_section_data_arm64 for arm64
arm64 kernel have no paravirt_patch_site or orc_entry structure
in vmlinux, we don't need to check these two struct for arm64.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/kpatch-build | 56 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 55 insertions(+), 1 deletion(-)
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index 18f79d4..59af250 100755
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -266,12 +266,66 @@ find_special_section_data_ppc64le() {
return
}
+find_special_section_data_arm64() {
+
+ # If $AWK_OPTIONS are blank gawk would treat "" as a blank script
+ # shellcheck disable=SC2086
+ SPECIAL_VARS="$(readelf -wi "$VMLINUX" |
+ gawk --non-decimal-data $AWK_OPTIONS '
+ BEGIN { a = b = e = c = f = s = i = r = j = h = 0 }
+
+ # Set state if name matches
+ a == 0 && /DW_AT_name.* alt_instr[[:space:]]*$/ {a = 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}
+ c == 0 && /DW_AT_name.* klp_func[[:space:]]*$/ {c = 1; next}
+ j == 0 && /DW_AT_name.* klp_object[[:space:]]*$/ {j = 1; next}
+
+ # Reset state unless this abbrev describes the struct size
+ a == 1 && !/DW_AT_byte_size/ { a = 0; next }
+ b == 1 && !/DW_AT_byte_size/ { b = 0; next }
+ e == 1 && !/DW_AT_byte_size/ { e = 0; next }
+ c == 1 && /DW_TAG_structure_type/ { c = 3; next }
+ j == 1 && /DW_TAG_structure_type/ { j = 3; next }
+ c == 1 && /DW_AT_name.* force[[:space:]]*$/ {f = 2; next}
+ c == 1 && /DW_AT_name.* old_sympos[[:space:]]*$/ {s = 2; next}
+ i == 1 && /DW_AT_name.* immediate[[:space:]]*$/ {i = 2; next}
+ j == 1 && /DW_AT_name.* relocs[[:space:]]*$/ {r = 2; next}
+ j == 1 && /DW_AT_name.* hooks_load[[:space:]]*$/ {h = 2; next}
+
+ # Now that we know the size, stop parsing for it
+ a == 1 {printf("export ALT_STRUCT_SIZE=%d\n", $4); a = 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}
+ f == 2 {printf("export KLP_SUPPORT_FORCE=y\n"); f = 3}
+ s == 2 {printf("export KLP_SUPPORT_OLD_SYMPOS=y\n"); s = 3}
+ i == 2 {printf("export KLP_SUPPORT_IMMEDIATE=y\n"); i = 3}
+ r == 2 {printf("export KLP_SUPPORT_RELOCS=y\n"); r = 3}
+ h == 2 {printf("export KLP_SUPPORT_LOADHOOKS=y\n"); h = 3}
+
+ # Bail out once we have everything
+ a == 2 && b == 2 && e == 2 && c == 3 && j == 3 {exit}')"
+
+ [[ -n "$SPECIAL_VARS" ]] && eval "$SPECIAL_VARS"
+
+ [[ -z "$ALT_STRUCT_SIZE" ]] && die "can't find special struct alt_instr 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"
+
+ return
+}
+
find_special_section_data() {
if [[ "$ARCH" = "ppc64le" ]]; then
find_special_section_data_ppc64le
return
fi
+ if [[ "$ARCH" = "arm64" ]]; then
+ find_special_section_data_arm64
+ return
+ fi
+
[[ "$CONFIG_PARAVIRT" -eq 0 ]] && AWK_OPTIONS="-vskip_p=1"
[[ "$CONFIG_UNWINDER_ORC" -eq 0 ]] && AWK_OPTIONS="$AWK_OPTIONS -vskip_o=1"
@@ -323,7 +377,7 @@ find_special_section_data() {
[[ -z "$ALT_STRUCT_SIZE" ]] && die "can't find special struct alt_instr size"
[[ -z "$BUG_STRUCT_SIZE" ]] && die "can't find special struct bug_entry size"
- [[ -z "$EX_STRUCT_SIZE" ]] && die "can't find special struct paravirt_patch_site size"
+ [[ -z "$EX_STRUCT_SIZE" ]] && die "can't find special struct exception_table_entry 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"
--
2.19.1

View File

@ -0,0 +1,31 @@
From 1069d212fd848f1f1e2425dffe8e9aea188c6150 Mon Sep 17 00:00:00 2001
From: Zhipeng Xie <xiezhipeng1@huawei.com>
Date: Tue, 21 Dec 2083 12:18:38 +0800
Subject: [PATCH] fix ref static local symbol for longname symbol
static local symbol have a "." which will confuse
the kernel livepatch klp_resolve_symbols. So, pass
static local symbols in lookup_ref_symbol_offset.
Signed-off-by: Zhipeng Xie <xiezhipeng1@huawei.com>
---
kpatch-build/lookup.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/kpatch-build/lookup.c b/kpatch-build/lookup.c
index 2e55862..01abc41 100644
--- a/kpatch-build/lookup.c
+++ b/kpatch-build/lookup.c
@@ -591,7 +591,8 @@ int lookup_ref_symbol_offset(struct lookup_table *table, char *name,
/*find a unique symbol in the same section first*/
for_each_obj_symbol(i, sym, table) {
if (!strcmp(sym->name, name) || sym->type == STT_FILE ||
- sym->sec_index != orig_sym->sec_index)
+ sym->sec_index != orig_sym->sec_index ||
+ strchr(sym->name, '.'))
continue;
if (!lookup_is_duplicate_symbol(table, sym->name, objname, 1)) {
--
2.19.1

View File

@ -0,0 +1,33 @@
From d6304fcd36edd4e9df48687517f30965d9a790e9 Mon Sep 17 00:00:00 2001
From: Bin Yang <robin.yb@huawei.com>
Date: Tue, 16 Jul 2019 14:39:27 +0800
Subject: [PATCH] add object in kpatch
---
kpatch-build/kpatch-build | 3 +++
1 file changed, 3 insertions(+)
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
index 59af250..f685654 100644
--- a/kpatch-build/kpatch-build
+++ b/kpatch-build/kpatch-build
@@ -1011,6 +1011,8 @@ echo -n "Patched objects:"
for i in $(echo "${objnames[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' ')
do
echo -n " $i"
+ echo -n " $(basename $i)"
+ echo -n "$(basename $i)" >> $TEMPDIR/patch/object
done
echo
@@ -1113,6 +1115,7 @@ UNDEFINED=$(comm -23 <(sort -u "${TEMPDIR}"/undefined_references) \
[[ -z "$USERMODDIR" ]] && [[ ! -z "$UNDEFINED" ]] && die "Undefined symbols: $UNDEFINED"
cp -f "$TEMPDIR/patch/$MODNAME.ko" "$BASE" || die
+cp -f "$TEMPDIR/patch/object" "$BASE" || die
[[ "$DEBUG" -eq 0 ]] && rm -f "$LOGFILE"
--
2.17.1

View File

@ -0,0 +1,34 @@
From da3eed612df1d26e19b0678763e116f666da13b2 Mon Sep 17 00:00:00 2001
From: Artem Savkov <asavkov@redhat.com>
Date: Wed, 14 Nov 2018 12:33:13 +0100
Subject: [PATCH] kmod/core: fix compilation with
CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
Kernel commit 7290d5809571 "module: use relative references for
__ksymtab entries" changed kernel_symbol structure on some
architectures. Adjust kmod/core/core.c accordingly.
Signed-off-by: Artem Savkov <asavkov@redhat.com>
---
kmod/core/core.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/kmod/core/core.c b/kmod/core/core.c
index 4a73a47..a91d417 100644
--- a/kmod/core/core.c
+++ b/kmod/core/core.c
@@ -651,7 +651,11 @@ static int kpatch_find_external_symbol(const char *objname, const char *name,
sym = find_symbol(name, NULL, NULL, true, true);
preempt_enable();
if (sym) {
+#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
+ *addr = (unsigned long)offset_to_ptr(&sym->value_offset);
+#else
*addr = sym->value;
+#endif
return 0;
}
--
2.19.1

View File

@ -1,39 +0,0 @@
# kpatch
#### 介绍
{**以下是码云平台说明,您可以替换此简介**
码云是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN。专为开发者提供稳定、高效、安全的云端软件开发协作平台
无论是个人、团队、或是企业,都能够用码云实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)}
#### 软件架构
软件架构说明
#### 安装教程
1. xxxx
2. xxxx
3. xxxx
#### 使用说明
1. xxxx
2. xxxx
3. xxxx
#### 参与贡献
1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
#### 码云特技
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
2. 码云官方博客 [blog.gitee.com](https://blog.gitee.com)
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解码云上的优秀开源项目
4. [GVP](https://gitee.com/gvp) 全称是码云最有价值开源项目,是码云综合评定出的优秀开源项目
5. 码云官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
6. 码云封面人物是一档用来展示码云会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

BIN
kpatch-0.6.1.tar.gz Normal file

Binary file not shown.

249
kpatch.spec Normal file
View File

@ -0,0 +1,249 @@
%global raw_version 0.6.1
Name: kpatch
Version: 2.0
Release: 3.1.22
Summary: A Linux dynamic kernel patching infrastructure
License: GPLv2
URL: https://github.com/dynup/kpatch
Source0: https://github.com/dynup/kpatch/archive/%{name}-%{raw_version}.tar.gz
Source1: os_hotpatch
Source2: livepatch
Source3: make_hotpatch
Patch9001: 9001-livepatch-patch-hook-don-t-active-patch-when-insmod.patch
Patch9002: 9002-kpatch-build-support-third-party-module-make-hotpatc.patch
Patch9003: 9003-kpatch-build-support-makefile-not-in-third-party-mod.patch
Patch9004: 9004-create-diff-object-new-static-var-should-be-included.patch
Patch9005: 9005-livepatch-fix-use-THIS-modname-as-the-name-of-ddebug.patch
Patch9006: 9006-create-diff-object-fix-correlate-static-local-variab.patch
Patch9007: 9007-create-diff-object-don-t-create-dynamic-reloc-for-sy.patch
Patch9008: 9008-livepatch-patch-hook-support-force-enable-disable-fu.patch
Patch9009: 9009-kmod-kpatch-build-support-build-patch-for-old-kernel.patch
Patch9010: 9010-kmod-kpatch-build-support-cross-compile-hotpatch-for.patch
Patch9011: 9011-kpatch-build-use-.klp.rela-in-euleros-7.5-kernel.patch
Patch9012: 9012-create-diff-object-create-dynamic-relocs-for-changed.patch
Patch9013: 9013-kmod-kpatch-build-fix-duplicate-symbol-relocation-fo.patch
Patch9014: 9014-create-diff-object-add-dynamic-reloction-for-functio.patch
Patch9015: 9015-create-diff-object-exclude-line-only-change-for-arm6.patch
Patch9016: 9016-kpatch-build-include-secsym-in-kpatch_mark_ignored_s.patch
Patch9017: 9017-support-compile-kpatch-on-aarch64.patch
Patch9018: 9018-support-c-plus-kernel-module.patch
Patch9019: 9019-fix-rodata.str-problem.patch
Patch9020: 0001-Add-__addressable_-to-maybe_discarded_sym.patch
Patch9021: 0002-kmod-patch-fix-patch-linking-with-4.20.patch
Patch9022: 0003-kmod-patch-more-linking-fixes.patch
Patch9023: 9023-kpatch-build-adapt-for-ksymtab-in-4.19-kernel.patch
Patch9024: 9024-support-force-enable-disable-for-kernel-4.19.patch
Patch9025: 9025-kpatch-build-adapt-for-native-compile_env.patch
Patch9026: 9026-add-find_special_section_data_arm64-for-arm64.patch
Patch9027: 9027-fix-ref-static-local-symbol-for-longname-symbol.patch
Patch9028: 9028-add-object-in-kpatch.patch
Patch9029: 0004-create-diff-object-allow-changing-subsections.patch
Patch9030: 9030-kmod-core-fix-compilation-with-CONFIG_HAVE_ARCH_PREL.patch
BuildRequires: gcc elfutils-libelf-devel uname-build-checks kernel kernel-devel
Requires: bc tar bash kmod
Provides: kpatch-runtime
Obsoletes: kpatch-runtime
%description
kpatch is a Linux dynamic kernel patching infrastructure which allows you to patch
a running kernel without rebooting or restarting any processes. It enables sysadmins
to apply critical security patches to the kernel immediately, without having to wait
for long-running tasks to complete, for users to log off, or for scheduled reboot
windows. It gives more control over uptime without sacrificing security or stability.
%package_help
%prep
%autosetup -n %{name}-%{raw_version} -p1
%build
export CFLAGS="$RPM_OPT_FLAGS" LDFLAGS="$RPM_LD_FLAGS"
%make_build
%install
%make_install PREFIX=%{_prefix}
install -Dm 0750 -t %{buildroot}/%{_bindir} %{SOURCE1} %{SOURCE2}
install -Dm 0500 -t %{buildroot}/opt/patch_workspace/ %{SOURCE3}
pushd %{buildroot}/opt/patch_workspace
mkdir hotpatch package
popd
%files
%defattr(-,root,root)
%doc COPYING README.md
%{_bindir}/*
%{_prefix}/lib/systemd/system/*
%{_libexecdir}/kpatch
%{_prefix}/sbin/kpatch
%{_datadir}/%{name}/*
%{_sysconfdir}/init/*
%{_bindir}/livepatch
%{_bindir}/os_hotpatch
/opt/patch_workspace/*
%ifarch x86_64
%{_prefix}/lib/kpatch
%endif
%files help
%{_mandir}/man1/*.1.gz
%changelog
* Mon Dec 30 2019 openEuler Buildteam <buildteam@openeuler.org> -2.0-3.1.22
- Type:enhancement
- ID:NA
- SUG:NA
- DESC:change some patch name and delete useless code
* Mon Dec 23 2019 openEuler Buildteam <buildteam@openeuler.org> -2.0-3.1.21
- Type:enhancement
- ID:NA
- SUG:NA
- DESC:modify email adress
* Thu Dec 19 2019 chengquan<chengquan3@huawei.com> -2.0-3.1.20
- Type:enhancement
- ID:NA
- SUG:NA
- DESC:remove useless description
* Thu Nov 28 2019 Yufa Fang<fangyufa1@huawei.com> - 2.0-3.1.19
- Type:bugfix
- ID:NA
- SUG:restart
- DESC:fix compilation with CONFIG_HAVE_ARCH_PREL32_RELOCATIONS
* Thu Oct 10 2019 Zhipeng Xie<xiezhipeng1@huawei.com> - 2.0-3.1.18
- Type:enhancement
- ID:NA
- SUG:restart
- DESC:add security compile flags
* Tue Sep 27 2019 Zhipeng Xie<xiezhipeng1@huawei.com> - 2.0-3.1.17
- Type:enhancement
- ID:NA
- SUG:restart
- DESC:create-diff-object: allow changing subsections
* Tue Sep 24 2019 shenyangyang<shenyangyang4@huawei.com> -2.0-3.1.16
- Type:enhancement
- ID:NA
- SUG:NA
- DESC:revise help package and subpackage
* Mon Aug 26 2019 openEuler Buildteam<buildteam@openeuler.org> -2.0-3.1.15
- Type:enhancement
- ID:NA
- SUG:NA
- DESC:changelog some patch commit message
* Tue Aug 20 2019 openEuler Builteam <buildteam@openeuler.org> -2.0-3.1.14
- Type:NA
- ID:NA
- SUG:NA
- DESC:rewrite spec
* Fri Jul 16 2019 yangbin<robin.yb@huawei.com> - 2.0-3.1.13
- Type:enhancement
- ID:NA
- SUG:restart
- DESC:add object in kpatch
* Fri Jul 5 2019 Zhipeng Xie<xiezhipeng1@huawei.com> - 2.0-3.1.12
- Type:bugfix
- ID:NA
- SUG:restart
- DESC:fix ref static local symbol for longname symbol
* Mon Jul 1 2019 Enbo Kang<kangenbo@huawei.com> - 2.0-3.1.11
- Type:enhancement
- ID:NA
- SUG:restart
- DESC:fix security problem
* Tue May 7 2019 Zhipeng Xie<xiezhipeng1@huawei.com> - 2.0-3.1.10
- Type:enhancement
- ID:NA
- SUG:restart
- DESC:change some patch to backport prefix
* Sat Apr 13 2019 hezhanyu<hezhanyu@huawei.com> - 2.0-3.1.9
- Type:enhancement
- ID:NA
- SUG:restart
- DESC:modify private key in sign-modules
* Thu Apr 4 2019 Enbo Kang<kangenbo@huawei.com> - 2.0-3.1.8
- Type:enhancement
- ID:NA
- SUG:restart
- DESC:delete sensitive information
* Thu Mar 28 2019 Enbo Kang<kangenbo@huawei.com> - 2.0-3.1.7
- Type:enhancement
- ID:NA
- SUG:restart
- DESC:add RELRO and PIE for create-kpatch-module, create-diff-object, create-klp-module
* Sat Mar 23 2019 Zhipeng Xie<xiezhipeng1@huawei.com> - 2.0-3.1.6
- Type:enhancement
- ID:NA
- SUG:restart
- DESC:upgrade to upstream version 0.6.1
* Thu Mar 7 2019 Zhipeng Xie<xiezhipeng1@huawei.com> - 2.0-3.1.5
- Type:bugfix
- ID:NA
- SUG:restart
- DESC:add find_special_section_data_arm64 for arm64
* Tue Feb 26 2019 Zhipeng Xie<xiezhipeng1@huawei.com> - 2.0-3.1.4
- Type:enhancement
- ID:NA
- SUG:restart
- DESC:add packages required by kpatch and kpatch-runtime
* Mon Feb 25 2019 Zhipeng Xie<xiezhipeng1@huawei.com> - 2.0-3.1.3
- Type:enhancement
- ID:NA
- SUG:restart
- DESC:adapt for native compile_env
* Mon Feb 11 2019 Zhipeng Xie<xiezhipeng1@huawei.com> - 2.0-3.1.2
- Type:enhancement
- ID:NA
- SUG:restart
- DESC:support kernel-4.19
* Thu Dec 20 2018 Zhipeng Xie<xiezhipeng1@huawei.com> - 2.0-3.1.1
- Type:enhancement
- ID:NA
- SUG:restart
- DESC:support c++ kernel module
* Wed Dec 19 2018 Zhipeng Xie<xiezhipeng1@huawei.com> - 2.0-3.1.0
- Type:enhancement
- ID:NA
- SUG:restart
- DESC:support compile kpatch on aarch64
* Fri Nov 23 2018 Zhipeng Xie<xiezhipeng1@huawei.com> - 2.0-2.7.2
- Type:enhancement
- ID:NA
- SUG:restart
- DESC:fix some kpatch-build fail cases
* Sat Nov 3 2018 Zhipeng Xie<xiezhipeng1@huawei.com> - 2.0-2.7.1
- Type:enhancement
- ID:NA
- SUG:restart
- DESC:rebase kpatch
* Thu Nov 16 2017 openEuler Builteam <buildteam@openeuler.org> 0.4.0-3
- Package init

65
livepatch Normal file
View File

@ -0,0 +1,65 @@
#!/bin/bash
# Copyright (C) 2019. Huawei Technologies Co., Ltd. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 and
# only version 2 as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
exe_tool=`which os_hotpatch`
fn_help()
{
cat <<EOFE
Usage: livepatch -l/--load -r/--remove -a/--activate -d/--deactivate <patch>
-q[patch]/--query[=patch]
-h/--help -v/--version
e.g. : livepatch --load <patch archive name>
EOFE
}
if [ "$1" = "-q" -o "$1" = "--query" ];then
$exe_tool -q all
exit 0
fi
input_args=`getopt -a -o l:a:r:d:q:v -l load:,activate:,remove:,deactivate:,query:,help,version -- "$@" 2>&1`
eval set -- "${input_args}"
while true;
do
case "$1" in
-l|--load)
$exe_tool -l "$2"
exit $?
;;
-a|--activate)
$exe_tool -a "klp_${2#klp_}"
exit $?
;;
-d|--deactivate)
$exe_tool -r "klp_${2#klp_}"
exit $?
;;
-r|--remove)
$exe_tool -d "klp_${2#klp_}"
exit $?
;;
-q|--query)
$exe_tool -q "klp_${2#klp_}"
exit $?
;;
-h|--help)
fn_help
exit 0
;;
-v|--version)
echo "LKP:livepatch version 2.0-00000"
exit 0
;;
*)
fn_help
exit 1
;;
esac
done

726
make_hotpatch Normal file
View File

@ -0,0 +1,726 @@
#!/bin/bash
# Copyright (C) 2019. Huawei Technologies Co., Ltd. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 and
# only version 2 as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
SHELL_DIR=$(dirname $0)
SHELL_DIR=$(cd $SHELL_DIR; pwd)
G_PRIVATE_MODULE=
G_HOTPATCH=
G_HOTPATCH_ID=
G_HOTPATCH_TAR=
G_DIFFEXT=
G_JOBS="$(getconf _NPROCESSORS_ONLN)"
G_PATCH_SRC=
G_KERNEL_SRC=/opt/patch_workspace/kernel-source
G_KERNEL_CONFIG=/opt/patch_workspace/.config
G_HOTPATCH_DIR=/opt/patch_workspace/hotpatch
G_VMLINUX=/opt/patch_workspace/vmlinux
G_PREFIX=klp
G_TMP_DIR=
G_PATCHFILE=
G_MODULE_SRC=
G_MODULE_MAKEFILE=
G_KPLICE_PWD_FIELD="KPLICE_PWD"
G_PRIVATE_MODULE_SRC_FIELD="PRIVATE_MODULE_SRC"
G_KPATCH_FLAGS=/opt/patch_workspace/.flags
G_DEBUG_INFO=
G_EXT_FLAGS=
USERMODBUILDDIR=
#########################################################
# Description: usage
# Input:
# Return: 0-success
#########################################################
function fn_usage()
{
cat << EOF
Usage:
make_hotpatch [*OPTIONS*] -d patch_diffext -i patch_id -m module_src
Options:
-d,--diffext
make hotpatch using the modified source files with
names ending in *patch_diffext*. The patch will be determined by
comparing all of the files in the build directory tree
whose names end with the extra extension *patch_diffext* against the
corresponding files without the extra extension.
-j,--jobs
Specifies the number of jobs to run simultaneously while
performing builds.
-i,--id
Specifies the unique value that will be used as the identifier
of the hotpatch.
-m,--modulesrc
Specifies the module src path for make user module hotpatch.
-f,--makefile
Specifies the module makefile for make user module hotpatch.
--extra_flags
Specifies extra flags file for make user module hotpatch.
--no_stack_check
make hotpatch without stack check when activating or deactivating this patch.
--debug_info
Save debug info when hotpatch building.Default is closed.
-p,--patch
Specifies the patch file
--kallsyms
Specifies module kallsyms in running system(cat /proc/kallsyms|grep mod)
-h,--help
help info
EOF
return 0
}
#########################################################
# Description: fn_do_clean, remove tmp file
# Input:
# $1: init flag
# Return: 0-success
#########################################################
function fn_do_clean()
{
local ret=0
G_EXT_FLAGS=
unset NO_STACK_CHECK
unset KALLSYMS
rm -rf $G_TMP_DIR
}
#########################################################
# Description: fn_check_reg_char
# Input:
# $@: input param
# Return: 0-success,1-failed
#########################################################
function fn_check_reg_char()
{
local l_str=$1
local l_str_maxlen=$2
local l_str_ex=$3
local len_str=${#l_str}
if [ -z "$l_str" ];then
echo "error: the string is empty, check string failed"
return 1
fi
##字符串长度
if [ -n "$l_str_maxlen" ] && [ -z "`echo $l_str_maxlen | sed 's/[0-9]//g'`" ];then
if [ $len_str -gt $l_str_maxlen ]; then
echo "error: The length of $l_str exceed max length $l_str_maxlen."
return 1
fi
fi
#不能包含其他字符
if [ -n "$l_str_ex" ] && [ -n "`echo $l_str | grep -E [$l_str_ex] 2>/dev/null`" ];then
echo "error: string $l_str included characters $l_str_ex."
return 1
fi
##数字和字母开头
if [ -z "`echo $l_str | grep -E '^[a-z0-9A-Z]'`" ];then
echo "error: string $l_str must start with a character ('0-9' or 'A-Z' or 'a-z')."
return 1
fi
##只能数字和字母 -_
if [ -n "`echo $l_str | grep -E '[^a-z0-9A-Z_-]'`" ];then
if [ -n "$l_str_ex" ] ;then
##这个日志写不好
echo "error: string $l_str can only contain characters included by ('0-9', 'a-z', 'A-Z')"
else
echo "error: string $l_str can only contain characters included by ('0-9', 'a-z', 'A-Z', '-', '_')."
fi
return 1
fi
}
#########################################################
# Description: fn_check_id
# Input:
# $1:
# Return: 0-success,1-failed
#########################################################
function fn_check_id()
{
local l_id=$1
fn_check_reg_char "$l_id" "20" "-_"
if [ $? -ne 0 ];then
echo "error: check hotpatch id failed"
return 1
fi
G_HOTPATCH_ID=$l_id
G_HOTPATCH=${G_PREFIX}_${G_HOTPATCH_ID}.ko
G_HOTPATCH_TAR=${G_PREFIX}_${G_HOTPATCH_ID}.tar.gz
if [ -f "$G_HOTPATCH_DIR/$G_HOTPATCH_TAR" ];then
echo "error: $G_HOTPATCH_DIR/$G_HOTPATCH_TAR is exist, check hotpatch id failed"
return 1
fi
return 0
}
#########################################################
# Description: fn_check_jobs
# Input:
# $1:
# Return: 0-success,1-failed
#########################################################
function fn_check_jobs()
{
local l_jobs=$1
if [ -z "`echo "$l_jobs" | grep ^[1-9]`" ] || [ -n "`echo "$l_jobs" | sed 's/[0-9]//g'`" ];then
echo "error: the '-j' option requires a positive integral argument"
return 1
fi
G_JOBS=$l_jobs
return 0
}
#########################################################
# Description: fn_check_patch
# Input:
# $1:
# Return: 0-success,1-failed
#########################################################
function fn_check_patch(){
local l_patch=$1
if [ ! -f $1 ];then
echo "error:patch file $1 not exit"
return 1
fi
G_PATCHFILE=$l_patch
}
#########################################################
# Description: fn_check_diffext
# Input:
# $1:
# Return: 0-success,1-failed
#########################################################
function fn_check_diffext()
{
local l_diffext=$1
if [ -z "$l_diffext" ];then
echo "error: diffext is empty, check diffext failed"
return 1
fi
G_DIFFEXT=$l_diffext
return 0
}
#########################################################
# Description: fn_check_kernelsrc
# Input:
# $1:
# Return: 0-success,1-failed
#########################################################
function fn_check_kernelsrc()
{
local l_kernelsrc=$1
if [ ! -d "$l_kernelsrc" ];then
echo "error: kernel src $l_kernelsrc is not exist, check kernel src failed"
return 1
fi
G_KERNEL_SRC=$l_kernelsrc
return 0
}
#########################################################
# Description: fn_check_modulesrc
# Input:
# $1:
# Return: 0-success,1-failed
#########################################################
function fn_check_modulesrc()
{
local l_modulesrc=$1
if [ ! -d "$l_modulesrc" ];then
echo "error: module src $l_modulesrc is not exist, check module src failed"
return 1
fi
echo "$l_modulesrc" | grep -q ^/
if [ $? -ne 0 ];then
echo "error: module src $l_modulesrc must be absolute path, check module src failed"
return 1
fi
G_MODULE_SRC="$l_modulesrc"
return 0
}
#########################################################
# Description: fn_check_makefile
# Input:
# $1:
# Return: 0-success,1-failed
#########################################################
function fn_check_makefile()
{
local l_module_makefile=$1
if [ ! -f "$l_module_makefile" ] && [ "$(basename $l_module_makefile)" = "Makefile" ];then
echo "error: module makefile $l_module_makefile is not exist or makefile name is not Makefile, check module makefile failed"
return 1
fi
echo "$l_module_makefile" | grep -q ^/
if [ $? -ne 0 ];then
echo "error: module makefile $l_module_makefile must be absolute path, check module src failed"
return 1
fi
G_MODULE_MAKEFILE=$l_module_makefile
return 0
}
#########################################################
# Description: fn_check_extra_flags
# Input:
# $1:
# Return: 0-success,1-failed
#########################################################
function fn_check_extra_flags()
{
local l_extra_flags=$1
if [ ! -f "$l_extra_flags" ];then
echo "error: extra flags file $l_extra_flags is not exist, check extra flags failed"
return 1
fi
G_EXT_FLAGS="`readlink -f ${l_extra_flags}`"
cp -a $l_extra_flags $G_KPATCH_FLAGS
if [ $? -ne 0 ];then
echo "error: copy $l_extra_flags to $G_KPATCH_FLAGS failed"
return 1
fi
return 0
}
#########################################################
# Description: verify input param
# Input:
# $@: input param
# Return: 0-success,1-failed
#########################################################
function fn_verify_input()
{
local input_param=$@
if [ $# -lt 1 ]; then
echo "error: missing param,please check it"
fn_do_clean
fn_usage
exit 1
fi
if [ -z "`echo "$input_param" | grep -w "\-i"`" \
-a -z "`echo $input_param | grep -w "\-\-id"`" \
-a $# -gt 1 ];then
echo "error: missing param -i or --id"
fn_do_clean
fn_usage
exit 1
fi
if [ -z "`echo "$input_param" | grep -w "\-d"`" \
-a -z "`echo $input_param | grep -w "\-\-diffext"`" \
-a -z "`echo $input_param | grep -w "\-p"`" \
-a -z "`echo $input_param | grep -w "\-\-patch"`" \
-a $# -gt 1 ];then
echo "error: missing param -d,--diffext or -p,--patch"
fn_do_clean
fn_usage
exit 1
fi
while [ $# -ge 1 ]; do
case "$1" in
-h|--help)
fn_usage
fn_do_clean
exit 0
;;
-j|--jobs)
fn_check_jobs $2
if [ $? -eq 0 ]; then
shift 2
else
fn_do_clean
fn_usage
exit 1
fi
;;
-i|--id)
fn_check_id $2
if [ $? -eq 0 ]; then
shift 2
else
fn_do_clean
fn_usage
exit 1
fi
;;
-d|--diffext)
fn_check_diffext $2
if [ $? -eq 0 ]; then
shift 2
else
fn_do_clean
fn_usage
exit 1
fi
;;
-p|--patch)
fn_check_patch $2
if [ $? -eq 0 ]; then
shift 2
else
fn_do_clean
fn_usage
exit 1
fi
;;
-k|--kernelsrc)
fn_check_kernelsrc $2
if [ $? -eq 0 ]; then
shift 2
else
fn_do_clean
fn_usage
exit 1
fi
;;
-m|--modulesrc)
fn_check_modulesrc $2
if [ $? -eq 0 ]; then
shift 2
else
fn_do_clean
fn_usage
exit 1
fi
;;
-f|--makefile)
fn_check_makefile $2
if [ $? -eq 0 ]; then
shift 2
else
fn_do_clean
fn_usage
exit 1
fi
;;
--extra_flags)
fn_check_extra_flags $2
if [ $? -eq 0 ]; then
shift 2
else
fn_do_clean
fn_usage
exit 1
fi
;;
--no_stack_check)
export NO_STACK_CHECK="yes"
shift 1
;;
--debug_info)
G_DEBUG_INFO="-d"
shift 1
;;
--kallsyms)
export KALLSYMS=$(readlink -f $2)
if [ $? -eq 0 ]; then
shift 2
else
fn_do_clean
fn_usage
exit 1
fi
;;
*)
echo "error: params is invalid,please check it."
fn_do_clean
fn_usage
exit 1
;;
esac
done
return 0
}
#########################################################
# Description: fn_init_module_build
# Input:
# Return: 0-success,1-failed
#########################################################
function fn_init_module_build()
{
local l_modulesrc=$1
local l_module_makefile=$2
local module=
module=`basename $l_modulesrc`
if [ ! -e $G_PRIVATE_MODULE ];then
mkdir -p $G_PRIVATE_MODULE
fi
rm -rf $G_PRIVATE_MODULE/*
if [ $? -ne 0 ];then
echo "error: remove $G_PRIVATE_MODULE/$module or Makefile failed"
return 1
fi
#make a new softlink 或改成链接
ln -sf $l_modulesrc $G_PRIVATE_MODULE
if [ $? -ne 0 ];then
echo "error: copy $l_modulesrc to $G_PRIVATE_MODULE failed"
return 1
fi
if [ -z "$l_module_makefile" ];then
l_module_makefile=$l_modulesrc/Makefile
fi
echo "${G_KPLICE_PWD_FIELD}=${l_modulesrc}/" >> $G_KPATCH_FLAGS
echo "${G_PRIVATE_MODULE_SRC_FIELD}=$(dirname $l_module_makefile)/" >> $G_KPATCH_FLAGS
fMake=`find ${G_PRIVATE_MODULE}/${module}/ -name Makefile`
#if no Makefile found in module dir
if [ -z "$fMake" ] && [ ! -f "$l_module_makefile" ];then
echo "[ERROR] no Makefilie found in module dir $l_modulesrc"
return 1
fi
#filter CC in module Makefile
if [ -n "$fMake" ];then
cat $fMake|grep -v '^#'|grep '^[ ,]CC[ ,:,=,?]'
if [ $? -eq 0 ];then
echo "[WARN] ${module}'s Makefile defined CC,please make sure \"CC:=\$(G_KSPLICECC) \$(CC)\" "
fi
fi
if [ -f "$l_module_makefile" ];then
cat $l_module_makefile|grep -v '^#'|grep '^[ ,]CC[ ,:,=,?]'
if [ $? -eq 0 ];then
echo "[WARN] ${module}'s Makefile defined CC,please make sure \"CC:=\$(G_KSPLICECC) \$(CC)\" "
fi
fi
}
#########################################################
# Description: fn_makepatch
# Input:
# Return: 0-success,1-failed
#########################################################
function fn_makepatch()
{
local l_extra_module=
local l_jobs=
local l_ret=0
local existflag=0
G_PATCH_SRC=`readlink -f $G_KERNEL_SRC`
if [ -d "$G_MODULE_SRC" ];then
echo "make out of tree module hotpath"
G_PATCH_SRC=$G_MODULE_SRC
#fn_init_module_build $G_MODULE_SRC $G_MODULE_MAKEFILE
#if [ $? -ne 0 ];then
# echo "error: init module build failed"
# return 1
#fi
l_extra_module="-m $G_MODULE_SRC"
fi
if [ -n "$G_JOBS" ];then
l_jobs="--jobs=$G_JOBS"
fi
G_TMP_DIR=/tmp/${G_PREFIX}_${G_HOTPATCH_ID}
mkdir -p $G_TMP_DIR
if [ -z "$G_PATCHFILE" ];then
#generate src patch file from G_DIFFEXT
G_PATCHFILE=$G_TMP_DIR/$G_HOTPATCH_ID.patch
rm -rf $G_PATCHFILE
cd $G_PATCH_SRC &>/dev/null
l_change_file=($(find -L -name "*$G_DIFFEXT" | xargs readlink -f 2>/dev/null| sort | uniq))
echo "detect change files:${l_change_file[@]}"
for file in ${l_change_file[@]};
do
file="./${file#$(readlink -f $G_PATCH_SRC)}"
orig_file=${file%$G_DIFFEXT}
if [ "${orig_file##*.}" == "h" ]; then
existflag=1 && break
fi
diff -u $orig_file $file >> $G_PATCHFILE
done
cd - &>/dev/null
if [ ${existflag} -eq 1 ]; then
echo "error: do not modify the header file"
return 1
fi
if [ -f $G_PATCHFILE ];then
echo "make patch $G_PATCHFILE"
else
echo "no change detected"
return 1
fi
else
cp $G_PATCHFILE $G_TMP_DIR/${G_HOTPATCH_ID}.patch
G_PATCHFILE=$G_TMP_DIR/${G_HOTPATCH_ID}.patch
fi
cd $G_TMP_DIR &>/dev/null
if [ -n "$G_MODULE_MAKEFILE" ];then
USERMODBUILDDIR=$(dirname $G_MODULE_MAKEFILE)
fi
export USERMODBUILDDIR
export USERMODFLAGS=`cat $G_KPATCH_FLAGS`
export NO_PROFILING_CALLS=yes
kpatch-build -s $G_KERNEL_SRC $l_extra_module -c $G_KERNEL_CONFIG -v $G_VMLINUX --skip-gcc-check -n "${G_PREFIX}_${G_HOTPATCH_ID}" -b /lib/modules/`uname -r`/build $G_DEBUG_INFO $G_PATCHFILE
l_ret=$?
cd - &>/dev/null
if [ $l_ret -eq 0 ] && [ -f "$G_TMP_DIR/$G_HOTPATCH" ];then
if grep -q "CONFIG_MODULE_SIG=y" .config ;then
echo "kernel compile with CONFIG_MODULE_SIG=y,please sign the patch module"
fi
cd /tmp &>/dev/null
l_env_file=$G_TMP_DIR/toolenv
if [ -n "`which rpm 2>/dev/null`" ]; then
echo "------------------------------------------------------------------------ " > "${l_env_file}"
echo >> "${l_env_file}"
echo "The kpatch tool version info and release date:" >> "${l_env_file}"
rpm -qi kpatch >> "${l_env_file}"
echo >> "${l_env_file}"
echo "------------------------------------------------------------------------ " >> "${l_env_file}"
else
echo "------------------------------------------------------------------------ " >> "${l_env_file}"
fi
echo >> "${l_env_file}"
echo "The hotpatch build time:" >> "${l_env_file}"
echo "`date '+%Y-%m-%d %H:%M:%S'`" >> "${l_env_file}"
echo >> "${l_env_file}"
echo "------------------------------------------------------------------------ " >> "${l_env_file}"
if [ -f "/etc/EulerLinux.conf" ]; then
echo >> "${l_env_file}"
echo "The euler compile env version info:" >> "${l_env_file}"
cat /etc/EulerLinux.conf >> "${l_env_file}"
echo >> "${l_env_file}"
echo "------------------------------------------------------------------------ " >> "${l_env_file}"
fi
if [ -n "${G_MODULE_SRC}" ]; then
echo >> "${l_env_file}"
echo "The module hotpatch compile path info:" >> "${l_env_file}"
echo "MODULE_SRC=${G_MODULE_SRC}" >> "${l_env_file}"
echo "MODULE_MAKEFILE=${G_MODULE_MAKEFILE}" >> "${l_env_file}"
echo >> "${l_env_file}"
echo "------------------------------------------------------------------------ " >> "${l_env_file}"
fi
if [ -f "${G_EXT_FLAGS}" ]; then
echo >> "${l_env_file}"
echo "The module hotpatch compile flags info:" >> "${l_env_file}"
cat "${G_EXT_FLAGS}" >> "${l_env_file}"
echo >> "${l_env_file}"
echo "------------------------------------------------------------------------ " >> "${l_env_file}"
fi
if [ -n "${G_DEBUG_INFO}" ]; then
echo >> "${l_env_file}"
echo "The debug option info:" >> "${l_env_file}"
echo "${G_DEBUG_INFO}" >> "${l_env_file}"
echo >> "${l_env_file}"
echo "------------------------------------------------------------------------ " >> "${l_env_file}"
fi
tar -czf $G_HOTPATCH_TAR ${G_PREFIX}_${G_HOTPATCH_ID}
mv ${G_HOTPATCH_TAR} ${G_HOTPATCH_DIR}
cd - &>/dev/null
if [ $? -ne 0 ];then
echo "error: move ${G_HOTPATCH} to ${G_KSPLICE_HOTPATCH} failed"
return 1
fi
else
echo "error: invoke kpatch-build shell script to build patch failed"
return 1
fi
}
#########################################################
# Description: main
# Input:
# Return: 0-success,1-failed
#########################################################
function fn_main()
{
local ret=
local pid=
fn_verify_input $@
if [ $? -ne 0 ]; then
fn_do_clean
return 1
fi
fn_makepatch
if [ $? -ne 0 ]; then
fn_do_clean
return 1
fi
fn_do_clean
return 0
}
function fn_prepare()
{
kerver=`uname -r`
kerver=${kerver%.x86_64}
kerver=${kerver%.aarch64}
echo kernel version:$kerver
if [ ! -L kernel-source ];then
if [ -d /arm/arm_kernel ];then
ln -s /arm/arm_kernel/linux-$kerver kernel-source
else
ln -s /usr/src/kernels/linux-$kerver kernel-source
cp /lib/modules/`uname -r`/build/Makefile /usr/src/kernels/linux-$kerver
fi
fi
if [ ! -L .config ];then
if [ -d /arm/arm_kernel ];then
ln -s /arm/arm_kernel/linux-$kerver/.config .config
else
ln -s /usr/src/kernels/linux-$kerver/.config .config
cp /lib/modules/`uname -r`/build/.config /usr/src/kernels/linux-$kerver
fi
fi
rm -rf $G_KPATCH_FLAGS
touch $G_KPATCH_FLAGS
}
G_NUM=`pidof -x make_hotpatch | wc -w`
if [ $G_NUM -gt 2 ];then
echo "[$0]someone is making, please try again later."
exit 1
fi
fn_prepare
fn_main $@
exit $?

337
os_hotpatch Normal file
View File

@ -0,0 +1,337 @@
#!/bin/sh
# Copyright (C) 2019. Huawei Technologies Co., Ltd. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 and
# only version 2 as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
SYS_LIVEPATCH=/sys/kernel/livepatch
G_TMP_DIR=/tmp/hotpatch.$$
G_PATCH_FILE=
#########################################################
# Description: usage
# Input:
# Return: 0-success
#########################################################
OS_HP_HELP()
{
echo "usage: os_hotpatch"
echo "-w|--check <filepath> : check hotpatch"
echo "-l|--load <filepath> : load hotpatch"
echo "-a|--active <patchname> : active hotpatch"
echo "-r|--rollback <patchname> : rollback/deactive hotpatch"
echo "-d|--delete <patchname> : delete/unload hotpatch"
echo "-q|--query <patchname>/all : query hotpatch"
echo "-h|--help : show this help information"
}
#########################################################
# Description: check hotpatch file before install
# Input:
# $1: hotpatch file path
# Return: 0-success,1-failed
#########################################################
OS_HP_CHECK()
{
path=$1
if [ ! -f "$path" ]; then
echo "The file $path is not exit"
exit 1;
fi
EXTRACT_HP $path
if [ $? -ne 0 -o ! -f "$G_PATCH_FILE" ];then
echo "The file $path is invalid"
CLEAN_UP
exit 1;
fi
CLEAN_UP
echo "The file $path is valid"
exit 0
}
#########################################################
# Description: active a hotpatch
# Input:
# $1: hotpatch name(klp-xxx.tar.gz)
# Return: 0-success,1-failed
#########################################################
OS_HP_ACTIVE()
{
file=$1
patch_name=`echo ${file%.tar.gz}|tr '-' '_'`
patch_install=`lsmod | grep -w $patch_name`
if [ "$patch_install" == "" ]; then
echo "patch $file not load"
exit 1
fi
is_active=`cat ${SYS_LIVEPATCH}/${patch_name}/enabled`
if [ ${is_active} == 1 ]; then
echo "patch already active"
exit 0
fi
echo 1 > ${SYS_LIVEPATCH}/${patch_name}/enabled
is_active=`cat ${SYS_LIVEPATCH}/${patch_name}/enabled`
if [ ${is_active} == 1 ]; then
echo "active patch $file success"
exit 0
else
echo "active patch $file fail"
exit 1
fi
}
#########################################################
# Description: deactive a hotpatch
# Input:
# $1: hotpatch name(klp-xxx.tar.gz)
# Return: 0-success,1-failed
#########################################################
OS_HP_DEACTIVE()
{
file=$1
patch_name=`echo ${file%.tar.gz}|tr '-' '_'`
patch_install=`lsmod | grep -w $patch_name`
if [ "$patch_install" == "" ]; then
echo "patch $file not load"
exit 1
fi
is_active=`cat ${SYS_LIVEPATCH}/${patch_name}/enabled`
if [ ${is_active} == 0 ]; then
echo "patch $file already deactive"
exit 0
else
echo 0 > ${SYS_LIVEPATCH}/${patch_name}/enabled
is_active=`cat ${SYS_LIVEPATCH}/${patch_name}/enabled`
if [ ${is_active} != 1 ]; then
echo "deactive patch $file success"
exit 0
else
echo "deactive patch $file fail"
exit 1
fi
fi
}
#########################################################
# Description: remove a hotpatch
# Input:
# $1: hotpatch name(klp-xxx.tar.gz)
# Return: 0-success,1-failed
#########################################################
OS_HP_REMOVE()
{
file=$1
patch_name=`echo ${file%.tar.gz}|tr '-' '_'`
patch_install=`lsmod | grep -w $patch_name`
if [ "$patch_install" == "" ]; then
echo "patch $file not load"
exit 1
fi
is_active=`cat ${SYS_LIVEPATCH}/${patch_name}/enabled`
if [ ${is_active} == 0 ]; then
rmmod ${patch_name}
else
echo 0 > ${SYS_LIVEPATCH}/${patch_name}/enabled
rmmod ${patch_name}
fi
patch_install=`lsmod | grep -w $patch_name`
if [ "$patch_install" == "" ]; then
echo "remove patch $file success"
exit 0
else
echo "remove patch $file failed"
exit 1
fi
}
#########################################################
# Description: query a hotpatch
# Input:
# $1: hotpatch name(klp-xxx.tar.gz) or all
# Return: 0-success,1-not load,2-deactive,3-active,4-fault
#########################################################
OS_HP_INQUIRY()
{
file=$1
lret=0
if [ "all" == $file ];then
cd ${SYS_LIVEPATCH}
if [ -z "`ls -d */ 2>/dev/null`" ];then
exit 0
fi
for patch in `ls -d */ 2>/dev/null`
do
patch_id=${patch%/}
patch_id=${patch_id#klp_}
echo "Patch Name: ${patch_id}"
lstate=`cat /${SYS_LIVEPATCH}/${patch}/enabled 2>/dev/null`
if [ -z "$lstate" ];then
echo "Patch State: Removing"
echo "-----------------------------------------------------------"
continue
fi
if [ $lstate -eq 1 ];then
echo "Patch State: Active"
else
echo "Patch State: Deactive"
fi
cd ${SYS_LIVEPATCH}/${patch} 2>/dev/null
depends=`ls -d */ 2>/dev/null`
echo "Changes:"
ls -l ${SYS_LIVEPATCH}/${patch}/*/ 2>/dev/null|grep '^d'|awk -F ' ' '{print "\t"$9}'
echo "Denpendency: ${depends%/}"
echo "-----------------------------------------------------------"
done
exit 0
fi
patch=`echo ${file%.tar.gz}|tr '-' '_'`
patch_install=`lsmod | grep -w $patch`
if [ "$patch_install" == "" ]; then
exit 1
fi
patch_id=${patch%/}
patch_id=${patch_id#klp_}
echo "Patch Name: ${patch_id}"
if [ `cat /${SYS_LIVEPATCH}/${patch}/enabled` -eq 1 ];then
echo "Patch State: Active"
lret=3
else
echo "Patch State: Deactive"
lret=2
fi
cd ${SYS_LIVEPATCH}/${patch}
depends=`ls -d */ 2>/dev/null`
echo "Changes:"
ls -l ${SYS_LIVEPATCH}/${patch}/*/ 2>/dev/null|grep '^d'|awk -F ' ' '{print "\t"$9}'
echo "Denpendency: ${depends%/}"
echo "-----------------------------------------------------------"
exit $lret
}
#########################################################
# Description: extract hotpatch tar to tmp dir
# Input:
# $1: hotpatch file path
# Return: 0-success,1-failed
#########################################################
EXTRACT_HP()
{
mkdir $G_TMP_DIR
tar xzf $1 -C $G_TMP_DIR
l_ret=$?
if [ $l_ret -eq 0 ];then
#find the hotpatch module
G_PATCH_FILE=$(find $G_TMP_DIR|grep -w "klp.*\.ko")
return 0
else
return 1
fi
}
#########################################################
# Description: clean up the tmp dir
# Input:
# Return: none
#########################################################
CLEAN_UP()
{
rm -rf $G_TMP_DIR
}
#########################################################
# Description: install a hotpatch
# Input:
# $1: hotpatch file path
# Return: 0-success,1-failed
#########################################################
OS_HP_INSTALL()
{
path=$1
if [ ! -f "$path" ]; then
echo "The file $path is not exit"
exit 1;
fi
EXTRACT_HP $path
if [ $? -ne 0 -o ! -f "$G_PATCH_FILE" ];then
echo "The file $path is invalid!"
CLEAN_UP
exit 1;
fi
patch_name=`echo ${G_PATCH_FILE%.ko}|tr '-' '_'`
patch_name=${patch_name##*/}
patch_install=`lsmod | grep -w $patch_name`
if [ "$patch_install" == "" ]; then
echo "insmod $G_PATCH_FILE"
insmod $G_PATCH_FILE
L_RET=$?
if [ 0 -ne ${L_RET} ]; then
echo "install patch $path fail"
CLEAN_UP
return 1
else
echo "install patch $path success"
fi
else
echo "patch $path already install"
fi
CLEAN_UP
return 0
}
#----------------------------main-------------------------#
if [ ! -d ${SYS_LIVEPATCH} ];then
echo "this OS does not support kernel livepatch"
exit 1
fi
input_args=`getopt -a -o l:a:r:d:w:q: -l load:,active:,delete:,check:,rollback:,query:,help, -- "$@" 2>&1`
eval set -- "${input_args}"
while true;
do
case "$1" in
-w|--check)
OS_HP_CHECK "$2"
exit $?
;;
-l|--load)
OS_HP_INSTALL "$2"
exit $?
;;
-a|--active)
OS_HP_ACTIVE "$2"
exit $?
;;
-r|--rollback)
OS_HP_DEACTIVE "$2"
exit $?
;;
-d|--delete)
OS_HP_REMOVE "$2"
exit $?
;;
-q|--query)
OS_HP_INQUIRY "$2"
exit $?
;;
-h|--help)
OS_HP_HELP
exit 0
;;
*)
OS_HP_HELP
exit 1
;;
esac
done