AArch64 support: add aarch64 support for libcareplus

Add related code which make libcareplus can run basic demo on aarch64.

Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
This commit is contained in:
Jiajie Li 2021-02-09 19:41:34 +08:00 committed by Ying Fang
parent 9389c4afb2
commit 2b0fff2855
47 changed files with 11416 additions and 3 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,152 @@
From 98833d06737a9a1128f548d15344b1cbaeed049f Mon Sep 17 00:00:00 2001
From: Pavel Boldin <pboldin@cloudlinux.com>
Date: Wed, 24 Jan 2018 13:14:10 +0200
Subject: [PATCH 03/89] cmd_patch: pass arguments directly
Signed-off-by: Pavel Boldin <pboldin@cloudlinux.com>
---
src/kpatch_user.c | 84 ++++++++++++++++-------------------------------
1 file changed, 29 insertions(+), 55 deletions(-)
diff --git a/src/kpatch_user.c b/src/kpatch_user.c
index 9ab77b9..d257b67 100644
--- a/src/kpatch_user.c
+++ b/src/kpatch_user.c
@@ -63,19 +63,36 @@ static int usage_patch(const char *err)
{
if (err)
fprintf(stderr, "err: %s\n", err);
- fprintf(stderr, "usage: libcare-ctl patch [options] <-p PID> <-r fd> <patch>\n");
+ fprintf(stderr, "usage: libcare-ctl patch [options] <-p PID> <patch>\n");
fprintf(stderr, "\nOptions:\n");
fprintf(stderr, " -h - this message\n");
- fprintf(stderr, " -s - process was just executed\n");
fprintf(stderr, " -p <PID> - target process\n");
- fprintf(stderr, " -r fd - fd used with LD_PRELOAD=execve.so.\n");
return err ? 0 : -1;
}
-int cmd_patch_user(int argc, char *argv[])
+static int
+patch_user(const char *storage_path, int pid,
+ int is_just_started, int send_fd)
{
+ int ret;
kpatch_storage_t storage;
- int opt, pid = -1, is_pid_set = 0, ret, start = 0, send_fd = -1;
+
+ ret = storage_init(&storage, storage_path);
+ if (ret < 0)
+ return ret;
+
+ ret = processes_patch(&storage, pid, is_just_started, send_fd);
+
+ storage_free(&storage);
+
+ return ret;
+}
+
+
+int cmd_patch_user(int argc, char *argv[])
+{
+ int opt, pid = -1, is_pid_set = 0, ret;
+ const char *storage_path;
if (argc < 4)
return usage_patch(NULL);
@@ -89,12 +106,6 @@ int cmd_patch_user(int argc, char *argv[])
pid = atoi(optarg);
is_pid_set = 1;
break;
- case 'r':
- send_fd = atoi(optarg);
- break;
- case 's':
- start = 1;
- break;
default:
return usage_patch("unknown option");
}
@@ -109,14 +120,9 @@ int cmd_patch_user(int argc, char *argv[])
if (!kpatch_check_system())
goto out_err;
- ret = storage_init(&storage, argv[argc - 1]);
- if (ret < 0)
- goto out_err;
-
-
- ret = processes_patch(&storage, pid, start, send_fd);
-
- storage_free(&storage);
+ storage_path = argv[argc - 1];
+ ret = patch_user(storage_path, pid,
+ /* is_just_started */ 0, /* send_fd */ -1);
out_err:
return ret;
@@ -474,24 +480,6 @@ static int
cmd_execve_startup(int fd, int argc, char *argv[], int is_just_started)
{
int rv, pid;
- char pid_str[64], send_fd_str[64];
- char *patch_pid_argv_execve[] = {
- "patch",
- "-s",
- "-p",
- pid_str,
- "-r",
- send_fd_str,
- storage_dir
- };
- char *patch_pid_argv_startup[] = {
- "patch",
- "-p",
- pid_str,
- "-r",
- send_fd_str,
- storage_dir
- };
rv = sscanf(argv[1], "%d", &pid);
if (rv != 1) {
@@ -499,16 +487,8 @@ cmd_execve_startup(int fd, int argc, char *argv[], int is_just_started)
return -1;
}
- sprintf(pid_str, "%d", pid);
- sprintf(send_fd_str, "%d", fd);
-
optind = 1;
- if (is_just_started)
- rv = cmd_patch_user(ARRAY_SIZE(patch_pid_argv_execve),
- patch_pid_argv_execve);
- else
- rv = cmd_patch_user(ARRAY_SIZE(patch_pid_argv_startup),
- patch_pid_argv_startup);
+ rv = patch_user(storage_dir, pid, is_just_started, fd);
if (rv < 0)
kperr("can't patch pid %d\n", pid);
@@ -578,15 +558,9 @@ cmd_storage(int argc, char *argv[])
static int
cmd_update(int argc, char *argv[])
{
- char *patch_all[] = {
- "patch",
- "-p",
- "all",
- storage_dir
- };
-
- optind = 1;
- return cmd_patch_user(ARRAY_SIZE(patch_all), patch_all);
+ return patch_user(storage_dir, /* pid */ -1,
+ /* is_just_started */ 0,
+ /* send_fd */ -1);
}
static int
--
2.23.0

View File

@ -0,0 +1,71 @@
From f4b6b37575e514f3e54f08166dc14e35815a8ebb Mon Sep 17 00:00:00 2001
From: Pavel Boldin <pboldin@cloudlinux.com>
Date: Tue, 30 Jan 2018 08:15:11 +0200
Subject: [PATCH 04/89] travis: use VM for now
Attaching even to a children process is broken in travis's Docker.
Use VM until https://github.com/travis-ci/travis-ci/issues/9033
is fixed.
Signed-off-by: Pavel Boldin <pboldin@cloudlinux.com>
---
.travis.yml | 2 +-
Makefile | 2 +-
tests/run_tests.sh | 18 +++++++++++++++++-
3 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 4bb2614..f3ccb4e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,7 +3,7 @@ script: make tests
language: c
dist: trusty
-sudo: false
+sudo: required
addons:
apt:
diff --git a/Makefile b/Makefile
index 2da227f..c5a2837 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-
+#dummy
all: src
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index fcfcd56..fbfb273 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -3,7 +3,23 @@
set -e
wait_file() {
- while ! test -s $1; do sleep ${2-1}; done
+ local file="$1"
+ local pause="${2-1}"
+ local i=0
+ local timeout=60
+
+ while test $i -lt $timeout; do
+ if test -s $file; then
+ break
+ fi
+ sleep $pause
+ i=$((i + 1))
+ done
+
+ if test $i -eq $timeout; then
+ return 1
+ fi
+
return 0
}
--
2.23.0

View File

@ -0,0 +1,39 @@
From 8e1d1d24e39464e88e92695ea5951639e789f72d Mon Sep 17 00:00:00 2001
From: Pavel Boldin <pboldin@cloudlinux.com>
Date: Sat, 28 Oct 2017 03:47:48 +0300
Subject: [PATCH 05/89] scripts/pkgbuild: add prepare_env hook
Change-Id: Iabb96a1b9f9cd8d1415029380f825da29156a840
Signed-off-by: Pavel Boldin <pboldin@cloudlinux.com>
---
scripts/pkgbuild | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/scripts/pkgbuild b/scripts/pkgbuild
index ea1f411..3697594 100755
--- a/scripts/pkgbuild
+++ b/scripts/pkgbuild
@@ -73,6 +73,11 @@ clean_dirs() {
rm -rf $KP_PROJECT_BUILD_ROOT /root/root.original /root/root.patched
}
+kp_prepare_env_hook() {
+ # use this to add repos
+ :
+}
+
kp_pack_prebuilt() {
echo " packing prebuilt $KP_PROJECT into $KP_PROJECT_PREBUILT"
pushd $KP_PROJECT_BUILD_ROOT
@@ -386,6 +391,8 @@ main() {
overwrite_utils
+ kp_prepare_env_hook
+
if [ "$ACTION" == "prebuild" ]; then
kp_prepare_source
kp_prebuild_hook
--
2.23.0

View File

@ -0,0 +1,42 @@
From 859be3502b57c87f3241c11d36059313cbdde46a Mon Sep 17 00:00:00 2001
From: Pavel Boldin <pboldin@cloudlinux.com>
Date: Tue, 31 Oct 2017 04:04:58 +0100
Subject: [PATCH 06/89] pkgbuild: fix for non-/root/rpmbuild built root
---
scripts/pkgbuild | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/scripts/pkgbuild b/scripts/pkgbuild
index 3697594..e2ac7c7 100755
--- a/scripts/pkgbuild
+++ b/scripts/pkgbuild
@@ -120,7 +120,8 @@ kp_prepare_source_rpm() {
sed -i 's/.rpm$//g' $KP_PROJECT_BUILD_ROOT/dependencies.txt
- rpm -ivh /kcdata/$KP_PROJECT_SOURCE
+ rpm -ivh /kcdata/$KP_PROJECT_SOURCE \
+ --define "_topdir $KP_PROJECT_BUILD_ROOT"
}
kp_prepare_source_deb() {
@@ -152,6 +153,7 @@ kp_prebuild_rpm() {
eval rpmbuild --nocheck --noclean \
-bc \
$KP_RPMBUILD_FLAGS \
+ '--define "_topdir $KP_PROJECT_BUILD_ROOT"' \
$KP_PROJECT_BUILD_ROOT/SPECS/$KP_PROJECT_SPEC 2>&1 | \
tee $KP_PROJECT_BUILD_ROOT/prebuild.log
}
@@ -237,6 +239,7 @@ kp_build_rpm() {
--short-circuit \
-bc \
$KP_RPMBUILD_FLAGS \
+ '--define "_topdir $KP_PROJECT_BUILD_ROOT"' \
$KP_PROJECT_BUILD_ROOT/SPECS/$KP_PROJECT_SPEC
}
--
2.23.0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,30 @@
From 066da27aaf6b153c215bee353e7190fe226f5b3b Mon Sep 17 00:00:00 2001
From: Pavel Boldin <pboldin@cloudlinux.com>
Date: Thu, 14 Dec 2017 18:02:15 +0200
Subject: [PATCH 08/89] pkgbuild: use yumdownloader if source url is missing
Signed-off-by: Pavel Boldin <pboldin@cloudlinux.com>
---
scripts/pkgbuild | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/scripts/pkgbuild b/scripts/pkgbuild
index 8803db3..97c78a9 100755
--- a/scripts/pkgbuild
+++ b/scripts/pkgbuild
@@ -105,7 +105,11 @@ kp_prepare_source_raw() {
kp_download_source_rpm() {
mkdir -p /kcdata
- curl $KP_PROJECT_SOURCE_URL -o /kcdata/$KP_PROJECT_SOURCE
+ if test -n "$KP_PROJECT_SOURCE_URL"; then
+ curl $KP_PROJECT_SOURCE_URL -o /kcdata/$KP_PROJECT_SOURCE
+ else
+ yumdownloader --source --destdir /kcdata ${KP_PROJECT_SOURCE%.src.rpm}
+ fi
}
kp_prepare_source_rpm() {
--
2.23.0

View File

@ -0,0 +1,52 @@
From 2343fef023a8cd64473161fa82a0d81cb5007cf9 Mon Sep 17 00:00:00 2001
From: Pavel Boldin <pboldin@cloudlinux.com>
Date: Tue, 30 Jan 2018 00:04:54 +0200
Subject: [PATCH 09/89] execve: abort() on failure
Signed-off-by: Pavel Boldin <pboldin@cloudlinux.com>
---
tests/execve/execve.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/tests/execve/execve.c b/tests/execve/execve.c
index b3df0e4..eb3e9d3 100644
--- a/tests/execve/execve.c
+++ b/tests/execve/execve.c
@@ -81,7 +81,7 @@ notify_listener(void)
sock = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
if (sock == -1) {
dprintf("socket() error: %s(%d)\n", strerror(errno), errno);
- return;
+ abort();
}
dprintf("socket()\n");
@@ -96,7 +96,7 @@ notify_listener(void)
if (rv == -1) {
fprintf(stderr, "libcare-execve: connect() error: %s(%d)\n", strerror(errno), errno);
(void) close(sock);
- return;
+ abort();
}
dprintf("connect()\n");
@@ -113,7 +113,7 @@ notify_listener(void)
if (rv == -1) {
fprintf(stderr, "send() error: %s(%d)\n", strerror(errno), errno);
(void) close(sock);
- return;
+ abort();
}
dprintf("send()\n");
@@ -123,6 +123,7 @@ notify_listener(void)
if (rv == -1) {
fprintf(stderr, "recv() error: %s(%d)\n", strerror(errno), errno);
+ abort();
}
dprintf("recv()\n");
--
2.23.0

View File

@ -0,0 +1,379 @@
From 7d431211063a9bf6c789bb67a2ed216025279a66 Mon Sep 17 00:00:00 2001
From: Roman Rashchupkin <rrashchupkin@cloudlinux.com>
Date: Tue, 23 Jan 2018 13:41:38 +0300
Subject: [PATCH 10/89] Add --test stage to pkgbuild
Signed-off-by: Roman Rashchupkin <rrashchupkin@cloudlinux.com>
---
packages/rhel7/glibc/glibc-2.17-55.el7/info | 36 ++++-----
.../glibc/glibc-2.17-55.el7/pkgfile.yaml | 1 +
scripts/pkgbuild | 81 ++++++++++++++++---
scripts/toil/build-patch.sh | 1 -
scripts/toil/pkgbuild.py | 57 +++++++++----
5 files changed, 126 insertions(+), 50 deletions(-)
diff --git a/packages/rhel7/glibc/glibc-2.17-55.el7/info b/packages/rhel7/glibc/glibc-2.17-55.el7/info
index 8cebabb..e5805c3 100644
--- a/packages/rhel7/glibc/glibc-2.17-55.el7/info
+++ b/packages/rhel7/glibc/glibc-2.17-55.el7/info
@@ -55,21 +55,6 @@ kp_build_hook() {
$KP_PROJECT_BUILD_ROOT/SPECS/$KP_PROJECT_SPEC
}
-# Replace patch build results with original libraries for testing
-_install_originals() {
- eval set -- $KP_INSTALL_FILES
- while test -n "$1"; do
- local buildpath="$1"
- local installpath="$2"
- shift 2
-
- if test "$installpath" = "IGNORE"; then
- continue
- fi
-
- /bin/cp -r /root/root.original/$installpath $KP_PROJECT_BUILD_DIR/$buildpath
- done
-}
_run_tests() {
if test -f $LIBCARE_DIR/execve/execve.so; then
@@ -113,15 +98,22 @@ _run_tests() {
export PATH=$KCPATH
}
-kp_patch_test() {
- _install_originals
+kp_prepare_test_binaries() {
+ # Replace patch build results with original libraries for testing
+ kp_install_files /root/root.original \
+ $KP_PROJECT_BUILD_DIR \
+ "to_prebuild" \
+ "$KP_INSTALL_FILES"
+}
+kp_patch_test() {
rm -f /var/run/libcare.sock
- PATCH_ROOT=/root/${KP_PROJECT_PATCH%.*}
+ PATCH_ROOT=$KP_PROJECT_BUILD_ROOT/storage
$KPATCH_PATH/libcare-ctl -v server /var/run/libcare.sock $PATCH_ROOT \
- >/data/test.log 2>&1 & :
+ >/data/libcare-ctl.log 2>&1 & :
LISTENER_PID=$!
+
sleep 1
kill -0 $LISTENER_PID
@@ -134,11 +126,11 @@ kp_patch_test() {
popd
- local patched=$(awk '/kpatch_ctl targeting/ { n++ } END { print n }' /data/test.log)
+ local patched=$(awk '/kpatch_ctl targeting/ { n++ } END { print n }' /data/libcare-ctl.log)
test $patched -ge $executed
- grep -vq 'No patch(es) applicable to' /data/test.log
- grep 'patch hunk(s) have been successfully applied' /data/test.log \
+ grep -vq 'No patch(es) applicable to' /data/libcare-ctl.log
+ grep 'patch hunk(s) have been successfully applied' /data/libcare-ctl.log \
| wc -l
}
diff --git a/packages/rhel7/glibc/glibc-2.17-55.el7/pkgfile.yaml b/packages/rhel7/glibc/glibc-2.17-55.el7/pkgfile.yaml
index 51028ed..b17e895 100644
--- a/packages/rhel7/glibc/glibc-2.17-55.el7/pkgfile.yaml
+++ b/packages/rhel7/glibc/glibc-2.17-55.el7/pkgfile.yaml
@@ -1,5 +1,6 @@
image: kernelcare/centos7:gcc-4.8.2-16.el7
prebuild: /tmp/build.orig-glibc-2.17-55.el7.x86_64.rpm.tgz
+patch: /tmp/kpatch-glibc-2.17-55.el7.x86_64.tgz
input:
- package: .
- patches: ../../../../patches/
diff --git a/scripts/pkgbuild b/scripts/pkgbuild
index 97c78a9..f91af57 100755
--- a/scripts/pkgbuild
+++ b/scripts/pkgbuild
@@ -17,6 +17,7 @@ die() {
usage() {
echo "Usage: build [--prebuild] [--help] [--arch ARCH] DIR"
echo " -p|--prebuild prebuild project for further use"
+ echo " -t|--test run unit and stress tests"
echo " -a|--arch ARCH target architecture(x86_64 by default)"
echo " -h|--help print this message"
echo " DIR directory with project's info file and other resources"
@@ -32,6 +33,9 @@ prepare() {
-p|--prebuild)
ACTION=prebuild
;;
+ -t|--test)
+ ACTION=test
+ ;;
-a|--arch)
shift
ARCH=$1
@@ -247,13 +251,17 @@ kp_build_rpm() {
-bc \
$KP_RPMBUILD_FLAGS \
'--define "_topdir $KP_PROJECT_BUILD_ROOT"' \
- $KP_PROJECT_BUILD_ROOT/SPECS/$KP_PROJECT_SPEC
+ $KP_PROJECT_BUILD_ROOT/SPECS/$KP_PROJECT_SPEC 2>&1 |
+ tee $KP_PROJECT_BUILD_ROOT/build.log
}
-kp_install_generic() {
- local ROOT_PATCHED="$HOME/root.patched"
+kp_install_files() {
+ local src="$1"
+ local dest="$2"
+ local direction="$3"
+ local files="$4"
- eval set -- $KP_INSTALL_FILES
+ eval set -- $files
while test -n "$1"; do
local buildpath="$1"
local installpath="$2"
@@ -263,12 +271,16 @@ kp_install_generic() {
continue
fi
- installpath="$ROOT_PATCHED/$installpath"
-
- mkdir -p "$(dirname "$installpath")"
-
- /bin/cp -ra $KP_PROJECT_BUILD_DIR/$buildpath $installpath
+ if test $direction = "from_prebuild"; then
+ install -D $src/$buildpath $dest/$installpath
+ else
+ install -D $src/$installpath $dest/$buildpath
+ fi
done
+}
+
+kp_check_missing_files() {
+ local builddir="$1"
local failed=
pushd $KP_PROJECT_BUILD_DIR
@@ -295,6 +307,16 @@ kp_install_generic() {
fi
}
+kp_install_generic() {
+ local root_patched="$HOME/root.patched"
+
+ kp_install_files $KP_PROJECT_BUILD_DIR \
+ $root_patched \
+ "from_prebuild" \
+ "$KP_INSTALL_FILES"
+ kp_check_missing_files $KP_PROJECT_BUILD_DIR
+}
+
kp_install_rpm() {
kp_install_orig_rpm
kp_install_generic
@@ -367,6 +389,33 @@ kp_pack_patch() {
popd
}
+kp_unpack_patch() {
+ local tmpdir=$(mktemp -d --tmpdir)
+
+ echo " unpacking patches for $KP_PROJECT into $KP_PROJECT_BUILD_ROOT/storage"
+
+ tar -xf /kcdata/$KP_PROJECT_PATCH -C $tmpdir
+
+ find $tmpdir -name \*.kpatch > $tmpdir/patchlist
+
+ while read patchfile; do
+ local patchname=${patchfile##*/}
+ local buildid=${patchname%.kpatch}
+
+ local KP_STORAGE=$KP_PROJECT_BUILD_ROOT/storage/$buildid
+
+ mkdir -p $KP_STORAGE/1
+ cp $patchfile $KP_STORAGE/1/kpatch.bin
+ ln -rs $KP_STORAGE/1 $KP_STORAGE/latest
+ done < $tmpdir/patchlist
+
+ rm -fr $tmpdir
+}
+
+kp_mark_tests_fail() {
+ touch /kcdata/Tests-FAIL
+}
+
overwrite_utils() {
TMPBIN=$(mktemp -d --tmpdir)
@@ -394,7 +443,8 @@ overwrite_utils() {
}
kp_patch_test() {
- :
+ echo "Empty kp_patch_test called, override it!"
+ exit 1
}
main() {
@@ -408,20 +458,25 @@ main() {
kp_prepare_env_hook
- if [ "$ACTION" == "prebuild" ]; then
+ if test "$ACTION" == "prebuild"; then
kp_prepare_source
kp_prebuild_hook
kp_prebuild
kp_pack_prebuilt
- else
+ elif test "$ACTION" == "build"; then
kp_unpack_prebuilt
kp_patch_source
kp_build_hook
kp_build
kp_sanity_check
kp_gen_kpatch
- kp_patch_test
kp_pack_patch
+ elif test "$ACTION" == "test"; then
+ kp_unpack_prebuilt
+ kp_prepare_test_binaries
+ kp_unpack_patch
+ #kp_patch_source
+ kp_patch_test
fi
#clean_dirs
diff --git a/scripts/toil/build-patch.sh b/scripts/toil/build-patch.sh
index 0e12de4..28720a1 100755
--- a/scripts/toil/build-patch.sh
+++ b/scripts/toil/build-patch.sh
@@ -15,4 +15,3 @@ make -C $KPATCH_PATH clean all
make -C /data/execve clean all
/kcdata/scripts/pkgbuild $@ /kcdata/package
-ls /kcdata -lR
diff --git a/scripts/toil/pkgbuild.py b/scripts/toil/pkgbuild.py
index c4b009a..e091032 100755
--- a/scripts/toil/pkgbuild.py
+++ b/scripts/toil/pkgbuild.py
@@ -12,8 +12,9 @@ The basic components are the following:
first job.
#. `DoBuild` checks presence of the object in the Storage and runs
- `prebuildJob` chained with `uploadJob` and `buildJob` if the object is missing.
- Only `buildJob` is run otherwise.
+ `prebuildJob` chained with `uploadPrebuildJob`, `buildJob`,
+ `uploadPatchJob` and `testJob` if the object is missing.
+ Only `buildJob` and it's children are run otherwise.
This is used to build missing parts such as an archive with the baseline
source code called `prebuilt` which is listed as optional for the
@@ -625,7 +626,7 @@ class S3DownloadJob(S3FileJob):
self.fileName = fileName
super(S3DownloadJob, self).__init__(
memory="1M", cores=1, unitName="download %s" % url,
- disk=self.obj['ContentLength'])
+ disk=max(4096, self.obj['ContentLength']))
def run(self, fileStore):
with fileStore.writeGlobalFileStream() as (fh, fileId):
@@ -731,24 +732,35 @@ class DoBuild(Job):
"""If prebuild archive is not in storage do a prebuild and upload it to the
specified location. Otherwise just do a build."""
- def __init__(self, fileName, prebuildJob, uploadJob, buildJob):
+ def __init__(self, prebuildFileName, buildFileName, prebuildJob, uploadPrebuildJob, buildJob, uploadPatchJob, testJob):
super(DoBuild, self).__init__(memory="256M")
- self.fileName = fileName
+ self.prebuildFileName = prebuildFileName
+ self.buildFileName = buildFileName
self.prebuildJob = prebuildJob
self.buildJob = buildJob
- self.uploadJob = uploadJob
+ self.uploadPrebuildJob = uploadPrebuildJob
+ self.uploadPatchJob = uploadPatchJob
+ self.testJob = testJob
def run(self, fileStore):
- if self.fileName not in self.storage:
+ if self.prebuildFileName not in self.storage:
self.addChild(self.prebuildJob)
self.prebuildJob.addChildNoStorage(self.buildJob)
- self.prebuildJob.addChildNoStorage(self.uploadJob)
+ self.prebuildJob.addChildNoStorage(self.uploadPrebuildJob)
+
+ self.buildJob.addChildNoStorage(self.uploadPatchJob)
+ self.buildJob.addChildNoStorage(self.testJob)
else:
- self.addChild(self.buildJob)
+ if self.buildFileName not in self.storage:
+ self.addChild(self.buildJob)
+ self.buildJob.addChildNoStorage(self.uploadPatchJob)
+ self.buildJob.addChildNoStorage(self.testJob)
+ else:
+ self.addChild(self.testJob)
- self._storage = self.buildJob.storage
+ self._storage = self.testJob.storage
class BuildPatchJob(toilJob):
@@ -784,21 +796,33 @@ class BuildPatchJob(toilJob):
prebuildUrl = self.packageDescription['prebuild']
prebuildName = os.path.basename(prebuildUrl)
+ patchUrl = self.packageDescription['patch']
+ buildName = os.path.basename(patchUrl)
+
prebuildJob = DockerScriptJob(
script=self.script,
image=self.image,
- args=['-p'],
+ args=['--prebuild'],
logfileName="prebuild.log")
- uploadJob = UploadJob([(prebuildName, prebuildUrl)])
+ uploadPrebuildJob = UploadJob([(prebuildName, prebuildUrl)])
+
buildJob = DockerScriptJob(
script=self.script,
image=self.image,
logfileName="build.log")
+ uploadPatchJob = UploadJob([(buildName, patchUrl)])
+ testJob = DockerScriptJob(
+ script=self.script,
+ image=self.image,
+ args=['--test'],
+ logfileName="test.log")
+
+ doBuild = DoBuild(prebuildFileName=prebuildName, buildFileName=buildName, prebuildJob=prebuildJob,
+ uploadPrebuildJob=uploadPrebuildJob, buildJob=buildJob,
+ uploadPatchJob=uploadPatchJob, testJob=testJob)
- doBuild = DoBuild(fileName=prebuildName, prebuildJob=prebuildJob,
- uploadJob=uploadJob, buildJob=buildJob)
tail.addFollowOn(doBuild)
tail = doBuild
@@ -831,6 +855,11 @@ def readPackageDescription(packageFile):
prebuildUrl = '*' + prebuildUrl
inputs.append(prebuildUrl)
+ patchUrl = packageDescription['patch']
+ if not patchUrl.startswith('*'):
+ patchUrl = '*' + patchUrl
+ inputs.append(patchUrl)
+
return packageDescription
def start(toil):
--
2.23.0

View File

@ -0,0 +1,36 @@
From 0c0f6387230d6164eaa58ae4a95656539ace5159 Mon Sep 17 00:00:00 2001
From: Pavel Boldin <pboldin@cloudlinux.com>
Date: Tue, 30 Jan 2018 16:42:32 +0200
Subject: [PATCH 11/89] glibc: minimal readme for toil builder
Signed-off-by: Pavel Boldin <pboldin@cloudlinux.com>
---
packages/rhel7/glibc/glibc-2.17-55.el7/README.md | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
create mode 100644 packages/rhel7/glibc/glibc-2.17-55.el7/README.md
diff --git a/packages/rhel7/glibc/glibc-2.17-55.el7/README.md b/packages/rhel7/glibc/glibc-2.17-55.el7/README.md
new file mode 100644
index 0000000..740d294
--- /dev/null
+++ b/packages/rhel7/glibc/glibc-2.17-55.el7/README.md
@@ -0,0 +1,16 @@
+Use toil-based build script to build patches for the `glibc`. For that simple
+run::
+
+```shell
+$ LIBCARE_DIR=~/libcare-opensource
+$ pip install -r $LIBCARE_DIR/scripts/toil/requirements.txt
+$ python $LIBCARE_DIR/scripts/toil/pkgbuild.py workdir pkgfile.yaml
+...
+```
+
+This should build the following files:
+```shell
+$ ls /tmp/build.orig-glibc-2.17-55.el7.x86_64.rpm.tgz /tmp/kpatch-glibc-2.17-55.el7.x86_64.tgz
+/tmp/build.orig-glibc-2.17-55.el7.x86_64.rpm.tgz
+/tmp/kpatch-glibc-2.17-55.el7.x86_64.tgz
+```
--
2.23.0

View File

@ -0,0 +1,46 @@
From 3566489ee43a348f41bb0fd9c779f1064956ea82 Mon Sep 17 00:00:00 2001
From: Roman Rashchupkin <rrashchupkin@cloudlinux.com>
Date: Thu, 25 Jan 2018 10:18:33 +0300
Subject: [PATCH 12/89] Fix kpatch_process_init/kpatch_coroutines_free
---
src/kpatch_coro.c | 7 ++++---
src/kpatch_process.c | 4 ++--
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/src/kpatch_coro.c b/src/kpatch_coro.c
index ff485fc..45d4a0b 100644
--- a/src/kpatch_coro.c
+++ b/src/kpatch_coro.c
@@ -622,7 +622,8 @@ void kpatch_coroutines_free(struct kpatch_process *proc)
if (proc->coro.unwd)
unw_destroy_addr_space(proc->coro.unwd);
- list_for_each_entry_safe(c, tmp, &proc->coro.coros, list) {
- kpatch_coro_free(c);
- }
+ if (!list_empty(&proc->coro.coros))
+ list_for_each_entry_safe(c, tmp, &proc->coro.coros, list) {
+ kpatch_coro_free(c);
+ }
}
diff --git a/src/kpatch_process.c b/src/kpatch_process.c
index d394925..2f85373 100644
--- a/src/kpatch_process.c
+++ b/src/kpatch_process.c
@@ -1121,10 +1121,10 @@ kpatch_process_init(kpatch_process_t *proc,
list_init(&proc->vmaholes);
proc->num_objs = 0;
- if (process_get_comm(proc))
- goto out_unlock;
if (kpatch_coroutines_init(proc))
goto out_unlock;
+ if (process_get_comm(proc))
+ goto out_unlock;
return 0;
--
2.23.0

View File

@ -0,0 +1,206 @@
From 4cd3610aa11c7b6add5cf090127c522d8004a528 Mon Sep 17 00:00:00 2001
From: Roman Rashchupkin <rrashchupkin@cloudlinux.com>
Date: Wed, 24 Jan 2018 16:01:51 +0300
Subject: [PATCH 13/89] Add libcare-stresstest
---
src/Makefile | 10 ++++-
src/kpatch_user.c | 106 +++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 114 insertions(+), 2 deletions(-)
diff --git a/src/Makefile b/src/Makefile
index cd766e1..58e942a 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -3,7 +3,8 @@ TARGETS = kpatch_gensrc \
kpatch_strip \
libcare-cc \
libcare-client \
- libcare-ctl
+ libcare-ctl \
+ libcare-stresstest
DEBUG = yes # comment out this line if not debug
CC = gcc
@@ -39,6 +40,10 @@ libcare-ctl: kpatch_user.o kpatch_storage.o kpatch_patch.c kpatch_elf.o kpatch_p
libcare-ctl: kpatch_process.o kpatch_common.o rbtree.o kpatch_log.o
libcare-ctl: LDLIBS += -lelf -lrt $(LIBUNWIND_LIBS)
+libcare-stresstest: kpatch_user-stresstest.o kpatch_storage.o kpatch_patch.c kpatch_elf.o kpatch_ptrace.o kpatch_coro.o
+libcare-stresstest: kpatch_process.o kpatch_common.o rbtree.o kpatch_log.o
+libcare-stresstest: LDLIBS += -lelf -lrt $(LIBUNWIND_LIBS)
+
libcare-client: libcare-client.o
kpatch_strip: kpatch_strip.o kpatch_elf_objinfo.o kpatch_log.o
@@ -61,6 +66,9 @@ endif
%.o: %.c deps/%.d
$(CC) $(CFLAGS) $(CFLAGS_$(*)) -o $(@) -c $(<)
+%-stresstest.o: %.c
+ $(CC) -DSTRESS_TEST=1 $(CFLAGS) $(CFLAGS_$(*)) -o $(@) -c $(<)
+
clean:
rm -rf *.o core.* deps/*.d $(TARGETS)
for f in tests/gensrc/*.s; do \
diff --git a/src/kpatch_user.c b/src/kpatch_user.c
index d257b67..e6649b0 100644
--- a/src/kpatch_user.c
+++ b/src/kpatch_user.c
@@ -6,6 +6,7 @@
#include <string.h>
#include <dirent.h>
#include <regex.h>
+#include <time.h>
#include <sys/fcntl.h>
#include <sys/socket.h>
#include <sys/un.h>
@@ -563,6 +564,88 @@ cmd_update(int argc, char *argv[])
/* send_fd */ -1);
}
+#ifdef STRESS_TEST
+
+struct test_data {
+ int option_period;
+ int stat_cycle_num;
+} test_info = { .option_period = 0, .stat_cycle_num = 0 };
+
+static int
+server_wait(int pid, int period)
+{
+ struct timespec req, rem;
+ int i;
+ req.tv_sec = 0;
+ req.tv_nsec = 1000*1000;
+ for (i=0; i<period; i++) {
+ nanosleep(&req, &rem);
+ if (kill(pid, 0) != 0) {
+ fprintf(stderr, "Process %d terminated.\n", pid);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int
+server_stress_test(int fd, int argc, char *argv[])
+{
+ int pid;
+ int delay;
+ test_info.stat_cycle_num = 0;
+ srand(time(NULL));
+
+ if (sscanf(argv[1], "%d", &pid) != 1) {
+ kperr("Can't parse pid from %s\n", argv[1]);
+ return -1;
+ }
+
+ while (1) {
+ while (patch_user(storage_dir, pid, 0, fd) < 0)
+ if (server_wait(pid, 1) < 0)
+ return 0;
+ if (fd > 0)
+ close(fd);
+ fd = -1;
+ if (test_info.option_period == 0)
+ return 0;
+ delay = rand() % test_info.option_period;
+ if (server_wait(pid, delay) < 0)
+ return 0;
+
+ while (processes_unpatch(pid, 0, 0) < 0)
+ if (server_wait(pid, 1) < 0)
+ return 0;
+ test_info.stat_cycle_num++;
+
+ delay = rand() % test_info.option_period;
+ if (server_wait(pid, delay) < 0)
+ return 0;
+ }
+
+ return 0;
+}
+
+static int cmd_stress_test(int fd, int argc, char *argv[])
+{
+ int child = fork();
+ if (child == 0) {
+ int rv = server_stress_test(fd, argc, argv);
+ exit(rv);
+ }
+ close(fd);
+ return 0;
+}
+
+static int usage_stresstest()
+{
+ fprintf(stderr, "usage: libcare-stresstest PERIOD(ms, 0 - only patch) <UNIX socket> [STORAGE ROOT]\n");
+ return -1;
+}
+
+#endif
+
static int
server_execute_cmd(int fd, int argc, char *argv[])
{
@@ -572,8 +655,13 @@ server_execute_cmd(int fd, int argc, char *argv[])
if (!strcmp(cmd, "execve"))
return cmd_execve_startup(fd, argc, argv, 1);
- if (!strcmp(cmd, "startup"))
+ if (!strcmp(cmd, "startup")) {
+#ifdef STRESS_TEST
+ return cmd_stress_test(fd, argc, argv);
+#else
return cmd_execve_startup(fd, argc, argv, 0);
+#endif
+ }
if (!strcmp(cmd, "update"))
return cmd_update(argc, argv);
if (!strcmp(cmd, "storage"))
@@ -739,6 +827,12 @@ cmd_server(int argc, char *argv[])
return -1;
}
+#ifdef STRESS_TEST
+ if (sscanf(argv[0], "%d", &test_info.option_period) != 1) {
+ kplogerror("Can't parse period from %s\n", argv[0]);
+ }
+#endif
+
sfd = server_bind_socket(argv[1]);
if (sfd < 0)
return sfd;
@@ -824,6 +918,9 @@ static int usage(const char *err)
{
if (err)
fprintf(stderr, "err: %s\n", err);
+#ifdef STRESS_TEST
+ return usage_stresstest();
+#endif
fprintf(stderr, "usage: libcare-ctl [options] <cmd> [args]\n");
fprintf(stderr, "\nOptions:\n");
fprintf(stderr, " -v - verbose mode\n");
@@ -872,6 +969,12 @@ int main(int argc, char *argv[])
argc -= optind;
argv += optind;
+#ifdef STRESS_TEST
+ if (argc < 3)
+ return usage("not enough arguments.");
+ signal(SIGCHLD, SIG_IGN);
+ return cmd_server(argc, argv);
+#else
if (argc < 1)
return usage("not enough arguments.");
@@ -879,4 +982,5 @@ int main(int argc, char *argv[])
return cmd_server(argc, argv);
else
return execute_cmd(argc, argv);
+#endif
}
--
2.23.0

View File

@ -0,0 +1,93 @@
From 212e98a668117a11aa528e5669189b58dcaacd95 Mon Sep 17 00:00:00 2001
From: Pavel Boldin <pboldin@cloudlinux.com>
Date: Wed, 7 Feb 2018 09:14:39 +0200
Subject: [PATCH 14/89] read auxv from /proc/pid/auxv
Signed-off-by: Pavel Boldin <pboldin@cloudlinux.com>
---
src/kpatch_ptrace.c | 54 +++++++++++++++++----------------------------
1 file changed, 20 insertions(+), 34 deletions(-)
diff --git a/src/kpatch_ptrace.c b/src/kpatch_ptrace.c
index f732004..f91b80e 100644
--- a/src/kpatch_ptrace.c
+++ b/src/kpatch_ptrace.c
@@ -143,55 +143,41 @@ int kpatch_process_mem_iter_peek_ulong(struct process_mem_iter *iter,
return kpatch_process_mem_iter_peek(iter, dst, sizeof(*dst), remote_addr);
}
-/* FIXME(pboldin): read these from /proc/pid/auxv */
int kpatch_ptrace_get_entry_point(struct kpatch_ptrace_ctx *pctx,
unsigned long *pentry_point)
{
- int ret;
- unsigned long *rstack, val;
- struct user_regs_struct regs;
- struct process_mem_iter *iter;
+ int fd, ret;
+ unsigned long entry[2] = { AT_NULL, 0 };
+ char path[sizeof("/proc/0123456789/auxv")];
kpdebug("Looking for entry point...");
- ret = ptrace(PTRACE_GETREGS, pctx->pid, NULL, &regs);
- if (ret < 0) {
- kplogerror("can't get regs\n");
- return -1;
- }
-
- iter = kpatch_process_mem_iter_init(pctx->proc);
- if (!iter) {
- kplogerror("can't allocate iterator\n");
+ sprintf(path, "/proc/%d/auxv", pctx->pid);
+ fd = open(path, O_RDONLY);
+ if (fd == -1) {
+ kplogerror("can't open %s\n", path);
return -1;
}
- /* Read stack and look for AUX data */
- rstack = (unsigned long*)regs.rsp;
-
- /* rstack now points to envs */
- rstack += PEEK_ULONG(rstack) + 2;
-
- /* Skip envs */
- for (; PEEK_ULONG(rstack); rstack++)
- continue;
+ do {
+ ret = read(fd, entry, sizeof(entry));
+ if (ret < 0 && errno == EINTR)
+ continue;
+ if (ret != sizeof(entry))
+ break;
- /* Now got to AUX */
- for (rstack++; (val = PEEK_ULONG(rstack)) != AT_NULL; rstack += 2) {
- if (val == AT_ENTRY) {
- *pentry_point = PEEK_ULONG(rstack + 1);
+ if (entry[0] == AT_ENTRY) {
+ *pentry_point = entry[1];
break;
}
- }
+ } while (1);
- if (val != AT_ENTRY)
- kpdebug("FAIL\n");
- else
- kpdebug("OK\n");
+ if (ret < 0)
+ kplogerror("reading %s\n", path);
- kpatch_process_mem_iter_free(iter);
+ close(fd);
- return val == AT_ENTRY ? 0 : -1;
+ return entry[0] == AT_ENTRY ? 0 : -1;
}
#define BREAK_INSN_LENGTH 1
--
2.23.0

View File

@ -0,0 +1,147 @@
From f25aa052cd31cab4c6301cca5eb8e5e5f129d5bd Mon Sep 17 00:00:00 2001
From: Pavel Boldin <pboldin@cloudlinux.com>
Date: Wed, 7 Feb 2018 23:59:39 +0200
Subject: [PATCH 15/89] add `fail to unpatch` test
Add a test sample where patch is always busy in the loop and cannot
be unapplied.
Signed-off-by: Pavel Boldin <pboldin@cloudlinux.com>
---
tests/fail_unpatch/Makefile | 4 ++++
tests/fail_unpatch/desc | 1 +
tests/fail_unpatch/fail_unpatch.c | 29 ++++++++++++++++++++++++++++
tests/fail_unpatch/fail_unpatch.diff | 11 +++++++++++
tests/run_tests.sh | 25 ++++++++++++++++++++++--
5 files changed, 68 insertions(+), 2 deletions(-)
create mode 100644 tests/fail_unpatch/Makefile
create mode 100644 tests/fail_unpatch/desc
create mode 100644 tests/fail_unpatch/fail_unpatch.c
create mode 100644 tests/fail_unpatch/fail_unpatch.diff
diff --git a/tests/fail_unpatch/Makefile b/tests/fail_unpatch/Makefile
new file mode 100644
index 0000000..d7680e9
--- /dev/null
+++ b/tests/fail_unpatch/Makefile
@@ -0,0 +1,4 @@
+
+LDLIBS:=-lpthread
+
+include ../makefile.inc
diff --git a/tests/fail_unpatch/desc b/tests/fail_unpatch/desc
new file mode 100644
index 0000000..02151c5
--- /dev/null
+++ b/tests/fail_unpatch/desc
@@ -0,0 +1 @@
+fails to unpatch the code
diff --git a/tests/fail_unpatch/fail_unpatch.c b/tests/fail_unpatch/fail_unpatch.c
new file mode 100644
index 0000000..6b5c50f
--- /dev/null
+++ b/tests/fail_unpatch/fail_unpatch.c
@@ -0,0 +1,29 @@
+#include <stdio.h>
+#include <unistd.h>
+
+void print_greetings_patched(void)
+{
+ while (1) {
+ printf("Hello. This a PATCHED version!\n");
+ sleep(1);
+ }
+}
+
+void print_greetings(void)
+{
+ printf("Hello. This is an UNPATCHED version!\n");
+}
+
+void do_work() {
+ while (1) {
+ print_greetings();
+ sleep(1);
+ }
+}
+
+int main()
+{
+ do_work();
+
+ return 0;
+}
diff --git a/tests/fail_unpatch/fail_unpatch.diff b/tests/fail_unpatch/fail_unpatch.diff
new file mode 100644
index 0000000..49738bd
--- /dev/null
+++ b/tests/fail_unpatch/fail_unpatch.diff
@@ -0,0 +1,11 @@
+--- ./fail_unpatch.c 2018-02-07 18:39:27.145493215 +0200
++++ ./fail_unpatch.c 2018-02-07 18:39:43.349482218 +0200
+@@ -11,7 +11,7 @@
+
+ void print_greetings(void)
+ {
+- printf("Hello. This is an UNPATCHED version!\n");
++ print_greetings_patched();
+ }
+
+ void do_work() {
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index fbfb273..2bdd303 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -105,6 +105,10 @@ check_result() {
! grep_tail 'UNPATCHED'
return $?
;;
+ fail_unpatch)
+ grep_tail '\<PATCHED'
+ return $?
+ ;;
fail_*)
grep_tail 'UNPATCHED'
return $?
@@ -163,9 +167,24 @@ test_patch_files_fini() {
check_result_unpatch() {
+ local testname="$1"
local outfile="$2"
+
check_result "$@"
- test $? -ne "$(cat ${outfile}_patched)"
+ test $? -eq 0
+ local is_unpatched=$?
+
+ test "$(cat ${outfile}_patched)" -eq 1
+ local was_patched=$?
+
+ case $testname in
+ fail_unpatch)
+ test $is_unpatched -eq 0 && test $was_patched -eq 1
+ ;;
+ *)
+ test $is_unpatched -eq 1 && test $was_patched -eq 1
+ ;;
+ esac
}
test_unpatch_files_init() {
@@ -200,9 +219,11 @@ test_unpatch_files() {
check_result $testname $outfile
echo $? >${outfile}_patched
+ cat ${outfile}_patched
+ echo "============unpatching===============" >>$logfile
libcare_ctl unpatch-user -p $pid \
- >$logfile 2>&1 || :
+ >>$logfile 2>&1 || :
sleep 2
--
2.23.0

View File

@ -0,0 +1,67 @@
From b6b35d80755caed0528dfdf3825ecf055fe9ea76 Mon Sep 17 00:00:00 2001
From: Roman Rashchupkin <rrashchupkin@cloudlinux.com>
Date: Wed, 28 Feb 2018 23:05:50 +0300
Subject: [PATCH 16/89] Waitpid for finished threads after detach.
---
src/kpatch_process.c | 14 +++++++++++++-
src/kpatch_ptrace.c | 2 +-
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/src/kpatch_process.c b/src/kpatch_process.c
index 2f85373..5c0374a 100644
--- a/src/kpatch_process.c
+++ b/src/kpatch_process.c
@@ -12,6 +12,11 @@
#include <sys/stat.h>
#include <sys/sysmacros.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/ptrace.h>
+
#include <gelf.h>
#include <libunwind.h>
#include <libunwind-ptrace.h>
@@ -537,6 +542,8 @@ static void
process_detach(kpatch_process_t *proc)
{
struct kpatch_ptrace_ctx *p, *ptmp;
+ int status;
+ pid_t pid;
if (proc->memfd >= 0 && close(proc->memfd) < 0)
kplogerror("can't close memfd");
@@ -546,9 +553,14 @@ process_detach(kpatch_process_t *proc)
unw_destroy_addr_space(proc->ptrace.unwd);
list_for_each_entry_safe(p, ptmp, &proc->ptrace.pctxs, list) {
- kpatch_ptrace_detach(p);
+ if (kpatch_ptrace_detach(p) == -ESRCH) {
+ do {
+ pid = waitpid(p->pid, &status, __WALL);
+ } while (pid > 0 && !WIFEXITED(status));
+ }
kpatch_ptrace_ctx_destroy(p);
}
+ kpinfo("Finished ptrace detaching.");
}
static int
diff --git a/src/kpatch_ptrace.c b/src/kpatch_ptrace.c
index f91b80e..a5f61b3 100644
--- a/src/kpatch_ptrace.c
+++ b/src/kpatch_ptrace.c
@@ -1186,7 +1186,7 @@ int kpatch_ptrace_detach(struct kpatch_ptrace_ctx *pctx)
ret = ptrace(PTRACE_DETACH, pctx->pid, NULL, NULL);
if (ret < 0) {
kplogerror("can't detach from %d\n", pctx->pid);
- return -1;
+ return -errno;
}
kpdebug("OK\n");
--
2.23.0

View File

@ -0,0 +1,28 @@
From 90a310f57710abb3f5e41c431d26e77fef63ad2b Mon Sep 17 00:00:00 2001
From: Pavel Boldin <boldin.pavel@gmail.com>
Date: Thu, 13 Sep 2018 12:00:02 +0300
Subject: [PATCH 17/89] .gitignore build artefacts
Signed-off-by: Pavel Boldin <boldin.pavel@gmail.com>
---
.gitignore | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/.gitignore b/.gitignore
index 5761abc..065f093 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,10 @@
*.o
+*.d
+src/kpatch_gensrc
+src/kpatch_make
+src/kpatch_strip
+src/libcare-cc
+src/libcare-client
+src/libcare-ctl
+src/libcare-stresstest
+tags
--
2.23.0

View File

@ -0,0 +1,29 @@
From 3954dd43124e87c788352ccc528cc79e8fca6f6d Mon Sep 17 00:00:00 2001
From: YiFan <loyfan@users.noreply.github.com>
Date: Tue, 13 Aug 2019 11:02:36 +0800
Subject: [PATCH 18/89] kpatch_storage: put an end to description string loaded
Description string should be ended up with a '\0'.
---
src/kpatch_storage.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/kpatch_storage.c b/src/kpatch_storage.c
index a466460..2375559 100644
--- a/src/kpatch_storage.c
+++ b/src/kpatch_storage.c
@@ -377,8 +377,10 @@ char *storage_get_description(kpatch_storage_t *storage,
if (rv == -1)
goto err_free;
- if (rv == 0)
+ if (rv == 0) {
+ desc[sz] = '\0';
break;
+ }
sz += rv;
}
--
2.23.0

View File

@ -0,0 +1,51 @@
From 43e10a5ef1db3c56a872e3a61edaf224b51822f0 Mon Sep 17 00:00:00 2001
From: Pavel Artsishevsky <polter.rnd@gmail.com>
Date: Tue, 18 Feb 2020 15:21:26 +0300
Subject: [PATCH 19/89] Fix README files
- Update patch build instructions for GHOST sample;
- Add Travis CI status image to main readme file.
---
README.rst | 3 +++
samples/ghost/README.rst | 11 +++++++++++
2 files changed, 14 insertions(+)
diff --git a/README.rst b/README.rst
index 927325d..932b7c5 100644
--- a/README.rst
+++ b/README.rst
@@ -1,6 +1,9 @@
LibCare -- Patch Userspace Code on Live Processes
=================================================
+.. image:: https://travis-ci.org/cloudlinux/libcare.svg?branch=master
+ :target: https://travis-ci.org/cloudlinux/libcare
+
Welcome to LibCare --- Live Patch Updates for Userspace Processes and Libraries.
LibCare delivers live patches to any of your Linux executables or libraries at
diff --git a/samples/ghost/README.rst b/samples/ghost/README.rst
index da97926..e274b54 100644
--- a/samples/ghost/README.rst
+++ b/samples/ghost/README.rst
@@ -32,6 +32,17 @@ Now, from inside the container let's install vulnerable version of glibc:
glibc-headers-2.17-55.el7 glibc-common-2.17-55.el7
...
+Also we have to downgrade elfutils since newer versions of ``eu-unstrip``
+fail to work with glibc utilities:
+
+.. code:: console
+
+ [root@... /]# yum downgrade -y --enablerepo=C7.0.1406-base \
+ elfutils-devel-0.158-3.el7.x86_64 elfutils-0.158-3.el7.x86_64 \
+ elfutils-libs-0.158-3.el7.x86_64 elfutils-libelf-0.158-3.el7.x86_64 \
+ elfutils-libelf-devel-0.158-3.el7.x86_64
+ ...
+
Build the ``libcare`` tools:
.. code:: console
--
2.23.0

View File

@ -0,0 +1,129 @@
From ca5872b354b7987ce2dfd6f5268771268ad006d0 Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Sat, 10 Oct 2020 16:46:38 +0800
Subject: [PATCH 20/89] include: Create include directory for header files
Move all header files from src directory into newly created include directory
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
src/{ => include}/kpatch_common.h | 0
src/{ => include}/kpatch_coro.h | 0
src/{ => include}/kpatch_dbgfilter.h | 0
src/{ => include}/kpatch_elf.h | 0
src/{ => include}/kpatch_elf_objinfo.h | 0
src/{ => include}/kpatch_file.h | 0
src/{ => include}/kpatch_flags.h | 0
src/{ => include}/kpatch_io.h | 0
src/{ => include}/kpatch_log.h | 0
src/{ => include}/kpatch_parse.h | 0
src/{ => include}/kpatch_patch.h | 0
src/{ => include}/kpatch_process.h | 0
src/{ => include}/kpatch_ptrace.h | 0
src/{ => include}/kpatch_storage.h | 0
src/{ => include}/kpatch_str.h | 0
src/{ => include}/kpatch_user.h | 0
src/{ => include}/list.h | 0
src/{ => include}/rbtree.h | 0
src/{ => include}/util.h | 0
19 files changed, 0 insertions(+), 0 deletions(-)
rename src/{ => include}/kpatch_common.h (100%)
rename src/{ => include}/kpatch_coro.h (100%)
rename src/{ => include}/kpatch_dbgfilter.h (100%)
rename src/{ => include}/kpatch_elf.h (100%)
rename src/{ => include}/kpatch_elf_objinfo.h (100%)
rename src/{ => include}/kpatch_file.h (100%)
rename src/{ => include}/kpatch_flags.h (100%)
rename src/{ => include}/kpatch_io.h (100%)
rename src/{ => include}/kpatch_log.h (100%)
rename src/{ => include}/kpatch_parse.h (100%)
rename src/{ => include}/kpatch_patch.h (100%)
rename src/{ => include}/kpatch_process.h (100%)
rename src/{ => include}/kpatch_ptrace.h (100%)
rename src/{ => include}/kpatch_storage.h (100%)
rename src/{ => include}/kpatch_str.h (100%)
rename src/{ => include}/kpatch_user.h (100%)
rename src/{ => include}/list.h (100%)
rename src/{ => include}/rbtree.h (100%)
rename src/{ => include}/util.h (100%)
diff --git a/src/kpatch_common.h b/src/include/kpatch_common.h
similarity index 100%
rename from src/kpatch_common.h
rename to src/include/kpatch_common.h
diff --git a/src/kpatch_coro.h b/src/include/kpatch_coro.h
similarity index 100%
rename from src/kpatch_coro.h
rename to src/include/kpatch_coro.h
diff --git a/src/kpatch_dbgfilter.h b/src/include/kpatch_dbgfilter.h
similarity index 100%
rename from src/kpatch_dbgfilter.h
rename to src/include/kpatch_dbgfilter.h
diff --git a/src/kpatch_elf.h b/src/include/kpatch_elf.h
similarity index 100%
rename from src/kpatch_elf.h
rename to src/include/kpatch_elf.h
diff --git a/src/kpatch_elf_objinfo.h b/src/include/kpatch_elf_objinfo.h
similarity index 100%
rename from src/kpatch_elf_objinfo.h
rename to src/include/kpatch_elf_objinfo.h
diff --git a/src/kpatch_file.h b/src/include/kpatch_file.h
similarity index 100%
rename from src/kpatch_file.h
rename to src/include/kpatch_file.h
diff --git a/src/kpatch_flags.h b/src/include/kpatch_flags.h
similarity index 100%
rename from src/kpatch_flags.h
rename to src/include/kpatch_flags.h
diff --git a/src/kpatch_io.h b/src/include/kpatch_io.h
similarity index 100%
rename from src/kpatch_io.h
rename to src/include/kpatch_io.h
diff --git a/src/kpatch_log.h b/src/include/kpatch_log.h
similarity index 100%
rename from src/kpatch_log.h
rename to src/include/kpatch_log.h
diff --git a/src/kpatch_parse.h b/src/include/kpatch_parse.h
similarity index 100%
rename from src/kpatch_parse.h
rename to src/include/kpatch_parse.h
diff --git a/src/kpatch_patch.h b/src/include/kpatch_patch.h
similarity index 100%
rename from src/kpatch_patch.h
rename to src/include/kpatch_patch.h
diff --git a/src/kpatch_process.h b/src/include/kpatch_process.h
similarity index 100%
rename from src/kpatch_process.h
rename to src/include/kpatch_process.h
diff --git a/src/kpatch_ptrace.h b/src/include/kpatch_ptrace.h
similarity index 100%
rename from src/kpatch_ptrace.h
rename to src/include/kpatch_ptrace.h
diff --git a/src/kpatch_storage.h b/src/include/kpatch_storage.h
similarity index 100%
rename from src/kpatch_storage.h
rename to src/include/kpatch_storage.h
diff --git a/src/kpatch_str.h b/src/include/kpatch_str.h
similarity index 100%
rename from src/kpatch_str.h
rename to src/include/kpatch_str.h
diff --git a/src/kpatch_user.h b/src/include/kpatch_user.h
similarity index 100%
rename from src/kpatch_user.h
rename to src/include/kpatch_user.h
diff --git a/src/list.h b/src/include/list.h
similarity index 100%
rename from src/list.h
rename to src/include/list.h
diff --git a/src/rbtree.h b/src/include/rbtree.h
similarity index 100%
rename from src/rbtree.h
rename to src/include/rbtree.h
diff --git a/src/util.h b/src/include/util.h
similarity index 100%
rename from src/util.h
rename to src/include/util.h
--
2.23.0

View File

@ -0,0 +1,373 @@
From 64f163e9bd26b0af65f12e7cc4205da0d787e7fc Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Sat, 10 Oct 2020 16:50:15 +0800
Subject: [PATCH 21/89] src: Update header file position
Update header file positon with include prefix to source file in src directory.
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
src/kpatch_common.c | 6 +++---
src/kpatch_coro.c | 12 ++++++------
src/kpatch_dbgfilter.c | 6 +++---
src/kpatch_elf.c | 14 +++++++-------
src/kpatch_elf_objinfo.c | 6 +++---
src/kpatch_gensrc.c | 8 ++++----
src/kpatch_io.c | 6 +++---
src/kpatch_log.c | 2 +-
src/kpatch_make.c | 2 +-
src/kpatch_parse.c | 6 +++---
src/kpatch_patch.c | 20 ++++++++++----------
src/kpatch_process.c | 14 +++++++-------
src/kpatch_ptrace.c | 8 ++++----
src/kpatch_storage.c | 14 +++++++-------
src/kpatch_strip.c | 8 ++++----
src/kpatch_user.c | 18 +++++++++---------
src/rbtree.c | 2 +-
17 files changed, 76 insertions(+), 76 deletions(-)
diff --git a/src/kpatch_common.c b/src/kpatch_common.c
index 99bc0b3..95d4a54 100644
--- a/src/kpatch_common.c
+++ b/src/kpatch_common.c
@@ -6,9 +6,9 @@
#include <errno.h>
#include <unistd.h>
-#include "kpatch_file.h"
-#include "kpatch_common.h"
-#include "kpatch_log.h"
+#include "include/kpatch_file.h"
+#include "include/kpatch_common.h"
+#include "include/kpatch_log.h"
int kpatch_openat_file(int atfd, const char *fname, struct kp_file *kpatch)
{
diff --git a/src/kpatch_coro.c b/src/kpatch_coro.c
index 45d4a0b..02d421b 100644
--- a/src/kpatch_coro.c
+++ b/src/kpatch_coro.c
@@ -8,12 +8,12 @@
#include <asm/prctl.h>
-#include "kpatch_user.h"
-#include "kpatch_coro.h"
-#include "kpatch_common.h"
-#include "kpatch_elf.h"
-#include "kpatch_ptrace.h"
-#include "kpatch_log.h"
+#include "include/kpatch_user.h"
+#include "include/kpatch_coro.h"
+#include "include/kpatch_common.h"
+#include "include/kpatch_elf.h"
+#include "include/kpatch_ptrace.h"
+#include "include/kpatch_log.h"
/* Indicates that the next CORO flavours should be tried */
#define CORO_SEARCH_NEXT (1<<31)
diff --git a/src/kpatch_dbgfilter.c b/src/kpatch_dbgfilter.c
index 73a9bc3..d385c18 100644
--- a/src/kpatch_dbgfilter.c
+++ b/src/kpatch_dbgfilter.c
@@ -1,9 +1,9 @@
#include <stdio.h>
#include <stdlib.h>
-#include "kpatch_parse.h"
-#include "kpatch_str.h"
-#include "kpatch_dbgfilter.h"
+#include "include/kpatch_parse.h"
+#include "include/kpatch_str.h"
+#include "include/kpatch_dbgfilter.h"
static int is_cold_hot(char *s)
{
diff --git a/src/kpatch_elf.c b/src/kpatch_elf.c
index e42642b..b1dfed0 100644
--- a/src/kpatch_elf.c
+++ b/src/kpatch_elf.c
@@ -7,13 +7,13 @@
#include <gelf.h>
-#include "kpatch_common.h"
-#include "kpatch_user.h"
-#include "kpatch_process.h"
-#include "kpatch_elf.h"
-#include "kpatch_file.h"
-#include "kpatch_ptrace.h"
-#include "kpatch_log.h"
+#include "include/kpatch_common.h"
+#include "include/kpatch_user.h"
+#include "include/kpatch_process.h"
+#include "include/kpatch_elf.h"
+#include "include/kpatch_file.h"
+#include "include/kpatch_ptrace.h"
+#include "include/kpatch_log.h"
static int
elf_object_peek_phdr(struct object_file *o)
diff --git a/src/kpatch_elf_objinfo.c b/src/kpatch_elf_objinfo.c
index 65b7144..c967c37 100644
--- a/src/kpatch_elf_objinfo.c
+++ b/src/kpatch_elf_objinfo.c
@@ -4,9 +4,9 @@
#include <gelf.h>
-#include "kpatch_common.h"
-#include "kpatch_elf_objinfo.h"
-#include "kpatch_log.h"
+#include "include/kpatch_common.h"
+#include "include/kpatch_elf_objinfo.h"
+#include "include/kpatch_log.h"
const char *kpatch_objinfo_strptr(kpatch_objinfo *oi, int type, size_t nameidx)
{
diff --git a/src/kpatch_gensrc.c b/src/kpatch_gensrc.c
index a15fa2c..a16b652 100644
--- a/src/kpatch_gensrc.c
+++ b/src/kpatch_gensrc.c
@@ -4,10 +4,10 @@
#include <stdarg.h>
#include <getopt.h>
-#include "kpatch_log.h"
-#include "kpatch_parse.h"
-#include "kpatch_dbgfilter.h"
-#include "kpatch_flags.h"
+#include "include/kpatch_log.h"
+#include "include/kpatch_parse.h"
+#include "include/kpatch_dbgfilter.h"
+#include "include/kpatch_flags.h"
#define OS_RHEL5 1
#define OS_RHEL6 2
diff --git a/src/kpatch_io.c b/src/kpatch_io.c
index 663bed0..7bdc298 100644
--- a/src/kpatch_io.c
+++ b/src/kpatch_io.c
@@ -4,9 +4,9 @@
#include <errno.h>
#include <libgen.h>
-#include "kpatch_log.h"
-#include "kpatch_io.h"
-#include "kpatch_str.h"
+#include "include/kpatch_log.h"
+#include "include/kpatch_io.h"
+#include "include/kpatch_str.h"
void *kp_realloc(void *p, int oldsz, int newsz)
{
diff --git a/src/kpatch_log.c b/src/kpatch_log.c
index de80f7b..6e48de4 100644
--- a/src/kpatch_log.c
+++ b/src/kpatch_log.c
@@ -4,7 +4,7 @@
#include <string.h>
#include <errno.h>
-#include "kpatch_log.h"
+#include "include/kpatch_log.h"
int log_level = LOG_INFO;
int log_indent;
diff --git a/src/kpatch_make.c b/src/kpatch_make.c
index c584b06..6a173e6 100644
--- a/src/kpatch_make.c
+++ b/src/kpatch_make.c
@@ -9,7 +9,7 @@
#include <errno.h>
#include <time.h>
-#include "kpatch_file.h"
+#include "include/kpatch_file.h"
#define ALIGN(x, align) ((x + align - 1) & (~(align - 1)))
diff --git a/src/kpatch_parse.c b/src/kpatch_parse.c
index 358916b..dfb3109 100644
--- a/src/kpatch_parse.c
+++ b/src/kpatch_parse.c
@@ -1,8 +1,8 @@
#include <stdlib.h>
-#include "kpatch_log.h"
-#include "kpatch_parse.h"
-#include "kpatch_flags.h"
+#include "include/kpatch_log.h"
+#include "include/kpatch_parse.h"
+#include "include/kpatch_flags.h"
char *cline(struct kp_file *f, int l)
{
diff --git a/src/kpatch_patch.c b/src/kpatch_patch.c
index e32c702..21a160a 100644
--- a/src/kpatch_patch.c
+++ b/src/kpatch_patch.c
@@ -10,16 +10,16 @@
#include <libunwind.h>
#include <libunwind-ptrace.h>
-#include "kpatch_patch.h"
-#include "kpatch_user.h"
-#include "kpatch_storage.h"
-#include "kpatch_process.h"
-#include "kpatch_file.h"
-#include "kpatch_common.h"
-#include "kpatch_elf.h"
-#include "kpatch_ptrace.h"
-#include "list.h"
-#include "kpatch_log.h"
+#include "include/kpatch_patch.h"
+#include "include/kpatch_user.h"
+#include "include/kpatch_storage.h"
+#include "include/kpatch_process.h"
+#include "include/kpatch_file.h"
+#include "include/kpatch_common.h"
+#include "include/kpatch_elf.h"
+#include "include/kpatch_ptrace.h"
+#include "include/list.h"
+#include "include/kpatch_log.h"
static inline int
diff --git a/src/kpatch_process.c b/src/kpatch_process.c
index 5c0374a..3f7f2f6 100644
--- a/src/kpatch_process.c
+++ b/src/kpatch_process.c
@@ -23,13 +23,13 @@
#include <sys/socket.h>
-#include "kpatch_process.h"
-#include "kpatch_file.h"
-#include "kpatch_common.h"
-#include "kpatch_elf.h"
-#include "kpatch_ptrace.h"
-#include "list.h"
-#include "kpatch_log.h"
+#include "include/kpatch_process.h"
+#include "include/kpatch_file.h"
+#include "include/kpatch_common.h"
+#include "include/kpatch_elf.h"
+#include "include/kpatch_ptrace.h"
+#include "include/list.h"
+#include "include/kpatch_log.h"
/*
* Locks process by opening /proc/<pid>/maps
diff --git a/src/kpatch_ptrace.c b/src/kpatch_ptrace.c
index a5f61b3..8910aa8 100644
--- a/src/kpatch_ptrace.c
+++ b/src/kpatch_ptrace.c
@@ -15,10 +15,10 @@
#include <sys/types.h>
#include <sys/socket.h>
-#include "kpatch_process.h"
-#include "kpatch_common.h"
-#include "kpatch_ptrace.h"
-#include "kpatch_log.h"
+#include "include/kpatch_process.h"
+#include "include/kpatch_common.h"
+#include "include/kpatch_ptrace.h"
+#include "include/kpatch_log.h"
#include <gelf.h>
diff --git a/src/kpatch_storage.c b/src/kpatch_storage.c
index 2375559..9165cbf 100644
--- a/src/kpatch_storage.c
+++ b/src/kpatch_storage.c
@@ -10,13 +10,13 @@
#include <sys/wait.h>
#include <gelf.h>
-#include "kpatch_storage.h"
-#include "kpatch_file.h"
-#include "kpatch_common.h"
-#include "kpatch_elf.h"
-#include "kpatch_ptrace.h"
-#include "list.h"
-#include "kpatch_log.h"
+#include "include/kpatch_storage.h"
+#include "include/kpatch_file.h"
+#include "include/kpatch_common.h"
+#include "include/kpatch_elf.h"
+#include "include/kpatch_ptrace.h"
+#include "include/list.h"
+#include "include/kpatch_log.h"
/*****************************************************************************
diff --git a/src/kpatch_strip.c b/src/kpatch_strip.c
index b4de32d..6ad56a3 100644
--- a/src/kpatch_strip.c
+++ b/src/kpatch_strip.c
@@ -7,13 +7,13 @@
#include <string.h>
#include <stdint.h>
#include <getopt.h>
-#include "kpatch_file.h"
-#include "kpatch_common.h"
+#include "include/kpatch_file.h"
+#include "include/kpatch_common.h"
#include <gelf.h>
-#include "kpatch_elf_objinfo.h"
+#include "include/kpatch_elf_objinfo.h"
-#include "kpatch_log.h"
+#include "include/kpatch_log.h"
#define ALIGN(off,sz) (((off)+(sz)-1)&~((sz)-1))
diff --git a/src/kpatch_user.c b/src/kpatch_user.c
index e6649b0..11e3408 100644
--- a/src/kpatch_user.c
+++ b/src/kpatch_user.c
@@ -16,15 +16,15 @@
#include <libunwind.h>
#include <libunwind-ptrace.h>
-#include "kpatch_user.h"
-#include "kpatch_storage.h"
-#include "kpatch_patch.h"
-#include "kpatch_process.h"
-#include "kpatch_file.h"
-#include "kpatch_common.h"
-#include "kpatch_elf.h"
-#include "list.h"
-#include "kpatch_log.h"
+#include "include/kpatch_user.h"
+#include "include/kpatch_storage.h"
+#include "include/kpatch_patch.h"
+#include "include/kpatch_process.h"
+#include "include/kpatch_file.h"
+#include "include/kpatch_common.h"
+#include "include/kpatch_elf.h"
+#include "include/list.h"
+#include "include/kpatch_log.h"
/* Global variables */
static char storage_dir[PATH_MAX] = "/var/lib/libcare";
diff --git a/src/rbtree.c b/src/rbtree.c
index fee5844..6aff1d1 100644
--- a/src/rbtree.c
+++ b/src/rbtree.c
@@ -21,7 +21,7 @@
linux/lib/rbtree.c
*/
-#include "rbtree.h"
+#include "include/rbtree.h"
/*
* red-black trees properties: http://en.wikipedia.org/wiki/Rbtree
--
2.23.0

View File

@ -0,0 +1,73 @@
From b0d5f7f4e15bd19e7dc055b3f24171a3b14aa445 Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Sat, 10 Oct 2020 16:59:16 +0800
Subject: [PATCH 22/89] arch: Create arch directory to support multi-arch
Create directory arch/aarch64 and arch/x86 hold arch-related source files.
Create arch-related source files in libcare.
Files list below are architecture dependent:
arch_coro.c
arch_elf.c
arch_parse.c
arch_patch.c
arch_ptrace.c
arch_process.c
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
src/arch/aarch64/arch_coro.c | 0
src/arch/aarch64/arch_elf.c | 0
src/arch/aarch64/arch_parse.c | 0
src/arch/aarch64/arch_patch.c | 0
src/arch/aarch64/arch_ptrace.c | 0
src/arch/x86/arch_coro.c | 0
src/arch/x86/arch_elf.c | 0
src/arch/x86/arch_parse.c | 0
src/arch/x86/arch_patch.c | 0
src/arch/x86/arch_ptrace.c | 0
10 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 src/arch/aarch64/arch_coro.c
create mode 100644 src/arch/aarch64/arch_elf.c
create mode 100644 src/arch/aarch64/arch_parse.c
create mode 100644 src/arch/aarch64/arch_patch.c
create mode 100644 src/arch/aarch64/arch_ptrace.c
create mode 100644 src/arch/x86/arch_coro.c
create mode 100644 src/arch/x86/arch_elf.c
create mode 100644 src/arch/x86/arch_parse.c
create mode 100644 src/arch/x86/arch_patch.c
create mode 100644 src/arch/x86/arch_ptrace.c
diff --git a/src/arch/aarch64/arch_coro.c b/src/arch/aarch64/arch_coro.c
new file mode 100644
index 0000000..e69de29
diff --git a/src/arch/aarch64/arch_elf.c b/src/arch/aarch64/arch_elf.c
new file mode 100644
index 0000000..e69de29
diff --git a/src/arch/aarch64/arch_parse.c b/src/arch/aarch64/arch_parse.c
new file mode 100644
index 0000000..e69de29
diff --git a/src/arch/aarch64/arch_patch.c b/src/arch/aarch64/arch_patch.c
new file mode 100644
index 0000000..e69de29
diff --git a/src/arch/aarch64/arch_ptrace.c b/src/arch/aarch64/arch_ptrace.c
new file mode 100644
index 0000000..e69de29
diff --git a/src/arch/x86/arch_coro.c b/src/arch/x86/arch_coro.c
new file mode 100644
index 0000000..e69de29
diff --git a/src/arch/x86/arch_elf.c b/src/arch/x86/arch_elf.c
new file mode 100644
index 0000000..e69de29
diff --git a/src/arch/x86/arch_parse.c b/src/arch/x86/arch_parse.c
new file mode 100644
index 0000000..e69de29
diff --git a/src/arch/x86/arch_patch.c b/src/arch/x86/arch_patch.c
new file mode 100644
index 0000000..e69de29
diff --git a/src/arch/x86/arch_ptrace.c b/src/arch/x86/arch_ptrace.c
new file mode 100644
index 0000000..e69de29
--
2.23.0

View File

@ -0,0 +1,26 @@
From d9b5d88e94b8be0100b0fc2ee0054c78fb0737be Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Tue, 13 Oct 2020 09:36:24 +0800
Subject: [PATCH 23/89] config: configure out the running arch
To support multi-arch, we need to figure out which architecture we stands on.
So let's get arch type before running the compilation process.
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
src/config | 2 ++
1 file changed, 2 insertions(+)
create mode 100755 src/config
diff --git a/src/config b/src/config
new file mode 100755
index 0000000..6c44cf2
--- /dev/null
+++ b/src/config
@@ -0,0 +1,2 @@
+#!/bin/bash
+uname -m > arch.desc
--
2.23.0

View File

@ -0,0 +1,72 @@
From d12c8e57c24649e6c8c74e6dc72f02f54e82aea7 Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Tue, 13 Oct 2020 14:55:53 +0800
Subject: [PATCH 24/89] Makefile: Adapt Makefile for different architectures
First take the arch information from config file. Then compile the
right file accroding to the architecture and find right header file
postion from src/include.
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
src/Makefile | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/src/Makefile b/src/Makefile
index 58e942a..9108a02 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -7,8 +7,10 @@ TARGETS = kpatch_gensrc \
libcare-stresstest
DEBUG = yes # comment out this line if not debug
+SRC_PATH := $(shell pwd)
+
CC = gcc
-CFLAGS_MISC = -Wall -g -O2 -D_GNU_SOURCE
+CFLAGS_MISC = -Wall -g -O2 -D_GNU_SOURCE -I $(SRC_PATH)
cc-option = $(shell if $(CC) $(CFLAGS_MISC) $(1) -S -o /dev/null -xc /dev/null \
> /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
@@ -18,6 +20,13 @@ CFLAGS_WARN += $(call cc-option,-Wno-builtin-macro-redefined)
CFLAGS_WARN += $(call cc-option,-Wno-deprecated-declarations)
CFLAGS = $(CFLAGS_MISC) $(CFLAGS_WARN)
+ARCH := $(shell cat arch.desc)
+ifeq ($(ARCH),aarch64)
+VPATH = arch/aarch64
+else
+VPATH = arch/x86
+endif
+
ifdef DEBUG
CFLAGS += -DDEBUG -O0 -g
endif
@@ -30,18 +39,18 @@ all: $(TARGETS)
.SUFFIXES:
-kpatch_gensrc: kpatch_gensrc.o kpatch_dbgfilter.o kpatch_parse.o kpatch_io.o rbtree.o kpatch_log.o
+kpatch_gensrc: kpatch_gensrc.o kpatch_dbgfilter.o kpatch_parse.o kpatch_io.o rbtree.o kpatch_log.o arch_parse.o
kpatch_make: kpatch_make.o
LIBUNWIND_LIBS := $(shell pkg-config --libs libunwind libunwind-ptrace)
-libcare-ctl: kpatch_user.o kpatch_storage.o kpatch_patch.c kpatch_elf.o kpatch_ptrace.o kpatch_coro.o
-libcare-ctl: kpatch_process.o kpatch_common.o rbtree.o kpatch_log.o
+libcare-ctl: kpatch_user.o kpatch_storage.o kpatch_patch.o kpatch_elf.o kpatch_ptrace.o kpatch_coro.o arch_patch.o arch_elf.o arch_ptrace.o arch_coro.o
+libcare-ctl: kpatch_process.o kpatch_common.o rbtree.o kpatch_log.o arch_process.o
libcare-ctl: LDLIBS += -lelf -lrt $(LIBUNWIND_LIBS)
-libcare-stresstest: kpatch_user-stresstest.o kpatch_storage.o kpatch_patch.c kpatch_elf.o kpatch_ptrace.o kpatch_coro.o
-libcare-stresstest: kpatch_process.o kpatch_common.o rbtree.o kpatch_log.o
+libcare-stresstest: kpatch_user-stresstest.o kpatch_storage.o kpatch_patch.o kpatch_elf.o kpatch_ptrace.o kpatch_coro.o arch_patch.o arch_elf.o arch_ptrace.o arch_coro.o
+libcare-stresstest: kpatch_process.o kpatch_common.o rbtree.o kpatch_log.o arch_process.o
libcare-stresstest: LDLIBS += -lelf -lrt $(LIBUNWIND_LIBS)
libcare-client: libcare-client.o
--
2.23.0

View File

@ -0,0 +1,31 @@
From 48a7b69f85710e1db33db994e79fdcd568ceacda Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Mon, 12 Oct 2020 10:53:28 +0800
Subject: [PATCH 25/89] kpatch_parse: Update asm_directives for aarch64
Update asm_directives in kpatch_parse.c, because
the golbal identifier in x86 is ".globl"
which is different from the ".global"in aarch64.
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
src/kpatch_parse.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/kpatch_parse.c b/src/kpatch_parse.c
index dfb3109..44e8a60 100644
--- a/src/kpatch_parse.c
+++ b/src/kpatch_parse.c
@@ -82,6 +82,8 @@ static struct {
{ DIRECTIVE_SUBSECTION, ".subsection"},
{ DIRECTIVE_GLOBL, ".globl"},
+ { DIRECTIVE_GLOBL, ".global"},
+
{ DIRECTIVE_LOCAL, ".local"},
{ DIRECTIVE_HIDDEN, ".hidden"},
{ DIRECTIVE_PROTECTED, ".protected"},
--
2.23.0

View File

@ -0,0 +1,154 @@
From 13dafd93cf011d79f1f4baf2c9035faeb52f4945 Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Mon, 12 Oct 2020 13:31:41 +0800
Subject: [PATCH 26/89] kpatch_parse: Split function parse_ctype
The parse_ctype function is arch related, so let's make two
separate definations in arch/x86/arch_parse.c and arch/aarch64/arch_parse.c
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
src/arch/aarch64/arch_parse.c | 34 ++++++++++++++++++++++++++++++++++
src/arch/x86/arch_parse.c | 31 +++++++++++++++++++++++++++++++
src/include/kpatch_parse.h | 2 ++
src/kpatch_parse.c | 28 +---------------------------
4 files changed, 68 insertions(+), 27 deletions(-)
diff --git a/src/arch/aarch64/arch_parse.c b/src/arch/aarch64/arch_parse.c
index e69de29..8eb88a9 100644
--- a/src/arch/aarch64/arch_parse.c
+++ b/src/arch/aarch64/arch_parse.c
@@ -0,0 +1,34 @@
+#include <stdlib.h>
+
+#include "include/kpatch_log.h"
+#include "include/kpatch_parse.h"
+#include "include/kpatch_flags.h"
+
+int parse_ctype(char *origs, bool with_checks)
+{
+ char *s = origs;
+ int type;
+ kpstr_t t;
+
+ s = skip_blanks(s);
+ if (s[0] == '#')
+ return DIRECTIVE_COMMENT; /* Single-line comment */
+
+ if (s[0] == '/' && s[1] == '/')
+ return DIRECTIVE_COMMENT; /* Arm disassembly support c style comment */
+
+ get_token(&s, &t);
+ type = find_ctype(&t);
+
+ if (type >= 0)
+ return type;
+
+ /*
+ * Asm labels starting from digits are local labels, they can be even created multiple times in the same function.
+ * So there is no reason to handle them and bother with renaming at all. It would create conflicts at our brains
+ * and require special tracking and matching... Brrrr.... */
+ if (s && *s == ':')
+ return !isdigit(t.s[0]) ? DIRECTIVE_LABEL : DIRECTIVE_LOCAL_LABEL;
+
+ return DIRECTIVE_OTHER;
+}
diff --git a/src/arch/x86/arch_parse.c b/src/arch/x86/arch_parse.c
index e69de29..5a67116 100644
--- a/src/arch/x86/arch_parse.c
+++ b/src/arch/x86/arch_parse.c
@@ -0,0 +1,31 @@
+#include <stdlib.h>
+
+#include "include/kpatch_log.h"
+#include "include/kpatch_parse.h"
+#include "include/kpatch_flags.h"
+
+int parse_ctype(char *origs, bool with_checks)
+{
+ char *s = origs;
+ int type;
+ kpstr_t t;
+
+ s = skip_blanks(s);
+ if (s[0] == '#')
+ return DIRECTIVE_COMMENT; /* Single-line comment */
+
+ get_token(&s, &t);
+ type = find_ctype(&t);
+
+ if (type >= 0)
+ return type;
+
+ /*
+ * Asm labels starting from digits are local labels, they can be even created multiple times in the same function.
+ * So there is no reason to handle them and bother with renaming at all. It would create conflicts at our brains
+ * and require special tracking and matching... Brrrr.... */
+ if (s && *s == ':')
+ return !isdigit(t.s[0]) ? DIRECTIVE_LABEL : DIRECTIVE_LOCAL_LABEL;
+
+ return DIRECTIVE_OTHER;
+}
diff --git a/src/include/kpatch_parse.h b/src/include/kpatch_parse.h
index 1012d5d..e1b7501 100644
--- a/src/include/kpatch_parse.h
+++ b/src/include/kpatch_parse.h
@@ -51,6 +51,8 @@ void init_ctypes(struct kp_file *f);
int ctype(struct kp_file *f, int l);
int is_sect_cmd(struct kp_file *f, int l);
+
+int find_ctype(kpstr_t *t);
int parse_ctype(char *s, bool with_checks);
/* ----------------------------------------- sections ----------------------------------------- */
diff --git a/src/kpatch_parse.c b/src/kpatch_parse.c
index 44e8a60..4bafdb7 100644
--- a/src/kpatch_parse.c
+++ b/src/kpatch_parse.c
@@ -109,7 +109,7 @@ static void get_type_args(char *s, kpstr_t *nm, kpstr_t *attr)
kpfatal("can't parse .type command");
}
-static int find_ctype(kpstr_t *t)
+int find_ctype(kpstr_t *t)
{
int i;
for (i = 0; i < (int)(sizeof(asm_directives)/sizeof(asm_directives[0])); i++) {
@@ -119,32 +119,6 @@ static int find_ctype(kpstr_t *t)
return -1;
}
-int parse_ctype(char *origs, bool with_checks)
-{
- char *s = origs;
- int type;
- kpstr_t t;
-
- s = skip_blanks(s);
- if (s[0] == '#')
- return DIRECTIVE_COMMENT; /* Single-line comment */
-
- get_token(&s, &t);
- type = find_ctype(&t);
-
- if (type >= 0)
- return type;
-
- /*
- * Asm labels starting from digits are local labels, they can be even created multiple times in the same function.
- * So there is no reason to handle them and bother with renaming at all. It would create conflicts at our brains
- * and require special tracking and matching... Brrrr.... */
- if (s && *s == ':')
- return !isdigit(t.s[0]) ? DIRECTIVE_LABEL : DIRECTIVE_LOCAL_LABEL;
-
- return DIRECTIVE_OTHER;
-}
-
int ctype(struct kp_file *f, int l)
{
if (l >= f->nr_lines)
--
2.23.0

View File

@ -0,0 +1,249 @@
From 0e0e7195fca05f706c1701484710fea9fc8b21f5 Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Mon, 12 Oct 2020 13:41:06 +0800
Subject: [PATCH 27/89] kpatch_parse: Split function init_multilines
The function init_multilines is arch related, so let's make
two definations in arch/x86/arch_parse.c and arch/aarch64/arch_parse.c
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
src/arch/aarch64/arch_parse.c | 67 +++++++++++++++++++++++++++++++++++
src/arch/x86/arch_parse.c | 65 +++++++++++++++++++++++++++++++++
src/kpatch_parse.c | 65 ---------------------------------
3 files changed, 132 insertions(+), 65 deletions(-)
diff --git a/src/arch/aarch64/arch_parse.c b/src/arch/aarch64/arch_parse.c
index 8eb88a9..1233e03 100644
--- a/src/arch/aarch64/arch_parse.c
+++ b/src/arch/aarch64/arch_parse.c
@@ -4,6 +4,73 @@
#include "include/kpatch_parse.h"
#include "include/kpatch_flags.h"
+/* break manually crafted multiple statements separated by ; to separate lines */
+void init_multilines(struct kp_file *f)
+{
+ int i, nr, sz = 64, slen, first_token;
+ char **lines = NULL, *s, *se;
+ int *lines_num = NULL;
+ kpstr_t t;
+
+ nr = 0;
+ for (i = 0; i < f->nr_lines; i++) {
+ if (nr + 1000 >= sz || !lines) {
+ sz *= 2;
+ lines = kp_realloc(lines, (sz/2) * sizeof(char *), sz * sizeof(char *));
+ lines_num = kp_realloc(lines_num, (sz/2) * sizeof(int), sz * sizeof(int));
+ }
+
+ s = f->lines[i];
+ if (strpbrk(s, ";:") != NULL) {
+ while (s && *s) {
+ se = s;
+ slen = strlen(s);
+ first_token = 1;
+ while (se) {
+ get_token(&se, &t);
+ if (t.l == 1 && t.s[0] == '#')
+ goto done;
+ if (t.l == 2 && t.s[0] == '/' && t.s[1] == '/')
+ goto done;
+ if (t.l == 1 && t.s[0] == ';') {
+ slen = t.s - s;
+ break;
+ }
+ /* first token with ':' after is
+ * the label, separate it unless
+ * it is done already (next non-blank
+ * is '\0')
+ */
+ if (first_token && se &&
+ se[0] == ':' &&
+ se[1] != '\0') {
+ slen = se - s + 1;
+ se++;
+ break;
+ }
+ first_token = 0;
+ }
+ lines[nr] = strndup(s, slen);
+ s = se;
+ lines_num[nr] = i;
+ nr++;
+ if (nr >= sz)
+ kpfatal("oops, not prepared to handle >1000 asm statements in single line");
+ }
+ free(f->lines[i]);
+ } else {
+done:
+ lines[nr] = s;
+ lines_num[nr] = i;
+ nr++;
+ }
+ }
+ free(f->lines);
+ f->lines = lines;
+ f->lines_num = lines_num;
+ f->nr_lines = nr;
+}
+
int parse_ctype(char *origs, bool with_checks)
{
char *s = origs;
diff --git a/src/arch/x86/arch_parse.c b/src/arch/x86/arch_parse.c
index 5a67116..92ff483 100644
--- a/src/arch/x86/arch_parse.c
+++ b/src/arch/x86/arch_parse.c
@@ -4,6 +4,71 @@
#include "include/kpatch_parse.h"
#include "include/kpatch_flags.h"
+/* break manually crafted multiple statements separated by ; to separate lines */
+void init_multilines(struct kp_file *f)
+{
+ int i, nr, sz = 64, slen, first_token;
+ char **lines = NULL, *s, *se;
+ int *lines_num = NULL;
+ kpstr_t t;
+
+ nr = 0;
+ for (i = 0; i < f->nr_lines; i++) {
+ if (nr + 1000 >= sz || !lines) {
+ sz *= 2;
+ lines = kp_realloc(lines, (sz/2) * sizeof(char *), sz * sizeof(char *));
+ lines_num = kp_realloc(lines_num, (sz/2) * sizeof(int), sz * sizeof(int));
+ }
+
+ s = f->lines[i];
+ if (strpbrk(s, ";:") != NULL) {
+ while (s && *s) {
+ se = s;
+ slen = strlen(s);
+ first_token = 1;
+ while (se) {
+ get_token(&se, &t);
+ if (t.l == 1 && t.s[0] == '#')
+ goto done;
+ if (t.l == 1 && t.s[0] == ';') {
+ slen = t.s - s;
+ break;
+ }
+ /* first token with ':' after is
+ * the label, separate it unless
+ * it is done already (next non-blank
+ * is '\0')
+ */
+ if (first_token && se &&
+ se[0] == ':' &&
+ se[1] != '\0') {
+ slen = se - s + 1;
+ se++;
+ break;
+ }
+ first_token = 0;
+ }
+ lines[nr] = strndup(s, slen);
+ s = se;
+ lines_num[nr] = i;
+ nr++;
+ if (nr >= sz)
+ kpfatal("oops, not prepared to handle >1000 asm statements in single line");
+ }
+ free(f->lines[i]);
+ } else {
+done:
+ lines[nr] = s;
+ lines_num[nr] = i;
+ nr++;
+ }
+ }
+ free(f->lines);
+ f->lines = lines;
+ f->lines_num = lines_num;
+ f->nr_lines = nr;
+}
+
int parse_ctype(char *origs, bool with_checks)
{
char *s = origs;
diff --git a/src/kpatch_parse.c b/src/kpatch_parse.c
index 4bafdb7..857dbf3 100644
--- a/src/kpatch_parse.c
+++ b/src/kpatch_parse.c
@@ -136,71 +136,6 @@ int is_sect_cmd(struct kp_file *f, int l)
t == DIRECTIVE_PREVIOUS || t == DIRECTIVE_SUBSECTION;
}
-/* break manually crafted multiple statements separated by ; to separate lines */
-void init_multilines(struct kp_file *f)
-{
- int i, nr, sz = 64, slen, first_token;
- char **lines = NULL, *s, *se;
- int *lines_num = NULL;
- kpstr_t t;
-
- nr = 0;
- for (i = 0; i < f->nr_lines; i++) {
- if (nr + 1000 >= sz || !lines) {
- sz *= 2;
- lines = kp_realloc(lines, (sz/2) * sizeof(char *), sz * sizeof(char *));
- lines_num = kp_realloc(lines_num, (sz/2) * sizeof(int), sz * sizeof(int));
- }
-
- s = f->lines[i];
- if (strpbrk(s, ";:") != NULL) {
- while (s && *s) {
- se = s;
- slen = strlen(s);
- first_token = 1;
- while (se) {
- get_token(&se, &t);
- if (t.l == 1 && t.s[0] == '#')
- goto done;
- if (t.l == 1 && t.s[0] == ';') {
- slen = t.s - s;
- break;
- }
- /* first token with ':' after is
- * the label, separate it unless
- * it is done already (next non-blank
- * is '\0')
- */
- if (first_token && se &&
- se[0] == ':' &&
- se[1] != '\0') {
- slen = se - s + 1;
- se++;
- break;
- }
- first_token = 0;
- }
- lines[nr] = strndup(s, slen);
- s = se;
- lines_num[nr] = i;
- nr++;
- if (nr >= sz)
- kpfatal("oops, not prepared to handle >1000 asm statements in single line");
- }
- free(f->lines[i]);
- } else {
-done:
- lines[nr] = s;
- lines_num[nr] = i;
- nr++;
- }
- }
- free(f->lines);
- f->lines = lines;
- f->lines_num = lines_num;
- f->nr_lines = nr;
-}
-
void init_ctypes(struct kp_file *f)
{
int i;
--
2.23.0

View File

@ -0,0 +1,282 @@
From a3fce6e82d24afe186a46461b9cf931f2f023f36 Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Mon, 12 Oct 2020 13:48:18 +0800
Subject: [PATCH 28/89] kpatch_parse: Split function is_variable_start
The function is_variable_start is arch related, since different arch may
use different assembly directives to describe variables. So let's make
two definations in arch/x86/arch_parse.c and arch/aarch64/arch_parse.c
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
src/arch/aarch64/arch_parse.c | 69 ++++++++++++++++++++++++++++++++++
src/arch/x86/arch_parse.c | 69 ++++++++++++++++++++++++++++++++++
src/include/kpatch_parse.h | 1 +
src/kpatch_parse.c | 71 +----------------------------------
4 files changed, 140 insertions(+), 70 deletions(-)
diff --git a/src/arch/aarch64/arch_parse.c b/src/arch/aarch64/arch_parse.c
index 1233e03..abbc38c 100644
--- a/src/arch/aarch64/arch_parse.c
+++ b/src/arch/aarch64/arch_parse.c
@@ -4,6 +4,75 @@
#include "include/kpatch_parse.h"
#include "include/kpatch_flags.h"
+int is_variable_start(struct kp_file *f, int l, int *e, int *pglobl, kpstr_t *nm)
+{
+ char *s;
+ int l0 = l, globl = 0;
+ kpstr_t nm2, attr;
+
+ kpstrset(nm, "", 0);
+ for ( ; cline(f, l); l++) {
+
+ /* first verify that all the commands we met has the same symbol name... just to be safe! */
+ s = cline(f, l);
+ if (*s == '\0' && l != l0)
+ continue;
+ switch (ctype(f, l)) {
+ case DIRECTIVE_TYPE:
+ case DIRECTIVE_GLOBL:
+ case DIRECTIVE_LOCAL:
+ get_token(&s, &nm2);
+ case DIRECTIVE_LABEL:
+ get_token(&s, &nm2);
+ if (nm->l && kpstrcmp(nm, &nm2)) /* some other symbol met... stop */
+ return 0;
+ *nm = nm2;
+ break;
+ }
+
+ switch (ctype(f, l)) {
+ case DIRECTIVE_TEXT:
+ case DIRECTIVE_DATA:
+ case DIRECTIVE_BSS:
+ case DIRECTIVE_SECTION:
+ case DIRECTIVE_PUSHSECTION:
+ case DIRECTIVE_POPSECTION:
+ case DIRECTIVE_PREVIOUS:
+ case DIRECTIVE_SUBSECTION:
+ break;
+ case DIRECTIVE_TYPE:
+ get_type_args(cline(f, l), &nm2, &attr);
+ if (kpstrcmpz(&attr, "%object") && kpstrcmpz(&attr, "%tls_object"))
+ return 0;
+ break;
+ case DIRECTIVE_GLOBL:
+ globl = 1;
+ break;
+ case DIRECTIVE_ALIGN:
+ break;
+ case DIRECTIVE_COMMENT:
+ case DIRECTIVE_SIZE:
+ /* can't start with .size */
+ if (l0 == l)
+ return 0;
+ break;
+ case DIRECTIVE_LABEL:
+ if (!is_data_sect(csect(f, l)))
+ return 0;
+ /* fall throught */
+ case DIRECTIVE_LOCAL:
+ if (e)
+ *e = l + 1;
+ if (pglobl)
+ *pglobl = globl;
+ return 1;
+ default:
+ return 0;
+ }
+ }
+ return 0;
+}
+
/* break manually crafted multiple statements separated by ; to separate lines */
void init_multilines(struct kp_file *f)
{
diff --git a/src/arch/x86/arch_parse.c b/src/arch/x86/arch_parse.c
index 92ff483..ca57507 100644
--- a/src/arch/x86/arch_parse.c
+++ b/src/arch/x86/arch_parse.c
@@ -4,6 +4,75 @@
#include "include/kpatch_parse.h"
#include "include/kpatch_flags.h"
+int is_variable_start(struct kp_file *f, int l, int *e, int *pglobl, kpstr_t *nm)
+{
+ char *s;
+ int l0 = l, globl = 0;
+ kpstr_t nm2, attr;
+
+ kpstrset(nm, "", 0);
+ for ( ; cline(f, l); l++) {
+
+ /* first verify that all the commands we met has the same symbol name... just to be safe! */
+ s = cline(f, l);
+ if (*s == '\0' && l != l0)
+ continue;
+ switch (ctype(f, l)) {
+ case DIRECTIVE_TYPE:
+ case DIRECTIVE_GLOBL:
+ case DIRECTIVE_LOCAL:
+ get_token(&s, &nm2);
+ case DIRECTIVE_LABEL:
+ get_token(&s, &nm2);
+ if (nm->l && kpstrcmp(nm, &nm2)) /* some other symbol met... stop */
+ return 0;
+ *nm = nm2;
+ break;
+ }
+
+ switch (ctype(f, l)) {
+ case DIRECTIVE_TEXT:
+ case DIRECTIVE_DATA:
+ case DIRECTIVE_BSS:
+ case DIRECTIVE_SECTION:
+ case DIRECTIVE_PUSHSECTION:
+ case DIRECTIVE_POPSECTION:
+ case DIRECTIVE_PREVIOUS:
+ case DIRECTIVE_SUBSECTION:
+ break;
+ case DIRECTIVE_TYPE:
+ get_type_args(cline(f, l), &nm2, &attr);
+ if (kpstrcmpz(&attr, "@object"))
+ return 0;
+ break;
+ case DIRECTIVE_GLOBL:
+ globl = 1;
+ break;
+ case DIRECTIVE_ALIGN:
+ break;
+ case DIRECTIVE_COMMENT:
+ case DIRECTIVE_SIZE:
+ /* can't start with .size */
+ if (l0 == l)
+ return 0;
+ break;
+ case DIRECTIVE_LABEL:
+ if (!is_data_sect(csect(f, l)))
+ return 0;
+ /* fall throught */
+ case DIRECTIVE_LOCAL:
+ if (e)
+ *e = l + 1;
+ if (pglobl)
+ *pglobl = globl;
+ return 1;
+ default:
+ return 0;
+ }
+ }
+ return 0;
+}
+
/* break manually crafted multiple statements separated by ; to separate lines */
void init_multilines(struct kp_file *f)
{
diff --git a/src/include/kpatch_parse.h b/src/include/kpatch_parse.h
index e1b7501..0f41509 100644
--- a/src/include/kpatch_parse.h
+++ b/src/include/kpatch_parse.h
@@ -109,6 +109,7 @@ void __get_token(char **str, kpstr_t *x, const char *delim);
int is_function_start(struct kp_file *f, int l, kpstr_t *nm);
int is_function_end(struct kp_file *f, int l, kpstr_t *nm);
+void get_type_args(char *s, kpstr_t *nm, kpstr_t *attr);
int is_variable_start(struct kp_file *f, int l, int *e, int *globl, kpstr_t *nm);
int is_data_def(char *s, int type);
diff --git a/src/kpatch_parse.c b/src/kpatch_parse.c
index 857dbf3..a3be7c0 100644
--- a/src/kpatch_parse.c
+++ b/src/kpatch_parse.c
@@ -93,7 +93,7 @@ static struct {
};
/* parse arguments of .type command */
-static void get_type_args(char *s, kpstr_t *nm, kpstr_t *attr)
+void get_type_args(char *s, kpstr_t *nm, kpstr_t *attr)
{
kpstr_t t, t2;
@@ -674,75 +674,6 @@ int is_function_end(struct kp_file *f, int l, kpstr_t *nm)
return 1;
}
-int is_variable_start(struct kp_file *f, int l, int *e, int *pglobl, kpstr_t *nm)
-{
- char *s;
- int l0 = l, globl = 0;
- kpstr_t nm2, attr;
-
- kpstrset(nm, "", 0);
- for ( ; cline(f, l); l++) {
-
- /* first verify that all the commands we met has the same symbol name... just to be safe! */
- s = cline(f, l);
- if (*s == '\0' && l != l0)
- continue;
- switch (ctype(f, l)) {
- case DIRECTIVE_TYPE:
- case DIRECTIVE_GLOBL:
- case DIRECTIVE_LOCAL:
- get_token(&s, &nm2);
- case DIRECTIVE_LABEL:
- get_token(&s, &nm2);
- if (nm->l && kpstrcmp(nm, &nm2)) /* some other symbol met... stop */
- return 0;
- *nm = nm2;
- break;
- }
-
- switch (ctype(f, l)) {
- case DIRECTIVE_TEXT:
- case DIRECTIVE_DATA:
- case DIRECTIVE_BSS:
- case DIRECTIVE_SECTION:
- case DIRECTIVE_PUSHSECTION:
- case DIRECTIVE_POPSECTION:
- case DIRECTIVE_PREVIOUS:
- case DIRECTIVE_SUBSECTION:
- break;
- case DIRECTIVE_TYPE:
- get_type_args(cline(f, l), &nm2, &attr);
- if (kpstrcmpz(&attr, "@object"))
- return 0;
- break;
- case DIRECTIVE_GLOBL:
- globl = 1;
- break;
- case DIRECTIVE_ALIGN:
- break;
- case DIRECTIVE_COMMENT:
- case DIRECTIVE_SIZE:
- /* can't start with .size */
- if (l0 == l)
- return 0;
- break;
- case DIRECTIVE_LABEL:
- if (!is_data_sect(csect(f, l)))
- return 0;
- /* fall throught */
- case DIRECTIVE_LOCAL:
- if (e)
- *e = l + 1;
- if (pglobl)
- *pglobl = globl;
- return 1;
- default:
- return 0;
- }
- }
- return 0;
-}
-
int is_data_def(char *s, int type)
{
kpstr_t t;
--
2.23.0

View File

@ -0,0 +1,180 @@
From eaff972f8edd58491eeca17f4b7553cceb1fb5d4 Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Mon, 12 Oct 2020 13:53:01 +0800
Subject: [PATCH 29/89] kpatch_parse: Split function is_data_def
The function is_data_def is arch related, so let's make two
separate definations in arch/x86/arch_parse.c and arch/aarch64/arch_parse.c
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
---
src/arch/aarch64/arch_parse.c | 64 +++++++++++++++++++++++++++++++++++
src/arch/x86/arch_parse.c | 34 +++++++++++++++++++
src/kpatch_parse.c | 33 ------------------
3 files changed, 98 insertions(+), 33 deletions(-)
diff --git a/src/arch/aarch64/arch_parse.c b/src/arch/aarch64/arch_parse.c
index abbc38c..fea09f6 100644
--- a/src/arch/aarch64/arch_parse.c
+++ b/src/arch/aarch64/arch_parse.c
@@ -4,6 +4,70 @@
#include "include/kpatch_parse.h"
#include "include/kpatch_flags.h"
+int is_data_def(char *s, int type)
+{
+ kpstr_t t;
+
+ get_token(&s, &t);
+ if (
+ /* strings */
+ !kpstrcmpz(&t, ".ascii") ||
+ !kpstrcmpz(&t, ".asciz") ||
+ !kpstrcmpz(&t, ".string") ||
+ !kpstrcmpz(&t, ".string8") ||
+ !kpstrcmpz(&t, ".string16") ||
+ !kpstrcmpz(&t, ".string32") ||
+ !kpstrcmpz(&t, ".string64") ||
+ /* numeric */
+ !kpstrcmpz(&t, ".byte") ||
+ !kpstrcmpz(&t, ".1byte") ||
+ !kpstrcmpz(&t, ".dc.b") ||
+
+ !kpstrcmpz(&t, ".hword") ||
+ !kpstrcmpz(&t, ".short") ||
+ !kpstrcmpz(&t, ".2byte") ||
+ !kpstrcmpz(&t, ".dc") ||
+ !kpstrcmpz(&t, ".dc.w") ||
+ !kpstrcmpz(&t, ".value") ||
+ !kpstrcmpz(&t, ".octa") ||
+
+ !kpstrcmpz(&t, ".word") ||
+ !kpstrcmpz(&t, ".4byte") ||
+ !kpstrcmpz(&t, ".long") ||
+ !kpstrcmpz(&t, ".int") ||
+ !kpstrcmpz(&t, ".dc.l") ||
+ !kpstrcmpz(&t, ".dc.a") ||// (AArch32 only)
+
+ !kpstrcmpz(&t, ".quad") ||
+ !kpstrcmpz(&t, ".8byte") ||
+ !kpstrcmpz(&t, ".xword") ||//(AArch64 only)
+ !kpstrcmpz(&t, ".dc.a") ||//(AArch64 only)
+
+ !kpstrcmpz(&t, ".short") ||
+ !kpstrcmpz(&t, ".int") ||
+ !kpstrcmpz(&t, ".long") ||
+ !kpstrcmpz(&t, ".quad") ||
+ /* float */
+ !kpstrcmpz(&t, ".double") ||
+ !kpstrcmpz(&t, ".dc.d") ||
+ !kpstrcmpz(&t, ".float") ||
+ !kpstrcmpz(&t, ".single") ||
+ !kpstrcmpz(&t, ".dc.s") ||
+ /* other */
+ !kpstrcmpz(&t, ".value") ||
+ !kpstrcmpz(&t, ".comm") ||
+ !kpstrcmpz(&t, ".zero") ||
+ !kpstrcmpz(&t, ".fill") ||
+ !kpstrcmpz(&t, ".space") ||
+ !kpstrcmpz(&t, ".skip") ||
+ /* dwarf types */
+ !kpstrcmpz(&t, ".uleb128") ||
+ !kpstrcmpz(&t, ".sleb128")
+ )
+ return 1;
+ return 0;
+}
+
int is_variable_start(struct kp_file *f, int l, int *e, int *pglobl, kpstr_t *nm)
{
char *s;
diff --git a/src/arch/x86/arch_parse.c b/src/arch/x86/arch_parse.c
index ca57507..81edaf8 100644
--- a/src/arch/x86/arch_parse.c
+++ b/src/arch/x86/arch_parse.c
@@ -4,6 +4,40 @@
#include "include/kpatch_parse.h"
#include "include/kpatch_flags.h"
+int is_data_def(char *s, int type)
+{
+ kpstr_t t;
+
+ get_token(&s, &t);
+ if (
+ /* strings */
+ !kpstrcmpz(&t, ".ascii") ||
+ !kpstrcmpz(&t, ".asciz") ||
+ !kpstrcmpz(&t, ".string") ||
+ /* numeric */
+ !kpstrcmpz(&t, ".byte") ||
+ !kpstrcmpz(&t, ".word") ||
+ !kpstrcmpz(&t, ".short") ||
+ !kpstrcmpz(&t, ".int") ||
+ !kpstrcmpz(&t, ".long") ||
+ !kpstrcmpz(&t, ".quad") ||
+ /* float */
+ !kpstrcmpz(&t, ".double") ||
+ !kpstrcmpz(&t, ".float") ||
+ !kpstrcmpz(&t, ".single") ||
+ /* other */
+ !kpstrcmpz(&t, ".value") ||
+ !kpstrcmpz(&t, ".comm") ||
+ !kpstrcmpz(&t, ".zero") ||
+ /* dwarf types */
+ !kpstrcmpz(&t, ".uleb128") ||
+ !kpstrcmpz(&t, ".sleb128") ||
+ !kpstrcmpz(&t, ".4byte")
+ )
+ return 1;
+ return 0;
+}
+
int is_variable_start(struct kp_file *f, int l, int *e, int *pglobl, kpstr_t *nm)
{
char *s;
diff --git a/src/kpatch_parse.c b/src/kpatch_parse.c
index a3be7c0..f486b55 100644
--- a/src/kpatch_parse.c
+++ b/src/kpatch_parse.c
@@ -674,37 +674,4 @@ int is_function_end(struct kp_file *f, int l, kpstr_t *nm)
return 1;
}
-int is_data_def(char *s, int type)
-{
- kpstr_t t;
-
- get_token(&s, &t);
- if (
- /* strings */
- !kpstrcmpz(&t, ".ascii") ||
- !kpstrcmpz(&t, ".asciz") ||
- !kpstrcmpz(&t, ".string") ||
- /* numeric */
- !kpstrcmpz(&t, ".byte") ||
- !kpstrcmpz(&t, ".word") ||
- !kpstrcmpz(&t, ".short") ||
- !kpstrcmpz(&t, ".int") ||
- !kpstrcmpz(&t, ".long") ||
- !kpstrcmpz(&t, ".quad") ||
- /* float */
- !kpstrcmpz(&t, ".double") ||
- !kpstrcmpz(&t, ".float") ||
- !kpstrcmpz(&t, ".single") ||
- /* other */
- !kpstrcmpz(&t, ".value") ||
- !kpstrcmpz(&t, ".comm") ||
- !kpstrcmpz(&t, ".zero") ||
- /* dwarf types */
- !kpstrcmpz(&t, ".uleb128") ||
- !kpstrcmpz(&t, ".sleb128") ||
- !kpstrcmpz(&t, ".4byte")
- )
- return 1;
- return 0;
-}
--
2.23.0

View File

@ -0,0 +1,149 @@
From 3ecebe9ea858d5502af5f5cd79141e4546ae3fe8 Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Mon, 12 Oct 2020 13:58:58 +0800
Subject: [PATCH 30/89] kpatch_parse: Split function is_function_start
The function is_function_start is arch related, so make two
separate definations in arch/x86/arch_parse.c and arch/aarch64/arch_parse.c
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
src/arch/aarch64/arch_parse.c | 32 ++++++++++++++++++++++++++++++++
src/arch/x86/arch_parse.c | 32 ++++++++++++++++++++++++++++++++
src/kpatch_parse.c | 33 ---------------------------------
3 files changed, 64 insertions(+), 33 deletions(-)
diff --git a/src/arch/aarch64/arch_parse.c b/src/arch/aarch64/arch_parse.c
index fea09f6..e0f0c8b 100644
--- a/src/arch/aarch64/arch_parse.c
+++ b/src/arch/aarch64/arch_parse.c
@@ -4,6 +4,38 @@
#include "include/kpatch_parse.h"
#include "include/kpatch_flags.h"
+int is_function_start(struct kp_file *f, int l, kpstr_t *nm)
+{
+ char *s;
+ kpstr_t nm2, attr;
+ int l0 = l, func = 0;
+
+ kpstrset(nm, "", 0);
+ for (; l < f->nr_lines; l++) {
+ if (l != l0 && cline(f, l)[0] == '\0')
+ continue;
+ if ((is_sect_cmd(f, l) && is_code_sect(csect(f, l))) ||
+ ctype(f, l) == DIRECTIVE_ALIGN)
+ continue;
+ get_type_args(cline(f, l), &nm2, &attr);
+ if ((ctype(f, l) == DIRECTIVE_WEAK && l0 != l) ||
+ ctype(f, l) == DIRECTIVE_GLOBL || ctype(f, l) == DIRECTIVE_HIDDEN ||
+ ctype(f, l) == DIRECTIVE_PROTECTED || ctype(f, l) == DIRECTIVE_INTERNAL ||
+ (ctype(f, l) == DIRECTIVE_TYPE && !kpstrcmpz(&attr, "%function"))) {
+ s = cline(f, l);
+ get_token(&s, &nm2); /* skip command */
+ get_token(&s, &nm2);
+ if (nm->l && kpstrcmp(nm, &nm2)) /* verify name matches in all .weak/.globl/.type commands */
+ return 0;
+ *nm = nm2;
+ func = func ? 1 : ctype(f, l) == DIRECTIVE_TYPE;
+ continue;
+ }
+ break;
+ }
+ return func;
+}
+
int is_data_def(char *s, int type)
{
kpstr_t t;
diff --git a/src/arch/x86/arch_parse.c b/src/arch/x86/arch_parse.c
index 81edaf8..c51c49b 100644
--- a/src/arch/x86/arch_parse.c
+++ b/src/arch/x86/arch_parse.c
@@ -4,6 +4,38 @@
#include "include/kpatch_parse.h"
#include "include/kpatch_flags.h"
+int is_function_start(struct kp_file *f, int l, kpstr_t *nm)
+{
+ char *s;
+ kpstr_t nm2, attr;
+ int l0 = l, func = 0;
+
+ kpstrset(nm, "", 0);
+ for (; l < f->nr_lines; l++) {
+ if (l != l0 && cline(f, l)[0] == '\0')
+ continue;
+ if ((is_sect_cmd(f, l) && is_code_sect(csect(f, l))) ||
+ ctype(f, l) == DIRECTIVE_ALIGN)
+ continue;
+ get_type_args(cline(f, l), &nm2, &attr);
+ if ((ctype(f, l) == DIRECTIVE_WEAK && l0 != l) ||
+ ctype(f, l) == DIRECTIVE_GLOBL || ctype(f, l) == DIRECTIVE_HIDDEN ||
+ ctype(f, l) == DIRECTIVE_PROTECTED || ctype(f, l) == DIRECTIVE_INTERNAL ||
+ (ctype(f, l) == DIRECTIVE_TYPE && !kpstrcmpz(&attr, "@function"))) {
+ s = cline(f, l);
+ get_token(&s, &nm2); /* skip command */
+ get_token(&s, &nm2);
+ if (nm->l && kpstrcmp(nm, &nm2)) /* verify name matches in all .weak/.globl/.type commands */
+ return 0;
+ *nm = nm2;
+ func = func ? 1 : ctype(f, l) == DIRECTIVE_TYPE;
+ continue;
+ }
+ break;
+ }
+ return func;
+}
+
int is_data_def(char *s, int type)
{
kpstr_t t;
diff --git a/src/kpatch_parse.c b/src/kpatch_parse.c
index f486b55..3df658d 100644
--- a/src/kpatch_parse.c
+++ b/src/kpatch_parse.c
@@ -625,39 +625,6 @@ void init_sections(struct kp_file *f)
}
/* ----------------------------------------- code block boundaries detection ---------------------------------------- */
-
-int is_function_start(struct kp_file *f, int l, kpstr_t *nm)
-{
- char *s;
- kpstr_t nm2, attr;
- int l0 = l, func = 0;
-
- kpstrset(nm, "", 0);
- for (; l < f->nr_lines; l++) {
- if (l != l0 && cline(f, l)[0] == '\0')
- continue;
- if ((is_sect_cmd(f, l) && is_code_sect(csect(f, l))) ||
- ctype(f, l) == DIRECTIVE_ALIGN)
- continue;
- get_type_args(cline(f, l), &nm2, &attr);
- if ((ctype(f, l) == DIRECTIVE_WEAK && l0 != l) ||
- ctype(f, l) == DIRECTIVE_GLOBL || ctype(f, l) == DIRECTIVE_HIDDEN ||
- ctype(f, l) == DIRECTIVE_PROTECTED || ctype(f, l) == DIRECTIVE_INTERNAL ||
- (ctype(f, l) == DIRECTIVE_TYPE && !kpstrcmpz(&attr, "@function"))) {
- s = cline(f, l);
- get_token(&s, &nm2); /* skip command */
- get_token(&s, &nm2);
- if (nm->l && kpstrcmp(nm, &nm2)) /* verify name matches in all .weak/.globl/.type commands */
- return 0;
- *nm = nm2;
- func = func ? 1 : ctype(f, l) == DIRECTIVE_TYPE;
- continue;
- }
- break;
- }
- return func;
-}
-
int is_function_end(struct kp_file *f, int l, kpstr_t *nm)
{
/* Functions should always end by .size directive. Previously used to detect .LFe labels, but they are not generated w/o frame pointers */
--
2.23.0

View File

@ -0,0 +1,43 @@
From 0430a8354e988a1a72896844d45b1a5c83743d74 Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Mon, 12 Oct 2020 14:02:50 +0800
Subject: [PATCH 31/89] kpatch_common.h: Factor out PAGE_SIZE marco
Since page size may be different on OS configuration. Let's make a
change it to get PAGE_SIZE dynamicly accquired from syscall.
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
src/include/kpatch_common.h | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/src/include/kpatch_common.h b/src/include/kpatch_common.h
index c160250..775ea14 100644
--- a/src/include/kpatch_common.h
+++ b/src/include/kpatch_common.h
@@ -41,4 +41,21 @@ int kpatch_close_file(struct kp_file *kpatch);
# define R_X86_64_GOTPCRELX 0x29
#endif
+static inline int page_shift(int n) {
+ int res = -1;
+
+ while(n) {
+ res++;
+ n >>= 1;
+ }
+
+ return res;
+}
+
+#ifndef PAGE_SIZE
+#define PAGE_SIZE getpagesize()
+#define PAGE_MASK (~(PAGE_SIZE-1))
+#define PAGE_SHIFT page_shift(PAGE_SIZE)
+#endif
+
#endif
--
2.23.0

View File

@ -0,0 +1,196 @@
From ae9e01aefed4105c808301e783d29ddd349dc0f6 Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Mon, 12 Oct 2020 14:22:45 +0800
Subject: [PATCH 32/89] kpatch_coro: Split function _UCORO_access_reg
The function _UCORO_access_reg is arch related, so make two
separate definations in arch/x86/arch_coro.c and arch/aarch64/arch_coro.c
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
src/arch/aarch64/arch_coro.c | 39 ++++++++++++++++++++++++++++++++
src/arch/x86/arch_coro.c | 43 ++++++++++++++++++++++++++++++++++++
src/include/kpatch_coro.h | 11 +++++++++
src/kpatch_coro.c | 37 -------------------------------
4 files changed, 93 insertions(+), 37 deletions(-)
diff --git a/src/arch/aarch64/arch_coro.c b/src/arch/aarch64/arch_coro.c
index e69de29..e6fe3d0 100644
--- a/src/arch/aarch64/arch_coro.c
+++ b/src/arch/aarch64/arch_coro.c
@@ -0,0 +1,39 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <libunwind-ptrace.h>
+#include <sys/utsname.h>
+
+#include "include/kpatch_user.h"
+#include "include/kpatch_coro.h"
+#include "include/kpatch_common.h"
+#include "include/kpatch_elf.h"
+#include "include/kpatch_ptrace.h"
+#include "include/kpatch_log.h"
+
+int _UCORO_access_reg(unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val,
+ int write, void *arg)
+{
+ struct UCORO_info *info = (struct UCORO_info *)arg;
+ unsigned long *regs = (unsigned long *)info->coro->env[0].__jmpbuf;
+
+ if (write) {
+ kperr("_UCORO_access_reg: write is not implemeneted (%d)\n", reg);
+ return -UNW_EINVAL;
+ }
+ switch (reg) {
+ case UNW_AARCH64_X9:
+ *val = regs[JB_RBX]; break;
+ case UNW_AARCH64_X29:
+ *val = regs[JB_RBP]; break;
+ case UNW_AARCH64_X12...UNW_AARCH64_X15:
+ *val = regs[reg - UNW_AARCH64_X12 + JB_R12]; break;
+ case UNW_AARCH64_SP:
+ *val = regs[JB_RSP]; break;
+ case UNW_AARCH64_PC:
+ *val = regs[JB_RIP]; break;
+ default:
+ return _UPT_access_reg(as, reg, val, write, arg);
+ }
+ return 0;
+}
diff --git a/src/arch/x86/arch_coro.c b/src/arch/x86/arch_coro.c
index e69de29..ce889df 100644
--- a/src/arch/x86/arch_coro.c
+++ b/src/arch/x86/arch_coro.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <libunwind-ptrace.h>
+
+#include <sys/utsname.h>
+
+#include <asm/prctl.h>
+
+#include "include/kpatch_user.h"
+#include "include/kpatch_coro.h"
+#include "include/kpatch_common.h"
+#include "include/kpatch_elf.h"
+#include "include/kpatch_ptrace.h"
+#include "include/kpatch_log.h"
+
+int _UCORO_access_reg(unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val,
+ int write, void *arg)
+{
+ struct UCORO_info *info = (struct UCORO_info *)arg;
+ unsigned long *regs = (unsigned long *)info->coro->env[0].__jmpbuf;
+
+ if (write) {
+ kperr("_UCORO_access_reg: write is not implemeneted (%d)\n", reg);
+ return -UNW_EINVAL;
+ }
+ switch (reg) {
+ case UNW_X86_64_RBX:
+ *val = regs[JB_RBX]; break;
+ case UNW_X86_64_RBP:
+ *val = regs[JB_RBP]; break;
+ case UNW_X86_64_R12...UNW_X86_64_R15:
+ *val = regs[reg - UNW_X86_64_R12 + JB_R12]; break;
+ case UNW_X86_64_RSP:
+ *val = regs[JB_RSP]; break;
+ case UNW_X86_64_RIP:
+ *val = regs[JB_RIP]; break;
+ default:
+ return _UPT_access_reg(as, reg, val, write, arg);
+ }
+ return 0;
+}
diff --git a/src/include/kpatch_coro.h b/src/include/kpatch_coro.h
index 1588b5e..760b1db 100644
--- a/src/include/kpatch_coro.h
+++ b/src/include/kpatch_coro.h
@@ -19,6 +19,17 @@ struct kpatch_coro {
void *_UCORO_create(struct kpatch_coro *coro, pid_t pid);
void _UCORO_destroy(void *arg);
+
+struct UCORO_info {
+ union {
+ void *upt;
+ char dummy[256];
+ };
+ struct kpatch_coro *coro;
+};
+int _UCORO_access_reg(unw_addr_space_t as, unw_regnum_t reg,
+ unw_word_t *val, int write, void *arg);
+
int kpatch_coroutines_init(struct kpatch_process *proc);
int kpatch_coroutines_find(struct kpatch_process *proc);
void kpatch_coroutines_free(struct kpatch_process *proc);
diff --git a/src/kpatch_coro.c b/src/kpatch_coro.c
index 02d421b..83d04ce 100644
--- a/src/kpatch_coro.c
+++ b/src/kpatch_coro.c
@@ -6,8 +6,6 @@
#include <sys/utsname.h>
-#include <asm/prctl.h>
-
#include "include/kpatch_user.h"
#include "include/kpatch_coro.h"
#include "include/kpatch_common.h"
@@ -505,13 +503,6 @@ static struct kpatch_coro_ops kpatch_coro_flavours[] = {
*
* That's why I had to do this hack
*/
-struct UCORO_info {
- union {
- void *upt;
- char dummy[256];
- };
- struct kpatch_coro *coro;
-};
void *_UCORO_create(struct kpatch_coro *coro, pid_t pid)
{
@@ -538,34 +529,6 @@ void _UCORO_destroy(void *arg)
_UPT_destroy(info);
}
-static int
-_UCORO_access_reg(unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val,
- int write, void *arg)
-{
- struct UCORO_info *info = (struct UCORO_info *)arg;
- unsigned long *regs = (unsigned long *)info->coro->env[0].__jmpbuf;
-
- if (write) {
- kperr("_UCORO_access_reg: write is not implemeneted (%d)\n", reg);
- return -UNW_EINVAL;
- }
- switch (reg) {
- case UNW_X86_64_RBX:
- *val = regs[JB_RBX]; break;
- case UNW_X86_64_RBP:
- *val = regs[JB_RBP]; break;
- case UNW_X86_64_R12...UNW_X86_64_R15:
- *val = regs[reg - UNW_X86_64_R12 + JB_R12]; break;
- case UNW_X86_64_RSP:
- *val = regs[JB_RSP]; break;
- case UNW_X86_64_RIP:
- *val = regs[JB_RIP]; break;
- default:
- return _UPT_access_reg(as, reg, val, write, arg);
- }
- return 0;
-}
-
static unw_accessors_t _UCORO_accessors = {
_UPT_find_proc_info,
_UPT_put_unwind_info,
--
2.23.0

View File

@ -0,0 +1,148 @@
From 612e06f2fc95029c13cfdb684014259fb49f18fe Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Mon, 12 Oct 2020 14:32:51 +0800
Subject: [PATCH 33/89] kpatch_coro: Split function get_ptr_guard
The function get_ptr_guard is arch related, so make two
separate definations in arch/x86/arch_coro.c and arch/aarch64/arch_coro.c
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
src/arch/aarch64/arch_coro.c | 24 ++++++++++++++++++++++++
src/arch/x86/arch_coro.c | 23 +++++++++++++++++++++++
src/include/kpatch_coro.h | 5 +++++
src/kpatch_coro.c | 25 -------------------------
4 files changed, 52 insertions(+), 25 deletions(-)
diff --git a/src/arch/aarch64/arch_coro.c b/src/arch/aarch64/arch_coro.c
index e6fe3d0..b93581e 100644
--- a/src/arch/aarch64/arch_coro.c
+++ b/src/arch/aarch64/arch_coro.c
@@ -11,6 +11,30 @@
#include "include/kpatch_ptrace.h"
#include "include/kpatch_log.h"
+int get_ptr_guard(struct kpatch_process *proc,
+ unsigned long *ptr_guard)
+{
+ int ret;
+ unsigned long tls = 0;
+
+ /*
+ ret = kpatch_arch_prctl_remote(proc2pctx(proc), ARCH_GET_FS, &tls);
+ if (ret < 0) {
+ kpdebug("FAIL. Can't get TLS base value\n");
+ return -1;
+ }*/
+ ret = kpatch_process_mem_read(proc,
+ tls + GLIBC_TLS_PTR_GUARD,
+ ptr_guard,
+ sizeof(*ptr_guard));
+ if (ret < 0) {
+ kpdebug("FAIL. Can't get pointer guard value\n");
+ return -1;
+ }
+
+ return 0;
+}
+
int _UCORO_access_reg(unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val,
int write, void *arg)
{
diff --git a/src/arch/x86/arch_coro.c b/src/arch/x86/arch_coro.c
index ce889df..86bf12f 100644
--- a/src/arch/x86/arch_coro.c
+++ b/src/arch/x86/arch_coro.c
@@ -15,6 +15,29 @@
#include "include/kpatch_ptrace.h"
#include "include/kpatch_log.h"
+int get_ptr_guard(struct kpatch_process *proc,
+ unsigned long *ptr_guard)
+{
+ int ret;
+ unsigned long tls;
+
+ ret = kpatch_arch_prctl_remote(proc2pctx(proc), ARCH_GET_FS, &tls);
+ if (ret < 0) {
+ kpdebug("FAIL. Can't get TLS base value\n");
+ return -1;
+ }
+ ret = kpatch_process_mem_read(proc,
+ tls + GLIBC_TLS_PTR_GUARD,
+ ptr_guard,
+ sizeof(*ptr_guard));
+ if (ret < 0) {
+ kpdebug("FAIL. Can't get pointer guard value\n");
+ return -1;
+ }
+
+ return 0;
+}
+
int _UCORO_access_reg(unw_addr_space_t as, unw_regnum_t reg, unw_word_t *val,
int write, void *arg)
{
diff --git a/src/include/kpatch_coro.h b/src/include/kpatch_coro.h
index 760b1db..272855e 100644
--- a/src/include/kpatch_coro.h
+++ b/src/include/kpatch_coro.h
@@ -30,6 +30,11 @@ struct UCORO_info {
int _UCORO_access_reg(unw_addr_space_t as, unw_regnum_t reg,
unw_word_t *val, int write, void *arg);
+#define GLIBC_TLS_PTR_GUARD 0x30
+int get_ptr_guard(struct kpatch_process *proc,
+ unsigned long *ptr_guard);
+
+
int kpatch_coroutines_init(struct kpatch_process *proc);
int kpatch_coroutines_find(struct kpatch_process *proc);
void kpatch_coroutines_free(struct kpatch_process *proc);
diff --git a/src/kpatch_coro.c b/src/kpatch_coro.c
index 83d04ce..ea4050f 100644
--- a/src/kpatch_coro.c
+++ b/src/kpatch_coro.c
@@ -105,8 +105,6 @@ kpatch_coro_free(struct kpatch_coro *c)
#define JB_RSP 6
#define JB_RIP 7
-#define GLIBC_TLS_PTR_GUARD 0x30
-
#define STACK_OFFSET_UC_LINK (2 * sizeof(long))
#define STACK_OFFSET_START_CONTEXT (3 * sizeof(long))
#define STACK_OFFSET_UC_LINK_PTR (4 * sizeof(long))
@@ -191,29 +189,6 @@ static int is_test_target(struct kpatch_process *proc,
return strcmp(proc->comm, procname) == 0;
}
-static int get_ptr_guard(struct kpatch_process *proc,
- unsigned long *ptr_guard)
-{
- int ret;
- unsigned long tls;
-
- ret = kpatch_arch_prctl_remote(proc2pctx(proc), ARCH_GET_FS, &tls);
- if (ret < 0) {
- kpdebug("FAIL. Can't get TLS base value\n");
- return -1;
- }
- ret = kpatch_process_mem_read(proc,
- tls + GLIBC_TLS_PTR_GUARD,
- ptr_guard,
- sizeof(*ptr_guard));
- if (ret < 0) {
- kpdebug("FAIL. Can't get pointer guard value\n");
- return -1;
- }
-
- return 0;
-}
-
int is_centos7_qemu(struct kpatch_process *proc)
{
struct utsname uts;
--
2.23.0

View File

@ -0,0 +1,307 @@
From 9ac8822b66bb06a463a29ec86088cfe8adc1e6d4 Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Mon, 12 Oct 2020 14:45:03 +0800
Subject: [PATCH 34/89] kpatch_coro: Split function locate_start_context_symbol
The function locate_start_context_symbol is arch related, so let's
make two separate definations in arch/x86/arch_coro.c and
arch/aarch64/arch_coro.c
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
src/arch/aarch64/arch_coro.c | 63 ++++++++++++++++++++++++++
src/arch/x86/arch_coro.c | 67 +++++++++++++++++++++++++++
src/include/kpatch_coro.h | 21 +++++++++
src/kpatch_coro.c | 87 ------------------------------------
4 files changed, 151 insertions(+), 87 deletions(-)
diff --git a/src/arch/aarch64/arch_coro.c b/src/arch/aarch64/arch_coro.c
index b93581e..f485cf9 100644
--- a/src/arch/aarch64/arch_coro.c
+++ b/src/arch/aarch64/arch_coro.c
@@ -11,6 +11,69 @@
#include "include/kpatch_ptrace.h"
#include "include/kpatch_log.h"
+asm (
+ "makecontext_call:\n"
+ "mov x29, sp\n"
+ "and x29,x29,#-16\n"
+ "sub x29, x29,#0x400\n"
+ "ldr x9,[x29,#-128]\n"
+ "str x9,[fp,#0x10]\n"
+ //"str #128,[fp.#0x20]\n"
+ "mov x0,fp\n"
+ "mov x1,#0x100\n"
+ "mov x2,#0\n"
+ "svc #0\n"
+ "brk #0\n"
+ "makecontext_call_end:"
+ );
+
+extern unsigned char makecontext_call, makecontext_call_end;
+
+int
+locate_start_context_symbol(struct kpatch_process *proc,
+ unsigned long *pstart_context)
+{
+ struct object_file *olibc;
+ struct user_regs_struct regs;
+ int rv;
+ unsigned long makecontext;
+
+ olibc = kpatch_process_get_obj_by_regex(proc, "^libc-.*\\.so");
+ if (olibc == NULL) {
+ kpdebug("FAIL. Can't find libc\n");
+ return -1;
+ }
+
+ rv = kpatch_resolve_undefined_single_dynamic(olibc,
+ "makecontext",
+ &makecontext);
+ makecontext = vaddr2addr(olibc, makecontext);
+ if (rv < 0 || makecontext == 0) {
+ kpdebug("FAIL. Can't find makecontext\n");
+ return -1;
+ }
+
+ regs.regs[8] = makecontext;
+ rv = kpatch_execute_remote(proc2pctx(proc),
+ &makecontext_call,
+ &makecontext_call_end - &makecontext_call,
+ &regs);
+ if (rv < 0) {
+ kpdebug("FAIL. Can't execute makecontext\n");
+ return -1;
+ }
+
+ rv = kpatch_process_mem_read(proc,
+ regs.regs[29]- STACK_OFFSET_START_CONTEXT,
+ pstart_context,
+ sizeof(*pstart_context));
+ if (rv < 0) {
+ kpdebug("FAIL. Can't peek __start_context address\n");
+ return -1;
+ }
+ return rv;
+}
+
int get_ptr_guard(struct kpatch_process *proc,
unsigned long *ptr_guard)
{
diff --git a/src/arch/x86/arch_coro.c b/src/arch/x86/arch_coro.c
index 86bf12f..27c834b 100644
--- a/src/arch/x86/arch_coro.c
+++ b/src/arch/x86/arch_coro.c
@@ -15,6 +15,73 @@
#include "include/kpatch_ptrace.h"
#include "include/kpatch_log.h"
+asm ("makecontext_call:\n"
+ "mov %rsp, %rbp\n"
+ "and $-16, %rbp\n"
+ /* ucontext_t is 0x3a8 bytes */
+ "sub $0x400, %rbp\n"
+ /* TODO interpolate these from the calculations above */
+
+ /* set uc_stack.ss_sp and uc_stack.ss_size */
+ /* TODO magic -128 is used below as well */
+ "lea -128(%rbp), %rbx\n"
+ "movq %rbx, 0x10(%rbp)\n"
+ "movq $128, 0x20(%rbp)\n"
+ "mov %rbp, %rdi\n"
+ "mov $0x100, %rsi\n"
+ "xor %rdx, %rdx\n"
+ /* call `makecontext` */
+ "call *%rax\n"
+ "int3\n"
+ "makecontext_call_end:");
+
+extern unsigned char makecontext_call, makecontext_call_end;
+
+int
+locate_start_context_symbol(struct kpatch_process *proc,
+ unsigned long *pstart_context)
+{
+ struct object_file *olibc;
+ struct user_regs_struct regs;
+ int rv;
+ unsigned long makecontext;
+
+ olibc = kpatch_process_get_obj_by_regex(proc, "^libc-.*\\.so");
+ if (olibc == NULL) {
+ kpdebug("FAIL. Can't find libc\n");
+ return -1;
+ }
+
+ rv = kpatch_resolve_undefined_single_dynamic(olibc,
+ "makecontext",
+ &makecontext);
+ makecontext = vaddr2addr(olibc, makecontext);
+ if (rv < 0 || makecontext == 0) {
+ kpdebug("FAIL. Can't find makecontext\n");
+ return -1;
+ }
+
+ regs.rax = makecontext;
+ rv = kpatch_execute_remote(proc2pctx(proc),
+ &makecontext_call,
+ &makecontext_call_end - &makecontext_call,
+ &regs);
+ if (rv < 0) {
+ kpdebug("FAIL. Can't execute makecontext\n");
+ return -1;
+ }
+
+ rv = kpatch_process_mem_read(proc,
+ regs.rbp - STACK_OFFSET_START_CONTEXT,
+ pstart_context,
+ sizeof(*pstart_context));
+ if (rv < 0) {
+ kpdebug("FAIL. Can't peek __start_context address\n");
+ return -1;
+ }
+ return rv;
+}
+
int get_ptr_guard(struct kpatch_process *proc,
unsigned long *ptr_guard)
{
diff --git a/src/include/kpatch_coro.h b/src/include/kpatch_coro.h
index 272855e..0b3a9a1 100644
--- a/src/include/kpatch_coro.h
+++ b/src/include/kpatch_coro.h
@@ -30,10 +30,31 @@ struct UCORO_info {
int _UCORO_access_reg(unw_addr_space_t as, unw_regnum_t reg,
unw_word_t *val, int write, void *arg);
+#define PTR_DEMANGLE(ptr, key) ((((ptr) >> 0x11) | ((ptr) << 47)) ^ key)
+#define JB_RBX 0
+#define JB_RBP 1
+#define JB_R12 2
+#define JB_R13 3
+#define JB_R14 4
+#define JB_R15 5
+#define JB_RSP 6
+#define JB_RIP 7
+
+#define STACK_OFFSET_UC_LINK (2 * sizeof(long))
+#define STACK_OFFSET_START_CONTEXT (3 * sizeof(long))
+#define STACK_OFFSET_UC_LINK_PTR (4 * sizeof(long))
+#define STACK_OFFSET_COROUTINE_UCONTEXT (7 * sizeof(long))
+#define STACK_OFFSET_COROUTINE (8 * sizeof(long))
+
+#define UCONTEXT_OFFSET_JMPBUF 0x38
+
#define GLIBC_TLS_PTR_GUARD 0x30
int get_ptr_guard(struct kpatch_process *proc,
unsigned long *ptr_guard);
+int locate_start_context_symbol(struct kpatch_process *proc,
+ unsigned long *pstart_context);
+
int kpatch_coroutines_init(struct kpatch_process *proc);
int kpatch_coroutines_find(struct kpatch_process *proc);
diff --git a/src/kpatch_coro.c b/src/kpatch_coro.c
index ea4050f..8457800 100644
--- a/src/kpatch_coro.c
+++ b/src/kpatch_coro.c
@@ -95,93 +95,6 @@ kpatch_coro_free(struct kpatch_coro *c)
* some kind of persistency (to allow kernelcare updates). This
* service also can listen to netlink events about new processes.
*/
-#define PTR_DEMANGLE(ptr, key) ((((ptr) >> 0x11) | ((ptr) << 47)) ^ key)
-#define JB_RBX 0
-#define JB_RBP 1
-#define JB_R12 2
-#define JB_R13 3
-#define JB_R14 4
-#define JB_R15 5
-#define JB_RSP 6
-#define JB_RIP 7
-
-#define STACK_OFFSET_UC_LINK (2 * sizeof(long))
-#define STACK_OFFSET_START_CONTEXT (3 * sizeof(long))
-#define STACK_OFFSET_UC_LINK_PTR (4 * sizeof(long))
-#define STACK_OFFSET_COROUTINE_UCONTEXT (7 * sizeof(long))
-#define STACK_OFFSET_COROUTINE (8 * sizeof(long))
-
-#define UCONTEXT_OFFSET_JMPBUF 0x38
-
-#define UCONTEXT_OFFSET_UC_STACK_SS_SP offsetof(ucontext_t, uc_stack.ss_sp)
-#define UCONTEXT_OFFSET_UC_STACK_SS_SIZE offsetof(ucontext_t, uc_stack.ss_size)
-
-asm ("makecontext_call:\n"
- "mov %rsp, %rbp\n"
- "and $-16, %rbp\n"
- /* ucontext_t is 0x3a8 bytes */
- "sub $0x400, %rbp\n"
- /* TODO interpolate these from the calculations above */
-
- /* set uc_stack.ss_sp and uc_stack.ss_size */
- /* TODO magic -128 is used below as well */
- "lea -128(%rbp), %rbx\n"
- "movq %rbx, 0x10(%rbp)\n"
- "movq $128, 0x20(%rbp)\n"
- "mov %rbp, %rdi\n"
- "mov $0x100, %rsi\n"
- "xor %rdx, %rdx\n"
- /* call `makecontext` */
- "call *%rax\n"
- "int3\n"
- "makecontext_call_end:");
-
-extern unsigned char makecontext_call, makecontext_call_end;
-
-static int
-locate_start_context_symbol(struct kpatch_process *proc,
- unsigned long *pstart_context)
-{
- struct object_file *olibc;
- struct user_regs_struct regs;
- int rv;
- unsigned long makecontext;
-
- olibc = kpatch_process_get_obj_by_regex(proc, "^libc-.*\\.so");
- if (olibc == NULL) {
- kpdebug("FAIL. Can't find libc\n");
- return -1;
- }
-
- rv = kpatch_resolve_undefined_single_dynamic(olibc,
- "makecontext",
- &makecontext);
- makecontext = vaddr2addr(olibc, makecontext);
- if (rv < 0 || makecontext == 0) {
- kpdebug("FAIL. Can't find makecontext\n");
- return -1;
- }
-
- regs.rax = makecontext;
- rv = kpatch_execute_remote(proc2pctx(proc),
- &makecontext_call,
- &makecontext_call_end - &makecontext_call,
- &regs);
- if (rv < 0) {
- kpdebug("FAIL. Can't execute makecontext\n");
- return -1;
- }
-
- rv = kpatch_process_mem_read(proc,
- regs.rbp - STACK_OFFSET_START_CONTEXT,
- pstart_context,
- sizeof(*pstart_context));
- if (rv < 0) {
- kpdebug("FAIL. Can't peek __start_context address\n");
- return -1;
- }
- return rv;
-}
static int is_test_target(struct kpatch_process *proc,
const char *procname)
--
2.23.0

View File

@ -0,0 +1,237 @@
From 4f165eacd6d1d64cc43a58dd54e35017663d99e2 Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Mon, 12 Oct 2020 14:58:18 +0800
Subject: [PATCH 35/89] kpatch_patch: Split function patch_apply_hunk
The function patch_apply_hunk is arch related, so make two
separate definations in arch/x86/arch_patch.c and arch/aarch64/arch_patch.c
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
src/arch/aarch64/arch_patch.c | 68 +++++++++++++++++++++++++++++++++++
src/arch/x86/arch_patch.c | 66 ++++++++++++++++++++++++++++++++++
src/include/kpatch_patch.h | 2 ++
src/kpatch_patch.c | 44 ++---------------------
4 files changed, 139 insertions(+), 41 deletions(-)
diff --git a/src/arch/aarch64/arch_patch.c b/src/arch/aarch64/arch_patch.c
index e69de29..9102621 100644
--- a/src/arch/aarch64/arch_patch.c
+++ b/src/arch/aarch64/arch_patch.c
@@ -0,0 +1,68 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/fcntl.h>
+#include <gelf.h>
+#include <libunwind.h>
+#include <libunwind-ptrace.h>
+#include "include/kpatch_patch.h"
+#include "include/kpatch_user.h"
+#include "include/kpatch_storage.h"
+#include "include/kpatch_process.h"
+#include "include/kpatch_file.h"
+#include "include/kpatch_common.h"
+#include "include/kpatch_elf.h"
+#include "include/kpatch_ptrace.h"
+#include "include/list.h"
+#include "include/kpatch_log.h"
+
+
+/*****************************************************************************
+ * Patch application subroutines
+ ****************************************************************************/
+/*
+ * This flag is local, i.e. it is never stored to the
+ * patch applied to patient's memory.
+ */
+int PATCH_APPLIED = (1 << 31);
+int HUNK_SIZE = 4;
+
+int patch_apply_hunk(struct object_file *o, size_t nhunk)
+{
+ int ret;
+ unsigned char code[] = {0x00, 0x00, 0x00, 0x00}; /* ins: b IMM */
+ struct kpatch_info *info = &o->info[nhunk];
+ unsigned long pundo;
+
+ if (is_new_func(info))
+ return 0;
+
+ pundo = o->kpta + o->kpfile.patch->user_undo + nhunk * HUNK_SIZE;
+ kpinfo("%s origcode from 0x%lx+0x%x to 0x%lx\n",
+ o->name, info->daddr, HUNK_SIZE, pundo);
+ ret = kpatch_process_memcpy(o->proc, pundo,
+ info->daddr, HUNK_SIZE);
+ if (ret < 0)
+ return ret;
+
+ kpinfo("%s hunk 0x%lx+0x%x -> 0x%lx+0x%x\n",
+ o->name, info->daddr, info->dlen, info->saddr, info->slen);
+
+ *(unsigned int *)(code) = (unsigned int)(info->saddr - info->daddr) / 4;
+ code[3] &= 0x3;
+ code[3] |= 0x14;
+
+ ret = kpatch_process_mem_write(o->proc,
+ code,
+ info->daddr,
+ sizeof(code));
+ /*
+ * NOTE(pboldin): This is only stored locally, as information have
+ * been copied to patient's memory already.
+ */
+ info->flags |= PATCH_APPLIED;
+ return ret ? -1 : 0;
+}
diff --git a/src/arch/x86/arch_patch.c b/src/arch/x86/arch_patch.c
index e69de29..a6e794d 100644
--- a/src/arch/x86/arch_patch.c
+++ b/src/arch/x86/arch_patch.c
@@ -0,0 +1,66 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/fcntl.h>
+
+#include <gelf.h>
+#include <libunwind.h>
+#include <libunwind-ptrace.h>
+
+#include "include/kpatch_patch.h"
+#include "include/kpatch_user.h"
+#include "include/kpatch_storage.h"
+#include "include/kpatch_process.h"
+#include "include/kpatch_file.h"
+#include "include/kpatch_common.h"
+#include "include/kpatch_elf.h"
+#include "include/kpatch_ptrace.h"
+#include "include/list.h"
+#include "include/kpatch_log.h"
+
+/*****************************************************************************
+ * Patch application subroutines
+ ****************************************************************************/
+/*
+ * This flag is local, i.e. it is never stored to the
+ * patch applied to patient's memory.
+ */
+int PATCH_APPLIED = (1 << 31);
+int HUNK_SIZE = 5;
+
+int patch_apply_hunk(struct object_file *o, size_t nhunk)
+{
+ int ret;
+ char code[] = {0xe9, 0x00, 0x00, 0x00, 0x00}; /* jmp IMM */
+ struct kpatch_info *info = &o->info[nhunk];
+ unsigned long pundo;
+
+ if (is_new_func(info))
+ return 0;
+
+ pundo = o->kpta + o->kpfile.patch->user_undo + nhunk * HUNK_SIZE;
+ kpinfo("%s origcode from 0x%lx+0x%x to 0x%lx\n",
+ o->name, info->daddr, HUNK_SIZE, pundo);
+ ret = kpatch_process_memcpy(o->proc, pundo,
+ info->daddr, HUNK_SIZE);
+ if (ret < 0)
+ return ret;
+
+ kpinfo("%s hunk 0x%lx+0x%x -> 0x%lx+0x%x\n",
+ o->name, info->daddr, info->dlen, info->saddr, info->slen);
+ *(unsigned int *)(code + 1) = (unsigned int)(info->saddr - info->daddr - 5);
+ ret = kpatch_process_mem_write(o->proc,
+ code,
+ info->daddr,
+ sizeof(code));
+ /*
+ * NOTE(pboldin): This is only stored locally, as information have
+ * been copied to patient's memory already.
+ */
+ info->flags |= PATCH_APPLIED;
+ return ret ? -1 : 0;
+}
+
diff --git a/src/include/kpatch_patch.h b/src/include/kpatch_patch.h
index 44806ab..fa96b08 100644
--- a/src/include/kpatch_patch.h
+++ b/src/include/kpatch_patch.h
@@ -25,4 +25,6 @@ struct unpatch_data {
int process_patch(int pid, void *_data);
int process_unpatch(int pid, void *_data);
+int patch_apply_hunk(struct object_file *o, size_t nhunk);
+
#endif
diff --git a/src/kpatch_patch.c b/src/kpatch_patch.c
index 21a160a..4a1d149 100644
--- a/src/kpatch_patch.c
+++ b/src/kpatch_patch.c
@@ -270,47 +270,6 @@ patch_ensure_safety(struct object_file *o,
/*****************************************************************************
* Patch application subroutines
****************************************************************************/
-/*
- * This flag is local, i.e. it is never stored to the
- * patch applied to patient's memory.
- */
-#define PATCH_APPLIED (1 << 31)
-
-#define HUNK_SIZE 5
-
-static int
-patch_apply_hunk(struct object_file *o, size_t nhunk)
-{
- int ret;
- char code[HUNK_SIZE] = {0xe9, 0x00, 0x00, 0x00, 0x00}; /* jmp IMM */
- struct kpatch_info *info = &o->info[nhunk];
- unsigned long pundo;
-
- if (is_new_func(info))
- return 0;
-
- pundo = o->kpta + o->kpfile.patch->user_undo + nhunk * HUNK_SIZE;
- kpinfo("%s origcode from 0x%lx+0x%x to 0x%lx\n",
- o->name, info->daddr, HUNK_SIZE, pundo);
- ret = kpatch_process_memcpy(o->proc, pundo,
- info->daddr, HUNK_SIZE);
- if (ret < 0)
- return ret;
-
- kpinfo("%s hunk 0x%lx+0x%x -> 0x%lx+0x%x\n",
- o->name, info->daddr, info->dlen, info->saddr, info->slen);
- *(unsigned int *)(code + 1) = (unsigned int)(info->saddr - info->daddr - 5);
- ret = kpatch_process_mem_write(o->proc,
- code,
- info->daddr,
- sizeof(code));
- /*
- * NOTE(pboldin): This is only stored locally, as information have
- * been copied to patient's memory already.
- */
- info->flags |= PATCH_APPLIED;
- return ret ? -1 : 0;
-}
static int
duplicate_kp_file(struct object_file *o)
@@ -328,6 +287,9 @@ duplicate_kp_file(struct object_file *o)
return 0;
}
+extern int PATCH_APPLIED;
+extern int HUNK_SIZE;
+
static int
object_apply_patch(struct object_file *o)
{
--
2.23.0

View File

@ -0,0 +1,151 @@
From 3352c27078a63b5bfc6ff4df639489fdabfd4dbe Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Mon, 12 Oct 2020 15:11:05 +0800
Subject: [PATCH 36/89] kpatch_elf: Split function kpatch_add_jmp_entry
The function kpatch_add_jmp_entry is arch related. To support multi-arch
let's rename it with kpatch_arch_add_jmp_entry, and make the defination in
arch/x86/arch_elf.c and arch/aarch64/arch_elf.c
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
src/arch/aarch64/arch_elf.c | 35 +++++++++++++++++++++++++++++++++++
src/arch/x86/arch_elf.c | 35 +++++++++++++++++++++++++++++++++++
src/include/kpatch_elf.h | 2 ++
src/kpatch_elf.c | 21 +--------------------
4 files changed, 73 insertions(+), 20 deletions(-)
diff --git a/src/arch/aarch64/arch_elf.c b/src/arch/aarch64/arch_elf.c
index e69de29..b977489 100644
--- a/src/arch/aarch64/arch_elf.c
+++ b/src/arch/aarch64/arch_elf.c
@@ -0,0 +1,35 @@
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <limits.h>
+
+#include <gelf.h>
+
+#include "include/kpatch_common.h"
+#include "include/kpatch_user.h"
+#include "include/kpatch_process.h"
+#include "include/kpatch_elf.h"
+#include "include/kpatch_file.h"
+#include "include/kpatch_ptrace.h"
+#include "include/kpatch_log.h"
+
+#define JMP_TABLE_JUMP 0xd61f022058000051 /* ldr x17 #8; br x17 */
+unsigned long kpatch_arch_add_jmp_entry(struct object_file *o, unsigned long addr)
+{
+ struct kpatch_jmp_table_entry entry = {JMP_TABLE_JUMP, addr};
+ int e;
+
+ if (o->jmp_table == NULL) {
+ kpfatalerror("JMP TABLE not found\n");
+ return 0;
+ }
+
+ if (o->jmp_table->cur_entry >= o->jmp_table->max_entry)
+ return 0;
+ e = o->jmp_table->cur_entry++;
+ o->jmp_table->entries[e] = entry;
+ return (unsigned long)(o->kpta + o->kpfile.patch->jmp_offset + \
+ ((void *)&o->jmp_table->entries[e] - (void *)o->jmp_table));
+}
diff --git a/src/arch/x86/arch_elf.c b/src/arch/x86/arch_elf.c
index e69de29..ef5564e 100644
--- a/src/arch/x86/arch_elf.c
+++ b/src/arch/x86/arch_elf.c
@@ -0,0 +1,35 @@
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <limits.h>
+
+#include <gelf.h>
+
+#include "include/kpatch_common.h"
+#include "include/kpatch_user.h"
+#include "include/kpatch_process.h"
+#include "include/kpatch_elf.h"
+#include "include/kpatch_file.h"
+#include "include/kpatch_ptrace.h"
+#include "include/kpatch_log.h"
+
+#define JMP_TABLE_JUMP 0x90900000000225ff /* jmp [rip+2]; nop; nop */
+unsigned long kpatch_arch_add_jmp_entry(struct object_file *o, unsigned long addr)
+{
+ struct kpatch_jmp_table_entry entry = {JMP_TABLE_JUMP, addr};
+ int e;
+
+ if (o->jmp_table == NULL) {
+ kpfatalerror("JMP TABLE not found\n");
+ return 0;
+ }
+
+ if (o->jmp_table->cur_entry >= o->jmp_table->max_entry)
+ return 0;
+ e = o->jmp_table->cur_entry++;
+ o->jmp_table->entries[e] = entry;
+ return (unsigned long)(o->kpta + o->kpfile.patch->jmp_offset + \
+ ((void *)&o->jmp_table->entries[e] - (void *)o->jmp_table));
+}
diff --git a/src/include/kpatch_elf.h b/src/include/kpatch_elf.h
index 8c0a4a4..7e5d8c3 100644
--- a/src/include/kpatch_elf.h
+++ b/src/include/kpatch_elf.h
@@ -43,4 +43,6 @@ struct kpatch_jmp_table {
struct kpatch_jmp_table_entry entries[0];
};
+unsigned long kpatch_arch_add_jmp_entry(struct object_file *o, unsigned long addr);
+
#endif
diff --git a/src/kpatch_elf.c b/src/kpatch_elf.c
index b1dfed0..21ba496 100644
--- a/src/kpatch_elf.c
+++ b/src/kpatch_elf.c
@@ -686,25 +686,6 @@ kpatch_resolve_undefined(struct object_file *obj,
return addr;
}
-#define JMP_TABLE_JUMP 0x90900000000225ff /* jmp [rip+2]; nop; nop */
-static unsigned long kpatch_add_jmp_entry(struct object_file *o, unsigned long addr)
-{
- struct kpatch_jmp_table_entry entry = {JMP_TABLE_JUMP, addr};
- int e;
-
- if (o->jmp_table == NULL) {
- kpfatalerror("JMP TABLE not found\n");
- return 0;
- }
-
- if (o->jmp_table->cur_entry >= o->jmp_table->max_entry)
- return 0;
- e = o->jmp_table->cur_entry++;
- o->jmp_table->entries[e] = entry;
- return (unsigned long)(o->kpta + o->kpfile.patch->jmp_offset + \
- ((void *)&o->jmp_table->entries[e] - (void *)o->jmp_table));
-}
-
static inline int
symbol_resolve(struct object_file *o,
GElf_Shdr *shdr,
@@ -737,7 +718,7 @@ symbol_resolve(struct object_file *o,
}
/* OK, we overuse st_size to store original offset */
s->st_size = uaddr;
- s->st_value = kpatch_add_jmp_entry(o, uaddr);
+ s->st_value = kpatch_arch_add_jmp_entry(o, uaddr);
kpdebug("symbol '%s' = 0x%lx\n",
symname, uaddr);
--
2.23.0

View File

@ -0,0 +1,414 @@
From 69837926282fc65d41be15390d9a125da97adc54 Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Mon, 12 Oct 2020 15:37:08 +0800
Subject: [PATCH 37/89] kpatch_elf: Split function kpatch_apply_relocate_add
The function kpatch_apply_relocate_add is arch related. To support multi-arch
let's rename it with kpatch_arch_apply_relocate_add, and make the defination
in arch/x86/arch_elf.c and arch/aarch64/arch_elf.c
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
src/arch/aarch64/arch_elf.c | 100 ++++++++++++++++++++++++++++++++++++
src/arch/x86/arch_elf.c | 89 ++++++++++++++++++++++++++++++++
src/include/bitops.h | 27 ++++++++++
src/include/kpatch_elf.h | 5 ++
src/kpatch_elf.c | 94 ++-------------------------------
5 files changed, 224 insertions(+), 91 deletions(-)
create mode 100644 src/include/bitops.h
diff --git a/src/arch/aarch64/arch_elf.c b/src/arch/aarch64/arch_elf.c
index b977489..deacb6f 100644
--- a/src/arch/aarch64/arch_elf.c
+++ b/src/arch/aarch64/arch_elf.c
@@ -14,6 +14,106 @@
#include "include/kpatch_file.h"
#include "include/kpatch_ptrace.h"
#include "include/kpatch_log.h"
+#include "include/bitops.h"
+
+static int kpatch_arch_apply_relocate(GElf_Rela *r, GElf_Sym *s,
+ void *loc, void *loc2, unsigned long val)
+{
+ switch (GELF_R_TYPE(r->r_info)) {
+ case R_AARCH64_ABS64:
+ *(unsigned long *)loc = val;
+ kpdebug("R_AARCH64_ABS64: loc=0x%x, val =0x%lx\n",*(unsigned int*)loc,val);
+ break;
+ case R_AARCH64_ADD_ABS_LO12_NC: {
+ //ADD ins
+ kpdebug("R_AARCH64_ADD_ABS_LO12_NC: val=0x%lx\n", val);
+ val = val & 0xfff;
+ uint32_t mask = 0xfff << 10;
+ *(unsigned int*)loc &= ~mask;
+ or_32(loc, (val & 0xfff) << 10);
+ kpdebug("R_AARCH64_ADD_ABS_LO12_NC: loc=0x%x, val =0x%lx\n",*(unsigned int*)loc,val);
+ break;
+ }
+ case R_AARCH64_CALL26: {
+ // TODO bl ins
+ kpdebug("R_AARCH64_CALL26: val=0x%lx\n", val);
+ val -= (unsigned long)loc2;
+ uint32_t mask = 0x03FFFFFF;;
+ *(unsigned int*)loc &= ~mask;
+ or_32(loc, (val >> 2) & mask);
+ kpdebug("R_AARCH64_CALL26: loc=0x%x, val =0x%lx\n",*(unsigned int*)loc, val);
+ break;
+ }
+ case R_AARCH64_ADR_PREL_PG_HI21: {
+ // TODO ADRP ins
+ kpdebug("RR_AARCH64_ADR_PREL_PG_HI21: val=0x%lx\n", val);
+ val = (val >> 12) - ((unsigned long)loc2 >> 12);
+ kpdebug("val=0x%lx\n",val);
+ uint32_t immLo = (val & 0x3) << 29;
+ uint32_t immHi = (val & 0x1FFFFC) << 3;
+ uint64_t mask = (0x3 << 29) | (0x1FFFFC << 3);
+ *(unsigned int*)loc = (*(unsigned int*)loc & ~mask) | immLo | immHi;
+ //*(unsigned int*)loc &= 0x7fffffff;
+ kpdebug("lo=0x%x hi=0x%x\n",immLo,immHi);
+ kpdebug("R_AARCH64_ADR_PREL_PG_HI21: loc=0x%x, val=0x%lx\n", *(unsigned int *)loc, val);
+ break;
+ }
+ default:
+ kperr("unknown relocation type: %lx\n", r->r_info);
+ return -1;
+ }
+ return 0;
+}
+
+int kpatch_arch_apply_relocate_add(struct object_file *o, GElf_Shdr *relsec)
+{
+ struct kpatch_file *kp = o->kpfile.patch;
+ GElf_Ehdr *ehdr = (void *)kp + kp->kpatch_offset;
+ GElf_Shdr *shdr = (void *)ehdr + ehdr->e_shoff, *symhdr;
+ GElf_Rela *relocs = (void *)ehdr + relsec->sh_offset;
+ GElf_Shdr *tshdr = shdr + relsec->sh_info;
+ void *t = (void *)ehdr + shdr[relsec->sh_info].sh_offset;
+ void *tshdr2 = (void *)shdr[relsec->sh_info].sh_addr;
+ int i, is_kpatch_info;
+ const char *scnname;
+
+ for (i = 1; i < ehdr->e_shnum; i++) {
+ if (shdr[i].sh_type == SHT_SYMTAB)
+ symhdr = &shdr[i];
+ }
+
+ scnname = secname(ehdr, shdr + relsec->sh_info);
+ kpdebug("applying relocations to '%s'\n", scnname);
+ is_kpatch_info = strcmp(scnname, ".kpatch.info") == 0;
+
+ for (i = 0; i < relsec->sh_size / sizeof(*relocs); i++) {
+ GElf_Rela *r = relocs + i;
+ GElf_Sym *s;
+ unsigned long val;
+ void *loc, *loc2;
+
+ if (r->r_offset < 0 || r->r_offset >= tshdr->sh_size)
+ kpfatalerror("Relocation offset for section '%s'"
+ " is at 0x%lx beyond the section size 0x%lx\n",
+ scnname, r->r_offset, tshdr->sh_size);
+
+ /* Location in our address space */
+ loc = t + r->r_offset;
+ /* Location in target process address space (for relative addressing) */
+ loc2 = tshdr2 + r->r_offset;
+ s = (GElf_Sym *)((void *)ehdr + symhdr->sh_offset) + GELF_R_SYM(r->r_info);
+ val = s->st_value + r->r_addend;
+
+ if (is_kpatch_info && is_undef_symbol(s)) {
+ val = s->st_size;
+ }
+
+ kpatch_arch_apply_relocate(r, s, loc, loc2, val);
+ }
+
+ return 0;
+}
+
#define JMP_TABLE_JUMP 0xd61f022058000051 /* ldr x17 #8; br x17 */
unsigned long kpatch_arch_add_jmp_entry(struct object_file *o, unsigned long addr)
diff --git a/src/arch/x86/arch_elf.c b/src/arch/x86/arch_elf.c
index ef5564e..52de117 100644
--- a/src/arch/x86/arch_elf.c
+++ b/src/arch/x86/arch_elf.c
@@ -15,6 +15,95 @@
#include "include/kpatch_ptrace.h"
#include "include/kpatch_log.h"
+int kpatch_arch_apply_relocate_add(struct object_file *o, GElf_Shdr *relsec)
+{
+ struct kpatch_file *kp = o->kpfile.patch;
+ GElf_Ehdr *ehdr = (void *)kp + kp->kpatch_offset;
+ GElf_Shdr *shdr = (void *)ehdr + ehdr->e_shoff, *symhdr;
+ GElf_Rela *relocs = (void *)ehdr + relsec->sh_offset;
+ GElf_Shdr *tshdr = shdr + relsec->sh_info;
+ void *t = (void *)ehdr + shdr[relsec->sh_info].sh_offset;
+ void *tshdr2 = (void *)shdr[relsec->sh_info].sh_addr;
+ int i, is_kpatch_info;
+ const char *scnname;
+
+ for (i = 1; i < ehdr->e_shnum; i++) {
+ if (shdr[i].sh_type == SHT_SYMTAB)
+ symhdr = &shdr[i];
+ }
+
+ scnname = secname(ehdr, shdr + relsec->sh_info);
+ kpdebug("applying relocations to '%s'\n", scnname);
+ is_kpatch_info = strcmp(scnname, ".kpatch.info") == 0;
+
+ for (i = 0; i < relsec->sh_size / sizeof(*relocs); i++) {
+ GElf_Rela *r = relocs + i;
+ GElf_Sym *s;
+ unsigned long val;
+ void *loc, *loc2;
+
+ if (r->r_offset < 0 || r->r_offset >= tshdr->sh_size)
+ kpfatalerror("Relocation offset for section '%s'"
+ " is at 0x%lx beyond the section size 0x%lx\n",
+ scnname, r->r_offset, tshdr->sh_size);
+
+ /* Location in our address space */
+ loc = t + r->r_offset;
+ /* Location in target process address space (for relative addressing) */
+ loc2 = tshdr2 + r->r_offset;
+ s = (GElf_Sym *)((void *)ehdr + symhdr->sh_offset) + GELF_R_SYM(r->r_info);
+ val = s->st_value + r->r_addend;
+
+ if (is_kpatch_info && is_undef_symbol(s)) {
+ val = s->st_size;
+ }
+
+ switch (GELF_R_TYPE(r->r_info)) {
+ case R_X86_64_NONE:
+ break;
+ case R_X86_64_64:
+ *(unsigned long *)loc = val;
+ break;
+ case R_X86_64_32:
+ *(unsigned int *)loc = val;
+ break;
+ case R_X86_64_32S:
+ *(signed int *)loc = val;
+ break;
+ case R_X86_64_GOTTPOFF:
+ case R_X86_64_GOTPCREL:
+ case R_X86_64_REX_GOTPCRELX:
+ case R_X86_64_GOTPCRELX:
+ if (is_undef_symbol(s)) {
+ /* This is an undefined symbol,
+ * use jmp table as the GOT */
+ val += sizeof(unsigned long);
+ } else if (GELF_ST_TYPE(s->st_info) == STT_TLS) {
+ /* This is GOTTPOFF that already points
+ * to an appropriate GOT entry in the
+ * patient's memory.
+ */
+ val = r->r_addend + o->load_offset - 4;
+ }
+ /* FALLTHROUGH */
+ case R_X86_64_PC32:
+ val -= (unsigned long)loc2;
+ *(unsigned int *)loc = val;
+ break;
+ case R_X86_64_TPOFF64:
+ case R_X86_64_TPOFF32:
+ kperr("TPOFF32/TPOFF64 should not be present\n");
+ break;
+ default:
+ kperr("unknown relocation type: %lx\n", r->r_info);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
#define JMP_TABLE_JUMP 0x90900000000225ff /* jmp [rip+2]; nop; nop */
unsigned long kpatch_arch_add_jmp_entry(struct object_file *o, unsigned long addr)
{
diff --git a/src/include/bitops.h b/src/include/bitops.h
new file mode 100644
index 0000000..aab1679
--- /dev/null
+++ b/src/include/bitops.h
@@ -0,0 +1,27 @@
+#ifndef BITOPS_H
+#define BITOPS_H
+
+#define BITS_PER_BYTE CHAR_BIT
+#define BITS_PER_LONG (sizeof (unsigned long) * BITS_PER_BYTE)
+
+#define BIT(nr) (1UL << (nr))
+#define BIT_ULL(nr) (1ULL << (nr))
+#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
+#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
+#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
+
+static inline void or_32(void *addr, unsigned int val)
+{
+ *(unsigned int*) addr = *(unsigned int*)addr | val;
+}
+
+static inline void or_64(void *addr, unsigned long val)
+{
+ *(unsigned long*) addr = *(unsigned long*)addr | val;
+}
+
+static inline void and_32(void *addr, unsigned int val)
+{
+ *(unsigned int*) addr = *(unsigned int*)addr & val;
+}
+#endif
diff --git a/src/include/kpatch_elf.h b/src/include/kpatch_elf.h
index 7e5d8c3..74efe04 100644
--- a/src/include/kpatch_elf.h
+++ b/src/include/kpatch_elf.h
@@ -1,6 +1,7 @@
#ifndef __KPATCH_ELF__
#define __KPATCH_ELF__
+#include <gelf.h>
#include "kpatch_process.h"
const char *kpatch_get_buildid(struct object_file *o);
@@ -45,4 +46,8 @@ struct kpatch_jmp_table {
unsigned long kpatch_arch_add_jmp_entry(struct object_file *o, unsigned long addr);
+char *secname(GElf_Ehdr *ehdr, GElf_Shdr *s);
+int is_undef_symbol(const Elf64_Sym *sym);
+int kpatch_arch_apply_relocate_add(struct object_file *o, GElf_Shdr *relsec);
+
#endif
diff --git a/src/kpatch_elf.c b/src/kpatch_elf.c
index 21ba496..5506292 100644
--- a/src/kpatch_elf.c
+++ b/src/kpatch_elf.c
@@ -410,7 +410,7 @@ out:
return rv;
}
-static char *secname(GElf_Ehdr *ehdr, GElf_Shdr *s)
+char *secname(GElf_Ehdr *ehdr, GElf_Shdr *s)
{
GElf_Shdr *shdr = (void *)ehdr + ehdr->e_shoff;
char *str = (void *)ehdr + shdr[ehdr->e_shstrndx].sh_offset;
@@ -450,7 +450,7 @@ struct kpatch_jmp_table *kpatch_new_jmp_table(int entries)
return jtbl;
}
-static inline int
+inline int
is_undef_symbol(const Elf64_Sym *sym)
{
return sym->st_shndx == SHN_UNDEF || sym->st_shndx >= SHN_LORESERVE;
@@ -805,94 +805,6 @@ int kpatch_resolve(struct object_file *o)
return 0;
}
-static int kpatch_apply_relocate_add(struct object_file *o, GElf_Shdr *relsec)
-{
- struct kpatch_file *kp = o->kpfile.patch;
- GElf_Ehdr *ehdr = (void *)kp + kp->kpatch_offset;
- GElf_Shdr *shdr = (void *)ehdr + ehdr->e_shoff, *symhdr;
- GElf_Rela *relocs = (void *)ehdr + relsec->sh_offset;
- GElf_Shdr *tshdr = shdr + relsec->sh_info;
- void *t = (void *)ehdr + shdr[relsec->sh_info].sh_offset;
- void *tshdr2 = (void *)shdr[relsec->sh_info].sh_addr;
- int i, is_kpatch_info;
- const char *scnname;
-
- for (i = 1; i < ehdr->e_shnum; i++) {
- if (shdr[i].sh_type == SHT_SYMTAB)
- symhdr = &shdr[i];
- }
-
- scnname = secname(ehdr, shdr + relsec->sh_info);
- kpdebug("applying relocations to '%s'\n", scnname);
- is_kpatch_info = strcmp(scnname, ".kpatch.info") == 0;
-
- for (i = 0; i < relsec->sh_size / sizeof(*relocs); i++) {
- GElf_Rela *r = relocs + i;
- GElf_Sym *s;
- unsigned long val;
- void *loc, *loc2;
-
- if (r->r_offset < 0 || r->r_offset >= tshdr->sh_size)
- kpfatalerror("Relocation offset for section '%s'"
- " is at 0x%lx beyond the section size 0x%lx\n",
- scnname, r->r_offset, tshdr->sh_size);
-
- /* Location in our address space */
- loc = t + r->r_offset;
- /* Location in target process address space (for relative addressing) */
- loc2 = tshdr2 + r->r_offset;
- s = (GElf_Sym *)((void *)ehdr + symhdr->sh_offset) + GELF_R_SYM(r->r_info);
- val = s->st_value + r->r_addend;
-
- if (is_kpatch_info && is_undef_symbol(s)) {
- val = s->st_size;
- }
-
- switch (GELF_R_TYPE(r->r_info)) {
- case R_X86_64_NONE:
- break;
- case R_X86_64_64:
- *(unsigned long *)loc = val;
- break;
- case R_X86_64_32:
- *(unsigned int *)loc = val;
- break;
- case R_X86_64_32S:
- *(signed int *)loc = val;
- break;
- case R_X86_64_GOTTPOFF:
- case R_X86_64_GOTPCREL:
- case R_X86_64_REX_GOTPCRELX:
- case R_X86_64_GOTPCRELX:
- if (is_undef_symbol(s)) {
- /* This is an undefined symbol,
- * use jmp table as the GOT */
- val += sizeof(unsigned long);
- } else if (GELF_ST_TYPE(s->st_info) == STT_TLS) {
- /* This is GOTTPOFF that already points
- * to an appropriate GOT entry in the
- * patient's memory.
- */
- val = r->r_addend + o->load_offset - 4;
- }
- /* FALLTHROUGH */
- case R_X86_64_PC32:
- val -= (unsigned long)loc2;
- *(unsigned int *)loc = val;
- break;
- case R_X86_64_TPOFF64:
- case R_X86_64_TPOFF32:
- kperr("TPOFF32/TPOFF64 should not be present\n");
- break;
- default:
- kperr("unknown relocation type: %lx\n", r->r_info);
- return -1;
- }
- }
-
- return 0;
-}
-
int kpatch_relocate(struct object_file *o)
{
GElf_Ehdr *ehdr;
@@ -907,7 +819,7 @@ int kpatch_relocate(struct object_file *o)
GElf_Shdr *s = shdr + i;
if (s->sh_type == SHT_RELA)
- ret = kpatch_apply_relocate_add(o, s);
+ ret = kpatch_arch_apply_relocate_add(o, s);
else if (shdr->sh_type == SHT_REL) {
kperr("TODO: handle SHT_REL\n");
return -1;
--
2.23.0

View File

@ -0,0 +1,416 @@
From 80c479726361710a9ac4f328687796a183cf780f Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Mon, 12 Oct 2020 15:56:42 +0800
Subject: [PATCH 38/89] kpatch_process: Split function object_find_patch_region
The function object_find_patch_region is arch related. Since process
virtual address layout may be different between x86 and aarch64,
let's make two separate definations in arch/x86/arch_process.c and
arch/aarch64/arch_process.c
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
src/arch.desc | 1 +
src/arch/aarch64/arch_process.c | 120 ++++++++++++++++++++++++++++++++
src/arch/x86/arch_process.c | 108 ++++++++++++++++++++++++++++
src/include/kpatch_process.h | 9 +++
src/kpatch_process.c | 87 ++---------------------
5 files changed, 242 insertions(+), 83 deletions(-)
create mode 100644 src/arch.desc
create mode 100644 src/arch/aarch64/arch_process.c
create mode 100644 src/arch/x86/arch_process.c
diff --git a/src/arch.desc b/src/arch.desc
new file mode 100644
index 0000000..9647742
--- /dev/null
+++ b/src/arch.desc
@@ -0,0 +1 @@
+aarch64
diff --git a/src/arch/aarch64/arch_process.c b/src/arch/aarch64/arch_process.c
new file mode 100644
index 0000000..3a64d77
--- /dev/null
+++ b/src/arch/aarch64/arch_process.c
@@ -0,0 +1,120 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <dirent.h>
+#include <regex.h>
+#include <sys/fcntl.h>
+#include <sys/mman.h>
+#include <sys/vfs.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/ptrace.h>
+
+#include <gelf.h>
+#include <libunwind.h>
+#include <libunwind-ptrace.h>
+
+#include <sys/socket.h>
+
+#include "include/kpatch_process.h"
+#include "include/kpatch_file.h"
+#include "include/kpatch_common.h"
+#include "include/kpatch_elf.h"
+#include "include/kpatch_ptrace.h"
+#include "include/list.h"
+#include "include/kpatch_log.h"
+
+/*
+ * Find region for a patch. Take object's `previous_hole` as a left candidate
+ * and the next hole as a right candidate. Pace through them until there is
+ * enough space in the hole for the patch.
+ *
+ * Since holes can be much larger than 2GiB take extra caution to allocate
+ * patch region inside the (-2GiB, +2GiB) range from the original object.
+ */
+unsigned long
+object_find_patch_region(struct object_file *obj,
+ size_t memsize,
+ struct vm_hole **hole)
+{
+ struct list_head *head = &obj->proc->vmaholes;
+ struct vm_hole *left_hole = obj->previous_hole,
+ *right_hole = next_hole(left_hole, head);
+ unsigned long max_distance = 0x80000000;
+ struct obj_vm_area *sovma;
+
+ unsigned long obj_start, obj_end;
+ unsigned long region_start = 0, region_end = 0;
+
+ kpdebug("Looking for patch region for '%s'...\n", obj->name);
+
+ sovma = list_first_entry(&obj->vma, struct obj_vm_area, list);
+ obj_start = sovma->inmem.start;
+ sovma = list_entry(obj->vma.prev, struct obj_vm_area, list);
+ obj_end = sovma->inmem.end;
+
+
+ max_distance -= memsize;
+
+ /* TODO carefully check for the holes laying between obj_start and
+ * obj_end, i.e. just after the executable segment of an executable
+ */
+ while (left_hole != NULL && right_hole != NULL) {
+ if (right_hole != NULL &&
+ right_hole->start - obj_start > max_distance)
+ right_hole = NULL;
+ else if (hole_size(right_hole) > memsize) {
+ region_start = right_hole->start;
+ region_end =
+ (right_hole->end - obj_start) <= max_distance ?
+ right_hole->end - memsize :
+ obj_start + max_distance;
+ *hole = right_hole;
+ break;
+ } else
+ right_hole = next_hole(right_hole, head);
+
+ if (left_hole != NULL &&
+ obj_end - left_hole->end > max_distance)
+ left_hole = NULL;
+ else if (hole_size(left_hole) > memsize) {
+ region_start =
+ (left_hole->start - obj_end) <= max_distance ?
+ left_hole->start : obj_end > max_distance ?
+ obj_end - max_distance : 0;
+ region_end = left_hole->end - memsize;
+ *hole = left_hole;
+ break;
+ } else
+ left_hole = prev_hole(left_hole, head);
+ }
+
+ if (region_start == region_end) {
+ kperr("can't find suitable region for patch on '%s'\n",
+ obj->name);
+ return -1UL;
+ }
+
+ /*
+ * On aarch64, virtual address of text and data segments may be continuous,
+ * gap between data segment and process heap may be huge. Need to have
+ * region_end fixed. Here goes the trick:
+ * The branch instruction jump size is in the range of +/-128MB.
+ * So we need to put limitation to the region_end.
+ */
+ region_end = region_start + (0x1<<25);
+ region_start = random_from_range(region_start >> PAGE_SHIFT,
+ region_end >> PAGE_SHIFT);
+ region_start <<= PAGE_SHIFT;
+ kpdebug("Found patch region for '%s' at %lx\n", obj->name, region_start);
+
+ return region_start;
+}
+
diff --git a/src/arch/x86/arch_process.c b/src/arch/x86/arch_process.c
new file mode 100644
index 0000000..ba66134
--- /dev/null
+++ b/src/arch/x86/arch_process.c
@@ -0,0 +1,108 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <dirent.h>
+#include <regex.h>
+#include <sys/fcntl.h>
+#include <sys/mman.h>
+#include <sys/vfs.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/ptrace.h>
+
+#include <gelf.h>
+#include <libunwind.h>
+#include <libunwind-ptrace.h>
+
+#include <sys/socket.h>
+
+#include "include/kpatch_process.h"
+#include "include/kpatch_file.h"
+#include "include/kpatch_common.h"
+#include "include/kpatch_elf.h"
+#include "include/kpatch_ptrace.h"
+#include "include/list.h"
+#include "include/kpatch_log.h"
+
+/*
+ * Find region for a patch. Take object's `previous_hole` as a left candidate
+ * and the next hole as a right candidate. Pace through them until there is
+ * enough space in the hole for the patch.
+ *
+ * Since holes can be much larger than 2GiB take extra caution to allocate
+ * patch region inside the (-2GiB, +2GiB) range from the original object.
+ */
+unsigned long object_find_patch_region(struct object_file *obj,
+ size_t memsize,
+ struct vm_hole **hole)
+{
+ struct list_head *head = &obj->proc->vmaholes;
+ struct vm_hole *left_hole = obj->previous_hole,
+ *right_hole = next_hole(left_hole, head);
+ unsigned long max_distance = 0x80000000;
+ struct obj_vm_area *sovma;
+
+ unsigned long obj_start, obj_end;
+ unsigned long region_start = 0, region_end = 0;
+
+ kpdebug("Looking for patch region for '%s'...\n", obj->name);
+
+ sovma = list_first_entry(&obj->vma, struct obj_vm_area, list);
+ obj_start = sovma->inmem.start;
+ sovma = list_entry(obj->vma.prev, struct obj_vm_area, list);
+ obj_end = sovma->inmem.end;
+
+
+ max_distance -= memsize;
+
+ /* TODO carefully check for the holes laying between obj_start and
+ * obj_end, i.e. just after the executable segment of an executable
+ */
+ while (left_hole != NULL && right_hole != NULL) {
+ if (right_hole != NULL &&
+ right_hole->start - obj_start > max_distance)
+ right_hole = NULL;
+ else if (hole_size(right_hole) > memsize) {
+ region_start = right_hole->start;
+ region_end =
+ (right_hole->end - obj_start) <= max_distance ?
+ right_hole->end - memsize :
+ obj_start + max_distance;
+ *hole = right_hole;
+ break;
+ } else
+ right_hole = next_hole(right_hole, head);
+
+ if (left_hole != NULL &&
+ obj_end - left_hole->end > max_distance)
+ left_hole = NULL;
+ else if (hole_size(left_hole) > memsize) {
+ region_start =
+ (left_hole->start - obj_end) <= max_distance ?
+ left_hole->start : obj_end > max_distance ?
+ obj_end - max_distance : 0;
+ region_end = left_hole->end - memsize;
+ *hole = left_hole;
+ break;
+ } else
+ left_hole = prev_hole(left_hole, head);
+ }
+
+ if (region_start == region_end) {
+ kperr("can't find suitable region for patch on '%s'\n",
+ obj->name);
+ return -1UL;
+ }
+
+ region_start += PAGE_SIZE;
+ kpdebug("Found patch region for '%s' at %lx\n", obj->name, region_start);
+
+ return region_start;
+}
diff --git a/src/include/kpatch_process.h b/src/include/kpatch_process.h
index abbb1af..b96a6da 100644
--- a/src/include/kpatch_process.h
+++ b/src/include/kpatch_process.h
@@ -211,4 +211,13 @@ is_kernel_object_name(char *name)
return 0;
}
+struct vm_hole *next_hole(struct vm_hole *hole, struct list_head *head);
+struct vm_hole *prev_hole(struct vm_hole *hole, struct list_head *head);
+unsigned long hole_size(struct vm_hole *hole);
+
+unsigned long random_from_range(unsigned long min, unsigned long max);
+unsigned long object_find_patch_region(struct object_file *obj,
+ size_t memsize,
+ struct vm_hole **hole);
+
#endif /* ifndef __KPATCH_PROCESS__ */
diff --git a/src/kpatch_process.c b/src/kpatch_process.c
index 3f7f2f6..9561962 100644
--- a/src/kpatch_process.c
+++ b/src/kpatch_process.c
@@ -965,7 +965,7 @@ vm_hole_split(struct vm_hole *hole,
return 0;
}
-static inline struct vm_hole *
+inline struct vm_hole *
next_hole(struct vm_hole *hole, struct list_head *head)
{
if (hole == NULL || hole->list.next == head)
@@ -974,7 +974,7 @@ next_hole(struct vm_hole *hole, struct list_head *head)
return list_entry(hole->list.next, struct vm_hole, list);
}
-static inline struct vm_hole *
+inline struct vm_hole *
prev_hole(struct vm_hole *hole, struct list_head *head)
{
if (hole == NULL || hole->list.prev == head)
@@ -983,7 +983,7 @@ prev_hole(struct vm_hole *hole, struct list_head *head)
return list_entry(hole->list.prev, struct vm_hole, list);
}
-static inline unsigned long
+inline unsigned long
hole_size(struct vm_hole *hole)
{
if (hole == NULL)
@@ -991,92 +991,13 @@ hole_size(struct vm_hole *hole)
return hole->end - hole->start;
}
-static unsigned long
+unsigned long
random_from_range(unsigned long min, unsigned long max)
{
/* TODO this is not uniform nor safe */
return min + random() % (max - min);
}
-/*
- * Find region for a patch. Take object's `previous_hole` as a left candidate
- * and the next hole as a right candidate. Pace through them until there is
- * enough space in the hole for the patch.
- *
- * Since holes can be much larger than 2GiB take extra caution to allocate
- * patch region inside the (-2GiB, +2GiB) range from the original object.
- */
-static unsigned long
-object_find_patch_region(struct object_file *obj,
- size_t memsize,
- struct vm_hole **hole)
-{
- struct list_head *head = &obj->proc->vmaholes;
- struct vm_hole *left_hole = obj->previous_hole,
- *right_hole = next_hole(left_hole, head);
- unsigned long max_distance = 0x80000000;
- struct obj_vm_area *sovma;
-
- unsigned long obj_start, obj_end;
- unsigned long region_start = 0, region_end = 0;
-
- kpdebug("Looking for patch region for '%s'...\n", obj->name);
-
- sovma = list_first_entry(&obj->vma, struct obj_vm_area, list);
- obj_start = sovma->inmem.start;
- sovma = list_entry(obj->vma.prev, struct obj_vm_area, list);
- obj_end = sovma->inmem.end;
-
-
- max_distance -= memsize;
-
- /* TODO carefully check for the holes laying between obj_start and
- * obj_end, i.e. just after the executable segment of an executable
- */
- while (left_hole != NULL && right_hole != NULL) {
- if (right_hole != NULL &&
- right_hole->start - obj_start > max_distance)
- right_hole = NULL;
- else if (hole_size(right_hole) > memsize) {
- region_start = right_hole->start;
- region_end =
- (right_hole->end - obj_start) <= max_distance ?
- right_hole->end - memsize :
- obj_start + max_distance;
- *hole = right_hole;
- break;
- } else
- right_hole = next_hole(right_hole, head);
-
- if (left_hole != NULL &&
- obj_end - left_hole->end > max_distance)
- left_hole = NULL;
- else if (hole_size(left_hole) > memsize) {
- region_start =
- (left_hole->start - obj_end) <= max_distance ?
- left_hole->start : obj_end > max_distance ?
- obj_end - max_distance : 0;
- region_end = left_hole->end - memsize;
- *hole = left_hole;
- break;
- } else
- left_hole = prev_hole(left_hole, head);
- }
-
- if (region_start == region_end) {
- kperr("can't find suitable region for patch on '%s'\n",
- obj->name);
- return -1UL;
- }
-
- region_start = random_from_range(region_start >> PAGE_SHIFT,
- region_end >> PAGE_SHIFT);
- region_start <<= PAGE_SHIFT;
- kpdebug("Found patch region for '%s' at %lx\n", obj->name, region_start);
-
- return region_start;
-}
-
int
kpatch_object_allocate_patch(struct object_file *o,
size_t sz)
--
2.23.0

View File

@ -0,0 +1,501 @@
From 35b9c6934fc5c1e2ea4cf7e30b91b3b91e48074d Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Mon, 12 Oct 2020 16:16:57 +0800
Subject: [PATCH 39/89] kpatch_ptrace: Split function kpatch_ptrace_waitpid
The function kpatch_ptrace_waitpid is arch related, let's
rename it with kpatch_arch_ptrace_waitpid, and make the
defination in arch/x86/arch_ptrace.c and arch/aarch64/arch_ptrace.c
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
src/arch/aarch64/arch_ptrace.c | 145 +++++++++++++++++++++++++++++++++
src/arch/x86/arch_ptrace.c | 140 +++++++++++++++++++++++++++++++
src/include/kpatch_ptrace.h | 20 +++++
src/kpatch_ptrace.c | 130 +----------------------------
4 files changed, 307 insertions(+), 128 deletions(-)
diff --git a/src/arch/aarch64/arch_ptrace.c b/src/arch/aarch64/arch_ptrace.c
index e69de29..fb19e86 100644
--- a/src/arch/aarch64/arch_ptrace.c
+++ b/src/arch/aarch64/arch_ptrace.c
@@ -0,0 +1,145 @@
+#include <stdlib.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <fcntl.h>
+#include <sys/ptrace.h>
+#include <sys/wait.h>
+#include <asm/unistd.h>
+
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <linux/auxvec.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "include/kpatch_process.h"
+#include "include/kpatch_common.h"
+#include "include/kpatch_ptrace.h"
+#include "include/kpatch_log.h"
+
+#include <gelf.h>
+
+int
+kpatch_arch_ptrace_waitpid(kpatch_process_t *proc,
+ struct timespec *timeout,
+ const sigset_t *sigset)
+{
+ struct kpatch_ptrace_ctx *pctx;
+ siginfo_t siginfo;
+ int ret, status;
+ pid_t pid;
+ struct user_regs_struct regs;
+ struct iovec regs_iov;
+
+ regs_iov.iov_base = &regs;
+ regs_iov.iov_len = sizeof(regs);
+
+ /* Immediately reap one attached thread */
+ pid = waitpid(-1, &status, __WALL | WNOHANG);
+
+ if (pid < 0) {
+ kplogerror("can't wait for tracees\n");
+ return -1;
+ }
+
+ /* There is none ready, wait for notification via signal */
+ if (pid == 0) {
+ ret = sigtimedwait(sigset, &siginfo, timeout);
+ if (ret == -1 && errno == EAGAIN) {
+ /* We have timeouted */
+ return -1;
+ }
+
+ if (ret == -1 && errno == EINVAL) {
+ kperr("invalid timeout\n");
+ return -1;
+ }
+
+ /* We have got EINTR and must restart */
+ if (ret == -1 && errno == EINTR)
+ return 0;
+
+ /**
+ * Kernel stacks signals that follow too quickly.
+ * Deal with it by waiting for any child, not just
+ * one that is specified in signal
+ */
+ pid = waitpid(-1, &status, __WALL | WNOHANG);
+
+ if (pid == 0) {
+ kperr("missing waitpid for %d\n", siginfo.si_pid);
+ return 0;
+ }
+
+ if (pid < 0) {
+ kplogerror("can't wait for tracee %d\n", siginfo.si_pid);
+ return -1;
+ }
+ }
+
+ if (!WIFSTOPPED(status) && WIFSIGNALED(status)) {
+ /* Continue, resending the signal */
+ ret = ptrace(PTRACE_CONT, pid, NULL,
+ (void *)(uintptr_t)WTERMSIG(status));
+ if (ret < 0) {
+ kplogerror("can't start tracee %d\n", pid);
+ return -1;
+ }
+ return 0;
+ }
+
+ if (WIFEXITED(status)) {
+ pctx = kpatch_ptrace_find_thread(proc, pid, 0UL);
+ if (pctx == NULL) {
+ kperr("got unexpected child '%d' exit\n", pid);
+ } else {
+ /* It's dead */
+ pctx->pid = pctx->running = 0;
+ }
+ return 1;
+ }
+
+ ret = ptrace(PTRACE_GETREGSET, pid, (void *)NT_PRSTATUS, (void *)&regs_iov);
+ if (ret < 0) {
+ kplogerror("can't get regs %d\n", pid);
+ return -1;
+ }
+
+ pctx = kpatch_ptrace_find_thread(proc, pid, regs.pc);
+
+ if (pctx == NULL) {
+ /* We either don't know anything about this thread or
+ * even worse -- we stopped it in the wrong place.
+ * Bail out.
+ */
+ pctx = kpatch_ptrace_find_thread(proc, pid, 0);
+ if (pctx != NULL)
+ pctx->running = 0;
+
+ /* TODO: fix the latter by SINGLESTEPping such a thread with
+ * the original instruction in place */
+ kperr("the thread ran out: %d, pc= %llx, expected = %lx\n", pid,
+ regs.pc, pctx->execute_until);
+ errno = ESRCH;
+ return -1;
+ }
+
+ pctx->running = 0;
+
+ /* Restore thread registers, pctx is now valid */
+ kpdebug("Got thread %d at %llx\n", pctx->pid,
+ regs.pc - BREAK_INSN_LENGTH);
+
+ regs.pc = pctx->execute_until;
+
+ ret = ptrace(PTRACE_SETREGSET, pctx->pid, (void*)NT_PRSTATUS, (void*)&regs_iov);
+ if (ret < 0) {
+ kplogerror("can't set regs - %d\n", pctx->pid);
+ return -1;
+ }
+
+ return 1;
+}
diff --git a/src/arch/x86/arch_ptrace.c b/src/arch/x86/arch_ptrace.c
index e69de29..6e943fd 100644
--- a/src/arch/x86/arch_ptrace.c
+++ b/src/arch/x86/arch_ptrace.c
@@ -0,0 +1,140 @@
+#include <stdlib.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <fcntl.h>
+#include <sys/ptrace.h>
+#include <sys/wait.h>
+#include <asm/unistd.h>
+
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <linux/auxvec.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "include/kpatch_process.h"
+#include "include/kpatch_common.h"
+#include "include/kpatch_ptrace.h"
+#include "include/kpatch_log.h"
+
+#include <gelf.h>
+
+int kpatch_arch_ptrace_waitpid(kpatch_process_t *proc,
+ struct timespec *timeout,
+ const sigset_t *sigset)
+{
+ struct kpatch_ptrace_ctx *pctx;
+ siginfo_t siginfo;
+ int ret, status;
+ pid_t pid;
+ struct user_regs_struct regs;
+
+ /* Immediately reap one attached thread */
+ pid = waitpid(-1, &status, __WALL | WNOHANG);
+
+ if (pid < 0) {
+ kplogerror("can't wait for tracees\n");
+ return -1;
+ }
+
+ /* There is none ready, wait for notification via signal */
+ if (pid == 0) {
+ ret = sigtimedwait(sigset, &siginfo, timeout);
+ if (ret == -1 && errno == EAGAIN) {
+ /* We have timeouted */
+ return -1;
+ }
+
+ if (ret == -1 && errno == EINVAL) {
+ kperr("invalid timeout\n");
+ return -1;
+ }
+
+ /* We have got EINTR and must restart */
+ if (ret == -1 && errno == EINTR)
+ return 0;
+
+ /**
+ * Kernel stacks signals that follow too quickly.
+ * Deal with it by waiting for any child, not just
+ * one that is specified in signal
+ */
+ pid = waitpid(-1, &status, __WALL | WNOHANG);
+
+ if (pid == 0) {
+ kperr("missing waitpid for %d\n", siginfo.si_pid);
+ return 0;
+ }
+
+ if (pid < 0) {
+ kplogerror("can't wait for tracee %d\n", siginfo.si_pid);
+ return -1;
+ }
+ }
+
+ if (!WIFSTOPPED(status) && WIFSIGNALED(status)) {
+ /* Continue, resending the signal */
+ ret = ptrace(PTRACE_CONT, pid, NULL,
+ (void *)(uintptr_t)WTERMSIG(status));
+ if (ret < 0) {
+ kplogerror("can't start tracee %d\n", pid);
+ return -1;
+ }
+ return 0;
+ }
+
+ if (WIFEXITED(status)) {
+ pctx = kpatch_ptrace_find_thread(proc, pid, 0UL);
+ if (pctx == NULL) {
+ kperr("got unexpected child '%d' exit\n", pid);
+ } else {
+ /* It's dead */
+ pctx->pid = pctx->running = 0;
+ }
+ return 1;
+ }
+
+ ret = ptrace(PTRACE_GETREGS, pid, NULL, &regs);
+ if (ret < 0) {
+ kplogerror("can't get regs %d\n", pid);
+ return -1;
+ }
+
+ pctx = kpatch_ptrace_find_thread(proc, pid, regs.rip);
+
+ if (pctx == NULL) {
+ /* We either don't know anything about this thread or
+ * even worse -- we stopped it in the wrong place.
+ * Bail out.
+ */
+ pctx = kpatch_ptrace_find_thread(proc, pid, 0);
+ if (pctx != NULL)
+ pctx->running = 0;
+
+ /* TODO: fix the latter by SINGLESTEPping such a thread with
+ * the original instruction in place */
+ kperr("the thread ran out: %d, rip = %llx, expected = %lx\n", pid,
+ regs.rip, pctx->execute_until);
+ errno = ESRCH;
+ return -1;
+ }
+
+ pctx->running = 0;
+
+ /* Restore thread registers, pctx is now valid */
+ kpdebug("Got thread %d at %llx\n", pctx->pid,
+ regs.rip - BREAK_INSN_LENGTH);
+
+ regs.rip = pctx->execute_until;
+
+ ret = ptrace(PTRACE_SETREGS, pctx->pid, NULL, &regs);
+ if (ret < 0) {
+ kplogerror("can't set regs - %d\n", pctx->pid);
+ return -1;
+ }
+
+ return 1;
+}
diff --git a/src/include/kpatch_ptrace.h b/src/include/kpatch_ptrace.h
index 7557e1f..1c7d33e 100644
--- a/src/include/kpatch_ptrace.h
+++ b/src/include/kpatch_ptrace.h
@@ -102,4 +102,24 @@ kpatch_process_memcpy(kpatch_process_t *proc,
unsigned long dst,
unsigned long src,
size_t size);
+
+#define BREAK_INSN_LENGTH 1
+#define BREAK_INSN {0xcc}
+
+#define SEC_TO_MSEC 1000
+#define MSEC_TO_NSEC 1000000
+
+#define for_each_thread(proc, pctx) \
+ list_for_each_entry(pctx, &proc->ptrace.pctxs, list)
+
+struct kpatch_ptrace_ctx *
+kpatch_ptrace_find_thread(kpatch_process_t *proc,
+ pid_t pid,
+ unsigned long rip);
+
+int
+kpatch_arch_ptrace_waitpid(kpatch_process_t *proc,
+ struct timespec *timeout,
+ const sigset_t *sigset);
+
#endif
diff --git a/src/kpatch_ptrace.c b/src/kpatch_ptrace.c
index 8910aa8..3c57288 100644
--- a/src/kpatch_ptrace.c
+++ b/src/kpatch_ptrace.c
@@ -180,16 +180,8 @@ int kpatch_ptrace_get_entry_point(struct kpatch_ptrace_ctx *pctx,
return entry[0] == AT_ENTRY ? 0 : -1;
}
-#define BREAK_INSN_LENGTH 1
-#define BREAK_INSN {0xcc}
-#define SEC_TO_MSEC 1000
-#define MSEC_TO_NSEC 1000000
-
-#define for_each_thread(proc, pctx) \
- list_for_each_entry(pctx, &proc->ptrace.pctxs, list)
-
-static struct kpatch_ptrace_ctx *
+struct kpatch_ptrace_ctx *
kpatch_ptrace_find_thread(kpatch_process_t *proc,
pid_t pid,
unsigned long rip)
@@ -213,124 +205,6 @@ kpatch_ptrace_find_thread(kpatch_process_t *proc,
return NULL;
}
-static inline int
-kpatch_ptrace_waitpid(kpatch_process_t *proc,
- struct timespec *timeout,
- const sigset_t *sigset)
-{
- struct kpatch_ptrace_ctx *pctx;
- siginfo_t siginfo;
- int ret, status;
- pid_t pid;
- struct user_regs_struct regs;
-
- /* Immediately reap one attached thread */
- pid = waitpid(-1, &status, __WALL | WNOHANG);
-
- if (pid < 0) {
- kplogerror("can't wait for tracees\n");
- return -1;
- }
-
- /* There is none ready, wait for notification via signal */
- if (pid == 0) {
- ret = sigtimedwait(sigset, &siginfo, timeout);
- if (ret == -1 && errno == EAGAIN) {
- /* We have timeouted */
- return -1;
- }
-
- if (ret == -1 && errno == EINVAL) {
- kperr("invalid timeout\n");
- return -1;
- }
-
- /* We have got EINTR and must restart */
- if (ret == -1 && errno == EINTR)
- return 0;
-
- /**
- * Kernel stacks signals that follow too quickly.
- * Deal with it by waiting for any child, not just
- * one that is specified in signal
- */
- pid = waitpid(-1, &status, __WALL | WNOHANG);
-
- if (pid == 0) {
- kperr("missing waitpid for %d\n", siginfo.si_pid);
- return 0;
- }
-
- if (pid < 0) {
- kplogerror("can't wait for tracee %d\n", siginfo.si_pid);
- return -1;
- }
- }
-
- if (!WIFSTOPPED(status) && WIFSIGNALED(status)) {
- /* Continue, resending the signal */
- ret = ptrace(PTRACE_CONT, pid, NULL,
- (void *)(uintptr_t)WTERMSIG(status));
- if (ret < 0) {
- kplogerror("can't start tracee %d\n", pid);
- return -1;
- }
- return 0;
- }
-
- if (WIFEXITED(status)) {
- pctx = kpatch_ptrace_find_thread(proc, pid, 0UL);
- if (pctx == NULL) {
- kperr("got unexpected child '%d' exit\n", pid);
- } else {
- /* It's dead */
- pctx->pid = pctx->running = 0;
- }
- return 1;
- }
-
- ret = ptrace(PTRACE_GETREGS, pid, NULL, &regs);
- if (ret < 0) {
- kplogerror("can't get regs %d\n", pid);
- return -1;
- }
-
- pctx = kpatch_ptrace_find_thread(proc, pid, regs.rip);
-
- if (pctx == NULL) {
- /* We either don't know anything about this thread or
- * even worse -- we stopped it in the wrong place.
- * Bail out.
- */
- pctx = kpatch_ptrace_find_thread(proc, pid, 0);
- if (pctx != NULL)
- pctx->running = 0;
-
- /* TODO: fix the latter by SINGLESTEPping such a thread with
- * the original instruction in place */
- kperr("the thread ran out: %d, rip = %llx, expected = %lx\n", pid,
- regs.rip, pctx->execute_until);
- errno = ESRCH;
- return -1;
- }
-
- pctx->running = 0;
-
- /* Restore thread registers, pctx is now valid */
- kpdebug("Got thread %d at %llx\n", pctx->pid,
- regs.rip - BREAK_INSN_LENGTH);
-
- regs.rip = pctx->execute_until;
-
- ret = ptrace(PTRACE_SETREGS, pctx->pid, NULL, &regs);
- if (ret < 0) {
- kplogerror("can't set regs - %d\n", pctx->pid);
- return -1;
- }
-
- return 1;
-}
-
struct breakpoint {
unsigned long addr;
unsigned char orig_code[BREAK_INSN_LENGTH];
@@ -441,7 +315,7 @@ kpatch_ptrace_execute_until(kpatch_process_t *proc,
break;
}
- rv = kpatch_ptrace_waitpid(proc, &timeout, &sigset);
+ rv = kpatch_arch_ptrace_waitpid(proc, &timeout, &sigset);
if (rv < 0)
break;
--
2.23.0

View File

@ -0,0 +1,137 @@
From 8c0199836e7944569dbbeb5e571d791b8e466275 Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Mon, 12 Oct 2020 16:24:09 +0800
Subject: [PATCH 40/89] kpatch_ptrace: Split function copy_regs
The function copy_regs is arch related, so make two separate
definations in arch/x86/arch_ptrace.c and arch/aarch64/arch_ptrace.c
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
src/arch/aarch64/arch_ptrace.c | 28 ++++++++++++++++++++++++++++
src/arch/x86/arch_ptrace.c | 22 ++++++++++++++++++++++
src/include/kpatch_ptrace.h | 3 +++
src/kpatch_ptrace.c | 22 ----------------------
4 files changed, 53 insertions(+), 22 deletions(-)
diff --git a/src/arch/aarch64/arch_ptrace.c b/src/arch/aarch64/arch_ptrace.c
index fb19e86..0366d4f 100644
--- a/src/arch/aarch64/arch_ptrace.c
+++ b/src/arch/aarch64/arch_ptrace.c
@@ -22,6 +22,34 @@
#include <gelf.h>
+void copy_regs(struct user_regs_struct *dst,
+ struct user_regs_struct *src)
+{
+#define COPY_REG(x) dst->x = src->x
+ COPY_REG(regs[0]);
+ COPY_REG(regs[1]);
+ COPY_REG(regs[2]);
+ COPY_REG(regs[3]);
+ COPY_REG(regs[4]);
+ COPY_REG(regs[5]);
+ COPY_REG(regs[8]);
+ COPY_REG(regs[29]);
+
+ COPY_REG(regs[9]);
+ COPY_REG(regs[10]);
+ COPY_REG(regs[11]);
+ COPY_REG(regs[12]);
+ COPY_REG(regs[13]);
+ COPY_REG(regs[14]);
+ COPY_REG(regs[15]);
+ COPY_REG(regs[16]);
+ COPY_REG(regs[17]);
+ COPY_REG(regs[18]);
+ COPY_REG(regs[19]);
+ COPY_REG(regs[20]);
+#undef COPY_REG
+}
+
int
kpatch_arch_ptrace_waitpid(kpatch_process_t *proc,
struct timespec *timeout,
diff --git a/src/arch/x86/arch_ptrace.c b/src/arch/x86/arch_ptrace.c
index 6e943fd..fa23757 100644
--- a/src/arch/x86/arch_ptrace.c
+++ b/src/arch/x86/arch_ptrace.c
@@ -22,6 +22,28 @@
#include <gelf.h>
+void copy_regs(struct user_regs_struct *dst,
+ struct user_regs_struct *src)
+{
+#define COPY_REG(x) dst->x = src->x
+ COPY_REG(r15);
+ COPY_REG(r14);
+ COPY_REG(r13);
+ COPY_REG(r12);
+ COPY_REG(rbp);
+ COPY_REG(rbx);
+ COPY_REG(r11);
+ COPY_REG(r10);
+ COPY_REG(r9);
+ COPY_REG(r8);
+ COPY_REG(rax);
+ COPY_REG(rcx);
+ COPY_REG(rdx);
+ COPY_REG(rsi);
+ COPY_REG(rdi);
+#undef COPY_REG
+}
+
int kpatch_arch_ptrace_waitpid(kpatch_process_t *proc,
struct timespec *timeout,
const sigset_t *sigset)
diff --git a/src/include/kpatch_ptrace.h b/src/include/kpatch_ptrace.h
index 1c7d33e..e434d68 100644
--- a/src/include/kpatch_ptrace.h
+++ b/src/include/kpatch_ptrace.h
@@ -122,4 +122,7 @@ kpatch_arch_ptrace_waitpid(kpatch_process_t *proc,
struct timespec *timeout,
const sigset_t *sigset);
+void copy_regs(struct user_regs_struct *dst,
+ struct user_regs_struct *src);
+
#endif
diff --git a/src/kpatch_ptrace.c b/src/kpatch_ptrace.c
index 3c57288..180bbaa 100644
--- a/src/kpatch_ptrace.c
+++ b/src/kpatch_ptrace.c
@@ -413,28 +413,6 @@ poke_back:
return ret;
}
-static void copy_regs(struct user_regs_struct *dst,
- struct user_regs_struct *src)
-{
-#define COPY_REG(x) dst->x = src->x
- COPY_REG(r15);
- COPY_REG(r14);
- COPY_REG(r13);
- COPY_REG(r12);
- COPY_REG(rbp);
- COPY_REG(rbx);
- COPY_REG(r11);
- COPY_REG(r10);
- COPY_REG(r9);
- COPY_REG(r8);
- COPY_REG(rax);
- COPY_REG(rcx);
- COPY_REG(rdx);
- COPY_REG(rsi);
- COPY_REG(rdi);
-#undef COPY_REG
-}
-
static
int
kpatch_execute_remote_func(struct kpatch_ptrace_ctx *pctx,
--
2.23.0

View File

@ -0,0 +1,328 @@
From e312d7a74924d6e3880fa27adb4bcd04c8c25983 Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Mon, 12 Oct 2020 16:30:58 +0800
Subject: [PATCH 41/89] kpatch_ptrace: Split function
kpatch_execute_remote_func
The function kpatch_execute_remote_func is arch related, first
rename it with kpatch_arch_execute_remote_func, and the make separate
definations in arch/x86/arch_ptrace.c and arch/aarch64/arch_ptrace.c
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
src/arch/aarch64/arch_ptrace.c | 87 ++++++++++++++++++++++++++++++++++
src/arch/x86/arch_ptrace.c | 79 ++++++++++++++++++++++++++++++
src/include/kpatch_ptrace.h | 9 ++++
src/kpatch_ptrace.c | 82 +-------------------------------
4 files changed, 176 insertions(+), 81 deletions(-)
diff --git a/src/arch/aarch64/arch_ptrace.c b/src/arch/aarch64/arch_ptrace.c
index 0366d4f..821b4e8 100644
--- a/src/arch/aarch64/arch_ptrace.c
+++ b/src/arch/aarch64/arch_ptrace.c
@@ -22,6 +22,93 @@
#include <gelf.h>
+int
+kpatch_arch_execute_remote_func(struct kpatch_ptrace_ctx *pctx,
+ const unsigned char *code,
+ size_t codelen,
+ struct user_regs_struct *pregs,
+ int (*func)(struct kpatch_ptrace_ctx *pctx,
+ void *data),
+ void *data)
+{
+ struct user_regs_struct orig_regs, regs;
+ struct iovec orig_regs_iov, regs_iov;
+
+ orig_regs_iov.iov_base = &orig_regs;
+ orig_regs_iov.iov_len = sizeof(orig_regs);
+ regs_iov.iov_base = &regs;
+ regs_iov.iov_len = sizeof(regs);
+
+ unsigned char orig_code[codelen];
+ int ret;
+ kpatch_process_t *proc = pctx->proc;
+ unsigned long libc_base = proc->libc_base;
+
+
+ ret = ptrace(PTRACE_GETREGSET, pctx->pid, (void*)NT_PRSTATUS, (void*)&orig_regs_iov);
+ if (ret < 0) {
+ kplogerror("can't get regs - %d\n", pctx->pid);
+ return -1;
+ }
+ ret = kpatch_process_mem_read(
+ proc,
+ libc_base,
+ (unsigned long *)orig_code,
+ codelen);
+ if (ret < 0) {
+ kplogerror("can't peek original code - %d\n", pctx->pid);
+ return -1;
+ }
+ ret = kpatch_process_mem_write(
+ proc,
+ (unsigned long *)code,
+ libc_base,
+ codelen);
+ if (ret < 0) {
+ kplogerror("can't poke syscall code - %d\n", pctx->pid);
+ goto poke_back;
+ }
+
+ regs = orig_regs;
+ regs.pc = libc_base;
+
+ copy_regs(&regs, pregs);
+
+ ret = ptrace(PTRACE_SETREGSET, pctx->pid, (void*)NT_PRSTATUS, (void*)&regs_iov);
+ if (ret < 0) {
+ kplogerror("can't set regs - %d\n", pctx->pid);
+ goto poke_back;
+ }
+
+ ret = func(pctx, data);
+ if (ret < 0) {
+ kplogerror("failed call to func\n");
+ goto poke_back;
+ }
+
+ ret = ptrace(PTRACE_GETREGSET, pctx->pid, (void*)NT_PRSTATUS, (void*)&regs_iov);
+ if (ret < 0) {
+ kplogerror("can't get updated regs - %d\n", pctx->pid);
+ goto poke_back;
+ }
+
+ ret = ptrace(PTRACE_SETREGSET, pctx->pid, (void*)NT_PRSTATUS, (void*)&orig_regs_iov);
+ if (ret < 0) {
+ kplogerror("can't restore regs - %d\n", pctx->pid);
+ goto poke_back;
+ }
+
+ *pregs = regs;
+
+poke_back:
+ kpatch_process_mem_write(
+ proc,
+ (unsigned long *)orig_code,
+ libc_base,
+ codelen);
+ return ret;
+}
+
void copy_regs(struct user_regs_struct *dst,
struct user_regs_struct *src)
{
diff --git a/src/arch/x86/arch_ptrace.c b/src/arch/x86/arch_ptrace.c
index fa23757..9239f52 100644
--- a/src/arch/x86/arch_ptrace.c
+++ b/src/arch/x86/arch_ptrace.c
@@ -22,6 +22,85 @@
#include <gelf.h>
+int
+kpatch_arch_execute_remote_func(struct kpatch_ptrace_ctx *pctx,
+ const unsigned char *code,
+ size_t codelen,
+ struct user_regs_struct *pregs,
+ int (*func)(struct kpatch_ptrace_ctx *pctx,
+ void *data),
+ void *data)
+{
+ struct user_regs_struct orig_regs, regs;
+ unsigned char orig_code[codelen];
+ int ret;
+ kpatch_process_t *proc = pctx->proc;
+ unsigned long libc_base = proc->libc_base;
+
+ ret = ptrace(PTRACE_GETREGS, pctx->pid, NULL, &orig_regs);
+ if (ret < 0) {
+ kplogerror("can't get regs - %d\n", pctx->pid);
+ return -1;
+ }
+ ret = kpatch_process_mem_read(
+ proc,
+ libc_base,
+ (unsigned long *)orig_code,
+ codelen);
+ if (ret < 0) {
+ kplogerror("can't peek original code - %d\n", pctx->pid);
+ return -1;
+ }
+ ret = kpatch_process_mem_write(
+ proc,
+ (unsigned long *)code,
+ libc_base,
+ codelen);
+ if (ret < 0) {
+ kplogerror("can't poke syscall code - %d\n", pctx->pid);
+ goto poke_back;
+ }
+
+ regs = orig_regs;
+ regs.rip = libc_base;
+
+ copy_regs(&regs, pregs);
+
+ ret = ptrace(PTRACE_SETREGS, pctx->pid, NULL, &regs);
+ if (ret < 0) {
+ kplogerror("can't set regs - %d\n", pctx->pid);
+ goto poke_back;
+ }
+
+ ret = func(pctx, data);
+ if (ret < 0) {
+ kplogerror("failed call to func\n");
+ goto poke_back;
+ }
+
+ ret = ptrace(PTRACE_GETREGS, pctx->pid, NULL, &regs);
+ if (ret < 0) {
+ kplogerror("can't get updated regs - %d\n", pctx->pid);
+ goto poke_back;
+ }
+
+ ret = ptrace(PTRACE_SETREGS, pctx->pid, NULL, &orig_regs);
+ if (ret < 0) {
+ kplogerror("can't restore regs - %d\n", pctx->pid);
+ goto poke_back;
+ }
+
+ *pregs = regs;
+
+poke_back:
+ kpatch_process_mem_write(
+ proc,
+ (unsigned long *)orig_code,
+ libc_base,
+ codelen);
+ return ret;
+}
+
void copy_regs(struct user_regs_struct *dst,
struct user_regs_struct *src)
{
diff --git a/src/include/kpatch_ptrace.h b/src/include/kpatch_ptrace.h
index e434d68..f35aabd 100644
--- a/src/include/kpatch_ptrace.h
+++ b/src/include/kpatch_ptrace.h
@@ -125,4 +125,13 @@ kpatch_arch_ptrace_waitpid(kpatch_process_t *proc,
void copy_regs(struct user_regs_struct *dst,
struct user_regs_struct *src);
+int
+kpatch_arch_execute_remote_func(struct kpatch_ptrace_ctx *pctx,
+ const unsigned char *code,
+ size_t codelen,
+ struct user_regs_struct *pregs,
+ int (*func)(struct kpatch_ptrace_ctx *pctx,
+ void *data),
+ void *data);
+
#endif
diff --git a/src/kpatch_ptrace.c b/src/kpatch_ptrace.c
index 180bbaa..9056815 100644
--- a/src/kpatch_ptrace.c
+++ b/src/kpatch_ptrace.c
@@ -413,86 +413,6 @@ poke_back:
return ret;
}
-static
-int
-kpatch_execute_remote_func(struct kpatch_ptrace_ctx *pctx,
- const unsigned char *code,
- size_t codelen,
- struct user_regs_struct *pregs,
- int (*func)(struct kpatch_ptrace_ctx *pctx,
- void *data),
- void *data)
-{
- struct user_regs_struct orig_regs, regs;
- unsigned char orig_code[codelen];
- int ret;
- kpatch_process_t *proc = pctx->proc;
- unsigned long libc_base = proc->libc_base;
-
- ret = ptrace(PTRACE_GETREGS, pctx->pid, NULL, &orig_regs);
- if (ret < 0) {
- kplogerror("can't get regs - %d\n", pctx->pid);
- return -1;
- }
- ret = kpatch_process_mem_read(
- proc,
- libc_base,
- (unsigned long *)orig_code,
- codelen);
- if (ret < 0) {
- kplogerror("can't peek original code - %d\n", pctx->pid);
- return -1;
- }
- ret = kpatch_process_mem_write(
- proc,
- (unsigned long *)code,
- libc_base,
- codelen);
- if (ret < 0) {
- kplogerror("can't poke syscall code - %d\n", pctx->pid);
- goto poke_back;
- }
-
- regs = orig_regs;
- regs.rip = libc_base;
-
- copy_regs(&regs, pregs);
-
- ret = ptrace(PTRACE_SETREGS, pctx->pid, NULL, &regs);
- if (ret < 0) {
- kplogerror("can't set regs - %d\n", pctx->pid);
- goto poke_back;
- }
-
- ret = func(pctx, data);
- if (ret < 0) {
- kplogerror("failed call to func\n");
- goto poke_back;
- }
-
- ret = ptrace(PTRACE_GETREGS, pctx->pid, NULL, &regs);
- if (ret < 0) {
- kplogerror("can't get updated regs - %d\n", pctx->pid);
- goto poke_back;
- }
-
- ret = ptrace(PTRACE_SETREGS, pctx->pid, NULL, &orig_regs);
- if (ret < 0) {
- kplogerror("can't restore regs - %d\n", pctx->pid);
- goto poke_back;
- }
-
- *pregs = regs;
-
-poke_back:
- kpatch_process_mem_write(
- proc,
- (unsigned long *)orig_code,
- libc_base,
- codelen);
- return ret;
-}
-
static int
wait_for_stop(struct kpatch_ptrace_ctx *pctx,
void *data)
@@ -592,7 +512,7 @@ kpatch_execute_remote(struct kpatch_ptrace_ctx *pctx,
size_t codelen,
struct user_regs_struct *pregs)
{
- return kpatch_execute_remote_func(pctx,
+ return kpatch_arch_execute_remote_func(pctx,
code,
codelen,
pregs,
--
2.23.0

View File

@ -0,0 +1,146 @@
From aeeded44db6e705717bd24f3ffbbe878af47833b Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Mon, 12 Oct 2020 16:40:42 +0800
Subject: [PATCH 42/89] kpatch_ptrace: Split function
kpatch_ptrace_resolve_ifunc
The function kpatch_ptrace_resolve_ifunc is arch related, first
rename it with kpatch_arch_ptrace_resolve_ifunc, and then make
separate definations in arch/x86/arch_ptrace.c and arch/aarch64/arch_ptrace.c
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
src/arch/aarch64/arch_ptrace.c | 20 ++++++++++++++++++++
src/arch/x86/arch_ptrace.c | 21 +++++++++++++++++++++
src/include/kpatch_ptrace.h | 2 +-
src/kpatch_elf.c | 4 ++--
src/kpatch_ptrace.c | 21 ---------------------
5 files changed, 44 insertions(+), 24 deletions(-)
diff --git a/src/arch/aarch64/arch_ptrace.c b/src/arch/aarch64/arch_ptrace.c
index 821b4e8..4dee0e5 100644
--- a/src/arch/aarch64/arch_ptrace.c
+++ b/src/arch/aarch64/arch_ptrace.c
@@ -22,6 +22,26 @@
#include <gelf.h>
+int kpatch_arch_ptrace_resolve_ifunc(struct kpatch_ptrace_ctx *pctx,
+ unsigned long *addr)
+{
+ struct user_regs_struct regs;
+
+ unsigned char callrax[] = {
+ 0x00, 0x01, 0x3f, 0xd6, // blr x8
+ 0xa0, 0x00, 0x20, 0xd4, // brk #5
+ };
+ int ret;
+ kpdebug("Executing callrax %lx (pid %d)\n", *addr, pctx->pid);
+ regs.regs[8] = *addr;
+
+ ret = kpatch_execute_remote(pctx, callrax, sizeof(callrax), &regs);
+ if (ret == 0)
+ *addr = regs.regs[0];
+
+ return ret;
+}
+
int
kpatch_arch_execute_remote_func(struct kpatch_ptrace_ctx *pctx,
const unsigned char *code,
diff --git a/src/arch/x86/arch_ptrace.c b/src/arch/x86/arch_ptrace.c
index 9239f52..3d49638 100644
--- a/src/arch/x86/arch_ptrace.c
+++ b/src/arch/x86/arch_ptrace.c
@@ -22,6 +22,27 @@
#include <gelf.h>
+int kpatch_arch_ptrace_resolve_ifunc(struct kpatch_ptrace_ctx *pctx,
+ unsigned long *addr)
+{
+ struct user_regs_struct regs;
+
+ unsigned char callrax[] = {
+ 0xff, 0xd0, /* call *%rax */
+ 0xcc, /* int3 */
+ };
+ int ret;
+
+ kpdebug("Executing callrax %lx (pid %d)\n", *addr, pctx->pid);
+ regs.rax = *addr;
+
+ ret = kpatch_execute_remote(pctx, callrax, sizeof(callrax), &regs);
+ if (ret == 0)
+ *addr = regs.rax;
+
+ return ret;
+}
+
int
kpatch_arch_execute_remote_func(struct kpatch_ptrace_ctx *pctx,
const unsigned char *code,
diff --git a/src/include/kpatch_ptrace.h b/src/include/kpatch_ptrace.h
index f35aabd..19a1b2c 100644
--- a/src/include/kpatch_ptrace.h
+++ b/src/include/kpatch_ptrace.h
@@ -70,7 +70,7 @@ int kpatch_execute_remote(struct kpatch_ptrace_ctx *pctx,
size_t codelen,
struct user_regs_struct *pregs);
-int kpatch_ptrace_resolve_ifunc(struct kpatch_ptrace_ctx *pctx,
+int kpatch_arch_ptrace_resolve_ifunc(struct kpatch_ptrace_ctx *pctx,
unsigned long *addr);
unsigned long
kpatch_mmap_remote(struct kpatch_ptrace_ctx *pctx,
diff --git a/src/kpatch_elf.c b/src/kpatch_elf.c
index 5506292..d443001 100644
--- a/src/kpatch_elf.c
+++ b/src/kpatch_elf.c
@@ -677,8 +677,8 @@ kpatch_resolve_undefined(struct object_file *obj,
addr = vaddr2addr(o, addr);
if (type == STT_GNU_IFUNC)
- if (kpatch_ptrace_resolve_ifunc(proc2pctx(obj->proc), &addr) < 0)
- kpfatalerror("kpatch_ptrace_resolve_ifunc failed\n");
+ if (kpatch_arch_ptrace_resolve_ifunc(proc2pctx(obj->proc), &addr) < 0)
+ kpfatalerror("kpatch_arch_ptrace_resolve_ifunc failed\n");
break;
}
diff --git a/src/kpatch_ptrace.c b/src/kpatch_ptrace.c
index 9056815..cd961e1 100644
--- a/src/kpatch_ptrace.c
+++ b/src/kpatch_ptrace.c
@@ -672,27 +672,6 @@ static int kpatch_syscall_remote(struct kpatch_ptrace_ctx *pctx, int nr,
return ret;
}
-int kpatch_ptrace_resolve_ifunc(struct kpatch_ptrace_ctx *pctx,
- unsigned long *addr)
-{
- struct user_regs_struct regs;
-
- unsigned char callrax[] = {
- 0xff, 0xd0, /* call *%rax */
- 0xcc, /* int3 */
- };
- int ret;
-
- kpdebug("Executing callrax %lx (pid %d)\n", *addr, pctx->pid);
- regs.rax = *addr;
-
- ret = kpatch_execute_remote(pctx, callrax, sizeof(callrax), &regs);
- if (ret == 0)
- *addr = regs.rax;
-
- return ret;
-}
-
#define MAX_ERRNO 4095
unsigned long
kpatch_mmap_remote(struct kpatch_ptrace_ctx *pctx,
--
2.23.0

View File

@ -0,0 +1,213 @@
From aa39ba7326c13546f68b51d95bf55004437c3110 Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Mon, 12 Oct 2020 16:49:15 +0800
Subject: [PATCH 43/89] kpatch_ptrace: Split function kpatch_arch_prctl_remote
The function kpatch_arch_prctl_remote is arch related, let's make two
separate definations in arch/x86/arch_ptrace.c and arch/aarch64/arch_ptrace.c
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
src/arch/aarch64/arch_ptrace.c | 49 ++++++++++++++++++++++++++++++++++
src/arch/x86/arch_ptrace.c | 45 +++++++++++++++++++++++++++++++
src/include/kpatch_ptrace.h | 2 ++
src/kpatch_ptrace.c | 46 -------------------------------
4 files changed, 96 insertions(+), 46 deletions(-)
diff --git a/src/arch/aarch64/arch_ptrace.c b/src/arch/aarch64/arch_ptrace.c
index 4dee0e5..735927e 100644
--- a/src/arch/aarch64/arch_ptrace.c
+++ b/src/arch/aarch64/arch_ptrace.c
@@ -22,6 +22,55 @@
#include <gelf.h>
+int kpatch_arch_prctl_remote(struct kpatch_ptrace_ctx *pctx, int code, unsigned long *addr)
+{
+ struct user_regs_struct regs;
+ struct iovec regs_iov;
+ regs_iov.iov_base = &regs;
+ regs_iov.iov_len = sizeof(regs);
+
+ unsigned long res, sp;
+ int ret;
+
+ kpdebug("arch_prctl_remote: %d, %p\n", code, addr);
+ ret = ptrace(PTRACE_GETREGSET, pctx->pid, (void*)NT_PRSTATUS, (void*)&regs_iov);
+ if (ret < 0) {
+ kpdebug("FAIL. Can't get regs - %s\n", strerror(errno));
+ return -1;
+ }
+ ret = kpatch_process_mem_read(pctx->proc,
+ regs.sp,
+ &sp,
+ sizeof(sp));
+ if (ret < 0) {
+ kplogerror("can't peek original stack data\n");
+ return -1;
+ }
+ //ret = kpatch_syscall_remote(pctx, __NR_arch_prctl, code, regs.sp, 0, 0, 0, 0, &res);
+ if (ret < 0)
+ goto poke;
+ if (ret == 0 && res >= (unsigned long)-MAX_ERRNO) {
+ errno = -(long)res;
+ ret = -1;
+ goto poke;
+ }
+ ret = kpatch_process_mem_read(pctx->proc,
+ regs.sp,
+ &res,
+ sizeof(res));
+ if (ret < 0)
+ kplogerror("can't peek new stack data\n");
+
+poke:
+ if (kpatch_process_mem_write(pctx->proc,
+ &sp,
+ regs.sp,
+ sizeof(sp)))
+ kplogerror("can't poke orig stack data\n");
+ *addr = res;
+ return ret;
+}
+
int kpatch_arch_ptrace_resolve_ifunc(struct kpatch_ptrace_ctx *pctx,
unsigned long *addr)
{
diff --git a/src/arch/x86/arch_ptrace.c b/src/arch/x86/arch_ptrace.c
index 3d49638..5f1e703 100644
--- a/src/arch/x86/arch_ptrace.c
+++ b/src/arch/x86/arch_ptrace.c
@@ -22,6 +22,51 @@
#include <gelf.h>
+int kpatch_arch_prctl_remote(struct kpatch_ptrace_ctx *pctx, int code, unsigned long *addr)
+{
+ struct user_regs_struct regs;
+ unsigned long res, rsp;
+ int ret;
+
+ kpdebug("arch_prctl_remote: %d, %p\n", code, addr);
+ ret = ptrace(PTRACE_GETREGS, pctx->pid, NULL, &regs);
+ if (ret < 0) {
+ kpdebug("FAIL. Can't get regs - %s\n", strerror(errno));
+ return -1;
+ }
+ ret = kpatch_process_mem_read(pctx->proc,
+ regs.rsp,
+ &rsp,
+ sizeof(rsp));
+ if (ret < 0) {
+ kplogerror("can't peek original stack data\n");
+ return -1;
+ }
+ ret = kpatch_syscall_remote(pctx, __NR_arch_prctl, code, regs.rsp, 0, 0, 0, 0, &res);
+ if (ret < 0)
+ goto poke;
+ if (ret == 0 && res >= (unsigned long)-MAX_ERRNO) {
+ errno = -(long)res;
+ ret = -1;
+ goto poke;
+ }
+ ret = kpatch_process_mem_read(pctx->proc,
+ regs.rsp,
+ &res,
+ sizeof(res));
+ if (ret < 0)
+ kplogerror("can't peek new stack data\n");
+
+poke:
+ if (kpatch_process_mem_write(pctx->proc,
+ &rsp,
+ regs.rsp,
+ sizeof(rsp)))
+ kplogerror("can't poke orig stack data\n");
+ *addr = res;
+ return ret;
+}
+
int kpatch_arch_ptrace_resolve_ifunc(struct kpatch_ptrace_ctx *pctx,
unsigned long *addr)
{
diff --git a/src/include/kpatch_ptrace.h b/src/include/kpatch_ptrace.h
index 19a1b2c..ddaa9e6 100644
--- a/src/include/kpatch_ptrace.h
+++ b/src/include/kpatch_ptrace.h
@@ -84,6 +84,8 @@ int
kpatch_munmap_remote(struct kpatch_ptrace_ctx *pctx,
unsigned long addr,
size_t length);
+
+#define MAX_ERRNO 4095
int kpatch_arch_prctl_remote(struct kpatch_ptrace_ctx *pctx, int code, unsigned long *addr);
int
diff --git a/src/kpatch_ptrace.c b/src/kpatch_ptrace.c
index cd961e1..4d2223e 100644
--- a/src/kpatch_ptrace.c
+++ b/src/kpatch_ptrace.c
@@ -672,7 +672,6 @@ static int kpatch_syscall_remote(struct kpatch_ptrace_ctx *pctx, int nr,
return ret;
}
-#define MAX_ERRNO 4095
unsigned long
kpatch_mmap_remote(struct kpatch_ptrace_ctx *pctx,
unsigned long addr,
@@ -717,51 +716,6 @@ int kpatch_munmap_remote(struct kpatch_ptrace_ctx *pctx,
return 0;
}
-int kpatch_arch_prctl_remote(struct kpatch_ptrace_ctx *pctx, int code, unsigned long *addr)
-{
- struct user_regs_struct regs;
- unsigned long res, rsp;
- int ret;
-
- kpdebug("arch_prctl_remote: %d, %p\n", code, addr);
- ret = ptrace(PTRACE_GETREGS, pctx->pid, NULL, &regs);
- if (ret < 0) {
- kpdebug("FAIL. Can't get regs - %s\n", strerror(errno));
- return -1;
- }
- ret = kpatch_process_mem_read(pctx->proc,
- regs.rsp,
- &rsp,
- sizeof(rsp));
- if (ret < 0) {
- kplogerror("can't peek original stack data\n");
- return -1;
- }
- ret = kpatch_syscall_remote(pctx, __NR_arch_prctl, code, regs.rsp, 0, 0, 0, 0, &res);
- if (ret < 0)
- goto poke;
- if (ret == 0 && res >= (unsigned long)-MAX_ERRNO) {
- errno = -(long)res;
- ret = -1;
- goto poke;
- }
- ret = kpatch_process_mem_read(pctx->proc,
- regs.rsp,
- &res,
- sizeof(res));
- if (ret < 0)
- kplogerror("can't peek new stack data\n");
-
-poke:
- if (kpatch_process_mem_write(pctx->proc,
- &rsp,
- regs.rsp,
- sizeof(rsp)))
- kplogerror("can't poke orig stack data\n");
- *addr = res;
- return ret;
-}
-
int
kpatch_remote_write(struct kpatch_ptrace_ctx *pctx,
unsigned long dst,
--
2.23.0

View File

@ -0,0 +1,191 @@
From 335b90a54e629e0dc2f954ec2c3bd0b7e149aeec Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Mon, 12 Oct 2020 16:55:27 +0800
Subject: [PATCH 44/89] kpatch_ptrace: Split function kpatch_syscall_remote
The function kpatch_syscall_remote is arch related, first
rename it with kpatch_arch_syscall_remote, and then make
separate definations in arch/x86/arch_ptrace.c and arch/aarch64/arch_ptrace.c
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
src/arch/aarch64/arch_ptrace.c | 31 ++++++++++++++++++++++++++++++-
src/arch/x86/arch_ptrace.c | 31 ++++++++++++++++++++++++++++++-
src/include/kpatch_ptrace.h | 5 +++++
src/kpatch_ptrace.c | 33 ++-------------------------------
4 files changed, 67 insertions(+), 33 deletions(-)
diff --git a/src/arch/aarch64/arch_ptrace.c b/src/arch/aarch64/arch_ptrace.c
index 735927e..a444285 100644
--- a/src/arch/aarch64/arch_ptrace.c
+++ b/src/arch/aarch64/arch_ptrace.c
@@ -22,6 +22,35 @@
#include <gelf.h>
+int kpatch_arch_syscall_remote(struct kpatch_ptrace_ctx *pctx, int nr,
+ unsigned long arg1, unsigned long arg2, unsigned long arg3,
+ unsigned long arg4, unsigned long arg5, unsigned long arg6,
+ unsigned long *res)
+{
+ struct user_regs_struct regs;
+
+ unsigned char syscall[] = {
+ 0x01, 0x00, 0x00, 0xd4, //0xd4000001 svc #0 = syscall
+ 0xa0, 0x00, 0x20, 0xd4, //0xd42000a0 brk #5 = int3
+ };
+ int ret;
+
+ kpdebug("Executing syscall %d (pid %d)...\n", nr, pctx->pid);
+ regs.regs[8] = (unsigned long)nr;
+ regs.regs[0] = arg1;
+ regs.regs[1] = arg2;
+ regs.regs[2] = arg3;
+ regs.regs[3] = arg4;
+ regs.regs[4] = arg5;
+ regs.regs[5] = arg6;
+
+ ret = kpatch_execute_remote(pctx, syscall, sizeof(syscall), &regs);
+ if (ret == 0)
+ *res = regs.regs[0];
+
+ return ret;
+}
+
int kpatch_arch_prctl_remote(struct kpatch_ptrace_ctx *pctx, int code, unsigned long *addr)
{
struct user_regs_struct regs;
@@ -46,7 +75,7 @@ int kpatch_arch_prctl_remote(struct kpatch_ptrace_ctx *pctx, int code, unsigned
kplogerror("can't peek original stack data\n");
return -1;
}
- //ret = kpatch_syscall_remote(pctx, __NR_arch_prctl, code, regs.sp, 0, 0, 0, 0, &res);
+ //ret = kpatch_arch_syscall_remote(pctx, __NR_arch_prctl, code, regs.sp, 0, 0, 0, 0, &res);
if (ret < 0)
goto poke;
if (ret == 0 && res >= (unsigned long)-MAX_ERRNO) {
diff --git a/src/arch/x86/arch_ptrace.c b/src/arch/x86/arch_ptrace.c
index 5f1e703..10127a3 100644
--- a/src/arch/x86/arch_ptrace.c
+++ b/src/arch/x86/arch_ptrace.c
@@ -22,6 +22,35 @@
#include <gelf.h>
+int kpatch_arch_syscall_remote(struct kpatch_ptrace_ctx *pctx, int nr,
+ unsigned long arg1, unsigned long arg2, unsigned long arg3,
+ unsigned long arg4, unsigned long arg5, unsigned long arg6,
+ unsigned long *res)
+{
+ struct user_regs_struct regs;
+
+ unsigned char syscall[] = {
+ 0x0f, 0x05, /* syscall */
+ 0xcc, /* int3 */
+ };
+ int ret;
+
+ kpdebug("Executing syscall %d (pid %d)...\n", nr, pctx->pid);
+ regs.rax = (unsigned long)nr;
+ regs.rdi = arg1;
+ regs.rsi = arg2;
+ regs.rdx = arg3;
+ regs.r10 = arg4;
+ regs.r8 = arg5;
+ regs.r9 = arg6;
+
+ ret = kpatch_execute_remote(pctx, syscall, sizeof(syscall), &regs);
+ if (ret == 0)
+ *res = regs.rax;
+
+ return ret;
+}
+
int kpatch_arch_prctl_remote(struct kpatch_ptrace_ctx *pctx, int code, unsigned long *addr)
{
struct user_regs_struct regs;
@@ -42,7 +71,7 @@ int kpatch_arch_prctl_remote(struct kpatch_ptrace_ctx *pctx, int code, unsigned
kplogerror("can't peek original stack data\n");
return -1;
}
- ret = kpatch_syscall_remote(pctx, __NR_arch_prctl, code, regs.rsp, 0, 0, 0, 0, &res);
+ ret = kpatch_arch_syscall_remote(pctx, __NR_arch_prctl, code, regs.rsp, 0, 0, 0, 0, &res);
if (ret < 0)
goto poke;
if (ret == 0 && res >= (unsigned long)-MAX_ERRNO) {
diff --git a/src/include/kpatch_ptrace.h b/src/include/kpatch_ptrace.h
index ddaa9e6..c8cfd41 100644
--- a/src/include/kpatch_ptrace.h
+++ b/src/include/kpatch_ptrace.h
@@ -136,4 +136,9 @@ kpatch_arch_execute_remote_func(struct kpatch_ptrace_ctx *pctx,
void *data),
void *data);
+int kpatch_arch_syscall_remote(struct kpatch_ptrace_ctx *pctx, int nr,
+ unsigned long arg1, unsigned long arg2, unsigned long arg3,
+ unsigned long arg4, unsigned long arg5, unsigned long arg6,
+ unsigned long *res);
+
#endif
diff --git a/src/kpatch_ptrace.c b/src/kpatch_ptrace.c
index 4d2223e..057b08a 100644
--- a/src/kpatch_ptrace.c
+++ b/src/kpatch_ptrace.c
@@ -643,35 +643,6 @@ kpatch_ptrace_kickstart_execve_wrapper(kpatch_process_t *proc)
return 0;
}
-static int kpatch_syscall_remote(struct kpatch_ptrace_ctx *pctx, int nr,
- unsigned long arg1, unsigned long arg2, unsigned long arg3,
- unsigned long arg4, unsigned long arg5, unsigned long arg6,
- unsigned long *res)
-{
- struct user_regs_struct regs;
-
- unsigned char syscall[] = {
- 0x0f, 0x05, /* syscall */
- 0xcc, /* int3 */
- };
- int ret;
-
- kpdebug("Executing syscall %d (pid %d)...\n", nr, pctx->pid);
- regs.rax = (unsigned long)nr;
- regs.rdi = arg1;
- regs.rsi = arg2;
- regs.rdx = arg3;
- regs.r10 = arg4;
- regs.r8 = arg5;
- regs.r9 = arg6;
-
- ret = kpatch_execute_remote(pctx, syscall, sizeof(syscall), &regs);
- if (ret == 0)
- *res = regs.rax;
-
- return ret;
-}
-
unsigned long
kpatch_mmap_remote(struct kpatch_ptrace_ctx *pctx,
unsigned long addr,
@@ -686,7 +657,7 @@ kpatch_mmap_remote(struct kpatch_ptrace_ctx *pctx,
kpdebug("mmap_remote: 0x%lx+%lx, %x, %x, %d, %lx\n", addr, length,
prot, flags, fd, offset);
- ret = kpatch_syscall_remote(pctx, __NR_mmap, (unsigned long)addr,
+ ret = kpatch_arch_syscall_remote(pctx, __NR_mmap, (unsigned long)addr,
length, prot, flags, fd, offset, &res);
if (ret < 0)
return 0;
@@ -705,7 +676,7 @@ int kpatch_munmap_remote(struct kpatch_ptrace_ctx *pctx,
unsigned long res;
kpdebug("munmap_remote: 0x%lx+%lx\n", addr, length);
- ret = kpatch_syscall_remote(pctx, __NR_munmap, (unsigned long)addr,
+ ret = kpatch_arch_syscall_remote(pctx, __NR_munmap, (unsigned long)addr,
length, 0, 0, 0, 0, &res);
if (ret < 0)
return -1;
--
2.23.0

View File

@ -0,0 +1,239 @@
From 05b64620354b8f8bd36c3f782eff9cd145f57fea Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Tue, 13 Oct 2020 11:10:11 +0800
Subject: [PATCH 45/89] kpatch_ptrace: Split function wait_for_mmap
The function wait_for_mmap is arch related, so make two separate
definations in arch/x86/arch_ptrace.c and arch/aarch64/arch_ptrace.c
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
src/arch/aarch64/arch_ptrace.c | 58 ++++++++++++++++++++++++++++++++++
src/arch/x86/arch_ptrace.c | 58 ++++++++++++++++++++++++++++++++++
src/include/kpatch_ptrace.h | 3 ++
src/kpatch_ptrace.c | 58 ----------------------------------
4 files changed, 119 insertions(+), 58 deletions(-)
diff --git a/src/arch/aarch64/arch_ptrace.c b/src/arch/aarch64/arch_ptrace.c
index a444285..b21189e 100644
--- a/src/arch/aarch64/arch_ptrace.c
+++ b/src/arch/aarch64/arch_ptrace.c
@@ -22,6 +22,64 @@
#include <gelf.h>
+int
+wait_for_mmap(struct kpatch_ptrace_ctx *pctx,
+ unsigned long *pbase)
+{
+ int ret, status = 0, insyscall = 0;
+ long rv;
+
+ while (1) {
+ ret = ptrace(PTRACE_SYSCALL, pctx->pid, NULL,
+ (void *)(uintptr_t)status);
+ if (ret < 0) {
+ kplogerror("can't PTRACE_SYSCALL tracee - %d\n",
+ pctx->pid);
+ return -1;
+ }
+
+ ret = waitpid(pctx->pid, &status, __WALL);
+ if (ret < 0) {
+ kplogerror("can't wait tracee - %d\n", pctx->pid);
+ return -1;
+ }
+
+ if (WIFEXITED(status)) {
+ status = WTERMSIG(status);
+ continue;
+ } else if (!WIFSTOPPED(status)) {
+ status = 0;
+ continue;
+ }
+
+ status = 0;
+
+ if (insyscall == 0) {
+ rv = ptrace(PTRACE_PEEKUSER, pctx->pid,
+ offsetof(struct user_regs_struct,
+ regs[29]),
+ NULL);
+ if (rv == -1) {
+ kplogerror("ptrace(PTRACE_PEEKUSER)\n");
+ return -1;
+ }
+ insyscall = rv;
+ continue;
+ } else if (insyscall == __NR_mmap) {
+ rv = ptrace(PTRACE_PEEKUSER, pctx->pid,
+ offsetof(struct user_regs_struct,
+ regs[8]),
+ NULL);
+ *pbase = rv;
+ break;
+ }
+
+ insyscall = !insyscall;
+ }
+
+ return 0;
+}
+
int kpatch_arch_syscall_remote(struct kpatch_ptrace_ctx *pctx, int nr,
unsigned long arg1, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5, unsigned long arg6,
diff --git a/src/arch/x86/arch_ptrace.c b/src/arch/x86/arch_ptrace.c
index 10127a3..0032cbd 100644
--- a/src/arch/x86/arch_ptrace.c
+++ b/src/arch/x86/arch_ptrace.c
@@ -22,6 +22,64 @@
#include <gelf.h>
+int
+wait_for_mmap(struct kpatch_ptrace_ctx *pctx,
+ unsigned long *pbase)
+{
+ int ret, status = 0, insyscall = 0;
+ long rv;
+
+ while (1) {
+ ret = ptrace(PTRACE_SYSCALL, pctx->pid, NULL,
+ (void *)(uintptr_t)status);
+ if (ret < 0) {
+ kplogerror("can't PTRACE_SYSCALL tracee - %d\n",
+ pctx->pid);
+ return -1;
+ }
+
+ ret = waitpid(pctx->pid, &status, __WALL);
+ if (ret < 0) {
+ kplogerror("can't wait tracee - %d\n", pctx->pid);
+ return -1;
+ }
+
+ if (WIFEXITED(status)) {
+ status = WTERMSIG(status);
+ continue;
+ } else if (!WIFSTOPPED(status)) {
+ status = 0;
+ continue;
+ }
+
+ status = 0;
+
+ if (insyscall == 0) {
+ rv = ptrace(PTRACE_PEEKUSER, pctx->pid,
+ offsetof(struct user_regs_struct,
+ orig_rax),
+ NULL);
+ if (rv == -1) {
+ kplogerror("ptrace(PTRACE_PEEKUSER)\n");
+ return -1;
+ }
+ insyscall = rv;
+ continue;
+ } else if (insyscall == __NR_mmap) {
+ rv = ptrace(PTRACE_PEEKUSER, pctx->pid,
+ offsetof(struct user_regs_struct,
+ rax),
+ NULL);
+ *pbase = rv;
+ break;
+ }
+
+ insyscall = !insyscall;
+ }
+
+ return 0;
+}
+
int kpatch_arch_syscall_remote(struct kpatch_ptrace_ctx *pctx, int nr,
unsigned long arg1, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5, unsigned long arg6,
diff --git a/src/include/kpatch_ptrace.h b/src/include/kpatch_ptrace.h
index c8cfd41..5abcf26 100644
--- a/src/include/kpatch_ptrace.h
+++ b/src/include/kpatch_ptrace.h
@@ -141,4 +141,7 @@ int kpatch_arch_syscall_remote(struct kpatch_ptrace_ctx *pctx, int nr,
unsigned long arg4, unsigned long arg5, unsigned long arg6,
unsigned long *res);
+int wait_for_mmap(struct kpatch_ptrace_ctx *pctx,
+ unsigned long *pbase);
+
#endif
diff --git a/src/kpatch_ptrace.c b/src/kpatch_ptrace.c
index 057b08a..7ab550c 100644
--- a/src/kpatch_ptrace.c
+++ b/src/kpatch_ptrace.c
@@ -448,64 +448,6 @@ wait_for_stop(struct kpatch_ptrace_ctx *pctx,
return 0;
}
-static int
-wait_for_mmap(struct kpatch_ptrace_ctx *pctx,
- unsigned long *pbase)
-{
- int ret, status = 0, insyscall = 0;
- long rv;
-
- while (1) {
- ret = ptrace(PTRACE_SYSCALL, pctx->pid, NULL,
- (void *)(uintptr_t)status);
- if (ret < 0) {
- kplogerror("can't PTRACE_SYSCALL tracee - %d\n",
- pctx->pid);
- return -1;
- }
-
- ret = waitpid(pctx->pid, &status, __WALL);
- if (ret < 0) {
- kplogerror("can't wait tracee - %d\n", pctx->pid);
- return -1;
- }
-
- if (WIFEXITED(status)) {
- status = WTERMSIG(status);
- continue;
- } else if (!WIFSTOPPED(status)) {
- status = 0;
- continue;
- }
-
- status = 0;
-
- if (insyscall == 0) {
- rv = ptrace(PTRACE_PEEKUSER, pctx->pid,
- offsetof(struct user_regs_struct,
- orig_rax),
- NULL);
- if (rv == -1) {
- kplogerror("ptrace(PTRACE_PEEKUSER)\n");
- return -1;
- }
- insyscall = rv;
- continue;
- } else if (insyscall == __NR_mmap) {
- rv = ptrace(PTRACE_PEEKUSER, pctx->pid,
- offsetof(struct user_regs_struct,
- rax),
- NULL);
- *pbase = rv;
- break;
- }
-
- insyscall = !insyscall;
- }
-
- return 0;
-}
-
int
kpatch_execute_remote(struct kpatch_ptrace_ctx *pctx,
const unsigned char *code,
--
2.23.0

View File

@ -0,0 +1,401 @@
From f53cbbe63cbe16b2b0eb0466b5c85ea35f68da2b Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Tue, 13 Oct 2020 11:22:27 +0800
Subject: [PATCH 46/89] kpatch_ptrace: Split function
kpatch_ptrace_kickstart_execve_wrapper
The function kpatch_ptrace_kickstart_execve_wrapper is arch related,
first rename it with kpatch_arch_ptrace_kickstart_execve_wrapper,
and then make separate definations in arch/x86/arch_ptrace.c and
arch/aarch64/arch_ptrace.c
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
src/arch/aarch64/arch_ptrace.c | 99 +++++++++++++++++++++++++++++++
src/arch/x86/arch_ptrace.c | 99 +++++++++++++++++++++++++++++++
src/include/kpatch_ptrace.h | 5 +-
src/kpatch_process.c | 2 +-
src/kpatch_ptrace.c | 103 +--------------------------------
5 files changed, 205 insertions(+), 103 deletions(-)
diff --git a/src/arch/aarch64/arch_ptrace.c b/src/arch/aarch64/arch_ptrace.c
index b21189e..9f87d10 100644
--- a/src/arch/aarch64/arch_ptrace.c
+++ b/src/arch/aarch64/arch_ptrace.c
@@ -22,6 +22,105 @@
#include <gelf.h>
+/**
+ * This is rather tricky since we are accounting for the non-main
+ * thread calling for execve(). See `ptrace(2)` for details.
+ *
+ * FIXME(pboldin): this is broken for multi-threaded calls
+ * to execve. Sight.
+ */
+int
+kpatch_arch_ptrace_kickstart_execve_wrapper(kpatch_process_t *proc)
+{
+ int ret, pid = 0;
+ struct kpatch_ptrace_ctx *pctx, *ptmp, *execve_pctx = NULL;
+ long rv;
+
+ kpdebug("kpatch_arch_ptrace_kickstart_execve_wrapper\n");
+
+ list_for_each_entry(pctx, &proc->ptrace.pctxs, list) {
+ /* proc->pid equals to THREAD ID of the thread
+ * executing execve.so's version of execve
+ */
+ if (pctx->pid != proc->pid)
+ continue;
+ execve_pctx = pctx;
+ break;
+ }
+
+ if (execve_pctx == NULL) {
+ kperr("can't find thread executing execve");
+ return -1;
+ }
+
+ /* Send a message to our `execve` wrapper so it will continue
+ * execution
+ */
+ ret = send(proc->send_fd, &ret, sizeof(ret), 0);
+ if (ret < 0) {
+ kplogerror("send failed\n");
+ return ret;
+ }
+
+ /* Wait for it to reach BRKN instruction just before real execve */
+ while (1) {
+ ret = wait_for_stop(execve_pctx, NULL);
+ if (ret < 0) {
+ kplogerror("wait_for_stop\n");
+ return ret;
+ }
+
+ rv = ptrace(PTRACE_PEEKUSER, execve_pctx->pid,
+ offsetof(struct user_regs_struct, pc),
+ NULL);
+ if (rv == -1)
+ return rv;
+
+ rv = ptrace(PTRACE_PEEKTEXT, execve_pctx->pid,
+ rv - 1, NULL);
+ if (rv == -1)
+ return rv;
+ if ((unsigned char)rv == 0xcc)
+ break;
+ }
+
+ /* Wait for SIGTRAP from the execve. It happens from the thread
+ * group ID, so find it if thread doing execve() is not it. */
+ if (execve_pctx != proc2pctx(proc)) {
+ pid = get_threadgroup_id(proc->pid);
+ if (pid < 0)
+ return -1;
+
+ proc->pid = pid;
+ }
+
+ ret = wait_for_stop(execve_pctx, (void *)(uintptr_t)pid);
+ if (ret < 0) {
+ kplogerror("waitpid\n");
+ return ret;
+ }
+
+ list_for_each_entry_safe(pctx, ptmp, &proc->ptrace.pctxs, list) {
+ if (pctx->pid == proc->pid)
+ continue;
+ kpatch_ptrace_detach(pctx);
+ kpatch_ptrace_ctx_destroy(pctx);
+ }
+
+ /* Suddenly, /proc/pid/mem gets invalidated */
+ {
+ char buf[128];
+ close(proc->memfd);
+
+ snprintf(buf, sizeof(buf), "/proc/%d/mem", proc->pid);
+ proc->memfd = open(buf, O_RDWR);
+ }
+
+ kpdebug("...done\n");
+
+ return 0;
+}
+
int
wait_for_mmap(struct kpatch_ptrace_ctx *pctx,
unsigned long *pbase)
diff --git a/src/arch/x86/arch_ptrace.c b/src/arch/x86/arch_ptrace.c
index 0032cbd..ef0f460 100644
--- a/src/arch/x86/arch_ptrace.c
+++ b/src/arch/x86/arch_ptrace.c
@@ -22,6 +22,105 @@
#include <gelf.h>
+/**
+ * This is rather tricky since we are accounting for the non-main
+ * thread calling for execve(). See `ptrace(2)` for details.
+ *
+ * FIXME(pboldin): this is broken for multi-threaded calls
+ * to execve. Sight.
+ */
+int
+kpatch_arch_ptrace_kickstart_execve_wrapper(kpatch_process_t *proc)
+{
+ int ret, pid = 0;
+ struct kpatch_ptrace_ctx *pctx, *ptmp, *execve_pctx = NULL;
+ long rv;
+
+ kpdebug("kpatch_arch_ptrace_kickstart_execve_wrapper\n");
+
+ list_for_each_entry(pctx, &proc->ptrace.pctxs, list) {
+ /* proc->pid equals to THREAD ID of the thread
+ * executing execve.so's version of execve
+ */
+ if (pctx->pid != proc->pid)
+ continue;
+ execve_pctx = pctx;
+ break;
+ }
+
+ if (execve_pctx == NULL) {
+ kperr("can't find thread executing execve");
+ return -1;
+ }
+
+ /* Send a message to our `execve` wrapper so it will continue
+ * execution
+ */
+ ret = send(proc->send_fd, &ret, sizeof(ret), 0);
+ if (ret < 0) {
+ kplogerror("send failed\n");
+ return ret;
+ }
+
+ /* Wait for it to reach BRKN instruction just before real execve */
+ while (1) {
+ ret = wait_for_stop(execve_pctx, NULL);
+ if (ret < 0) {
+ kplogerror("wait_for_stop\n");
+ return ret;
+ }
+
+ rv = ptrace(PTRACE_PEEKUSER, execve_pctx->pid,
+ offsetof(struct user_regs_struct, rip),
+ NULL);
+ if (rv == -1)
+ return rv;
+
+ rv = ptrace(PTRACE_PEEKTEXT, execve_pctx->pid,
+ rv - 1, NULL);
+ if (rv == -1)
+ return rv;
+ if ((unsigned char)rv == 0xcc)
+ break;
+ }
+
+ /* Wait for SIGTRAP from the execve. It happens from the thread
+ * group ID, so find it if thread doing execve() is not it. */
+ if (execve_pctx != proc2pctx(proc)) {
+ pid = get_threadgroup_id(proc->pid);
+ if (pid < 0)
+ return -1;
+
+ proc->pid = pid;
+ }
+
+ ret = wait_for_stop(execve_pctx, (void *)(uintptr_t)pid);
+ if (ret < 0) {
+ kplogerror("waitpid\n");
+ return ret;
+ }
+
+ list_for_each_entry_safe(pctx, ptmp, &proc->ptrace.pctxs, list) {
+ if (pctx->pid == proc->pid)
+ continue;
+ kpatch_ptrace_detach(pctx);
+ kpatch_ptrace_ctx_destroy(pctx);
+ }
+
+ /* Suddenly, /proc/pid/mem gets invalidated */
+ {
+ char buf[128];
+ close(proc->memfd);
+
+ snprintf(buf, sizeof(buf), "/proc/%d/mem", proc->pid);
+ proc->memfd = open(buf, O_RDWR);
+ }
+
+ kpdebug("...done\n");
+
+ return 0;
+}
+
int
wait_for_mmap(struct kpatch_ptrace_ctx *pctx,
unsigned long *pbase)
diff --git a/src/include/kpatch_ptrace.h b/src/include/kpatch_ptrace.h
index 5abcf26..f0e83c0 100644
--- a/src/include/kpatch_ptrace.h
+++ b/src/include/kpatch_ptrace.h
@@ -55,7 +55,10 @@ int kpatch_ptrace_detach(struct kpatch_ptrace_ctx *pctx);
int kpatch_ptrace_handle_ld_linux(kpatch_process_t *proc,
unsigned long *pentry_point);
-int kpatch_ptrace_kickstart_execve_wrapper(kpatch_process_t *proc);
+
+int wait_for_stop(struct kpatch_ptrace_ctx *pctx, void *data);
+int get_threadgroup_id(int tid);
+int kpatch_arch_ptrace_kickstart_execve_wrapper(kpatch_process_t *proc);
int kpatch_ptrace_get_entry_point(struct kpatch_ptrace_ctx *pctx,
unsigned long *pentry_point);
diff --git a/src/kpatch_process.c b/src/kpatch_process.c
index 9561962..f987b7e 100644
--- a/src/kpatch_process.c
+++ b/src/kpatch_process.c
@@ -856,7 +856,7 @@ kpatch_process_kickstart_execve_wrapper(kpatch_process_t *proc)
{
int ret;
- ret = kpatch_ptrace_kickstart_execve_wrapper(proc);
+ ret = kpatch_arch_ptrace_kickstart_execve_wrapper(proc);
if (ret < 0)
return -1;
diff --git a/src/kpatch_ptrace.c b/src/kpatch_ptrace.c
index 7ab550c..d0bfbdd 100644
--- a/src/kpatch_ptrace.c
+++ b/src/kpatch_ptrace.c
@@ -413,7 +413,7 @@ poke_back:
return ret;
}
-static int
+int
wait_for_stop(struct kpatch_ptrace_ctx *pctx,
void *data)
{
@@ -463,7 +463,7 @@ kpatch_execute_remote(struct kpatch_ptrace_ctx *pctx,
}
/* FIXME(pboldin) buf might be too small */
-static int
+int
get_threadgroup_id(int tid)
{
FILE *fh;
@@ -486,105 +486,6 @@ get_threadgroup_id(int tid)
return pid;
}
-/**
- * This is rather tricky since we are accounting for the non-main
- * thread calling for execve(). See `ptrace(2)` for details.
- *
- * FIXME(pboldin): this is broken for multi-threaded calls
- * to execve. Sight.
- */
-int
-kpatch_ptrace_kickstart_execve_wrapper(kpatch_process_t *proc)
-{
- int ret, pid = 0;
- struct kpatch_ptrace_ctx *pctx, *ptmp, *execve_pctx = NULL;
- long rv;
-
- kpdebug("kpatch_ptrace_kickstart_execve_wrapper\n");
-
- list_for_each_entry(pctx, &proc->ptrace.pctxs, list) {
- /* proc->pid equals to THREAD ID of the thread
- * executing execve.so's version of execve
- */
- if (pctx->pid != proc->pid)
- continue;
- execve_pctx = pctx;
- break;
- }
-
- if (execve_pctx == NULL) {
- kperr("can't find thread executing execve");
- return -1;
- }
-
- /* Send a message to our `execve` wrapper so it will continue
- * execution
- */
- ret = send(proc->send_fd, &ret, sizeof(ret), 0);
- if (ret < 0) {
- kplogerror("send failed\n");
- return ret;
- }
-
- /* Wait for it to reach BRKN instruction just before real execve */
- while (1) {
- ret = wait_for_stop(execve_pctx, NULL);
- if (ret < 0) {
- kplogerror("wait_for_stop\n");
- return ret;
- }
-
- rv = ptrace(PTRACE_PEEKUSER, execve_pctx->pid,
- offsetof(struct user_regs_struct, rip),
- NULL);
- if (rv == -1)
- return rv;
-
- rv = ptrace(PTRACE_PEEKTEXT, execve_pctx->pid,
- rv - 1, NULL);
- if (rv == -1)
- return rv;
- if ((unsigned char)rv == 0xcc)
- break;
- }
-
- /* Wait for SIGTRAP from the execve. It happens from the thread
- * group ID, so find it if thread doing execve() is not it. */
- if (execve_pctx != proc2pctx(proc)) {
- pid = get_threadgroup_id(proc->pid);
- if (pid < 0)
- return -1;
-
- proc->pid = pid;
- }
-
- ret = wait_for_stop(execve_pctx, (void *)(uintptr_t)pid);
- if (ret < 0) {
- kplogerror("waitpid\n");
- return ret;
- }
-
- list_for_each_entry_safe(pctx, ptmp, &proc->ptrace.pctxs, list) {
- if (pctx->pid == proc->pid)
- continue;
- kpatch_ptrace_detach(pctx);
- kpatch_ptrace_ctx_destroy(pctx);
- }
-
- /* Suddenly, /proc/pid/mem gets invalidated */
- {
- char buf[128];
- close(proc->memfd);
-
- snprintf(buf, sizeof(buf), "/proc/%d/mem", proc->pid);
- proc->memfd = open(buf, O_RDWR);
- }
-
- kpdebug("...done\n");
-
- return 0;
-}
-
unsigned long
kpatch_mmap_remote(struct kpatch_ptrace_ctx *pctx,
unsigned long addr,
--
2.23.0

View File

@ -1,15 +1,60 @@
Version: 0.1.4
Name: libcareplus
Summary: LibcarePlus tools
Release: 2
Release: 3
Group: Applications/System
License: GPLv2
Url: https://gitee.com/openeuler/libcareplus
Source0: %{name}-%{version}.tar.gz
Patch0001: src-Makefile-install-kpatch_gensrc-into-bindir.patch
Patch0002: 0001-Split-kpatch_storage.c-from-kpatch_user.c.patch
Patch0003: 0002-Split-kpatch_patch.c-from-kpatch_user.c.patch
Patch0004: 0003-cmd_patch-pass-arguments-directly.patch
Patch0005: 0004-travis-use-VM-for-now.patch
Patch0006: 0005-scripts-pkgbuild-add-prepare_env-hook.patch
Patch0007: 0006-pkgbuild-fix-for-non-root-rpmbuild-built-root.patch
Patch0008: 0007-Toil-package-builder.patch
Patch0009: 0008-pkgbuild-use-yumdownloader-if-source-url-is-missing.patch
Patch0010: 0009-execve-abort-on-failure.patch
Patch0011: 0010-Add-test-stage-to-pkgbuild.patch
Patch0012: 0011-glibc-minimal-readme-for-toil-builder.patch
Patch0013: 0012-Fix-kpatch_process_init-kpatch_coroutines_free.patch
Patch0014: 0013-Add-libcare-stresstest.patch
Patch0015: 0014-read-auxv-from-proc-pid-auxv.patch
Patch0016: 0015-add-fail-to-unpatch-test.patch
Patch0017: 0016-Waitpid-for-finished-threads-after-detach.patch
Patch0018: 0017-.gitignore-build-artefacts.patch
Patch0019: 0018-kpatch_storage-put-an-end-to-description-string-load.patch
Patch0020: 0019-Fix-README-files.patch
Patch0021: 0020-include-Create-include-directory-for-header-files.patch
Patch0022: 0021-src-Update-header-file-position.patch
Patch0023: 0022-arch-Create-arch-directory-to-support-multi-arch.patch
Patch0024: 0023-config-configure-out-the-running-arch.patch
Patch0025: 0024-Makefile-Adapt-Makefile-for-different-architectures.patch
Patch0026: 0025-kpatch_parse-Update-asm_directives-for-aarch64.patch
Patch0027: 0026-kpatch_parse-Split-function-parse_ctype.patch
Patch0028: 0027-kpatch_parse-Split-function-init_multilines.patch
Patch0029: 0028-kpatch_parse-Split-function-is_variable_start.patch
Patch0030: 0029-kpatch_parse-Split-function-is_data_def.patch
Patch0031: 0030-kpatch_parse-Split-function-is_function_start.patch
Patch0032: 0031-kpatch_common.h-Factor-out-PAGE_SIZE-marco.patch
Patch0033: 0032-kpatch_coro-Split-function-_UCORO_access_reg.patch
Patch0034: 0033-kpatch_coro-Split-function-get_ptr_guard.patch
Patch0035: 0034-kpatch_coro-Split-function-locate_start_context_symb.patch
Patch0036: 0035-kpatch_patch-Split-function-patch_apply_hunk.patch
Patch0037: 0036-kpatch_elf-Split-function-kpatch_add_jmp_entry.patch
Patch0038: 0037-kpatch_elf-Split-function-kpatch_apply_relocate_add.patch
Patch0039: 0038-kpatch_process-Split-function-object_find_patch_regi.patch
Patch0040: 0039-kpatch_ptrace-Split-function-kpatch_ptrace_waitpid.patch
Patch0041: 0040-kpatch_ptrace-Split-function-copy_regs.patch
Patch0042: 0041-kpatch_ptrace-Split-function-kpatch_execute_remote_f.patch
Patch0043: 0042-kpatch_ptrace-Split-function-kpatch_ptrace_resolve_i.patch
Patch0044: 0043-kpatch_ptrace-Split-function-kpatch_arch_prctl_remot.patch
Patch0045: 0044-kpatch_ptrace-Split-function-kpatch_syscall_remote.patch
Patch0046: 0045-kpatch_ptrace-Split-function-wait_for_mmap.patch
Patch0047: 0046-kpatch_ptrace-Split-function-kpatch_ptrace_kickstart.patch
ExclusiveArch: x86_64
BuildRequires: elfutils-libelf-devel libunwind-devel
%if 0%{with selinux}
@ -53,7 +98,9 @@ LibcarePlus devel files.
%autopatch -p1
%build
cd src
sh ./config
cd ../
make -C src
%if 0%{with selinux}
make -C dist/selinux
@ -163,6 +210,9 @@ exit 0
%endif
%changelog
* Tue Feb 09 2021 Jiajie Li <lijiajie11@huawei.com> - 0.1.4-3
- Add basic support libcareplus on aarch64
* Mon Dec 28 2020 sunguoshuai <sunguoshuai@huawei.com> - 0.1.4-2
- Del the {dist} in release.