diff --git a/syscare-1.0.0.tar.gz b/syscare-1.0.1.tar.gz similarity index 46% rename from syscare-1.0.0.tar.gz rename to syscare-1.0.1.tar.gz index 0e5537ad2661e55eeeb244990919a3e5fae4eb37..307092f414d75746bd0e8f71d848122eff031a35 100644 Binary files a/syscare-1.0.0.tar.gz and b/syscare-1.0.1.tar.gz differ diff --git a/syscare.spec b/syscare.spec index 693944b3816363d56a7af00f1aa84c34fb41441a..18c6038946ccf2543268390d7b9161960b7c0a06 100644 --- a/syscare.spec +++ b/syscare.spec @@ -1,14 +1,13 @@ %global debug_package %{nil} Name: syscare -Version: 1.0.0 -Release: 7 +Version: 1.0.1 +Release: 1 Summary: system hot-fix service -License: MulanPSL-2.0 GPL-2.0-only +License: MulanPSL-2.0 and GPL-2.0-only URL: https://gitee.com/openeuler/syscare Source0: %{name}-%{version}.tar.gz -Patch1: v1.0.0-7.patch BuildRequires: rust cargo gcc gcc-g++ cmake make BuildRequires: elfutils-libelf-devel @@ -21,11 +20,11 @@ SysCare is a system-level hot-fix software that provides single-machine-level an The host can fix the system problem without rebooting. %package build -Summary: Tools for build syscare patch. -Requires: %{name} = %{version}-%{release} -Requires: kpatch make gcc openssl-devel dwarves python3-devel bison flex -Requires: elfutils-libelf-devel -Requires: rpm-build +Summary: Tools for build syscare patch. +Requires: %{name} = %{version}-%{release} +Requires: kpatch make gcc openssl-devel dwarves python3-devel bison flex +Requires: elfutils-libelf-devel +Requires: rpm-build %description build Syscare build tools. @@ -36,77 +35,79 @@ Syscare build tools. %autosetup -p1 %build -mkdir -p tmp_build -cd tmp_build -cmake -DSYSCARE_BUILD_VERSION=%{version}-%{release} -DKERNEL_VERSION=%{kernel_version} .. +mkdir -p build_tmp +cd build_tmp + +cmake -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_VERSION=%{version}-%{release} -DKERNEL_VERSION=%{kernel_version} .. make %install -cd tmp_build +cd build_tmp %make_install - -mkdir -p %{buildroot}/lib/modules/%{kernel_version}/extra/syscare %ifarch x86_64 -install -m 0640 %{buildroot}/usr/libexec/%{name}/upatch.ko %{buildroot}/lib/modules/%{kernel_version}/extra/syscare -%endif - -mkdir -p %{buildroot}/usr/lib/systemd/system -%ifarch aarch64 -install -m 0644 %{_builddir}/%{name}-%{version}/misc/%{name}-restore-arm64.service %{buildroot}/usr/lib/systemd/system/%{name}-restore.service -%else -install -m 0644 %{_builddir}/%{name}-%{version}/misc/%{name}-restore.service %{buildroot}/usr/lib/systemd/system -install -m 0644 %{_builddir}/%{name}-%{version}/misc/%{name}-pre.service %{buildroot}/usr/lib/systemd/system -%endif - -mkdir -p %{buildroot}/usr/lib/syscare - -%ifarch x86_64 -cd %{buildroot} -find lib -name "upatch.ko" \ - -fprintf %{_builddir}/%{name}-%{version}/ko.files.list "/%p\n" + mkdir -p %{buildroot}/lib/modules/%{kernel_version}/extra/syscare + install -m 0640 %{buildroot}/usr/libexec/syscare/upatch.ko %{buildroot}/lib/modules/%{kernel_version}/extra/syscare + cd %{buildroot} + find lib -name "upatch.ko" -fprintf %{_builddir}/%{name}-%{version}/ko.files.list "/%p\n" %endif %post -%systemd_post %{name}-restore.service +mkdir -p /usr/lib/syscare/patches %ifarch x86_64 -%{_bindir}/systemctl enable %{name}-pre.service + depmod -a > /dev/null 2>&1 || true + + %systemd_post syscare-pre.service + %systemd_post syscare.service + + systemctl enable syscare-pre.service + systemctl enable syscare.service + systemctl start syscare-pre + systemctl start syscare %endif -depmod -a > /dev/null 2>&1 || true %preun -%systemd_preun %{name}-restore.service +rm -rf /usr/lib/syscare/patches %ifarch x86_64 -%systemd_preun %{name}-pre.service + %systemd_preun syscare-pre.service + %systemd_preun syscare.service %endif %postun -depmod -a > /dev/null 2>&1 || true +%ifarch x86_64 + depmod -a > /dev/null 2>&1 || true +%endif %ifarch x86_64 %files -f ko.files.list %endif + %files %defattr(-,root,root,-) -%dir /usr/lib/syscare %attr(755,root,root) /usr/bin/syscare +%attr(644,root,root) /usr/lib/systemd/system/syscare-pre.service +%attr(644,root,root) /usr/lib/systemd/system/syscare.service %ifarch x86_64 -%attr(755,root,root) /usr/libexec/%{name}/upatch-tool -%attr(640,root,root) /usr/libexec/%{name}/upatch.ko -%attr(644,root,root) /usr/lib/systemd/system/%{name}-pre.service + %dir /usr/libexec/syscare + %attr(640,root,root) /usr/libexec/syscare/upatch.ko + %attr(755,root,root) /usr/libexec/syscare/upatch-tool %endif -%attr(755,root,root) /usr/libexec/%{name}/auto-recovery.sh -%attr(644,root,root) /usr/lib/systemd/system/%{name}-restore.service %files build %defattr(-,root,root,-) -%dir /usr/libexec/%{name} -%attr(755,root,root) /usr/libexec/%{name}/syscare-build +%dir /usr/libexec/syscare +%attr(755,root,root) /usr/libexec/syscare/syscare-build +%attr(755,root,root) /usr/libexec/syscare/upatch-build %ifarch x86_64 -%attr(755,root,root) /usr/libexec/%{name}/upatch-diff -%attr(755,root,root) /usr/libexec/%{name}/upatch-build + %attr(755,root,root) /usr/libexec/syscare/upatch-diff %endif %changelog +* Wed Mar 15 2023 renoseven - 1.0.1-1 +- New syscare cli +- Support building patch for C++ code +- Support patch version verification +- Support elf name derivation +- Support fast reboot * Wed Dec 21 2022 snoweay - 1.0.0-7 - Fix 42 relocation caused by gcc 11. * Tue Dec 20 2022 snoweay - 1.0.0-6 diff --git a/v1.0.0-7.patch b/v1.0.0-7.patch deleted file mode 100644 index 843be19b1bddd1aa0b23dd99c449e9440a4d7382..0000000000000000000000000000000000000000 --- a/v1.0.0-7.patch +++ /dev/null @@ -1,2554 +0,0 @@ -From 81008c77dba79eb311ad537051086f10ba1ccd22 Mon Sep 17 00:00:00 2001 -From: Longjun Luo -Date: Tue, 13 Dec 2022 16:08:45 +0800 -Subject: [PATCH 01/20] kmod: make it normal when using hack-gcc without env - -Signed-off-by: Longjun Luo ---- - upatch/kmod/compiler.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/upatch/kmod/compiler.c b/upatch/kmod/compiler.c -index 87cdc3e..9f45cb7 100755 ---- a/upatch/kmod/compiler.c -+++ b/upatch/kmod/compiler.c -@@ -443,8 +443,8 @@ static int rewrite_object_path(char __user **argv, char __user **envp) - - ret = obtain_parameter_addr(envp, ASSEMBLER_DIR_ENV, &dir_addr, NULL); - if (ret || dir_addr == 0) { -- pr_warn("no valid %s found %s \n", ASSEMBLER_DIR_ENV, object_path); -- ret = -EINVAL; -+ pr_debug("no valid %s found %s \n", ASSEMBLER_DIR_ENV, object_path); -+ ret = 0; - goto out; - } - --- -2.33.0 - - -From 024e9cd683055ca1702710a60d9c8abebfdbcbb3 Mon Sep 17 00:00:00 2001 -From: snoweay -Date: Wed, 14 Dec 2022 01:37:26 +0000 -Subject: [PATCH 02/20] manager: Allow apply to actived kernel patch - -Signed-off-by: snoweay ---- - manager/cli/main.sh | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/manager/cli/main.sh b/manager/cli/main.sh -index 6e6c86a..8ee3bd0 100755 ---- a/manager/cli/main.sh -+++ b/manager/cli/main.sh -@@ -167,6 +167,8 @@ function do_build() { - function apply_patch() { - if [ "${PATCH_TYPE}" == "kernel" ] ; then - check_kversion || return 1 -+ [ "${PATCH_STATUS}" == "ACTIVED" ] && return -+ - if [ "${PATCH_STATUS}" == "NOT-APPLIED" ]; then - insmod "${PATCH_ROOT}/${PATCH_NAME}.ko" || return 1 - fi --- -2.33.0 - - -From 5874b79701fe7854575f710277f241a63a50afeb Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Wed, 14 Dec 2022 03:34:01 +0800 -Subject: [PATCH 03/20] build: only 'NOT-APPLIED' patch package can be removed - -Signed-off-by: renoseven ---- - build/src/package/rpm_spec_generator.rs | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/build/src/package/rpm_spec_generator.rs b/build/src/package/rpm_spec_generator.rs -index 9781eb1..917e12e 100644 ---- a/build/src/package/rpm_spec_generator.rs -+++ b/build/src/package/rpm_spec_generator.rs -@@ -115,8 +115,8 @@ impl RpmSpecGenerator { - writeln!(writer)?; - - writeln!(writer, "%preun")?; -- writeln!(writer, "if [ \"$(syscare status %{{patch_name}})\" == \"ACTIVED\" ]; then")?; -- writeln!(writer, " echo \"error: cannot remove actived patch \'%{{patch_name}}\'\" >&2")?; -+ writeln!(writer, "if [ \"$(syscare status %{{patch_name}})\" != \"NOT-APPLIED\" ]; then")?; -+ writeln!(writer, " echo \"error: cannot remove applied patch \'%{{patch_name}}\'\" >&2")?; - writeln!(writer, " exit 1")?; - writeln!(writer, "fi")?; - --- -2.33.0 - - -From 1506b703935004b04fbf73f8875f33b5a8b8fe87 Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Wed, 14 Dec 2022 23:50:03 +0800 -Subject: [PATCH 04/20] build: fix 'kernel patch cannot be insmod during system - start' issue - -1. change ko file(s) security context type to 'modules_object_t' after - package install, as selinux blocks loading unconfigured kernel module - -Signed-off-by: renoseven ---- - build/src/package/rpm_spec_generator.rs | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/build/src/package/rpm_spec_generator.rs b/build/src/package/rpm_spec_generator.rs -index 917e12e..f76e109 100644 ---- a/build/src/package/rpm_spec_generator.rs -+++ b/build/src/package/rpm_spec_generator.rs -@@ -114,6 +114,10 @@ impl RpmSpecGenerator { - writeln!(writer, "%{{patch_root}}")?; - writeln!(writer)?; - -+ writeln!(writer, "%post")?; -+ writeln!(writer, "readonly KO_LIST=\"$(find %{{patch_root}} -name *.ko)\"")?; -+ writeln!(writer, "chcon -t modules_object_t \"${{KO_LIST}}\"")?; -+ - writeln!(writer, "%preun")?; - writeln!(writer, "if [ \"$(syscare status %{{patch_name}})\" != \"NOT-APPLIED\" ]; then")?; - writeln!(writer, " echo \"error: cannot remove applied patch \'%{{patch_name}}\'\" >&2")?; --- -2.33.0 - - -From dc73e5833888096518321e6ba15503d9806199fb Mon Sep 17 00:00:00 2001 -From: Longjun Luo -Date: Wed, 14 Dec 2022 12:43:46 +0800 -Subject: [PATCH 05/20] kmod: adjust order of the misc device (un)register - -After all init finished, then provides the device -for users. - -When exit starts, unregister the device first. - -Signed-off-by: Longjun Luo ---- - upatch/kmod/kmod.c | 10 +++++----- - upatch/upatch-tool/upatch-tool.c | 1 - - 2 files changed, 5 insertions(+), 6 deletions(-) - -diff --git a/upatch/kmod/kmod.c b/upatch/kmod/kmod.c -index 3ce40ae..d31037f 100755 ---- a/upatch/kmod/kmod.c -+++ b/upatch/kmod/kmod.c -@@ -227,16 +227,16 @@ static int __init upatch_init(void) - { - int ret; - -+ ret = compiler_hack_init(); -+ if (ret < 0) -+ return ret; -+ - ret = misc_register(&upatch_dev); - if (ret) { - pr_err("register misc device for %s failed\n", UPATCH_DEV_NAME); - return ret; - } - -- ret = compiler_hack_init(); -- if (ret < 0) -- return ret; -- - pr_info("upatch - %s load successfully \n", UPATCH_VERSION); - - return 0; -@@ -244,8 +244,8 @@ static int __init upatch_init(void) - - static void __exit upatch_exit(void) - { -- compiler_hack_exit(); - misc_deregister(&upatch_dev); -+ compiler_hack_exit(); - } - - module_init(upatch_init); -diff --git a/upatch/upatch-tool/upatch-tool.c b/upatch/upatch-tool/upatch-tool.c -index c96836b..d1328aa 100644 ---- a/upatch/upatch-tool/upatch-tool.c -+++ b/upatch/upatch-tool/upatch-tool.c -@@ -23,7 +23,6 @@ - #include "upatch-manage.h" - #include "upatch-ioctl.h" - #include "upatch-resolve.h" --#include "upatch-manage.h" - - #define COMMAND_SIZE 9 - char* command[COMMAND_SIZE] = --- -2.33.0 - - -From d54264a83c2cc997ebaba0be8c32fc90682a9c04 Mon Sep 17 00:00:00 2001 -From: lzwycc -Date: Wed, 14 Dec 2022 19:44:23 +0800 -Subject: [PATCH 06/20] kmod: unregister when rmmod upatch - -unregister compiler and assembler when rmmod upatch - -Signed-off-by: lzwycc ---- - upatch/kmod/compiler.c | 50 +++++++++++++++++++++++------------------- - 1 file changed, 27 insertions(+), 23 deletions(-) - -diff --git a/upatch/kmod/compiler.c b/upatch/kmod/compiler.c -index 9f45cb7..899b83f 100755 ---- a/upatch/kmod/compiler.c -+++ b/upatch/kmod/compiler.c -@@ -135,20 +135,6 @@ void delete_elf_path(unsigned int cmd, char *name) - } - } - --void clear_compiler_path(void) --{ -- struct elf_path *ep, *tmp; -- list_for_each_entry_safe(ep, tmp, &compiler_paths_list, list) -- delete_elf_path(UPATCH_UNREGISTER_COMPILER, ep->name); --} -- --void clear_assembler_path(void) --{ -- struct elf_path *ep, *tmp; -- list_for_each_entry_safe(ep, tmp, &assembler_paths_list, list) -- delete_elf_path(UPATCH_UNREGISTER_ASSEMBLER, ep->name); --} -- - static int generate_file_name(char *buf, int buf_len) - { - unsigned long id; -@@ -658,13 +644,13 @@ out: - return ret; - } - --static int elf_check(const char *buf, char *elf_path, loff_t *entry_offset) -+static int elf_check(char *elf_path, loff_t *entry_offset) - { - struct file *file; - int ret; - char *p; - -- file = filp_open(buf, O_RDONLY, 0); -+ file = filp_open(elf_path, O_RDONLY, 0); - if (IS_ERR(file)) { - ret = PTR_ERR(file); - pr_err("open elf failed - %d \n", ret); -@@ -688,13 +674,13 @@ out: - return ret; - } - --static int __register_uprobe(const char *buf, unsigned int cmd, struct elf_path *ep, struct uprobe_consumer *uc) -+static int __register_uprobe(unsigned int cmd, struct elf_path *ep, struct uprobe_consumer *uc) - { - int ret; - struct path path; - struct inode *inode; - -- ret = elf_check(buf, ep->name, &ep->entry_offset); -+ ret = elf_check(ep->name, &ep->entry_offset); - if (ret) - goto out; - -@@ -705,7 +691,7 @@ static int __register_uprobe(const char *buf, unsigned int cmd, struct elf_path - } - inode = path.dentry->d_inode; - -- pr_debug("register uprobe for %s \n", buf); -+ pr_debug("register uprobe for %s \n", ep->name); - ret = uprobe_register(inode, ep->entry_offset, uc); - if (ret) { - pr_err("uprobe register failed - %d \n", ret); -@@ -749,14 +735,14 @@ int handle_compiler_cmd(unsigned long user_addr, unsigned int cmd) - ep->count = 1; - ep->entry_offset = 0; - list_add(&ep->list, &compiler_paths_list); -- ret = __register_uprobe(path, cmd, ep, &uprobe_compiler_consumer); -+ ret = __register_uprobe(cmd, ep, &uprobe_compiler_consumer); - } else { - ep->count++; - } - break; - - case UPATCH_UNREGISTER_COMPILER: -- if (ep) { -+ if (ep && ep->count > 0) { - ep->count--; - if (!ep->count) - ret = __unregister_uprobe(cmd, ep, &uprobe_compiler_consumer); -@@ -773,14 +759,14 @@ int handle_compiler_cmd(unsigned long user_addr, unsigned int cmd) - ep->count = 1; - ep->entry_offset = 0; - list_add(&ep->list, &assembler_paths_list); -- ret = __register_uprobe(path, cmd, ep, &uprobe_assembler_consumer); -+ ret = __register_uprobe(cmd, ep, &uprobe_assembler_consumer); - } else { - ep->count++; - } - break; - - case UPATCH_UNREGISTER_ASSEMBLER: -- if (ep) { -+ if (ep && ep->count > 0) { - ep->count--; - if (!ep->count) - ret = __unregister_uprobe(cmd, ep, &uprobe_assembler_consumer); -@@ -812,6 +798,24 @@ out: - return ret; - } - -+void clear_compiler_path(void) -+{ -+ struct elf_path *ep, *tmp; -+ list_for_each_entry_safe(ep, tmp, &compiler_paths_list, list) { -+ ep->count = 0; -+ __unregister_uprobe(UPATCH_UNREGISTER_COMPILER, ep, &uprobe_compiler_consumer); -+ } -+} -+ -+void clear_assembler_path(void) -+{ -+ struct elf_path *ep, *tmp; -+ list_for_each_entry_safe(ep, tmp, &assembler_paths_list, list) { -+ ep->count = 0; -+ __unregister_uprobe(UPATCH_UNREGISTER_ASSEMBLER, ep, &uprobe_assembler_consumer); -+ } -+} -+ - void __exit compiler_hack_exit(void) - { - clear_compiler_path(); --- -2.33.0 - - -From 8b8a62377a425c273c2a584ff9f299f88b70f0e5 Mon Sep 17 00:00:00 2001 -From: snoweay -Date: Thu, 15 Dec 2022 18:34:53 +0800 -Subject: [PATCH 07/20] Revert "build: fix 'kernel patch cannot be insmod - during system start' issue" - -This reverts commit 1506b703935004b04fbf73f8875f33b5a8b8fe87. ---- - build/src/package/rpm_spec_generator.rs | 4 ---- - 1 file changed, 4 deletions(-) - -diff --git a/build/src/package/rpm_spec_generator.rs b/build/src/package/rpm_spec_generator.rs -index f76e109..917e12e 100644 ---- a/build/src/package/rpm_spec_generator.rs -+++ b/build/src/package/rpm_spec_generator.rs -@@ -114,10 +114,6 @@ impl RpmSpecGenerator { - writeln!(writer, "%{{patch_root}}")?; - writeln!(writer)?; - -- writeln!(writer, "%post")?; -- writeln!(writer, "readonly KO_LIST=\"$(find %{{patch_root}} -name *.ko)\"")?; -- writeln!(writer, "chcon -t modules_object_t \"${{KO_LIST}}\"")?; -- - writeln!(writer, "%preun")?; - writeln!(writer, "if [ \"$(syscare status %{{patch_name}})\" != \"NOT-APPLIED\" ]; then")?; - writeln!(writer, " echo \"error: cannot remove applied patch \'%{{patch_name}}\'\" >&2")?; --- -2.33.0 - - -From 5171debddcbd632cb25c30d2325f0a655945c0f2 Mon Sep 17 00:00:00 2001 -From: snoweay -Date: Thu, 15 Dec 2022 18:37:42 +0800 -Subject: [PATCH 08/20] manager: Set kpatch's scontext to modules_object_t - -Signed-off-by: snoweay ---- - manager/cli/main.sh | 17 +++++++++++++---- - 1 file changed, 13 insertions(+), 4 deletions(-) - -diff --git a/manager/cli/main.sh b/manager/cli/main.sh -index 8ee3bd0..c056f62 100755 ---- a/manager/cli/main.sh -+++ b/manager/cli/main.sh -@@ -130,7 +130,7 @@ function get_patch_type() { - } - - function get_patch_elf_path() { -- [ "${PATCH_TYPE}" == "kernel" ] && return -+ [ "${PATCH_TYPE}" == "kernel" ] && return 0 - - local patch_name="$1" - local patch_root=$(get_patch_root_by_patch_name "${patch_name}") -@@ -164,12 +164,21 @@ function do_build() { - "${SYSCARE_PATCH_BUILD}" "$@" - } - -+function set_kpatch_scontext() { -+ local getenforce_bin=$(which getenforce 2> /dev/null) -+ [ -n "${getenforce_bin}" ] || return 0 -+ -+ "${getenforce_bin}" | grep -q "Enforcing" 2> /dev/null || return 0 -+ chcon -t modules_object_t "${PATCH_ROOT}/${PATCH_NAME}.ko" -+} -+ - function apply_patch() { - if [ "${PATCH_TYPE}" == "kernel" ] ; then - check_kversion || return 1 -- [ "${PATCH_STATUS}" == "ACTIVED" ] && return -+ [ "${PATCH_STATUS}" == "ACTIVED" ] && return 0 - - if [ "${PATCH_STATUS}" == "NOT-APPLIED" ]; then -+ set_kpatch_scontext - insmod "${PATCH_ROOT}/${PATCH_NAME}.ko" || return 1 - fi - PATCH_STATUS="DEACTIVED" -@@ -191,7 +200,7 @@ function apply_patch() { - - function remove_patch() { - if [ "${PATCH_TYPE}" == "kernel" ] ; then -- [ "${PATCH_STATUS}" == "NOT-APPLIED" ] && return -+ [ "${PATCH_STATUS}" == "NOT-APPLIED" ] && return 0 - [ "${PATCH_STATUS}" == "ACTIVED" ] && deactive_patch - rmmod "${PATCH_NAME}" || return 1 - else -@@ -306,7 +315,7 @@ function initialize_patch_info() { - if [ "${PATCH_TYPE}" == "kernel" ]; then - if [ ! -f "${KPATCH_STATE_FILE}" ]; then - PATCH_STATUS="NOT-APPLIED" -- return -+ return 0 - fi - - if [ $(cat "${KPATCH_STATE_FILE}") -eq 1 ]; then --- -2.33.0 - - -From d8ef956b6e5ee05e95c757fe79a1bde58908efb4 Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Fri, 16 Dec 2022 19:37:53 +0800 -Subject: [PATCH 09/20] upatch: file searching would not follow symlinks - -Signed-off-by: renoseven ---- - upatch/upatch-build/src/tool/fs.rs | 17 ++++++++++++++--- - 1 file changed, 14 insertions(+), 3 deletions(-) - -diff --git a/upatch/upatch-build/src/tool/fs.rs b/upatch/upatch-build/src/tool/fs.rs -index 17fd307..9f15dc2 100644 ---- a/upatch/upatch-build/src/tool/fs.rs -+++ b/upatch/upatch-build/src/tool/fs.rs -@@ -61,8 +61,11 @@ pub fn list_all_files>(directory: P, recursive: bool) -> std::io: - for dir_entry in std::fs::read_dir(search_path)? { - if let Ok(entry) = dir_entry { - let current_path = entry.path(); -- let current_path_type = current_path.metadata()?.file_type(); -+ let current_path_type = current_path.symlink_metadata()?.file_type(); - -+ if current_path_type.is_symlink() { -+ continue; -+ } - if current_path_type.is_file() { - file_list.push(self::realpath(current_path.as_path())?); - } -@@ -90,7 +93,12 @@ pub fn list_all_dirs>(directory: P, recursive: bool) -> std::io:: - for dir_entry in std::fs::read_dir(search_path)? { - if let Ok(entry) = dir_entry { - let current_path = entry.path(); -- if !current_path.is_dir() { -+ let current_path_type = current_path.symlink_metadata()?.file_type(); -+ -+ if current_path_type.is_symlink() { -+ continue; -+ } -+ if !current_path_type.is_dir() { - continue; - } - dir_list.push(self::realpath(current_path.as_path())?); -@@ -116,8 +124,11 @@ pub fn list_all_files_ext>(directory: P, file_ext: &str, recursiv - for dir_entry in std::fs::read_dir(search_path)? { - if let Ok(entry) = dir_entry { - let current_path = entry.path(); -- let current_path_type = current_path.metadata()?.file_type(); -+ let current_path_type = current_path.symlink_metadata()?.file_type(); - -+ if current_path_type.is_symlink() { -+ continue; -+ } - if current_path_type.is_file() { - let current_path_ext = current_path.extension().unwrap_or_default(); - if current_path_ext == file_ext { --- -2.33.0 - - -From 7c61c25746a4f9ef82b3383d093123da7888c532 Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Fri, 16 Dec 2022 19:42:42 +0800 -Subject: [PATCH 10/20] build: file searching would not follow symlinks - -Signed-off-by: renoseven ---- - build/src/util/fs.rs | 17 ++++++++++++++--- - 1 file changed, 14 insertions(+), 3 deletions(-) - -diff --git a/build/src/util/fs.rs b/build/src/util/fs.rs -index 8ac2e9e..3343256 100644 ---- a/build/src/util/fs.rs -+++ b/build/src/util/fs.rs -@@ -68,7 +68,12 @@ pub fn list_all_dirs>(directory: P, recursive: bool) -> std::io:: - for dir_entry in std::fs::read_dir(search_path)? { - if let Ok(entry) = dir_entry { - let current_path = entry.path(); -- if !current_path.is_dir() { -+ let current_path_type = current_path.symlink_metadata()?.file_type(); -+ -+ if current_path_type.is_symlink() { -+ continue; -+ } -+ if !current_path_type.is_dir() { - continue; - } - dir_list.push(self::realpath(current_path.as_path())?); -@@ -94,8 +99,11 @@ pub fn list_all_files>(directory: P, recursive: bool) -> std::io: - for dir_entry in std::fs::read_dir(search_path)? { - if let Ok(entry) = dir_entry { - let current_path = entry.path(); -- let current_path_type = current_path.metadata()?.file_type(); -+ let current_path_type = current_path.symlink_metadata()?.file_type(); - -+ if current_path_type.is_symlink() { -+ continue; -+ } - if current_path_type.is_file() { - file_list.push(self::realpath(current_path.as_path())?); - } -@@ -124,8 +132,11 @@ pub fn list_all_files_ext>(directory: P, file_ext: &str, recursiv - for dir_entry in std::fs::read_dir(search_path)? { - if let Ok(entry) = dir_entry { - let current_path = entry.path(); -- let current_path_type = current_path.metadata()?.file_type(); -+ let current_path_type = current_path.symlink_metadata()?.file_type(); - -+ if current_path_type.is_symlink() { -+ continue; -+ } - if current_path_type.is_file() { - let current_path_ext = current_path.extension().unwrap_or_default(); - if current_path_ext == file_ext { --- -2.33.0 - - -From 641b7a2cc731cf3a1fe4874ed5cfc51f328b764e Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Sat, 17 Dec 2022 11:51:31 +0800 -Subject: [PATCH 11/20] build: match release of source pkg & debuginfo pkg - -Signed-off-by: renoseven ---- - build/src/cli/cli.rs | 9 +++------ - 1 file changed, 3 insertions(+), 6 deletions(-) - -diff --git a/build/src/cli/cli.rs b/build/src/cli/cli.rs -index 79dec44..a8980c2 100644 ---- a/build/src/cli/cli.rs -+++ b/build/src/cli/cli.rs -@@ -129,17 +129,14 @@ impl PatchBuildCLI { - info!("{}", dbg_pkg_info); - info!("------------------------------\n"); - -- let src_pkg_name = src_pkg_info.get_name(); -- let src_pkg_ver = src_pkg_info.get_version(); -- let dbg_pkg_name = dbg_pkg_info.get_name(); -- let dbg_pkg_ver = dbg_pkg_info.get_version(); -- if !dbg_pkg_name.contains(src_pkg_name) || (src_pkg_ver != dbg_pkg_ver) { -+ if !dbg_pkg_info.get_name().contains(src_pkg_info.get_name()) || -+ (src_pkg_info.get_version() != dbg_pkg_info.get_version()) || -+ (src_pkg_info.get_release() != dbg_pkg_info.get_release()) { - return Err(std::io::Error::new( - std::io::ErrorKind::InvalidInput, - format!("Debuginfo package does not match the source package"), - )); - } -- - Ok(src_pkg_info) - } - --- -2.33.0 - - -From bec264ec1ba7eb30c360caa3806c34711e6d8f83 Mon Sep 17 00:00:00 2001 -From: Longjun Luo -Date: Mon, 19 Dec 2022 02:38:34 +0800 -Subject: [PATCH 12/20] upatch: resolve local symbols within upatch-diff - -Symbol resolution will be finished in 3 steps: -1. local symbols resolved in upatch-diff -2. global symbols resolved in upatch-tool -3. external symbols resolved in kmod - -Signed-off-by: Longjun Luo ---- - upatch/kmod/common.c | 2 ++ - upatch/upatch-diff/create-diff-object.c | 3 ++ - upatch/upatch-diff/elf-resolve.c | 42 +++++++++++++++++++++++++ - upatch/upatch-diff/elf-resolve.h | 27 ++++++++++++++++ - upatch/upatch-tool/upatch-resolve.c | 14 ++++++--- - 5 files changed, 83 insertions(+), 5 deletions(-) - create mode 100755 upatch/upatch-diff/elf-resolve.c - create mode 100755 upatch/upatch-diff/elf-resolve.h - -diff --git a/upatch/kmod/common.c b/upatch/kmod/common.c -index 638c955..ebd04f8 100644 ---- a/upatch/kmod/common.c -+++ b/upatch/kmod/common.c -@@ -65,6 +65,8 @@ struct file *d_open_inode(struct inode *inode) - goto out_unlock; - - d_file = filp_open(p, O_RDWR, 0); -+ if (IS_ERR(d_file)) -+ pr_err("open patch file failed - %ld \n", PTR_ERR(d_file)); - out_unlock: - __putname(name); - // spin_unlock_irqrestore(&inode->i_lock, flags); -diff --git a/upatch/upatch-diff/create-diff-object.c b/upatch/upatch-diff/create-diff-object.c -index dba549f..9179947 100644 ---- a/upatch/upatch-diff/create-diff-object.c -+++ b/upatch/upatch-diff/create-diff-object.c -@@ -53,6 +53,7 @@ - #include "elf-insn.h" - #include "elf-compare.h" - #include "elf-correlate.h" -+#include "elf-resolve.h" - #include "elf-create.h" - #include "running-elf.h" - #include "upatch-manage.h" -@@ -861,6 +862,8 @@ int main(int argc, char*argv[]) - - upatch_create_strtab(&uelf_out); - -+ upatch_partly_resolve(&uelf_out, &relf); -+ - upatch_create_symtab(&uelf_out); - - upatch_dump_kelf(&uelf_out); -diff --git a/upatch/upatch-diff/elf-resolve.c b/upatch/upatch-diff/elf-resolve.c -new file mode 100755 -index 0000000..3878079 ---- /dev/null -+++ b/upatch/upatch-diff/elf-resolve.c -@@ -0,0 +1,42 @@ -+/* -+ * upatch-resolve.c -+ * -+ * Copyright (C) 2022 Longjun Luo -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2 -+ * of the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, -+ * 02110-1301, USA. -+ */ -+ -+ -+#include -+ -+#include "running-elf.h" -+ -+/* To avoid mutiple definiation, only handle local symbols */ -+void upatch_partly_resolve(struct upatch_elf *uelf, struct running_elf *relf) -+{ -+ struct symbol *sym; -+ struct lookup_result symbol; -+ -+ list_for_each_entry(sym, &uelf->symbols, list) { -+ if (sym->sym.st_shndx == SHN_UNDEF && sym->bind == STB_LOCAL) { -+ if (!lookup_relf(relf, sym, &symbol)) -+ continue; -+ /* keep it undefined for link purpose */ -+ sym->sym.st_value = symbol.symbol->addr; -+ sym->sym.st_size = symbol.symbol->size; -+ } -+ } -+} -\ No newline at end of file -diff --git a/upatch/upatch-diff/elf-resolve.h b/upatch/upatch-diff/elf-resolve.h -new file mode 100755 -index 0000000..ef031f3 ---- /dev/null -+++ b/upatch/upatch-diff/elf-resolve.h -@@ -0,0 +1,27 @@ -+/* -+ * upatch-resolve.h -+ * -+ * Copyright (C) 2022 Longjun Luo -+ * -+ * This program is free software; you can redistribute it and/or -+ * modify it under the terms of the GNU General Public License -+ * as published by the Free Software Foundation; either version 2 -+ * of the License, or (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA, -+ * 02110-1301, USA. -+ */ -+ -+#ifndef __UPATCH_RESOLVE_H_ -+#define __UPATCH_RESOLVE_H_ -+ -+void upatch_partly_resolve(struct upatch_elf *, struct running_elf *); -+ -+#endif /* __UPATCH_RESOLVE_H_ */ -\ No newline at end of file -diff --git a/upatch/upatch-tool/upatch-resolve.c b/upatch/upatch-tool/upatch-resolve.c -index 0b94def..9427cf3 100644 ---- a/upatch/upatch-tool/upatch-resolve.c -+++ b/upatch/upatch-tool/upatch-resolve.c -@@ -133,12 +133,16 @@ static int partly_resolve_patch(int patch_fd, Elf64_Sym *binary_symtab, - - name = strtab + sym->st_name; - if (sym->st_shndx == SHN_UNDEF) { -- ret = __partly_resolve_patch(sym, name, -- binary_symtab, binary_symnum, binary_strtab); -- if (ret) -- goto out; -+ if (ELF64_ST_BIND(sym->st_info) == STB_LOCAL) { -+ /* only partly resolved undefined symbol could have st_value */ -+ if (sym->st_value) -+ sym->st_shndx = SHN_LIVEPATCH; -+ } else { -+ ret = __partly_resolve_patch(sym, name, -+ binary_symtab, binary_symnum, binary_strtab); -+ if (ret) goto out; -+ } - } -- - } - - ret = 0; --- -2.33.0 - - -From 1158ae346a870bc706e61619dbc8d2178963f49e Mon Sep 17 00:00:00 2001 -From: Longjun Luo -Date: Tue, 20 Dec 2022 21:33:15 +0800 -Subject: [PATCH 13/20] kmod: do the patch read within attach - -Since uprobe handler is a soft interrupt handler, -it is forbidden to call block API in its context. - -For filp_open, single thread is non-block. -While mutiple threads are blocked. - -Signed-off-by: Longjun Luo ---- - upatch/kmod/common.c | 25 ------- - upatch/kmod/common.h | 2 - - upatch/kmod/compiler.c | 2 +- - upatch/kmod/kmod.c | 9 ++- - upatch/kmod/patch-load.c | 23 +++--- - upatch/kmod/patch.c | 150 ++++++++++++++++++++++++++++++--------- - upatch/kmod/patch.h | 16 ++++- - 7 files changed, 148 insertions(+), 79 deletions(-) - -diff --git a/upatch/kmod/common.c b/upatch/kmod/common.c -index ebd04f8..a39cde5 100644 ---- a/upatch/kmod/common.c -+++ b/upatch/kmod/common.c -@@ -47,28 +47,3 @@ struct file *get_binary_file_from_addr(struct task_struct *task, unsigned long a - return vma->vm_file; - } - --/* TODO: handle read from inode, need handle lock here */ --struct file *d_open_inode(struct inode *inode) --{ -- struct dentry *alias; -- // unsigned long flags; -- char *name = __getname(), *p; -- struct file *d_file = NULL; -- -- if (hlist_empty(&inode->i_dentry)) -- return NULL; -- -- // raw_spin_lock_bh(&inode->i_lock, flags); -- alias = hlist_entry(inode->i_dentry.first, struct dentry, d_u.d_alias); -- p = dentry_path_raw(alias, name, PATH_MAX); -- if (IS_ERR(p)) -- goto out_unlock; -- -- d_file = filp_open(p, O_RDWR, 0); -- if (IS_ERR(d_file)) -- pr_err("open patch file failed - %ld \n", PTR_ERR(d_file)); --out_unlock: -- __putname(name); -- // spin_unlock_irqrestore(&inode->i_lock, flags); -- return d_file; --} -diff --git a/upatch/kmod/common.h b/upatch/kmod/common.h -index bf0af51..4046904 100644 ---- a/upatch/kmod/common.h -+++ b/upatch/kmod/common.h -@@ -20,8 +20,6 @@ int copy_para_from_user(unsigned long, char *, size_t); - - struct file *get_binary_file_from_addr(struct task_struct *, unsigned long); - --struct file *d_open_inode(struct inode *); -- - static bool inline streql(const char *a, const char *b) - { - return strlen(a) == strlen(b) && !strncmp(a, b, strlen(a)); -diff --git a/upatch/kmod/compiler.c b/upatch/kmod/compiler.c -index 899b83f..12a6f51 100755 ---- a/upatch/kmod/compiler.c -+++ b/upatch/kmod/compiler.c -@@ -669,7 +669,7 @@ static int elf_check(char *elf_path, loff_t *entry_offset) - - ret = __elf_check(file, entry_offset); - put_file: -- fput(file); -+ filp_close(file, NULL); - out: - return ret; - } -diff --git a/upatch/kmod/kmod.c b/upatch/kmod/kmod.c -index d31037f..29655b7 100755 ---- a/upatch/kmod/kmod.c -+++ b/upatch/kmod/kmod.c -@@ -90,15 +90,18 @@ static int update_status(unsigned long user_addr, - entity->set_status = status; - } - -- if (entity->set_status == UPATCH_STATE_REMOVED) -+ if (entity->set_status == UPATCH_STATE_REMOVED) { -+ upatch_put_patch_entity(entity->patch_entity); -+ entity->patch_entity = NULL; - entity->set_patch = NULL; -+ } - - ret = 0; - out_lock: - mutex_unlock(&entity->entity_status_lock); - out: - if (elf_file && !IS_ERR(elf_file)) -- fput(elf_file); -+ filp_close(elf_file, NULL); - return ret; - } - -@@ -127,7 +130,7 @@ static int check_status(unsigned long user_addr) - mutex_unlock(&entity->entity_status_lock); - out: - if (elf_file && !IS_ERR(elf_file)) -- fput(elf_file); -+ filp_close(elf_file, NULL); - return ret; - } - -diff --git a/upatch/kmod/patch-load.c b/upatch/kmod/patch-load.c -index 169ee1f..f753104 100644 ---- a/upatch/kmod/patch-load.c -+++ b/upatch/kmod/patch-load.c -@@ -883,14 +883,19 @@ static int complete_formation(struct upatch_module *mod, struct inode *patch) - } - - /* The main idea is from insmod */ --int upatch_load(struct file *binary_file, struct file *patch_file, -- struct upatch_load_info *info) -+int upatch_load(struct file *binary_file, struct inode *set_patch, -+ struct patch_entity *patch_entity, struct upatch_load_info *info) - { - int err; -- loff_t offset; - elf_addr_t min_addr; - struct upatch_module *mod; - -+ if (patch_entity == NULL) { -+ pr_err("invalid patch entity \n"); -+ err = -EINVAL; -+ goto free_hdr; -+ } -+ - min_addr = calculate_load_address(binary_file, true); - if (min_addr == -1) { - pr_err("unable to obtain minimal execuatable address \n"); -@@ -913,21 +918,15 @@ int upatch_load(struct file *binary_file, struct file *patch_file, - - info->running_elf.load_info = info; - -- info->len = i_size_read(file_inode(patch_file)); -+ info->len = patch_entity->patch_size; - info->hdr = vmalloc(info->len); - if (!info->hdr) { - err = -ENOMEM; - goto free_hdr; - } - -- offset = 0; - /* read patch file into kernel memory */ -- err = kernel_read(patch_file, info->hdr, info->len, &offset); -- if (err != info->len) { -- pr_err("read kernel failed - %d \n", err); -- err = -EINVAL; -- goto free_hdr; -- } -+ memcpy(info->hdr, patch_entity->patch_buff, info->len); - - err = patch_header_check(info); - if (err) { -@@ -969,7 +968,7 @@ int upatch_load(struct file *binary_file, struct file *patch_file, - if (err < 0) - goto free_module; - -- err = complete_formation(mod, file_inode(patch_file)); -+ err = complete_formation(mod, set_patch); - if (err < 0) - goto free_module; - -diff --git a/upatch/kmod/patch.c b/upatch/kmod/patch.c -index 7bebd1b..39ed363 100644 ---- a/upatch/kmod/patch.c -+++ b/upatch/kmod/patch.c -@@ -9,6 +9,7 @@ - - #include - #include -+#include - #include /* for MAX_ARG_STRLEN */ - #include - #include -@@ -16,6 +17,7 @@ - #include - #include - #include -+#include - - #include "common.h" - #include "patch.h" -@@ -26,6 +28,9 @@ - static DEFINE_MUTEX(upatch_entity_lock); - static LIST_HEAD(upatch_entity_list); - -+/* lock for all patch entity, since we need free its memory */ -+static DEFINE_SPINLOCK(patch_entity_lock); -+ - static struct upatch_entity *__get_upatch_entity(struct inode *uinode) - { - struct upatch_entity *entity; -@@ -45,17 +50,84 @@ struct upatch_entity *upatch_entity_get(struct inode *uinode) - return entity; - } - --static int __insert_upatch_entity(struct inode *binary, struct inode *patch) -+void __remove_patch_entity(struct patch_entity *patch_entity) - { -- struct upatch_entity *entity; -+ if (patch_entity->patch_buff) -+ vm_munmap((unsigned long)patch_entity->patch_buff, patch_entity->patch_size); -+ patch_entity->patch_buff = NULL; -+ patch_entity->patch_size = 0; -+ kfree(patch_entity); -+} -+ -+/* After put, holder should never use this memory */ -+void upatch_put_patch_entity(struct patch_entity *patch_entity) -+{ -+ if (patch_entity == NULL) -+ return; -+ -+ spin_lock(&patch_entity_lock); -+ patch_entity->ref --; -+ if (patch_entity->ref == 0) -+ __remove_patch_entity(patch_entity); -+ spin_unlock(&patch_entity_lock); -+} -+ -+void upatch_get_patch_entity(struct patch_entity *patch_entity) -+{ -+ if (patch_entity == NULL) -+ return; -+ -+ spin_lock(&patch_entity_lock); -+ patch_entity->ref ++; -+ spin_unlock(&patch_entity_lock); -+} -+ -+int upatch_init_patch_entity(struct patch_entity *patch_entity, struct file *patch) -+{ -+ int ret; -+ -+ if (patch == NULL) -+ return 0; -+ -+ patch_entity->ref = 1; -+ patch_entity->patch_size = i_size_read(file_inode(patch)); -+ patch_entity->patch_buff = vmalloc(patch_entity->patch_size); -+ if (!patch_entity->patch_buff) -+ return -ENOMEM; -+ -+ ret = kernel_read(patch, patch_entity->patch_buff, patch_entity->patch_size, 0); -+ if (ret != patch_entity->patch_size) { -+ pr_err("read patch file for entity failed. \n"); -+ vm_munmap((unsigned long)patch_entity->patch_buff, patch_entity->patch_size); -+ return -ENOEXEC; -+ } -+ return 0; -+} -+ -+static int __insert_upatch_entity(struct file *binary, struct file *patch) -+{ -+ struct upatch_entity *entity = NULL; -+ int err; - - entity = kzalloc(sizeof(*entity), GFP_KERNEL); - if (!entity) - return -ENOMEM; - -- entity->binary = binary; -- entity->set_patch = patch; -+ entity->patch_entity = kzalloc(sizeof(*entity->patch_entity), GFP_KERNEL); -+ if (!entity->patch_entity) { -+ err = -ENOMEM; -+ goto err_out; -+ } -+ -+ err = upatch_init_patch_entity(entity->patch_entity, patch); -+ if (err) { -+ err = -ENOMEM; -+ goto err_out; -+ } -+ -+ entity->set_patch = file_inode(patch); - entity->set_status = UPATCH_STATE_ATTACHED; -+ entity->binary = file_inode(binary); - - mutex_init(&entity->entity_status_lock); - INIT_LIST_HEAD(&entity->offset_list); -@@ -64,19 +136,45 @@ static int __insert_upatch_entity(struct inode *binary, struct inode *patch) - /* when everything is ok, add it to the list */ - list_add(&entity->list, &upatch_entity_list); - return 0; -+ -+err_out: -+ if (entity && entity->patch_entity) -+ __remove_patch_entity(entity->patch_entity); -+ if (entity && entity->patch_entity) -+ kfree(entity->patch_entity); -+ if (entity) -+ kfree(entity); -+ return err; - } - --static int __update_upatch_entity(struct upatch_entity *entity, struct inode *patch) -+static int __update_upatch_entity(struct upatch_entity *entity, struct file *patch) - { -- /* if lock upatch_entity_lock necessary, always before entity_status_lock */ -+ int ret; -+ -+ if (patch == NULL) -+ return -EINVAL; -+ -+ /* upatch_entity_lock > entity_status_lock > patch_entity_lock */ - mutex_lock(&entity->entity_status_lock); -- entity->set_patch = patch; -+ -+ upatch_put_patch_entity(entity->patch_entity); -+ entity->patch_entity = NULL; -+ -+ entity->patch_entity = kzalloc(sizeof(*entity->patch_entity), GFP_KERNEL); -+ ret = upatch_init_patch_entity(entity->patch_entity, patch); -+ if (ret != 0) { -+ kfree(entity->patch_entity); -+ goto out; -+ } -+ -+ entity->set_patch = file_inode(patch); - entity->set_status = UPATCH_STATE_ATTACHED; -+out: - mutex_unlock(&entity->entity_status_lock); -- return 0; -+ return ret; - } - --static int update_upatch_entity(struct inode *binary, struct inode *patch) -+static int update_upatch_entity(struct file *binary, struct file *patch) - { - int ret; - struct upatch_entity *entity; -@@ -85,7 +183,7 @@ static int update_upatch_entity(struct inode *binary, struct inode *patch) - return -EINVAL; - - mutex_lock(&upatch_entity_lock); -- entity = __get_upatch_entity(binary); -+ entity = __get_upatch_entity(file_inode(binary)); - if (entity) - ret = __update_upatch_entity(entity, patch); - else -@@ -141,26 +239,6 @@ static bool check_upatch(Elf_Ehdr *ehdr) - return true; - } - --static int do_module_load(struct upatch_entity *entity, struct file *binary_file, -- struct upatch_load_info *info) --{ -- int ret; -- struct file *patch_file = NULL; -- -- patch_file = d_open_inode(entity->set_patch); -- if (!patch_file || IS_ERR(patch_file)) { -- pr_err("open patch inode failed \n"); -- ret = -ENOEXEC; -- goto out; -- } -- -- ret = upatch_load(binary_file, patch_file, info); --out: -- if (patch_file && !IS_ERR(patch_file)) -- fput(patch_file); -- return ret; --} -- - static int do_module_active(struct upatch_module *module, struct pt_regs *regs) - { - struct upatch_patch_func __user *upatch_funs; -@@ -237,6 +315,7 @@ static int uprobe_patch_handler(struct uprobe_consumer *self, struct pt_regs *re - - enum upatch_module_state set_status; - struct inode *set_patch; -+ struct patch_entity *patch_entity = NULL; - - pc = instruction_pointer(regs); - -@@ -259,6 +338,8 @@ static int uprobe_patch_handler(struct uprobe_consumer *self, struct pt_regs *re - mutex_lock(&entity->entity_status_lock); - set_status = entity->set_status; - set_patch = entity->set_patch; -+ patch_entity = entity->patch_entity; -+ upatch_get_patch_entity(patch_entity); - mutex_unlock(&entity->entity_status_lock); - - upatch_mod = upatch_module_get_or_create(entity, task_pid_nr(current)); -@@ -297,7 +378,7 @@ static int uprobe_patch_handler(struct uprobe_consumer *self, struct pt_regs *re - } - - /* we can be sure module->real_patch == set_patch/NULL */ -- if (need_resolve && do_module_load(entity, binary_file, &info)) { -+ if (need_resolve && upatch_load(binary_file, set_patch, patch_entity, &info)) { - pr_err("load patch failed \n"); - goto out_unlock; - } -@@ -310,6 +391,7 @@ static int uprobe_patch_handler(struct uprobe_consumer *self, struct pt_regs *re - out_unlock: - mutex_unlock(&upatch_mod->module_status_lock); - out: -+ upatch_put_patch_entity(patch_entity); - return ret; - } - -@@ -427,7 +509,7 @@ static int handle_upatch_funcs(struct file *binary_file, struct file *patch_file - /* TODO: if failed, we need clean this entity */ - /* TODO: check if other patch has taken effect */ - /* before uprobe works, we must set upatch entity first */ -- ret = update_upatch_entity(file_inode(binary_file), file_inode(patch_file)); -+ ret = update_upatch_entity(binary_file, patch_file); - if (ret) { - pr_err("update upatch entity failed - %d \n", ret); - goto out; -@@ -571,8 +653,8 @@ out: - if (eshdrs) - kfree(eshdrs); - if (patch_file && !IS_ERR(patch_file)) -- fput(patch_file); -+ filp_close(patch_file, NULL); - if (binary_file && !IS_ERR(binary_file)) -- fput(binary_file); -+ filp_close(binary_file, NULL); - return ret; - } -diff --git a/upatch/kmod/patch.h b/upatch/kmod/patch.h -index f9e1b2e..91b7fb0 100644 ---- a/upatch/kmod/patch.h -+++ b/upatch/kmod/patch.h -@@ -90,6 +90,12 @@ struct uprobe_offset { - struct list_head list; - }; - -+struct patch_entity { -+ unsigned int ref; -+ void *patch_buff; -+ size_t patch_size; -+}; -+ - struct upatch_entity { - struct inode *binary; - struct list_head list; -@@ -98,8 +104,11 @@ struct upatch_entity { - struct mutex entity_status_lock; - - /* used to handle command */ -- struct inode *set_patch; - enum upatch_module_state set_status; -+ struct inode *set_patch; -+ -+ /* sync with set_patch */ -+ struct patch_entity *patch_entity; - - struct list_head offset_list; - struct list_head module_list; -@@ -144,9 +153,12 @@ struct upatch_load_info { - struct upatch_entity *upatch_entity_get(struct inode *); - struct upatch_module *upatch_module_get_or_create(struct upatch_entity *, pid_t); - void upatch_module_deallocate(struct upatch_module *); -+void upatch_put_patch_entity(struct patch_entity *); -+void upatch_get_patch_entity(struct patch_entity *); - - /* management releated */ - int upatch_attach(const char *, const char *); --int upatch_load(struct file *, struct file *, struct upatch_load_info *); -+int upatch_load(struct file *, struct inode *, struct patch_entity *, -+ struct upatch_load_info *); - - #endif /* _UPATCH_PATCH_H */ --- -2.33.0 - - -From c49e2351a906d595b686a810d9f8e095e8a8eced Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Tue, 20 Dec 2022 22:17:46 +0800 -Subject: [PATCH 14/20] build: add rpm epoch support - -Signed-off-by: renoseven ---- - build/src/cli/args.rs | 12 ++ - build/src/cli/cli.rs | 38 +++-- - build/src/constants.rs | 7 +- - build/src/package/package_info.rs | 74 +++++++-- - build/src/package/rpm_builder.rs | 5 +- - build/src/package/rpm_extractor.rs | 2 +- - build/src/package/rpm_helper.rs | 2 +- - build/src/package/rpm_spec_generator.rs | 42 +++-- - build/src/package/rpm_spec_helper.rs | 7 +- - .../src/patch/kernel_patch/kpatch_builder.rs | 10 +- - .../patch/kernel_patch/kpatch_builder_args.rs | 4 +- - build/src/patch/kernel_patch/kpatch_helper.rs | 2 +- - build/src/patch/patch_builder_factory.rs | 4 +- - build/src/patch/patch_info.rs | 147 +++++++----------- - build/src/patch/user_patch/upatch_builder.rs | 2 +- - build/src/patch/user_patch/upatch_helper.rs | 2 +- - build/src/util/sys.rs | 2 +- - 17 files changed, 196 insertions(+), 166 deletions(-) - -diff --git a/build/src/cli/args.rs b/build/src/cli/args.rs -index f4b9ed4..583df2c 100644 ---- a/build/src/cli/args.rs -+++ b/build/src/cli/args.rs -@@ -10,6 +10,10 @@ pub struct CliArguments { - #[arg(short='n', long)] - pub patch_name: String, - -+ /// Patch architecture -+ #[arg(long, default_value=CLI_DEFAULT_PATCH_ARCH)] -+ pub patch_arch: String, -+ - /// Patch version - #[arg(long, default_value=CLI_DEFAULT_PATCH_VERSION)] - pub patch_version: String, -@@ -26,6 +30,14 @@ pub struct CliArguments { - #[arg(short, long)] - pub target_elfname: Option, - -+ /// parch target architecture -+ #[arg(long)] -+ pub target_arch: Option, -+ -+ /// Patch target epoch -+ #[arg(long)] -+ pub target_epoch: Option, -+ - /// Patch target version - #[arg(long)] - pub target_version: Option, -diff --git a/build/src/cli/cli.rs b/build/src/cli/cli.rs -index a8980c2..d88d830 100644 ---- a/build/src/cli/cli.rs -+++ b/build/src/cli/cli.rs -@@ -4,14 +4,14 @@ use regex::Regex; - use crate::package::{PackageInfo, PackageType}; - use crate::package::{RpmExtractor, RpmHelper, RpmSpecHelper, RpmBuilder}; - --use crate::patch::{PatchInfo, PatchName}; -+use crate::patch::PatchInfo; - use crate::patch::{PatchHelper, PatchBuilderFactory}; - - use crate::log::{Logger, LevelFilter}; - use crate::log::{info, warn, error}; - - use crate::constants::*; --use crate::util::fs; -+use crate::util::{sys, fs}; - - use super::args::CliArguments; - use super::workdir::CliWorkDir; -@@ -130,6 +130,8 @@ impl PatchBuildCLI { - info!("------------------------------\n"); - - if !dbg_pkg_info.get_name().contains(src_pkg_info.get_name()) || -+ (src_pkg_info.get_arch() != dbg_pkg_info.get_arch()) || -+ (src_pkg_info.get_epoch() != dbg_pkg_info.get_epoch()) || - (src_pkg_info.get_version() != dbg_pkg_info.get_version()) || - (src_pkg_info.get_release() != dbg_pkg_info.get_release()) { - return Err(std::io::Error::new( -@@ -182,19 +184,22 @@ impl PatchBuildCLI { - let patch_target_file = fs::find_file(pkg_source_dir, PKG_TARGET_FILE_NAME, false, false); - match &patch_target_file { - Ok(file_path) => { -- let patch_target_name = fs::read_file_to_string(file_path)?.parse::()?; -- args.target_name.get_or_insert(patch_target_name.get_name().to_owned()); -- args.target_version.get_or_insert(patch_target_name.get_version().to_owned()); -- args.target_release.get_or_insert(patch_target_name.get_release().to_owned()); -- args.target_license.get_or_insert(pkg_info.get_license().to_owned()); -+ let patch_target = fs::read_file_to_string(file_path)?.parse::()?; -+ args.target_name.get_or_insert(patch_target.get_name().to_owned()); -+ args.target_arch.get_or_insert(patch_target.get_arch().to_owned()); -+ args.target_epoch.get_or_insert(patch_target.get_epoch().to_owned()); -+ args.target_version.get_or_insert(patch_target.get_version().to_owned()); -+ args.target_release.get_or_insert(patch_target.get_release().to_owned()); - }, - Err(_) => { - args.target_name.get_or_insert(pkg_info.get_name().to_owned()); -+ args.target_arch.get_or_insert(pkg_info.get_arch().to_owned()); -+ args.target_epoch.get_or_insert(pkg_info.get_epoch().to_owned()); - args.target_version.get_or_insert(pkg_info.get_version().to_owned()); - args.target_release.get_or_insert(pkg_info.get_release().to_owned()); -- args.target_license.get_or_insert(pkg_info.get_license().to_owned()); - } - } -+ args.target_license.get_or_insert(pkg_info.get_license().to_owned()); - - // Collect patch list from patched source package - if patch_version_file.is_ok() && patch_target_file.is_ok() { -@@ -213,22 +218,27 @@ impl PatchBuildCLI { - fn check_build_args(&self) -> std::io::Result<()> { - let args = &self.args; - -- if args.target_name.is_none() || args.target_version.is_none() || args.target_release.is_none() { -+ let patch_arch = args.patch_arch.as_str(); -+ if patch_arch != sys::get_cpu_arch() { - return Err(std::io::Error::new( - std::io::ErrorKind::InvalidInput, -- format!("Patch target info is not complete"), -+ format!("Patch arch '{}' is unsupported", patch_arch), - )); - } - -- if args.target_elfname.is_none() { -+ let target_arch = args.target_arch.as_deref().unwrap(); -+ if args.patch_arch.as_str() != target_arch { - return Err(std::io::Error::new( - std::io::ErrorKind::InvalidInput, -- format!("Patch target elf name is empty"), -+ format!("Target arch '{}' is not match patch arch '{}'", target_arch, patch_arch), - )); - } - -- if args.target_license.is_none() { -- warn!("Warning: Patch target license is not set"); -+ if args.target_elfname.is_none() { -+ return Err(std::io::Error::new( -+ std::io::ErrorKind::InvalidInput, -+ format!("Patch target elf name is empty"), -+ )); - } - - if args.skip_compiler_check { -diff --git a/build/src/constants.rs b/build/src/constants.rs -index 6940989..c3dff49 100644 ---- a/build/src/constants.rs -+++ b/build/src/constants.rs -@@ -1,4 +1,4 @@ --use crate::cmd::ExternCommand; -+use crate::{cmd::ExternCommand, util::sys}; - - // CLI Strings - pub const CLI_NAME: &str = env!("CARGO_PKG_NAME"); -@@ -6,8 +6,9 @@ pub const CLI_VERSION: &str = env!("CARGO_PKG_VERSION"); - pub const CLI_DESCRIPTION: &str = env!("CARGO_PKG_DESCRIPTION"); - pub const CLI_COMMAND_NAME: &str = "syscare build"; - pub const CLI_LOG_FILE_NAME: &str = "build.log"; -+pub const CLI_DEFAULT_PATCH_ARCH: &str = sys::get_cpu_arch(); - pub const CLI_DEFAULT_PATCH_VERSION: &str = "1"; --pub const CLI_DEFAULT_PATCH_DESCRIPTION: &str = "None"; -+pub const CLI_DEFAULT_PATCH_DESCRIPTION: &str = "(none)"; - pub const CLI_DEFAULT_WORKDIR: &str = "."; - pub const CLI_DEFAULT_OUTPUT_DIR: &str = "."; - pub const CLI_DEFAULT_SKIP_COMPILER_CHECK: &str = "false"; -@@ -34,7 +35,7 @@ pub const PKG_BUILD_ROOT_DIR_NAME: &str = "rpmbuild"; - pub const PKG_FILE_EXTENSION: &str = "rpm"; - pub const PKG_FLAG_PATCH_BINARY: &str = "patch"; - pub const PKG_FLAG_PATCHED_SOURCE: &str = "patched"; --pub const PKG_FLAG_NO_SOURCE_PKG: &str = "(none)"; -+pub const PKG_FLAG_NONE: &str = "(none)"; - pub const PKG_VERSION_FILE_NAME: &str = "syscare-patch-version"; - pub const PKG_TARGET_FILE_NAME: &str = "syscare-patch-target"; - pub const PKG_SPEC_FILE_EXTENSION: &str = "spec"; -diff --git a/build/src/package/package_info.rs b/build/src/package/package_info.rs -index e2a9531..f8af773 100644 ---- a/build/src/package/package_info.rs -+++ b/build/src/package/package_info.rs -@@ -16,13 +16,17 @@ impl std::fmt::Display for PackageType { - } - } - -+#[derive(Clone)] - #[derive(Debug)] - pub struct PackageInfo { -- name: String, -- version: String, -- release: String, -- license: String, -- kind: PackageType, -+ name: String, -+ kind: PackageType, -+ arch: String, -+ epoch: String, -+ version: String, -+ release: String, -+ license: String, -+ source_rpm: String, - } - - impl PackageInfo { -@@ -30,6 +34,18 @@ impl PackageInfo { - &self.name - } - -+ pub fn get_type(&self) -> PackageType { -+ self.kind -+ } -+ -+ pub fn get_arch(&self) -> &str { -+ &self.arch -+ } -+ -+ pub fn get_epoch(&self) -> &str { -+ &self.epoch -+ } -+ - pub fn get_version(&self) -> &str { - &self.version - } -@@ -42,18 +58,38 @@ impl PackageInfo { - &self.license - } - -- pub fn get_type(&self) -> PackageType { -- self.kind -+ pub fn get_source_rpm(&self) -> &str { -+ &self.source_rpm - } - } - - impl PackageInfo { -- pub fn parse_from(pkg_path: &str) -> std::io::Result { -+ pub fn get_simple_name(&self) -> String { -+ format!("{}-{}-{}", -+ self.get_name(), -+ self.get_version(), -+ self.get_release() -+ ) -+ } -+ -+ pub fn query_from(pkg_path: &str) -> std::io::Result { - Ok(RpmHelper::query_package_info( - pkg_path, -- "%{NAME}|%{VERSION}|%{RELEASE}|%{LICENSE}|%{SOURCERPM}" -+ "%{NAME}|%{ARCH}|%{EPOCH}|%{VERSION}|%{RELEASE}|%{LICENSE}|%{SOURCERPM}" - )?.parse::()?) - } -+ -+ pub fn to_query_str(&self) -> String { -+ format!("{}|{}|{}|{}|{}|{}|{}", -+ self.get_name(), -+ self.get_arch(), -+ self.get_epoch(), -+ self.get_version(), -+ self.get_release(), -+ self.get_license(), -+ self.get_source_rpm(), -+ ) -+ } - } - - impl std::str::FromStr for PackageInfo { -@@ -61,7 +97,7 @@ impl std::str::FromStr for PackageInfo { - - fn from_str(s: &str) -> Result { - let pkg_info = s.split('|').collect::>(); -- if pkg_info.len() < 5 { -+ if pkg_info.len() < 7 { - return Err(std::io::Error::new( - std::io::ErrorKind::InvalidData, - format!("Parse package info failed") -@@ -69,17 +105,19 @@ impl std::str::FromStr for PackageInfo { - } - - let name = pkg_info[0].to_owned(); -- let version = pkg_info[1].to_owned(); -- let release = pkg_info[2].to_owned(); -- let license = pkg_info[3].to_owned(); -- let source_rpm = pkg_info[4].to_owned(); -- -- let kind = match source_rpm == PKG_FLAG_NO_SOURCE_PKG { -+ let arch = pkg_info[1].to_owned(); -+ let epoch = pkg_info[2].to_owned(); -+ let version = pkg_info[3].to_owned(); -+ let release = pkg_info[4].to_owned(); -+ let license = pkg_info[5].to_owned(); -+ let source_rpm = pkg_info[6].to_owned(); -+ -+ let kind = match source_rpm == PKG_FLAG_NONE { - true => PackageType::SourcePackage, - false => PackageType::BinaryPackage, - }; - -- Ok(Self { name, version, release, license, kind }) -+ Ok(Self { name, kind, arch, epoch, version, release, license, source_rpm }) - } - } - -@@ -87,6 +125,8 @@ impl std::fmt::Display for PackageInfo { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_fmt(format_args!("name: {}\n", self.get_name()))?; - f.write_fmt(format_args!("type: {}\n", self.get_type()))?; -+ f.write_fmt(format_args!("arch: {}\n", self.get_arch()))?; -+ f.write_fmt(format_args!("epoch: {}\n", self.get_epoch()))?; - f.write_fmt(format_args!("version: {}\n", self.get_version()))?; - f.write_fmt(format_args!("release: {}\n", self.get_release()))?; - f.write_fmt(format_args!("license: {}", self.get_license()))?; -diff --git a/build/src/package/rpm_builder.rs b/build/src/package/rpm_builder.rs -index e507708..2897c6e 100644 ---- a/build/src/package/rpm_builder.rs -+++ b/build/src/package/rpm_builder.rs -@@ -30,14 +30,13 @@ impl RpmBuilder { - let rpm_source_dir = self.build_root.sources_dir(); - let version_file_path = format!("{}/{}", rpm_source_dir, PKG_VERSION_FILE_NAME); - let target_file_path = format!("{}/{}", rpm_source_dir, PKG_TARGET_FILE_NAME); -- - fs::write_string_to_file( - version_file_path, -- patch_info.get_patch().get_version() -+ patch_info.get_version() - )?; - fs::write_string_to_file( - target_file_path, -- patch_info.get_target().to_string().as_str() -+ &patch_info.get_target().to_query_str() - )?; - - Ok(()) -diff --git a/build/src/package/rpm_extractor.rs b/build/src/package/rpm_extractor.rs -index 0f2ffc0..2f63755 100644 ---- a/build/src/package/rpm_extractor.rs -+++ b/build/src/package/rpm_extractor.rs -@@ -33,7 +33,7 @@ impl RpmExtractor { - pub fn extract_package(pkg_path: &str, output_dir: &str) -> std::io::Result { - Self::install_package(pkg_path, output_dir)?; - -- let pkg_info = PackageInfo::parse_from(pkg_path)?; -+ let pkg_info = PackageInfo::query_from(pkg_path)?; - if pkg_info.get_type() == PackageType::SourcePackage { - RpmBuilder::new( - RpmHelper::find_build_root( -diff --git a/build/src/package/rpm_helper.rs b/build/src/package/rpm_helper.rs -index 2ee1078..b75638b 100644 ---- a/build/src/package/rpm_helper.rs -+++ b/build/src/package/rpm_helper.rs -@@ -45,7 +45,7 @@ impl RpmHelper { - } - - pub fn find_source_directory(directory: &str, patch_info: &PatchInfo) -> std::io::Result { -- let search_name = match patch_info.get_patch_type() { -+ let search_name = match patch_info.get_type() { - PatchType::UserPatch => patch_info.get_target().get_name(), - PatchType::KernelPatch => KERNEL_SOURCE_DIR_PREFIX, - }; -diff --git a/build/src/package/rpm_spec_generator.rs b/build/src/package/rpm_spec_generator.rs -index 917e12e..3a189ff 100644 ---- a/build/src/package/rpm_spec_generator.rs -+++ b/build/src/package/rpm_spec_generator.rs -@@ -11,43 +11,55 @@ impl RpmSpecGenerator { - fn parse_pkg_root(patch_info: &PatchInfo) -> String { - format!("{}/{}", - PATCH_INSTALL_PATH, -- patch_info.get_target()) -+ patch_info.get_target().get_simple_name()) - } - - fn parse_patch_name(patch_info: &PatchInfo) -> String { -- patch_info.get_patch().get_name().to_owned() -+ patch_info.get_name().to_owned() - } - - fn parse_patch_root(patch_info: &PatchInfo) -> String { - format!("{}/{}/{}", - PATCH_INSTALL_PATH, -- patch_info.get_target(), -- patch_info.get_patch().get_name()) -+ patch_info.get_target().get_simple_name(), -+ patch_info.get_name()) - } - - fn parse_pkg_name(patch_info: &PatchInfo) -> String { - format!("{}-{}-{}", - PKG_FLAG_PATCH_BINARY, -- patch_info.get_target(), -- patch_info.get_patch().get_name()) -+ patch_info.get_target().get_simple_name(), -+ patch_info.get_name()) - } - - fn parse_pkg_version(patch_info: &PatchInfo) -> String { -- patch_info.get_patch().get_version().to_owned() -+ patch_info.get_version().to_owned() - } - - fn parse_pkg_release(patch_info: &PatchInfo) -> String { -- patch_info.get_patch().get_release().to_owned() -+ patch_info.get_release().to_owned() - } - - fn parse_requires(patch_info: &PatchInfo) -> String { - let patch_target = patch_info.get_target(); - -- format!("{} = {}-{}", -- patch_target.get_name(), -- patch_target.get_version(), -- patch_target.get_release() -- ) -+ match patch_target.get_epoch() == PKG_FLAG_NONE { -+ true => { -+ format!("{} = {}-{}", -+ patch_target.get_name(), -+ patch_target.get_version(), -+ patch_target.get_release() -+ ) -+ }, -+ false => { -+ format!("{} = {}:{}-{}", -+ patch_target.get_name(), -+ patch_target.get_epoch(), -+ patch_target.get_version(), -+ patch_target.get_release() -+ ) -+ } -+ } - } - - fn parse_license(patch_info: &PatchInfo) -> String { -@@ -56,8 +68,8 @@ impl RpmSpecGenerator { - - fn parse_summary(patch_info: &PatchInfo) -> String { - format!("Syscare patch '{}' for {}", -- patch_info.get_patch().get_name(), -- patch_info.get_target() -+ patch_info.get_name(), -+ patch_info.get_target().get_simple_name() - ) - } - -diff --git a/build/src/package/rpm_spec_helper.rs b/build/src/package/rpm_spec_helper.rs -index aa318f2..7786d62 100644 ---- a/build/src/package/rpm_spec_helper.rs -+++ b/build/src/package/rpm_spec_helper.rs -@@ -12,16 +12,15 @@ pub struct RpmSpecHelper; - - impl RpmSpecHelper { - fn create_new_release_tag(orig_release_tag: RpmSpecTag, patch_info: &PatchInfo) -> RpmSpecTag { -- let patch = patch_info.get_patch(); - let target = patch_info.get_target(); - - let tag_name = orig_release_tag.get_name().to_string(); - let tag_value = format!("{}.{}.{}.{}.{}", - target.get_release(), - PKG_FLAG_PATCHED_SOURCE, -- patch.get_name(), -- patch.get_version(), -- patch.get_release() -+ patch_info.get_name(), -+ patch_info.get_version(), -+ patch_info.get_release() - ); - - RpmSpecTag::new_tag(tag_name, tag_value) -diff --git a/build/src/patch/kernel_patch/kpatch_builder.rs b/build/src/patch/kernel_patch/kpatch_builder.rs -index 741dde0..f3e4d11 100644 ---- a/build/src/patch/kernel_patch/kpatch_builder.rs -+++ b/build/src/patch/kernel_patch/kpatch_builder.rs -@@ -18,7 +18,7 @@ impl KernelPatchBuilder { - - fn parse_arg_list<'a>(&self, args: &'a KernelPatchBuilderArguments) -> Vec<&'a str> { - let mut arg_list = vec![ -- "--name", args.patch_name.get_name(), -+ "--name", args.patch_name.as_str(), - "--sourcedir", args.source_dir.as_str(), - "--config", args.config.as_str(), - "--vmlinux", args.vmlinux.as_str(), -@@ -62,15 +62,15 @@ impl PatchBuilderArgumentsParser for KernelPatchBuilder { - let kernel_config = KernelPatchHelper::find_kernel_config(&kernel_source_dir)?; - debug!("kernel config: '{}'", kernel_config); - -- let vmlinux_file = KernelPatchHelper::find_vmlinux_file(debug_pkg_dir)?; -- debug!("vmlinux: '{}'", vmlinux_file); -+ let debuginfo_file = KernelPatchHelper::find_debuginfo_file(debug_pkg_dir)?; -+ debug!("debuginfo file: '{}'", debuginfo_file); - - let builder_args = KernelPatchBuilderArguments { - build_root: patch_build_root.to_owned(), -- patch_name: patch_info.get_patch().to_owned(), -+ patch_name: patch_info.get_name().to_owned(), - source_dir: kernel_source_dir, - config: kernel_config, -- vmlinux: vmlinux_file, -+ vmlinux: debuginfo_file, - jobs: args.kjobs, - output_dir: patch_output_dir.to_owned(), - skip_compiler_check: args.skip_compiler_check, -diff --git a/build/src/patch/kernel_patch/kpatch_builder_args.rs b/build/src/patch/kernel_patch/kpatch_builder_args.rs -index 0e83bb6..0013051 100644 ---- a/build/src/patch/kernel_patch/kpatch_builder_args.rs -+++ b/build/src/patch/kernel_patch/kpatch_builder_args.rs -@@ -1,8 +1,8 @@ --use crate::patch::{PatchName, PatchFile}; -+use crate::patch::PatchFile; - - pub struct KernelPatchBuilderArguments { - pub build_root: String, -- pub patch_name: PatchName, -+ pub patch_name: String, - pub source_dir: String, - pub config: String, - pub vmlinux: String, -diff --git a/build/src/patch/kernel_patch/kpatch_helper.rs b/build/src/patch/kernel_patch/kpatch_helper.rs -index b639844..44c7cc5 100644 ---- a/build/src/patch/kernel_patch/kpatch_helper.rs -+++ b/build/src/patch/kernel_patch/kpatch_helper.rs -@@ -32,7 +32,7 @@ impl KernelPatchHelper { - Ok(fs::stringtify(config_file_path)) - } - -- pub fn find_vmlinux_file(directory: &str) -> std::io::Result { -+ pub fn find_debuginfo_file(directory: &str) -> std::io::Result { - let vmlinux_file_path = fs::find_file( - directory, - KERNEL_VMLINUX_FILE, -diff --git a/build/src/patch/patch_builder_factory.rs b/build/src/patch/patch_builder_factory.rs -index 249dcb8..88b3a5d 100644 ---- a/build/src/patch/patch_builder_factory.rs -+++ b/build/src/patch/patch_builder_factory.rs -@@ -10,14 +10,14 @@ pub struct PatchBuilderFactory; - - impl PatchBuilderFactory { - pub fn get_builder(patch_info: &PatchInfo) -> Box { -- match patch_info.get_patch_type() { -+ match patch_info.get_type() { - PatchType::KernelPatch => Box::new(KernelPatchBuilder::new()), - PatchType::UserPatch => Box::new(UserPatchBuilder::new()), - } - } - - pub fn parse_args(patch_info: &PatchInfo, workdir: &CliWorkDir, args: &CliArguments) -> std::io::Result { -- match patch_info.get_patch_type() { -+ match patch_info.get_type() { - PatchType::KernelPatch => KernelPatchBuilder::parse_args(patch_info, workdir, args), - PatchType::UserPatch => UserPatchBuilder::parse_args(patch_info, workdir, args), - } -diff --git a/build/src/patch/patch_info.rs b/build/src/patch/patch_info.rs -index b3793ae..98b8ecd 100644 ---- a/build/src/patch/patch_info.rs -+++ b/build/src/patch/patch_info.rs -@@ -6,61 +6,11 @@ use lazy_static::*; - - use crate::constants::*; - use crate::log::*; --use crate::util::{sys, fs}; -+use crate::util::fs; - - use crate::package::PackageInfo; - use crate::cli::CliArguments; - --#[derive(Clone)] --#[derive(Debug)] --pub struct PatchName { -- name: String, -- version: String, -- release: String, --} -- --impl PatchName { -- pub fn get_name(&self) -> &str { -- &self.name -- } -- -- pub fn get_version(&self) -> &str { -- &self.version -- } -- -- pub fn get_release(&self) -> &str { -- &self.release -- } --} -- --impl std::fmt::Display for PatchName { -- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { -- f.write_fmt(format_args!("{}-{}-{}", self.get_name(), self.get_version(), self.get_release())) -- } --} -- --impl std::str::FromStr for PatchName { -- type Err = std::io::Error; -- -- fn from_str(s: &str) -> Result { -- let str_slice = s.split('-').collect::>(); -- if str_slice.len() != 3 { -- return Err(std::io::Error::new( -- std::io::ErrorKind::InvalidData, -- format!("Parse patch name failed"), -- )); -- } -- -- Ok(Self { -- name: str_slice[0].to_owned(), -- version: str_slice[1].to_owned(), -- release: str_slice[2].to_owned(), -- }) -- } --} -- --pub type PatchTargetName = PatchName; -- - #[derive(Clone, Copy)] - #[derive(Debug)] - pub enum PatchType { -@@ -167,31 +117,39 @@ impl PatchFile { - #[derive(Clone)] - #[derive(Debug)] - pub struct PatchInfo { -- patch: PatchName, -- patch_type: PatchType, -- patch_arch: String, -- target: PatchTargetName, -+ name: String, -+ kind: PatchType, -+ version: String, -+ release: String, -+ target: PackageInfo, - target_elf_name: String, -- license: String, - description: String, - builder: String, - file_list: Vec, - } - - impl PatchInfo { -- pub fn get_patch(&self) -> &PatchName { -- &self.patch -+ pub fn get_name(&self) -> &str { -+ &self.name -+ } -+ -+ pub fn get_type(&self) -> PatchType { -+ self.kind - } - -- pub fn get_patch_type(&self) -> PatchType { -- self.patch_type -+ pub fn get_arch(&self) -> &str { -+ self.target.get_arch() - } - -- pub fn get_patch_arch(&self) -> &str { -- &self.patch_arch -+ pub fn get_version(&self) -> &str { -+ &self.version - } - -- pub fn get_target(&self) -> &PatchTargetName { -+ pub fn get_release(&self) -> &str { -+ &self.release -+ } -+ -+ pub fn get_target(&self) -> &PackageInfo { - &self.target - } - -@@ -200,7 +158,7 @@ impl PatchInfo { - } - - pub fn get_license(&self) -> &str { -- &self.license -+ &self.target.get_license() - } - - pub fn get_description(&self) -> &str { -@@ -217,16 +175,16 @@ impl PatchInfo { - } - - impl PatchInfo { -- fn parse_patch(args: &CliArguments) -> std::io::Result { -- Ok(PatchName { -- name: args.patch_name.to_owned(), -- version: args.patch_version.to_owned(), -- release: fs::sha256_digest_file_list(&args.patches)?[..PATCH_VERSION_DIGITS].to_string(), -- }) -+ fn parse_patch_name(args: &CliArguments) -> String { -+ args.patch_name.to_owned() - } - -- fn parse_patch_arch() -> String { -- sys::get_cpu_arch().to_owned() -+ fn parse_patch_version(args: &CliArguments) -> String { -+ args.patch_version.to_owned() -+ } -+ -+ fn parse_patch_release(args: &CliArguments) -> std::io::Result { -+ Ok(fs::sha256_digest_file_list(&args.patches)?[..PATCH_VERSION_DIGITS].to_string()) - } - - fn parse_patch_type(pkg_info: &PackageInfo) -> PatchType { -@@ -236,18 +194,17 @@ impl PatchInfo { - } - } - -- fn parse_license(args: &CliArguments) -> String { -- args.target_license.as_ref() -- .expect("Parse target license failed") -- .to_owned() -- } -- -- fn parse_target(args: &CliArguments) -> PatchName { -- PatchName { -- name: args.target_name.as_ref().expect("Parse target name failed").to_owned(), -- version: args.target_version.as_ref().expect("Parse target version failed").to_owned(), -- release: args.target_release.as_ref().expect("Parse target release failed").to_owned(), -- } -+ fn parse_target(args: &CliArguments) -> std::io::Result { -+ let query_str = format!("{}|{}|{}|{}|{}|{}|{}", -+ args.target_name.as_ref().expect("Parse target name failed").to_owned(), -+ args.target_arch.as_ref().expect("Parse target arch failed").to_owned(), -+ args.target_epoch.as_ref().expect("Parse target epoch failed").to_owned(), -+ args.target_version.as_ref().expect("Parse target version failed").to_owned(), -+ args.target_release.as_ref().expect("Parse target release failed").to_owned(), -+ args.target_license.as_ref().expect("Parse target license failed").to_owned(), -+ PKG_FLAG_NONE -+ ); -+ query_str.parse::() - } - - fn parse_target_elf_name(args: &CliArguments) -> String { -@@ -278,12 +235,12 @@ impl PatchInfo { - - pub fn parse_from(pkg_info: &PackageInfo, args: &CliArguments) -> std::io::Result { - Ok(PatchInfo { -- patch: Self::parse_patch(args)?, -- patch_type: Self::parse_patch_type(pkg_info), -- patch_arch: Self::parse_patch_arch(), -- target: Self::parse_target(args), -+ name: Self::parse_patch_name(args), -+ version: Self::parse_patch_version(args), -+ release: Self::parse_patch_release(args)?, -+ kind: Self::parse_patch_type(pkg_info), -+ target: Self::parse_target(args)?, - target_elf_name: Self::parse_target_elf_name(args), -- license: Self::parse_license(args), - description: Self::parse_description(args), - builder: Self::parse_builder(), - file_list: Self::parse_file_list(args)? -@@ -293,14 +250,14 @@ impl PatchInfo { - - impl std::fmt::Display for PatchInfo { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { -- f.write_fmt(format_args!("name: {}\n", self.get_patch().get_name()))?; -- f.write_fmt(format_args!("type: {}\n", self.get_patch_type()))?; -- f.write_fmt(format_args!("arch: {}\n", self.get_patch_arch()))?; -- f.write_fmt(format_args!("target: {}\n", self.get_target()))?; -+ f.write_fmt(format_args!("name: {}\n", self.get_name()))?; -+ f.write_fmt(format_args!("type: {}\n", self.get_type()))?; -+ f.write_fmt(format_args!("arch: {}\n", self.get_arch()))?; -+ f.write_fmt(format_args!("target: {}\n", self.get_target().get_simple_name()))?; - f.write_fmt(format_args!("elf_name: {}\n", self.get_target_elf_name()))?; - f.write_fmt(format_args!("license: {}\n", self.get_license()))?; -- f.write_fmt(format_args!("version: {}\n", self.get_patch().get_version()))?; -- f.write_fmt(format_args!("release: {}\n", self.get_patch().get_release()))?; -+ f.write_fmt(format_args!("version: {}\n", self.get_version()))?; -+ f.write_fmt(format_args!("release: {}\n", self.get_release()))?; - f.write_fmt(format_args!("description: {}\n", self.get_description()))?; - f.write_fmt(format_args!("builder: {}\n", self.get_builder()))?; - f.write_str("\npatch list:")?; -diff --git a/build/src/patch/user_patch/upatch_builder.rs b/build/src/patch/user_patch/upatch_builder.rs -index e841fb4..8636677 100644 ---- a/build/src/patch/user_patch/upatch_builder.rs -+++ b/build/src/patch/user_patch/upatch_builder.rs -@@ -66,7 +66,7 @@ impl PatchBuilderArgumentsParser for UserPatchBuilder { - let build_patched_cmd = format!("{} --define '_topdir {}' -bc --noprep --noclean {}", RPM_BUILD, pkg_root, spec_file_path); - - let builder_args = UserPatchBuilderArguments { -- name: patch_info.get_patch().get_name().to_owned(), -+ name: patch_info.get_name().to_owned(), - build_root: patch_build_root.to_owned(), - source_dir: patch_source_dir, - elf_name: patch_info.get_target_elf_name().to_owned(), -diff --git a/build/src/patch/user_patch/upatch_helper.rs b/build/src/patch/user_patch/upatch_helper.rs -index 403d370..6a88a23 100644 ---- a/build/src/patch/user_patch/upatch_helper.rs -+++ b/build/src/patch/user_patch/upatch_helper.rs -@@ -7,7 +7,7 @@ impl UserPatchHelper { - pub fn find_debuginfo_file(directory: &str, patch_info: &PatchInfo) -> std::io::Result { - let target = patch_info.get_target(); - let file_name = format!("{}-{}-{}.{}.debug", -- patch_info.get_target_elf_name(), target.get_version(), target.get_release(), patch_info.get_patch_arch() -+ patch_info.get_target_elf_name(), target.get_version(), target.get_release(), patch_info.get_arch() - ); - - let debuginfo_file_path = fs::find_file( -diff --git a/build/src/util/sys.rs b/build/src/util/sys.rs -index c716f3d..3bbc8dc 100644 ---- a/build/src/util/sys.rs -+++ b/build/src/util/sys.rs -@@ -40,7 +40,7 @@ impl SysInitializer { - } - } - --pub fn get_cpu_arch() -> &'static str { -+pub const fn get_cpu_arch() -> &'static str { - std::env::consts::ARCH - } - --- -2.33.0 - - -From 6c5bdd855ecc2409248d98321a898a2b10f79e67 Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Tue, 20 Dec 2022 23:01:48 +0800 -Subject: [PATCH 15/20] build: update readme - -Signed-off-by: renoseven ---- - build/README.md | 39 ++++++++++++++++++++++----------------- - 1 file changed, 22 insertions(+), 17 deletions(-) - -diff --git a/build/README.md b/build/README.md -index 14493f7..94bb4c1 100644 ---- a/build/README.md -+++ b/build/README.md -@@ -16,10 +16,13 @@ Arguments: - - Options: - -n, --patch-name Patch name -+ --patch-arch Patch architecture [default: x86_64] - --patch-version Patch version [default: 1] -- --patch-description Patch description [default: None] -+ --patch-description Patch description [default: (none)] - --target-name Patch target name - -t, --target-elfname Patch target executable name -+ --target-arch parch target architecture -+ --target-epoch Patch target epoch - --target-version Patch target version - --target-release Patch target release - --target-license Patch target license -@@ -38,13 +41,13 @@ Options: - - 必要参数: - --| 字段名称 | 字段描述 | -+| 字段名称 | 字段描述 | - | ---------------- | -------------------------------------- | --| --patch-name | 补丁名称 | --| --source | 目标软件源码包 | --| --debuginfo | 目标软件调试信息包 | --| --target-elfname | 目标软件可执行文件名(内核补丁可忽略) | --| \ | 补丁列表 | -+| --patch-name | 补丁名称 | -+| --source | 目标软件源码包 | -+| --debuginfo | 目标软件调试信息包 | -+| --target-elfname | 目标软件可执行文件名(内核补丁可忽略) | -+| \ | 补丁列表 | - - - -@@ -81,17 +84,18 @@ syscare-build \ - - 补丁元信息中包含以下字段: - --| 字段名称 | 字段描述 | -+| 字段名称 | 字段描述 | - | ----------- | ---------------------- | --| name | 补丁名称 | --| type | 补丁类型 | --| target | 目标软件名 | --| elf_name | 目标软件可执行文件名称 | --| license | 目标软件许可证 | --| version | 补丁版本 | -+| name | 补丁名称 | -+| type | 补丁类型 | -+| arch | 补丁架构 | -+| target | 目标软件名 | -+| elf_name | 目标软件可执行文件名称 | -+| license | 目标软件许可证 | -+| version | 补丁版本 | - | release | 补丁Release | --| description | 补丁描述 | --| builder | 补丁制作工具版本 | -+| description | 补丁描述 | -+| builder | 补丁制作工具版本 | - - - -@@ -101,13 +105,14 @@ syscare-build \ - ------------------------------ - name: CVE-2021-32675 - type: UserPatch -+arch: x86_64 - target: redis-6.2.5-1 - elf_name: redis-server - license: BSD and MIT - version: 1 - release: 31fc7544 - description: When parsing an incoming Redis Standard Protocol (RESP) request, Redis allocates memory according to user-specified values which determine the number of elements (in the multi-bulk header) and size of each element (in the bulk header). An attacker delivering specially crafted requests over multiple connections can cause the server to allocate significant amount of memory. Because the same parsing mechanism is used to handle authentication requests, this vulnerability can also be exploited by unauthenticated users. --builder: syscare-build v0.1.0 -+builder: syscare-build 1.0.0 - - patch list: - 0001-Prevent-unauthenticated-client-from-easily-consuming.patch 31fc7544 --- -2.33.0 - - -From d90bfc405121a4c1293da055e734149c1f8b7cf6 Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Wed, 21 Dec 2022 12:29:38 +0800 -Subject: [PATCH 16/20] build: fix 'cannot build from patched source package' - issue - -1. overrides source package info from patched source package -2. move package matching process from extract_packages() to check_build_args() -3. treats duplicated patch or illegal patch type as error - -Signed-off-by: renoseven ---- - build/src/cli/cli.rs | 39 +++++++++++++++++++---------------- - build/src/patch/patch_info.rs | 13 +++++++----- - 2 files changed, 29 insertions(+), 23 deletions(-) - -diff --git a/build/src/cli/cli.rs b/build/src/cli/cli.rs -index d88d830..27b09f1 100644 ---- a/build/src/cli/cli.rs -+++ b/build/src/cli/cli.rs -@@ -98,7 +98,7 @@ impl PatchBuildCLI { - Ok(()) - } - -- fn extract_packages(&self) -> std::io::Result { -+ fn extract_packages(&self) -> std::io::Result<(PackageInfo, PackageInfo)> { - info!("Extracting source package"); - let src_pkg_info = RpmExtractor::extract_package( - &self.args.source, -@@ -129,17 +129,7 @@ impl PatchBuildCLI { - info!("{}", dbg_pkg_info); - info!("------------------------------\n"); - -- if !dbg_pkg_info.get_name().contains(src_pkg_info.get_name()) || -- (src_pkg_info.get_arch() != dbg_pkg_info.get_arch()) || -- (src_pkg_info.get_epoch() != dbg_pkg_info.get_epoch()) || -- (src_pkg_info.get_version() != dbg_pkg_info.get_version()) || -- (src_pkg_info.get_release() != dbg_pkg_info.get_release()) { -- return Err(std::io::Error::new( -- std::io::ErrorKind::InvalidInput, -- format!("Debuginfo package does not match the source package"), -- )); -- } -- Ok(src_pkg_info) -+ Ok((src_pkg_info, dbg_pkg_info)) - } - - fn collect_patch_info(&self, pkg_info: &PackageInfo) -> std::io::Result { -@@ -153,7 +143,7 @@ impl PatchBuildCLI { - Ok(patch_info) - } - -- fn complete_build_args(&mut self, pkg_info: &PackageInfo) -> std::io::Result<()> { -+ fn complete_build_args(&mut self, pkg_info: &mut PackageInfo) -> std::io::Result<()> { - let mut args = &mut self.args; - - // If the source package is kernel, append target elf name 'vmlinux' to arguments -@@ -190,6 +180,8 @@ impl PatchBuildCLI { - args.target_epoch.get_or_insert(patch_target.get_epoch().to_owned()); - args.target_version.get_or_insert(patch_target.get_version().to_owned()); - args.target_release.get_or_insert(patch_target.get_release().to_owned()); -+ // Override original package info with saved data in package -+ *pkg_info = patch_target; - }, - Err(_) => { - args.target_name.get_or_insert(pkg_info.get_name().to_owned()); -@@ -215,9 +207,20 @@ impl PatchBuildCLI { - Ok(()) - } - -- fn check_build_args(&self) -> std::io::Result<()> { -+ fn check_build_args(&self, src_pkg_info: &PackageInfo, dbg_pkg_info: &PackageInfo) -> std::io::Result<()> { - let args = &self.args; - -+ if !dbg_pkg_info.get_name().contains(src_pkg_info.get_name()) || -+ (src_pkg_info.get_arch() != dbg_pkg_info.get_arch()) || -+ (src_pkg_info.get_epoch() != dbg_pkg_info.get_epoch()) || -+ (src_pkg_info.get_version() != dbg_pkg_info.get_version()) || -+ (src_pkg_info.get_release() != dbg_pkg_info.get_release()) { -+ return Err(std::io::Error::new( -+ std::io::ErrorKind::InvalidInput, -+ format!("Debuginfo package does not match the source package"), -+ )); -+ } -+ - let patch_arch = args.patch_arch.as_str(); - if patch_arch != sys::get_cpu_arch() { - return Err(std::io::Error::new( -@@ -295,12 +298,12 @@ impl PatchBuildCLI { - info!("=============================="); - info!("{}", CLI_DESCRIPTION); - info!("==============================\n"); -- let pkg_info = self.extract_packages()?; -- self.complete_build_args(&pkg_info)?; -+ let (mut src_pkg_info, dbg_pkg_info) = self.extract_packages()?; -+ self.complete_build_args(&mut src_pkg_info)?; - -- self.check_build_args()?; -+ self.check_build_args(&src_pkg_info, &dbg_pkg_info)?; - -- let patch_info = self.collect_patch_info(&pkg_info)?; -+ let patch_info = self.collect_patch_info(&src_pkg_info)?; - self.build_patch_package(&patch_info)?; - self.build_source_package(&patch_info)?; - -diff --git a/build/src/patch/patch_info.rs b/build/src/patch/patch_info.rs -index 98b8ecd..dad27ab 100644 ---- a/build/src/patch/patch_info.rs -+++ b/build/src/patch/patch_info.rs -@@ -5,7 +5,6 @@ use std::sync::Mutex; - use lazy_static::*; - - use crate::constants::*; --use crate::log::*; - use crate::util::fs; - - use crate::package::PackageInfo; -@@ -62,14 +61,18 @@ impl PatchFile { - - let file_ext = fs::file_ext(file_path.as_path())?; - if file_ext != PATCH_FILE_EXTENSION { -- error!("File {} is not a patch", file_name); -- return Ok(None); -+ return Err(std::io::Error::new( -+ std::io::ErrorKind::InvalidInput, -+ format!("File {} is not a patch", file_name) -+ )); - } - - let file_digest = &fs::sha256_digest_file(file_path.as_path())?[..PATCH_VERSION_DIGITS]; - if !file_digests.insert(file_digest.to_owned()) { -- error!("Patch file '{}' is duplicated", file_name); -- return Ok(None); -+ return Err(std::io::Error::new( -+ std::io::ErrorKind::InvalidInput, -+ format!("File {} is duplicated", file_name) -+ )); - } - - *file_id += 1; --- -2.33.0 - - -From 5537cc4e6396c8cccc334996e126ec3e082b15e0 Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Wed, 21 Dec 2022 16:28:32 +0800 -Subject: [PATCH 17/20] build: add '--skip-cleanup' flag - -Signed-off-by: renoseven ---- - build/src/cli/args.rs | 4 ++++ - build/src/cli/cli.rs | 4 +++- - build/src/constants.rs | 1 + - 3 files changed, 8 insertions(+), 1 deletion(-) - -diff --git a/build/src/cli/args.rs b/build/src/cli/args.rs -index 583df2c..4917d87 100644 ---- a/build/src/cli/args.rs -+++ b/build/src/cli/args.rs -@@ -74,6 +74,10 @@ pub struct CliArguments { - #[arg(long, default_value=CLI_DEFAULT_SKIP_COMPILER_CHECK)] - pub skip_compiler_check: bool, - -+ /// Skip post-build cleanup -+ #[arg(long, default_value=CLI_DEFAULT_SKIP_CLEANUP_FLAG)] -+ pub skip_cleanup: bool, -+ - /// Provide more detailed info - #[arg(short, long, default_value=CLI_DEFAULT_VERBOSE_FLAG)] - pub verbose: bool, -diff --git a/build/src/cli/cli.rs b/build/src/cli/cli.rs -index 27b09f1..07af853 100644 ---- a/build/src/cli/cli.rs -+++ b/build/src/cli/cli.rs -@@ -328,6 +328,8 @@ impl PatchBuildCLI { - return; - } - -- self.workdir.remove().ok(); -+ if !self.args.skip_cleanup { -+ self.workdir.remove().ok(); -+ } - } - } -diff --git a/build/src/constants.rs b/build/src/constants.rs -index c3dff49..87f6bc3 100644 ---- a/build/src/constants.rs -+++ b/build/src/constants.rs -@@ -12,6 +12,7 @@ pub const CLI_DEFAULT_PATCH_DESCRIPTION: &str = "(none)"; - pub const CLI_DEFAULT_WORKDIR: &str = "."; - pub const CLI_DEFAULT_OUTPUT_DIR: &str = "."; - pub const CLI_DEFAULT_SKIP_COMPILER_CHECK: &str = "false"; -+pub const CLI_DEFAULT_SKIP_CLEANUP_FLAG: &str = "false"; - pub const CLI_DEFAULT_VERBOSE_FLAG: &str = "false"; - - // External commands --- -2.33.0 - - -From ece643d23ae16a5c61a4c87de1395f3605834f3e Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Wed, 21 Dec 2022 16:28:58 +0800 -Subject: [PATCH 18/20] build: update readme - ---- - build/README.md | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/build/README.md b/build/README.md -index 94bb4c1..7714e0b 100644 ---- a/build/README.md -+++ b/build/README.md -@@ -32,6 +32,7 @@ Options: - -o, --output Generated patch output directory [default: .] - --kjobs Kernel make jobs [default: 32] - --skip-compiler-check Skip compiler version check (not recommended) -+ --skip-cleanup Skip post-build cleanup - -v, --verbose Provide more detailed info - -h, --help Print help information - -V, --version Print version information --- -2.33.0 - - -From e52fad8f68b1df70d093dc39a55909829559d07b Mon Sep 17 00:00:00 2001 -From: Longjun Luo -Date: Wed, 21 Dec 2022 19:14:35 +0800 -Subject: [PATCH 19/20] kmod: add support for R_X86_64_REX_GOTPCRELX - -R_X86_64_REX_GOTPCRELX is calculated by: - -G + GOT + A -p. - -Signed-off-by: Longjun Luo ---- - upatch/kmod/patch-load.c | 65 ++++++++++++++++++++++++++++++---------- - 1 file changed, 50 insertions(+), 15 deletions(-) - -diff --git a/upatch/kmod/patch-load.c b/upatch/kmod/patch-load.c -index f753104..2f726c3 100644 ---- a/upatch/kmod/patch-load.c -+++ b/upatch/kmod/patch-load.c -@@ -30,6 +30,10 @@ - #define ARCH_SHF_SMALL 0 - #endif - -+#ifndef R_X86_64_REX_GOTPCRELX -+#define R_X86_64_REX_GOTPCRELX 42 -+#endif -+ - /* If this is set, the section belongs in the init part of the module */ - #define INIT_OFFSET_MASK (1UL << (BITS_PER_LONG-1)) - -@@ -277,18 +281,15 @@ static void layout_jmptable(struct upatch_module *mod, struct upatch_load_info * - } - - /* TODO: lock for mm */ --unsigned long get_upatch_pole(unsigned long hint, unsigned long size) -+unsigned long get_upatch_pole(unsigned long search, unsigned long size) - { -- unsigned long range; -- unsigned search = hint; -- struct vm_area_struct *vma = find_vma(current->mm, search); -+ struct vm_area_struct *vma = -+ find_vma_intersection(current->mm, search, search + size); - while (vma) { - search = vma->vm_end; -- range = vma->vm_next->vm_start - vma->vm_end; -- if (range > size) -- break; -- vma = vma->vm_next; -+ vma = find_vma_intersection(current->mm, search, search + size); - } -+ pr_debug("find search address at 0x%lx \n", search); - return search; - } - -@@ -341,11 +342,13 @@ void upatch_module_deallocate(struct upatch_module *mod) - static int upatch_module_alloc(struct upatch_load_info *info, - struct upatch_module_layout *layout, unsigned long user_limit) - { -- layout->base = __upatch_module_alloc(info->running_elf.load_min, layout->size); -+ unsigned long hint = info->running_elf.load_min + info->running_elf.load_bias; -+ -+ layout->base = __upatch_module_alloc(hint, layout->size); - if (!layout->base) - return -ENOMEM; - -- if ((unsigned long)layout->base - info->running_elf.load_min >= user_limit) { -+ if ((unsigned long)layout->base - hint >= user_limit) { - pr_err("out of range limit \n"); - __upatch_module_memfree(layout->base, layout->size); - return -ENOMEM; -@@ -515,6 +518,29 @@ static unsigned long setup_jmp_table(struct upatch_load_info *info, unsigned lon - + index * sizeof(struct upatch_jmp_table_entry)); - } - -+/* -+ * Jmp tabale records address and used call instruction to execute it. -+ * So, we need 'Inst' and 'addr' -+ * GOT only need record address and resolve it by [got_addr]. -+ * To simplify design, use same table for both jmp table and GOT. -+ */ -+static unsigned long setup_got_table(struct upatch_load_info *info, unsigned long jmp_addr) -+{ -+ struct upatch_jmp_table_entry *table = -+ info->mod->core_layout.kbase + info->jmp_offs; -+ unsigned int index = info->jmp_cur_entry; -+ if (index >= info->jmp_max_entry) { -+ pr_err("got table overflow \n"); -+ return 0; -+ } -+ -+ table[index].inst = jmp_addr; -+ table[index].addr = 0xffffffff; -+ info->jmp_cur_entry ++; -+ return (unsigned long)(info->mod->core_layout.base + info->jmp_offs -+ + index * sizeof(struct upatch_jmp_table_entry)); -+} -+ - static unsigned long - resolve_symbol(struct running_elf_info *elf_info, const char *name) - { -@@ -647,14 +673,15 @@ static int simplify_symbols(struct upatch_module *mod, struct upatch_load_info * - } - - /* TODO: arch releated */ --int apply_relocate_add(Elf64_Shdr *sechdrs, const char *strtab, -- unsigned int symindex, unsigned int relsec, struct upatch_module *me) -+int apply_relocate_add(struct upatch_load_info *info, Elf64_Shdr *sechdrs, -+ const char *strtab, unsigned int symindex, -+ unsigned int relsec, struct upatch_module *me) - { - unsigned int i; - Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr; - Elf64_Sym *sym; - void *loc, *real_loc; -- u64 val; -+ u64 val, got; - const char *name; - - pr_debug("Applying relocate section %u to %u\n", -@@ -702,7 +729,15 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, const char *strtab, - && (ELF_ST_TYPE(sym->st_info) != STT_SECTION)) - goto overflow; - break; -- case R_X86_64_PC32: -+ case R_X86_64_REX_GOTPCRELX: -+ /* get GOT address */ -+ got = setup_got_table(info, sym->st_value); -+ if (got == 0) -+ goto overflow; -+ /* G + GOT + A*/ -+ val = got + rel[i].r_addend; -+ fallthrough; -+ case R_X86_64_PC32: - case R_X86_64_PLT32: - if (*(u32 *)loc != 0) - goto invalid_relocation; -@@ -757,7 +792,7 @@ static int apply_relocations(struct upatch_module *mod, struct upatch_load_info - return -EPERM; - } else if (info->sechdrs[i].sh_type == SHT_RELA) { - pr_debug("do rela relocations for %s \n", name); -- err = apply_relocate_add(info->sechdrs, info->strtab, -+ err = apply_relocate_add(info, info->sechdrs, info->strtab, - info->index.sym, i, mod); - } - --- -2.33.0 - - -From 5869dca3761942411ff54a443627c21005cef813 Mon Sep 17 00:00:00 2001 -From: Longjun Luo -Date: Wed, 21 Dec 2022 19:26:28 +0800 -Subject: [PATCH 20/20] kmod: add support for R_X86_64_GOTPCRELX - -same as R_X86_64_REX_GOTPCRELX - -Signed-off-by: Longjun Luo ---- - upatch/kmod/patch-load.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/upatch/kmod/patch-load.c b/upatch/kmod/patch-load.c -index 2f726c3..ff25e26 100644 ---- a/upatch/kmod/patch-load.c -+++ b/upatch/kmod/patch-load.c -@@ -30,6 +30,10 @@ - #define ARCH_SHF_SMALL 0 - #endif - -+#ifndef R_X86_64_GOTPCRELX -+#define R_X86_64_GOTPCRELX 41 -+#endif -+ - #ifndef R_X86_64_REX_GOTPCRELX - #define R_X86_64_REX_GOTPCRELX 42 - #endif -@@ -729,6 +733,7 @@ int apply_relocate_add(struct upatch_load_info *info, Elf64_Shdr *sechdrs, - && (ELF_ST_TYPE(sym->st_info) != STT_SECTION)) - goto overflow; - break; -+ case R_X86_64_GOTPCRELX: - case R_X86_64_REX_GOTPCRELX: - /* get GOT address */ - got = setup_got_table(info, sym->st_value); --- -2.33.0 -