diff --git a/0001-upatch-fix-memory-leak.patch b/0001-upatch-fix-memory-leak.patch deleted file mode 100644 index bc21fdca5997086b3e1ab4d0c1a4ed82dec6dc45..0000000000000000000000000000000000000000 --- a/0001-upatch-fix-memory-leak.patch +++ /dev/null @@ -1,362 +0,0 @@ -From 433594d38d6c35c6189af97dfdd0007eb9c114b7 Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Tue, 26 Dec 2023 08:49:07 +0000 -Subject: [PATCH] upatch: fix memory leak - ---- - upatch/upatch-manage/upatch-patch.c | 4 +- - upatch/upatch-tool/upatch-meta.c | 8 ++- - upatch/upatch-tool/upatch-resolve.c | 63 +++++++--------- - upatch/upatch-tool/upatch-resolve.h | 3 +- - upatch/upatch-tool/upatch-tool-lib.c | 104 +++++++++++++++++++++------ - 5 files changed, 117 insertions(+), 65 deletions(-) - -diff --git a/upatch/upatch-manage/upatch-patch.c b/upatch/upatch-manage/upatch-patch.c -index 733f6fa..0e09cb2 100644 ---- a/upatch/upatch-manage/upatch-patch.c -+++ b/upatch/upatch-manage/upatch-patch.c -@@ -590,8 +590,8 @@ static int upatch_apply_patches(struct upatch_process *proc, - - if (!found) { - ret = -1; -- log_debug("can't found inode %lu in pid %d\n", -- uelf->relf->info.inode, proc->pid); -+ log_debug("Cannot find inode %lu in pid %d, file is not loaded\n", -+ uelf->relf->info.inode, proc->pid); - goto out; - } - -diff --git a/upatch/upatch-tool/upatch-meta.c b/upatch/upatch-tool/upatch-meta.c -index 0956f57..62ba907 100644 ---- a/upatch/upatch-tool/upatch-meta.c -+++ b/upatch/upatch-tool/upatch-meta.c -@@ -197,9 +197,11 @@ static int patch_deactive_in_cover(struct upatch_meta_patch *patch) - static int list_add_symbol(struct list_head *head, struct upatch_meta_symbol *sym) - { - struct upatch_meta_symbol *newsym = (struct upatch_meta_symbol *)malloc(sizeof(struct upatch_meta_symbol)); -- if (newsym == NULL) -+ if (newsym == NULL) { - return ENOMEM; -+ } - memset(newsym, 0, sizeof(struct upatch_meta_symbol)); -+ - strncpy(newsym->name, sym->name, sizeof(newsym->name)); - newsym->offset = sym->offset; - INIT_LIST_HEAD(&newsym->self); -@@ -212,9 +214,11 @@ static int list_add_symbol(struct list_head *head, struct upatch_meta_symbol *sy - static int list_add_symbol_for_patch(struct upatch_meta_patch *patch, struct list_head *head, struct upatch_meta_symbol *sym) - { - struct upatch_meta_symbol *newsym = (struct upatch_meta_symbol *)malloc(sizeof(struct upatch_meta_symbol)); -- if (newsym == NULL) -+ if (newsym == NULL) { - return ENOMEM; -+ } - memset(newsym, 0, sizeof(struct upatch_meta_symbol)); -+ - strncpy(newsym->name, sym->name, sizeof(newsym->name)); - newsym->offset = sym->offset; - INIT_LIST_HEAD(&newsym->self); -diff --git a/upatch/upatch-tool/upatch-resolve.c b/upatch/upatch-tool/upatch-resolve.c -index fc1caaf..4e5441f 100644 ---- a/upatch/upatch-tool/upatch-resolve.c -+++ b/upatch/upatch-tool/upatch-resolve.c -@@ -42,79 +42,66 @@ out: - static int list_add_symbol(struct list_head *head, patch_symbols_t *sym) - { - patch_symbols_t *newsym = (patch_symbols_t *)malloc(sizeof(patch_symbols_t)); -- if (newsym == NULL) -+ if (newsym == NULL) { - return ENOMEM; -+ } - - memset(newsym, 0, sizeof(patch_symbols_t)); - strncpy(newsym->name, sym->name, sizeof(newsym->name)); - newsym->offset = sym->offset; - INIT_LIST_HEAD(&newsym->self); - list_add(&newsym->self, head); -+ - return 0; - } - --struct list_head* patch_symbols_resolve(const char *target_elf, const char *patch_file) { -- struct upatch_elf uelf; -- struct running_elf relf; -- GElf_Shdr *upatch_shdr = NULL; -- struct upatch_patch_func *upatch_funcs = NULL; -- GElf_Off min_addr; // binary base -- int num; -- struct list_head *head = malloc(sizeof(struct list_head)); -+struct list_head* patch_symbols_resolve(struct upatch_elf *uelf, struct running_elf *relf) { -+ struct list_head *head = NULL; - -- INIT_LIST_HEAD(head); -- -- int ret = upatch_init(&uelf, patch_file); -- if (ret < 0) { -- log_warn("upatch-resolve: upatch_init failed\n"); -- goto out; -- } -- -- ret = binary_init(&relf, target_elf); -- if (ret < 0) { -- log_warn("upatch-resolve: binary_init failed %d \n", ret); -- goto out; -- } -- -- if (check_build_id(&uelf.info, &relf.info) == false) { -+ if (check_build_id(&uelf->info, &relf->info) == false) { - log_error("upatch-resolve: Build id mismatched!\n"); - goto out; - } - -- uelf.relf = &relf; -- upatch_shdr = &uelf.info.shdrs[uelf.index.upatch_funcs]; -- upatch_funcs = uelf.info.patch_buff + upatch_shdr->sh_offset; -- min_addr = calculate_load_address(uelf.relf, false); -+ GElf_Shdr *upatch_shdr = &uelf->info.shdrs[uelf->index.upatch_funcs]; -+ GElf_Off min_addr = calculate_load_address(uelf->relf, false); - if (min_addr == (GElf_Off)-1) { - goto out; - } - -- num = upatch_shdr->sh_size / sizeof(*upatch_funcs); -+ struct upatch_patch_func *upatch_funcs = uelf->info.patch_buff + upatch_shdr->sh_offset; -+ int num = upatch_shdr->sh_size / sizeof(*upatch_funcs); - - log_debug("upatch-resolve: sh_size %lu, sizeof %lu \n", upatch_shdr->sh_size, sizeof(*upatch_funcs)); - log_debug("upatch-resolve: elf base addr is 0x%lx, num is %d\n", min_addr, num); - -+ head = malloc(sizeof(struct list_head)); -+ INIT_LIST_HEAD(head); -+ - for (int i = 0; i < num; i++) { -- patch_symbols_t *sym = malloc(sizeof(patch_symbols_t)); -- sprintf(sym->name, "sym_%d", i); -- sym->offset = upatch_funcs[i].old_addr - min_addr;; -- log_debug("+upatch-resolve: sym->offset addr is 0x%lx\n", sym->offset); -- list_add_symbol(head, sym); -+ patch_symbols_t sym; -+ -+ sprintf(sym.name, "sym_%d", i); -+ sym.offset = upatch_funcs[i].old_addr - min_addr; -+ log_debug("upatch-resolve: sym->offset addr is 0x%lx\n", sym.offset); -+ -+ list_add_symbol(head, &sym); // This would copy the symbol - } - - return head; -+ - out: -- free(head); -+ if (head != NULL) { -+ free(head); -+ } - return NULL; - } - - void patch_symbols_free(struct list_head *symbols) { - patch_symbols_t *sym, *next; -- -- if (!symbols) -- return; - list_for_each_entry_safe (sym, next, symbols, self) { - list_del(&sym->self); - free(sym); - } -+ free(symbols); - } -diff --git a/upatch/upatch-tool/upatch-resolve.h b/upatch/upatch-tool/upatch-resolve.h -index 78e25f3..b4e4924 100644 ---- a/upatch/upatch-tool/upatch-resolve.h -+++ b/upatch/upatch-tool/upatch-resolve.h -@@ -2,8 +2,9 @@ - #define __UPATCH_RESOLVE_H_ - - #include "list.h" -+#include "upatch-elf.h" - --struct list_head* patch_symbols_resolve(const char *target_elf, const char *patch_file); -+struct list_head* patch_symbols_resolve(struct upatch_elf *uelf, struct running_elf *relf); - void patch_symbols_free(struct list_head *symbols); - - #endif -diff --git a/upatch/upatch-tool/upatch-tool-lib.c b/upatch/upatch-tool/upatch-tool-lib.c -index 85739fe..9a6caa1 100644 ---- a/upatch/upatch-tool/upatch-tool-lib.c -+++ b/upatch/upatch-tool/upatch-tool-lib.c -@@ -14,21 +14,43 @@ - - #include "log.h" - #include "list.h" -+#include "upatch-elf.h" - #include "upatch-meta.h" - #include "upatch-resolve.h" - #include "upatch-ioctl.h" - - int upatch_check(const char *target_elf, const char *patch_file, char *err_msg, size_t max_len) - { -- struct list_head *patch_syms = patch_symbols_resolve(target_elf, patch_file); -+ int ret = 0; -+ struct list_head *patch_syms = NULL; -+ struct list_head *collision_list = NULL; -+ -+ struct upatch_elf uelf; -+ ret = upatch_init(&uelf, patch_file); -+ if (ret < 0) { -+ snprintf(err_msg, max_len, "Failed to read patch"); -+ goto out; -+ } -+ -+ struct running_elf relf; -+ ret = binary_init(&relf, target_elf); -+ if (ret < 0) { -+ snprintf(err_msg, max_len, "Failed to read target elf"); -+ goto out; -+ } -+ uelf.relf = &relf; -+ -+ patch_syms = patch_symbols_resolve(&uelf, &relf); - if (patch_syms == NULL) { - snprintf(err_msg, max_len, "Patch format error"); -- return ENOEXEC; -+ ret = ENOEXEC; -+ goto out; - } - -- struct list_head *collision_list = meta_get_symbol_collision(target_elf, patch_syms); -+ collision_list = meta_get_symbol_collision(target_elf, patch_syms); - if (collision_list == NULL) { -- return 0; -+ ret = 0; -+ goto out; - } - - int offset = snprintf(err_msg, max_len, "Patch is conflicted with "); -@@ -39,50 +61,78 @@ int upatch_check(const char *target_elf, const char *patch_file, char *err_msg, - offset = snprintf(err_msg, max_len, "\"%s\" ", collision->uuid); - } - -- patch_symbols_free(patch_syms); -- meta_put_symbol_collision(collision_list); -+out: -+ if (patch_syms != NULL) { -+ patch_symbols_free(patch_syms); -+ } -+ if (collision_list != NULL) { -+ meta_put_symbol_collision(collision_list); -+ } -+ binary_close(&relf); -+ upatch_close(&uelf); - -- return EEXIST; -+ return ret; - } - - int upatch_load(const char *uuid, const char *target, const char *patch, bool force) - { -+ int ret = 0; -+ struct list_head *patch_syms = NULL; -+ patch_entity_t *patch_entity = NULL; -+ struct list_head *collision_syms = NULL; -+ - // Pointer check - if (uuid == NULL || target == NULL || patch == NULL) { - return EINVAL; - } - log_normal("Loading patch {%s} (\"%s\") for \"%s\"\n", uuid, patch, target); - -+ struct upatch_elf uelf; -+ ret = upatch_init(&uelf, patch); -+ if (ret < 0) { -+ log_warn("Failed to read patch\n"); -+ goto out; -+ } -+ -+ struct running_elf relf; -+ ret = binary_init(&relf, target); -+ if (ret < 0) { -+ log_warn("Failed to read target elf\n"); -+ goto out; -+ } -+ uelf.relf = &relf; -+ - // Fails if patch is already exist - if (meta_get_patch_status(uuid) != UPATCH_PATCH_STATUS_NOT_APPLIED) { - log_warn("{%s}: Patch status is invalid\n", uuid); -- return EPERM; -+ ret = EPERM; -+ goto out; - } - - // Resolve patch symbols -- struct list_head *patch_syms = patch_symbols_resolve(target, patch); -+ patch_syms = patch_symbols_resolve(&uelf, &relf); - if (patch_syms == NULL) { - log_warn("{%s}: Patch format error\n", uuid); -- return ENOEXEC; -+ ret = ENOEXEC; -+ goto out; - } - - // Check patch symbol collision - if (!force) { -- struct list_head *collision_syms = meta_get_symbol_collision(target, patch_syms); -+ collision_syms = meta_get_symbol_collision(target, patch_syms); - if (collision_syms != NULL) { - log_warn("{%s}: Patch symbol conflicted\n", uuid); -- patch_symbols_free(patch_syms); -- meta_put_symbol_collision(collision_syms); -- return EEXIST; -+ ret = EEXIST; -+ goto out; - } - } - - // Alloc memory for patch -- patch_entity_t *patch_entity = calloc(1, sizeof(patch_entity_t)); -+ patch_entity = calloc(1, sizeof(patch_entity_t)); - if (patch_entity == NULL) { - log_warn("{%s}: Failed to alloc memory\n", uuid); -- patch_symbols_free(patch_syms); -- return ENOMEM; -+ ret = ENOMEM; -+ goto out; - } - - strncpy(patch_entity->target_path, target, strnlen(target, PATH_MAX)); -@@ -91,17 +141,27 @@ int upatch_load(const char *uuid, const char *target, const char *patch, bool fo - log_normal("patch: %s, patch_path: %s\n", patch, patch_entity->patch_path); - patch_entity->symbols = patch_syms; - -- int ret = meta_create_patch(uuid, patch_entity); -+ ret = meta_create_patch(uuid, patch_entity); - if (ret != 0) { - log_warn("{%s}: Failed to create patch entity\n", uuid); -- free(patch_entity); -- patch_symbols_free(patch_syms); -- return ret; -+ goto out; - } - -- free(patch_entity); - meta_set_patch_status(uuid, UPATCH_PATCH_STATUS_DEACTIVED); - -+out: -+ if (collision_syms != NULL) { -+ meta_put_symbol_collision(collision_syms); -+ } -+ if (patch_syms != NULL) { -+ patch_symbols_free(patch_syms); -+ } -+ if (patch_entity != NULL) { -+ free(patch_entity); -+ } -+ binary_close(&relf); -+ upatch_close(&uelf); -+ - return ret; - } - --- -2.33.0 - diff --git a/0001-upatch-hijacker-fix-compile-bug.patch b/0001-upatch-hijacker-fix-compile-bug.patch new file mode 100644 index 0000000000000000000000000000000000000000..0eed4947ebbbb447ad3c6ee311bd52fd7270f495 --- /dev/null +++ b/0001-upatch-hijacker-fix-compile-bug.patch @@ -0,0 +1,33 @@ +From 8c09e8b3d9d59012c1019c01ac2246c770501c75 Mon Sep 17 00:00:00 2001 +From: ningyu <405888464@qq.com> +Date: Sun, 7 Apr 2024 10:50:13 +0800 +Subject: [PATCH] upatch-hijacker: fix compile bug container_of_safe => + container_of + +--- + upatch-hijacker/ko/map.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/upatch-hijacker/ko/map.c b/upatch-hijacker/ko/map.c +index a9c18ba..3049556 100644 +--- a/upatch-hijacker/ko/map.c ++++ b/upatch-hijacker/ko/map.c +@@ -70,7 +70,7 @@ static inline void remove_entry(struct map_entry *entry) + + static inline void release_entry(struct kref *kref) + { +- remove_entry(container_of_safe(kref, struct map_entry, ref)); ++ remove_entry(container_of(kref, struct map_entry, ref)); + } + + static inline struct map_entry *lookup_entry(struct map *map, const void *param) +@@ -234,4 +234,4 @@ void *map_get(struct map *map, const void *param) + size_t map_size(const struct map *map) + { + return (map != NULL) ? map->length : 0; +-} +\ No newline at end of file ++} +-- +2.34.1 + diff --git a/0002-daemon-fix-cannot-get-file-selinux-xattr-when-selinu.patch b/0002-daemon-fix-cannot-get-file-selinux-xattr-when-selinu.patch new file mode 100644 index 0000000000000000000000000000000000000000..6e1df0466e04a89916f881e7a379c9a148e8d02c --- /dev/null +++ b/0002-daemon-fix-cannot-get-file-selinux-xattr-when-selinu.patch @@ -0,0 +1,219 @@ +From a535e14a7db49df3c8aab017e32b92d8e5bb4087 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Wed, 10 Apr 2024 10:25:21 +0800 +Subject: [PATCH] daemon: fix 'cannot get file selinux xattr when selinux is + not enforcing' issue + +Signed-off-by: renoseven +--- + syscared/src/patch/driver/kpatch/mod.rs | 10 +---- + syscared/src/patch/driver/kpatch/sys.rs | 22 +++++----- + upatchd/src/hijacker/kmod.rs | 57 +++++++++++++------------ + upatchd/src/hijacker/mod.rs | 4 +- + 4 files changed, 44 insertions(+), 49 deletions(-) + +diff --git a/syscared/src/patch/driver/kpatch/mod.rs b/syscared/src/patch/driver/kpatch/mod.rs +index 72cbfc3..e6ab14e 100644 +--- a/syscared/src/patch/driver/kpatch/mod.rs ++++ b/syscared/src/patch/driver/kpatch/mod.rs +@@ -17,7 +17,7 @@ use std::{ + fmt::Write, + }; + +-use anyhow::{ensure, Context, Result}; ++use anyhow::{ensure, Result}; + use indexmap::{indexset, IndexMap, IndexSet}; + use log::debug; + +@@ -209,13 +209,7 @@ impl KernelPatchDriver { + } + + pub fn apply(&mut self, patch: &KernelPatch) -> Result<()> { +- let selinux_status = os::selinux::get_status()?; +- if selinux_status == os::selinux::Status::Enforcing { +- debug!("SELinux is enforcing"); +- sys::set_security_attribute(&patch.patch_file) +- .context("Kpatch: Failed to set security attribute")?; +- } +- ++ sys::selinux_relable_patch(patch)?; + sys::apply_patch(patch) + } + +diff --git a/syscared/src/patch/driver/kpatch/sys.rs b/syscared/src/patch/driver/kpatch/sys.rs +index c5cde8c..5035d06 100644 +--- a/syscared/src/patch/driver/kpatch/sys.rs ++++ b/syscared/src/patch/driver/kpatch/sys.rs +@@ -12,10 +12,7 @@ + * See the Mulan PSL v2 for more details. + */ + +-use std::{ +- ffi::{CString, OsString}, +- path::Path, +-}; ++use std::ffi::{CString, OsString}; + + use anyhow::{anyhow, bail, Context, Result}; + use log::debug; +@@ -39,15 +36,21 @@ pub fn list_kernel_modules() -> Result> { + Ok(module_names) + } + +-pub fn set_security_attribute>(patch_file: P) -> Result<()> { ++pub fn selinux_relable_patch(patch: &KernelPatch) -> Result<()> { + const KPATCH_PATCH_SEC_TYPE: &str = "modules_object_t"; + +- let file_path = patch_file.as_ref(); +- let mut sec_context = os::selinux::get_security_context(file_path)?; ++ if os::selinux::get_status()? != os::selinux::Status::Enforcing { ++ return Ok(()); ++ } + ++ debug!( ++ "Relabeling patch module '{}'...", ++ patch.module_name.to_string_lossy() ++ ); ++ let mut sec_context = os::selinux::get_security_context(&patch.patch_file)?; + if sec_context.kind != KPATCH_PATCH_SEC_TYPE { + sec_context.kind = OsString::from(KPATCH_PATCH_SEC_TYPE); +- os::selinux::set_security_context(file_path, sec_context)?; ++ os::selinux::set_security_context(&patch.patch_file, sec_context)?; + } + + Ok(()) +@@ -85,12 +88,11 @@ fn write_patch_status(patch: &KernelPatch, value: &str) -> Result<()> { + } + + pub fn apply_patch(patch: &KernelPatch) -> Result<()> { +- let patch_module = fs::open_file(&patch.patch_file)?; +- + debug!( + "Inserting patch module '{}'...", + patch.module_name.to_string_lossy() + ); ++ let patch_module = fs::open_file(&patch.patch_file)?; + kmod::finit_module( + &patch_module, + CString::new("")?.as_c_str(), +diff --git a/upatchd/src/hijacker/kmod.rs b/upatchd/src/hijacker/kmod.rs +index 1fe4def..fc89f5f 100644 +--- a/upatchd/src/hijacker/kmod.rs ++++ b/upatchd/src/hijacker/kmod.rs +@@ -27,50 +27,49 @@ const KMOD_SYS_PATH: &str = "/sys/module"; + /// An RAII guard of the kernel module. + pub struct HijackerKmodGuard { + kmod_name: String, ++ kmod_path: PathBuf, + sys_path: PathBuf, + } + + impl HijackerKmodGuard { +- pub fn new, P: AsRef>(name: S, path: P) -> Result { +- let kmod_name = name.as_ref().to_string(); +- let sys_path = Path::new(KMOD_SYS_PATH).join(name.as_ref()); +- let kmod_path = path.as_ref().to_path_buf(); +- +- let instance: HijackerKmodGuard = Self { +- kmod_name, +- sys_path, ++ pub fn new, P: AsRef>(name: S, kmod_path: P) -> Result { ++ let instance = Self { ++ kmod_name: name.as_ref().to_string(), ++ kmod_path: kmod_path.as_ref().to_path_buf(), ++ sys_path: Path::new(KMOD_SYS_PATH).join(name.as_ref()), + }; +- if !instance.is_installed() { +- instance.install(kmod_path)?; +- } ++ instance.selinux_relabel_kmod()?; ++ instance.install_kmod()?; ++ + Ok(instance) + } + } + + impl HijackerKmodGuard { +- #[inline] +- fn is_installed(&self) -> bool { +- self.sys_path.exists() +- } +- +- fn selinux_relable_module>(patch_file: P) -> Result<()> { ++ fn selinux_relabel_kmod(&self) -> Result<()> { + const KMOD_SECURITY_TYPE: &str = "modules_object_t"; + +- let file_path = patch_file.as_ref(); +- let mut sec_context = os::selinux::get_security_context(file_path)?; ++ if os::selinux::get_status()? != os::selinux::Status::Enforcing { ++ return Ok(()); ++ } + ++ info!("Relabeling kernel module '{}'...", self.kmod_name); ++ let mut sec_context = os::selinux::get_security_context(&self.kmod_path)?; + if sec_context.kind != KMOD_SECURITY_TYPE { + sec_context.kind = OsString::from(KMOD_SECURITY_TYPE); +- os::selinux::set_security_context(file_path, sec_context)?; ++ os::selinux::set_security_context(&self.kmod_path, sec_context)?; + } + + Ok(()) + } + +- fn install>(&self, kmod_path: P) -> Result<()> { ++ fn install_kmod(&self) -> Result<()> { ++ if self.sys_path.exists() { ++ return Ok(()); ++ } ++ + info!("Installing kernel module '{}'...", self.kmod_name); +- Self::selinux_relable_module(&kmod_path)?; +- let ko_file = fs::open_file(kmod_path)?; ++ let ko_file = fs::open_file(&self.kmod_path)?; + kmod::finit_module( + &ko_file, + CString::new("")?.as_c_str(), +@@ -79,7 +78,11 @@ impl HijackerKmodGuard { + .with_context(|| format!("Failed to install kernel module '{}'", self.kmod_name)) + } + +- fn remove(&self) -> Result<()> { ++ fn remove_kmod(&self) -> Result<()> { ++ if !self.sys_path.exists() { ++ return Ok(()); ++ } ++ + info!("Removing kernel module '{}'...", self.kmod_name); + kmod::delete_module( + CString::new(self.kmod_name.as_str())?.as_c_str(), +@@ -91,10 +94,8 @@ impl HijackerKmodGuard { + + impl Drop for HijackerKmodGuard { + fn drop(&mut self) { +- if self.is_installed() { +- if let Err(e) = self.remove() { +- error!("{:?}", e); +- } ++ if let Err(e) = self.remove_kmod() { ++ error!("{:?}", e); + } + } + } +diff --git a/upatchd/src/hijacker/mod.rs b/upatchd/src/hijacker/mod.rs +index 028a4c8..8ac12e7 100644 +--- a/upatchd/src/hijacker/mod.rs ++++ b/upatchd/src/hijacker/mod.rs +@@ -98,9 +98,7 @@ impl Hijacker { + info!("Using elf mapping: {}", config); + + debug!("Initializing hijacker kernel module..."); +- let kmod_name = KMOD_NAME.to_string(); +- let kmod_path = KMOD_FILE_PATH.to_string(); +- let kmod = HijackerKmodGuard::new(kmod_name, kmod_path)?; ++ let kmod = HijackerKmodGuard::new(KMOD_NAME, KMOD_FILE_PATH)?; + + debug!("Initializing hijacker ioctl channel..."); + let ioctl = HijackerIoctl::new(KMOD_DEV_PATH)?; +-- +2.34.1 + diff --git a/0003-syscared-fix-syscare-check-command-does-not-check-sy.patch b/0003-syscared-fix-syscare-check-command-does-not-check-sy.patch new file mode 100644 index 0000000000000000000000000000000000000000..514fa92a77ea73587117cd08a952d0449e2dfdb7 --- /dev/null +++ b/0003-syscared-fix-syscare-check-command-does-not-check-sy.patch @@ -0,0 +1,385 @@ +From e5294afa8135f54f44196bd92e5a32c2b09b9bda Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Wed, 10 Apr 2024 12:19:51 +0800 +Subject: [PATCH] syscared: fix 'syscare check command does not check symbol + confiliction' issue + +Signed-off-by: renoseven +--- + syscared/src/patch/driver/kpatch/mod.rs | 23 ++------- + syscared/src/patch/driver/mod.rs | 66 +++++++++++++++++++------ + syscared/src/patch/driver/upatch/mod.rs | 35 +++++-------- + syscared/src/patch/manager.rs | 21 ++++---- + 4 files changed, 79 insertions(+), 66 deletions(-) + +diff --git a/syscared/src/patch/driver/kpatch/mod.rs b/syscared/src/patch/driver/kpatch/mod.rs +index e6ab14e..e4509d8 100644 +--- a/syscared/src/patch/driver/kpatch/mod.rs ++++ b/syscared/src/patch/driver/kpatch/mod.rs +@@ -24,7 +24,6 @@ use log::debug; + use syscare_abi::PatchStatus; + use syscare_common::{concat_os, os, util::digest}; + +-use super::PatchOpFlag; + use crate::patch::entity::KernelPatch; + + mod sys; +@@ -103,7 +102,7 @@ impl KernelPatchDriver { + Ok(()) + } + +- fn check_conflict_symbols(&self, patch: &KernelPatch) -> Result<()> { ++ pub fn check_conflict_symbols(&self, patch: &KernelPatch) -> Result<()> { + let mut conflict_patches = indexset! {}; + + let target_symbols = PatchTarget::classify_symbols(&patch.symbols); +@@ -132,7 +131,7 @@ impl KernelPatchDriver { + Ok(()) + } + +- fn check_override_symbols(&self, patch: &KernelPatch) -> Result<()> { ++ pub fn check_override_symbols(&self, patch: &KernelPatch) -> Result<()> { + let mut override_patches = indexset! {}; + + let target_symbols = PatchTarget::classify_symbols(&patch.symbols); +@@ -196,11 +195,7 @@ impl KernelPatchDriver { + sys::read_patch_status(patch) + } + +- pub fn check(&self, patch: &KernelPatch, flag: PatchOpFlag) -> Result<()> { +- if flag == PatchOpFlag::Force { +- return Ok(()); +- } +- ++ pub fn check(&self, patch: &KernelPatch) -> Result<()> { + Self::check_consistency(patch)?; + Self::check_compatiblity(patch)?; + Self::check_dependency(patch)?; +@@ -217,22 +212,14 @@ impl KernelPatchDriver { + sys::remove_patch(patch) + } + +- pub fn active(&mut self, patch: &KernelPatch, flag: PatchOpFlag) -> Result<()> { +- if flag != PatchOpFlag::Force { +- self.check_conflict_symbols(patch)?; +- } +- ++ pub fn active(&mut self, patch: &KernelPatch) -> Result<()> { + sys::active_patch(patch)?; + self.add_patch_symbols(patch); + + Ok(()) + } + +- pub fn deactive(&mut self, patch: &KernelPatch, flag: PatchOpFlag) -> Result<()> { +- if flag != PatchOpFlag::Force { +- self.check_override_symbols(patch)?; +- } +- ++ pub fn deactive(&mut self, patch: &KernelPatch) -> Result<()> { + sys::deactive_patch(patch)?; + self.remove_patch_symbols(patch); + +diff --git a/syscared/src/patch/driver/mod.rs b/syscared/src/patch/driver/mod.rs +index 9dff9dd..e6dab94 100644 +--- a/syscared/src/patch/driver/mod.rs ++++ b/syscared/src/patch/driver/mod.rs +@@ -36,6 +36,22 @@ pub struct PatchDriver { + upatch: UserPatchDriver, + } + ++impl PatchDriver { ++ fn check_conflict_symbols(&self, patch: &Patch) -> Result<()> { ++ match patch { ++ Patch::KernelPatch(patch) => self.kpatch.check_conflict_symbols(patch), ++ Patch::UserPatch(patch) => self.upatch.check_conflict_symbols(patch), ++ } ++ } ++ ++ fn check_override_symbols(&self, patch: &Patch) -> Result<()> { ++ match patch { ++ Patch::KernelPatch(patch) => self.kpatch.check_override_symbols(patch), ++ Patch::UserPatch(patch) => self.upatch.check_override_symbols(patch), ++ } ++ } ++} ++ + impl PatchDriver { + pub fn new() -> Result { + info!("Initializing kernel patch driver..."); +@@ -53,26 +69,40 @@ impl PatchDriver { + } + + /// Fetch and return the patch status. +- pub fn status(&self, patch: &Patch) -> Result { ++ pub fn patch_status(&self, patch: &Patch) -> Result { + match patch { + Patch::KernelPatch(patch) => self.kpatch.status(patch), + Patch::UserPatch(patch) => self.upatch.status(patch), + } ++ .with_context(|| format!("Failed to get patch '{}' status", patch)) + } + +- /// Perform file intergrity & consistency check.
+- /// Should be used befor patch application. +- pub fn check(&self, patch: &Patch, flag: PatchOpFlag) -> Result<()> { ++ /// Perform patch file intergrity & consistency check.
++ /// Should be used before patch application. ++ pub fn check_patch(&self, patch: &Patch, flag: PatchOpFlag) -> Result<()> { ++ if flag == PatchOpFlag::Force { ++ return Ok(()); ++ } + match patch { +- Patch::KernelPatch(patch) => self.kpatch.check(patch, flag), +- Patch::UserPatch(patch) => self.upatch.check(patch, flag), ++ Patch::KernelPatch(patch) => self.kpatch.check(patch), ++ Patch::UserPatch(patch) => self.upatch.check(patch), ++ } ++ .with_context(|| format!("Patch '{}' is not patchable", patch)) ++ } ++ ++ /// Perform patch confliction check.
++ /// Used for patch check. ++ pub fn check_confliction(&self, patch: &Patch, flag: PatchOpFlag) -> Result<()> { ++ if flag == PatchOpFlag::Force { ++ return Ok(()); + } +- .with_context(|| format!("Patch '{}' check failed", patch)) ++ self.check_conflict_symbols(patch) ++ .with_context(|| format!("Patch '{}' is conflicted", patch)) + } + + /// Apply a patch.
+ /// After this action, the patch status would be changed to 'DEACTIVED'. +- pub fn apply(&mut self, patch: &Patch) -> Result<()> { ++ pub fn apply_patch(&mut self, patch: &Patch) -> Result<()> { + match patch { + Patch::KernelPatch(patch) => self.kpatch.apply(patch), + Patch::UserPatch(patch) => self.upatch.apply(patch), +@@ -82,7 +112,7 @@ impl PatchDriver { + + /// Remove a patch.
+ /// After this action, the patch status would be changed to 'NOT-APPLIED'. +- pub fn remove(&mut self, patch: &Patch) -> Result<()> { ++ pub fn remove_patch(&mut self, patch: &Patch) -> Result<()> { + match patch { + Patch::KernelPatch(patch) => self.kpatch.remove(patch), + Patch::UserPatch(patch) => self.upatch.remove(patch), +@@ -92,20 +122,26 @@ impl PatchDriver { + + /// Active a patch.
+ /// After this action, the patch status would be changed to 'ACTIVED'. +- pub fn active(&mut self, patch: &Patch, flag: PatchOpFlag) -> Result<()> { ++ pub fn active_patch(&mut self, patch: &Patch, flag: PatchOpFlag) -> Result<()> { ++ if flag != PatchOpFlag::Force { ++ self.check_conflict_symbols(patch)?; ++ } + match patch { +- Patch::KernelPatch(patch) => self.kpatch.active(patch, flag), +- Patch::UserPatch(patch) => self.upatch.active(patch, flag), ++ Patch::KernelPatch(patch) => self.kpatch.active(patch), ++ Patch::UserPatch(patch) => self.upatch.active(patch), + } + .with_context(|| format!("Failed to active patch '{}'", patch)) + } + + /// Deactive a patch.
+ /// After this action, the patch status would be changed to 'DEACTIVED'. +- pub fn deactive(&mut self, patch: &Patch, flag: PatchOpFlag) -> Result<()> { ++ pub fn deactive_patch(&mut self, patch: &Patch, flag: PatchOpFlag) -> Result<()> { ++ if flag != PatchOpFlag::Force { ++ self.check_override_symbols(patch)?; ++ } + match patch { +- Patch::KernelPatch(patch) => self.kpatch.deactive(patch, flag), +- Patch::UserPatch(patch) => self.upatch.deactive(patch, flag), ++ Patch::KernelPatch(patch) => self.kpatch.deactive(patch), ++ Patch::UserPatch(patch) => self.upatch.deactive(patch), + } + .with_context(|| format!("Failed to deactive patch '{}'", patch)) + } +diff --git a/syscared/src/patch/driver/upatch/mod.rs b/syscared/src/patch/driver/upatch/mod.rs +index 2ca3539..98fc54c 100644 +--- a/syscared/src/patch/driver/upatch/mod.rs ++++ b/syscared/src/patch/driver/upatch/mod.rs +@@ -28,7 +28,6 @@ use uuid::Uuid; + use syscare_abi::PatchStatus; + use syscare_common::util::digest; + +-use super::PatchOpFlag; + use crate::patch::entity::UserPatch; + + mod monitor; +@@ -71,7 +70,7 @@ impl UserPatchDriver { + } + + impl UserPatchDriver { +- fn check_consistency(&self, patch: &UserPatch) -> Result<()> { ++ fn check_consistency(patch: &UserPatch) -> Result<()> { + let patch_file = patch.patch_file.as_path(); + let real_checksum = digest::file(patch_file)?; + debug!("Target checksum: '{}'", patch.checksum); +@@ -84,11 +83,11 @@ impl UserPatchDriver { + Ok(()) + } + +- fn check_compatiblity(&self, _patch: &UserPatch) -> Result<()> { ++ fn check_compatiblity(_patch: &UserPatch) -> Result<()> { + Ok(()) + } + +- fn check_conflict_symbols(&self, patch: &UserPatch) -> Result<()> { ++ pub fn check_conflict_symbols(&self, patch: &UserPatch) -> Result<()> { + let patch_symbols = patch.symbols.as_slice(); + let target_name = patch.target_elf.as_os_str(); + let conflict_patches = match self.patch_target_map.get(target_name) { +@@ -114,7 +113,7 @@ impl UserPatchDriver { + Ok(()) + } + +- fn check_override_symbols(&self, patch: &UserPatch) -> Result<()> { ++ pub fn check_override_symbols(&self, patch: &UserPatch) -> Result<()> { + let patch_uuid = patch.uuid; + let patch_symbols = patch.symbols.as_slice(); + let target_name = patch.target_elf.as_os_str(); +@@ -233,13 +232,9 @@ impl UserPatchDriver { + .unwrap_or(PatchStatus::NotApplied)) + } + +- pub fn check(&self, patch: &UserPatch, flag: PatchOpFlag) -> Result<()> { +- if flag == PatchOpFlag::Force { +- return Ok(()); +- } +- +- self.check_consistency(patch)?; +- self.check_compatiblity(patch)?; ++ pub fn check(&self, patch: &UserPatch) -> Result<()> { ++ Self::check_consistency(patch)?; ++ Self::check_compatiblity(patch)?; + + Ok(()) + } +@@ -272,7 +267,7 @@ impl UserPatchDriver { + Ok(()) + } + +- pub fn active(&mut self, patch: &UserPatch, flag: PatchOpFlag) -> Result<()> { ++ pub fn active(&mut self, patch: &UserPatch) -> Result<()> { + let patch_uuid = patch.uuid; + let patch_status = self.get_patch_status(patch_uuid)?; + ensure!( +@@ -280,10 +275,6 @@ impl UserPatchDriver { + "Upatch: Invalid patch status" + ); + +- if flag != PatchOpFlag::Force { +- self.check_conflict_symbols(patch)?; +- } +- + let target_elf = patch.target_elf.as_path(); + let patch_file = patch.patch_file.as_path(); + let pid_list = process::find_target_process(target_elf)?; +@@ -300,13 +291,13 @@ impl UserPatchDriver { + + drop(active_patch_map); + +- self.add_patch_symbols(patch); + self.set_patch_status(patch_uuid, PatchStatus::Actived)?; ++ self.add_patch_symbols(patch); + + Ok(()) + } + +- pub fn deactive(&mut self, patch: &UserPatch, flag: PatchOpFlag) -> Result<()> { ++ pub fn deactive(&mut self, patch: &UserPatch) -> Result<()> { + let patch_uuid = patch.uuid; + let patch_status = self.get_patch_status(patch_uuid)?; + ensure!( +@@ -314,10 +305,6 @@ impl UserPatchDriver { + "Upatch: Invalid patch status" + ); + +- if flag != PatchOpFlag::Force { +- self.check_override_symbols(patch)?; +- } +- + let target_elf = patch.target_elf.as_path(); + let patch_file = patch.patch_file.as_path(); + let pid_list = process::find_target_process(target_elf)?; +@@ -337,8 +324,8 @@ impl UserPatchDriver { + + drop(active_patch_map); + +- self.remove_patch_symbols(patch); + self.set_patch_status(patch_uuid, PatchStatus::Deactived)?; ++ self.remove_patch_symbols(patch); + + Ok(()) + } +diff --git a/syscared/src/patch/manager.rs b/syscared/src/patch/manager.rs +index b353bdf..f633567 100644 +--- a/syscared/src/patch/manager.rs ++++ b/syscared/src/patch/manager.rs +@@ -134,7 +134,7 @@ impl PatchManager { + .unwrap_or_default(); + + if status == PatchStatus::Unknown { +- status = self.driver_get_patch_status(patch, PatchOpFlag::Normal)?; ++ status = self.driver_patch_status(patch, PatchOpFlag::Normal)?; + self.set_patch_status(patch, status)?; + } + +@@ -142,7 +142,10 @@ impl PatchManager { + } + + pub fn check_patch(&mut self, patch: &Patch, flag: PatchOpFlag) -> Result<()> { +- self.driver_check_patch(patch, flag) ++ self.driver.check_patch(patch, flag)?; ++ self.driver.check_confliction(patch, flag)?; ++ ++ Ok(()) + } + + pub fn apply_patch(&mut self, patch: &Patch, flag: PatchOpFlag) -> Result { +@@ -438,31 +441,31 @@ impl PatchManager { + } + + impl PatchManager { +- fn driver_get_patch_status(&self, patch: &Patch, _flag: PatchOpFlag) -> Result { +- self.driver.status(patch) ++ fn driver_patch_status(&self, patch: &Patch, _flag: PatchOpFlag) -> Result { ++ self.driver.patch_status(patch) + } + + fn driver_check_patch(&mut self, patch: &Patch, flag: PatchOpFlag) -> Result<()> { +- self.driver.check(patch, flag) ++ self.driver.check_patch(patch, flag) + } + + fn driver_apply_patch(&mut self, patch: &Patch, _flag: PatchOpFlag) -> Result<()> { +- self.driver.apply(patch)?; ++ self.driver.apply_patch(patch)?; + self.set_patch_status(patch, PatchStatus::Deactived) + } + + fn driver_remove_patch(&mut self, patch: &Patch, _flag: PatchOpFlag) -> Result<()> { +- self.driver.remove(patch)?; ++ self.driver.remove_patch(patch)?; + self.set_patch_status(patch, PatchStatus::NotApplied) + } + + fn driver_active_patch(&mut self, patch: &Patch, flag: PatchOpFlag) -> Result<()> { +- self.driver.active(patch, flag)?; ++ self.driver.active_patch(patch, flag)?; + self.set_patch_status(patch, PatchStatus::Actived) + } + + fn driver_deactive_patch(&mut self, patch: &Patch, flag: PatchOpFlag) -> Result<()> { +- self.driver.deactive(patch, flag)?; ++ self.driver.deactive_patch(patch, flag)?; + self.set_patch_status(patch, PatchStatus::Deactived) + } + +-- +2.34.1 + diff --git a/0004-syscared-fix-cannot-find-process-of-dynlib-patch-iss.patch b/0004-syscared-fix-cannot-find-process-of-dynlib-patch-iss.patch new file mode 100644 index 0000000000000000000000000000000000000000..1bdb55ba2468d7f29c1cfc0fd9ba538628f1f5c9 --- /dev/null +++ b/0004-syscared-fix-cannot-find-process-of-dynlib-patch-iss.patch @@ -0,0 +1,686 @@ +From 32c3d16175b93627504981d05a1a3e3ec603415e Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Wed, 10 Apr 2024 19:30:56 +0800 +Subject: [PATCH] syscared: fix 'cannot find process of dynlib patch' issue + +1. For detecting process mapped dynamic library, + we use /proc/$pid/map_files instead. + We do readlink() to get it's real file path and then + read it's inode to judge if it's the file we want. +2. For calculating processes to be actived / deactived, we + use IndexSet::difference() / IndexSet::intersection() between + all current target process and the recorded process set. + +Signed-off-by: renoseven +--- + syscared/src/patch/driver/upatch/mod.rs | 217 ++++++++++++++------ + syscared/src/patch/driver/upatch/monitor.rs | 18 +- + syscared/src/patch/driver/upatch/process.rs | 126 +++++++----- + syscared/src/patch/driver/upatch/sys.rs | 108 ++++------ + 4 files changed, 270 insertions(+), 199 deletions(-) + +diff --git a/syscared/src/patch/driver/upatch/mod.rs b/syscared/src/patch/driver/upatch/mod.rs +index 98fc54c..a7fa154 100644 +--- a/syscared/src/patch/driver/upatch/mod.rs ++++ b/syscared/src/patch/driver/upatch/mod.rs +@@ -21,7 +21,7 @@ use std::{ + + use anyhow::{ensure, Context, Result}; + use indexmap::{indexset, IndexMap, IndexSet}; +-use log::{debug, info}; ++use log::{debug, error}; + use parking_lot::Mutex; + use uuid::Uuid; + +@@ -38,31 +38,31 @@ mod target; + use monitor::UserPatchMonitor; + use target::PatchTarget; + +-pub(self) type ActivePatchMap = Arc>>; ++type ElfPatchMap = Arc>>; + + #[derive(Default)] +-struct ActivePatch { +- patch_list: Vec<(Uuid, PathBuf)>, // Patch applied to target elf (uuid and patch file) +- process_list: IndexSet, // Target elf process list ++struct ElfPatchRecord { ++ patch_map: IndexMap, // Patch applied to target elf (uuid and patch file) ++ processes: IndexSet, // Target elf process list + } + + pub struct UserPatchDriver { + patch_target_map: IndexMap, + patch_status_map: IndexMap, +- active_patch_map: ActivePatchMap, ++ elf_patch_map: ElfPatchMap, + patch_monitor: UserPatchMonitor, + } + + impl UserPatchDriver { + pub fn new() -> Result { +- let active_patch_map = Arc::new(Mutex::new(IndexMap::new())); ++ let elf_patch_map = Arc::new(Mutex::new(IndexMap::new())); + let patch_monitor = +- UserPatchMonitor::new(active_patch_map.clone(), Self::on_new_process_created)?; ++ UserPatchMonitor::new(elf_patch_map.clone(), Self::patch_new_process)?; + + let instance = Self { + patch_target_map: IndexMap::new(), + patch_status_map: IndexMap::new(), +- active_patch_map, ++ elf_patch_map, + patch_monitor, + }; + Ok(instance) +@@ -168,36 +168,51 @@ impl UserPatchDriver { + } + + impl UserPatchDriver { +- fn on_new_process_created(active_patch_map: ActivePatchMap, target_elf: &Path) -> Result<()> { +- // find actived patch +- if let Some(patch_record) = active_patch_map.lock().get_mut(target_elf) { +- let current_process_list = process::find_target_process(target_elf)?; +- let patched_process_list = &patch_record.process_list; +- +- // Filter patched pid +- let pid_list = current_process_list +- .iter() +- .filter(|pid| !patched_process_list.contains(*pid)) +- .copied() +- .collect::>(); +- if pid_list.is_empty() { +- return Ok(()); +- } ++ fn patch_new_process(elf_patch_map: ElfPatchMap, target_elf: &Path) { ++ let process_list = match process::find_target_process(target_elf) { ++ Ok(processes) => processes, ++ Err(_) => return, ++ }; ++ ++ let mut patch_map = elf_patch_map.lock(); ++ let patch_record = match patch_map.get_mut(target_elf) { ++ Some(record) => record, ++ None => return, ++ }; ++ ++ let need_active = process_list ++ .difference(&patch_record.processes) ++ .copied() ++ .collect::>(); + +- for (uuid, patch_file) in &patch_record.patch_list { +- info!( +- "Patching '{}' ({}) to process {:?}", ++ // Active patch ++ for (uuid, patch_file) in &patch_record.patch_map { ++ if !need_active.is_empty() { ++ debug!( ++ "Upatch: Activating patch '{}' ({}) to process {:?}", + uuid, + target_elf.display(), +- pid_list, ++ need_active, + ); +- sys::active_patch(uuid, target_elf, patch_file, &pid_list)?; + } +- +- patch_record.process_list = current_process_list; ++ for pid in &need_active { ++ if let Err(e) = sys::active_patch(uuid, *pid, target_elf, patch_file) { ++ error!("{:?}", e); ++ continue; ++ } ++ patch_record.processes.insert(*pid); ++ } + } + +- Ok(()) ++ // Remove process no longer exists ++ let need_remove = patch_record ++ .processes ++ .difference(&process_list) ++ .copied() ++ .collect::>(); ++ for pid in need_remove { ++ patch_record.processes.remove(&pid); ++ } + } + } + +@@ -246,7 +261,11 @@ impl UserPatchDriver { + "Upatch: Patch already exists" + ); + +- debug!("Upatch: Applying patch '{}'", patch_uuid); ++ debug!( ++ "Upatch: Applying patch '{}', patch_file: {}", ++ patch_uuid, ++ patch.patch_file.display() ++ ); + self.patch_status_map + .insert(patch_uuid, PatchStatus::Deactived); + +@@ -261,15 +280,19 @@ impl UserPatchDriver { + "Upatch: Invalid patch status" + ); + +- debug!("Upatch: Removing patch '{}'", patch_uuid); ++ debug!( ++ "Upatch: Removing patch '{}', patch_file: {}", ++ patch_uuid, ++ patch.patch_file.display() ++ ); + self.patch_status_map.remove(&patch_uuid); + + Ok(()) + } + + pub fn active(&mut self, patch: &UserPatch) -> Result<()> { +- let patch_uuid = patch.uuid; +- let patch_status = self.get_patch_status(patch_uuid)?; ++ let uuid = patch.uuid; ++ let patch_status = self.get_patch_status(uuid)?; + ensure!( + patch_status == PatchStatus::Deactived, + "Upatch: Invalid patch status" +@@ -277,29 +300,65 @@ impl UserPatchDriver { + + let target_elf = patch.target_elf.as_path(); + let patch_file = patch.patch_file.as_path(); +- let pid_list = process::find_target_process(target_elf)?; +- sys::active_patch(&patch_uuid, target_elf, patch_file, &pid_list)?; ++ let process_list = process::find_target_process(target_elf)?; ++ ++ let mut patch_map = self.elf_patch_map.lock(); ++ let patch_record = patch_map.entry(target_elf.to_path_buf()).or_default(); ++ ++ let need_active = process_list ++ .difference(&patch_record.processes) ++ .copied() ++ .collect::>(); ++ let need_remove = patch_record ++ .processes ++ .difference(&process_list) ++ .copied() ++ .collect::>(); ++ let mut need_start_watch = false; ++ ++ // Active patch ++ if !need_active.is_empty() { ++ debug!( ++ "Upatch: Activating patch '{}' ({}) to process {:?}", ++ uuid, ++ target_elf.display(), ++ need_active, ++ ); ++ } ++ for pid in need_active { ++ if let Err(e) = sys::active_patch(&uuid, pid, target_elf, patch_file) { ++ error!("{:?}", e); ++ } ++ patch_record.processes.insert(pid); ++ } + +- let mut active_patch_map = self.active_patch_map.lock(); +- let active_patch = active_patch_map +- .entry(target_elf.to_path_buf()) +- .or_default(); +- let patch_list = &mut active_patch.patch_list; ++ // Remove process no longer exists ++ for pid in need_remove { ++ patch_record.processes.remove(&pid); ++ } + +- patch_list.push((patch_uuid, patch_file.to_path_buf())); +- self.patch_monitor.watch_file(target_elf)?; ++ // If elf is not patched before, start watching it & add a new entry ++ if !patch_record.patch_map.contains_key(&uuid) { ++ patch_record ++ .patch_map ++ .insert(uuid, patch_file.to_path_buf()); ++ need_start_watch = true; ++ } + +- drop(active_patch_map); ++ drop(patch_map); + +- self.set_patch_status(patch_uuid, PatchStatus::Actived)?; ++ if need_start_watch { ++ self.patch_monitor.watch_file(target_elf)?; ++ } ++ self.set_patch_status(uuid, PatchStatus::Actived)?; + self.add_patch_symbols(patch); + + Ok(()) + } + + pub fn deactive(&mut self, patch: &UserPatch) -> Result<()> { +- let patch_uuid = patch.uuid; +- let patch_status = self.get_patch_status(patch_uuid)?; ++ let uuid = patch.uuid; ++ let patch_status = self.get_patch_status(uuid)?; + ensure!( + patch_status == PatchStatus::Actived, + "Upatch: Invalid patch status" +@@ -307,24 +366,58 @@ impl UserPatchDriver { + + let target_elf = patch.target_elf.as_path(); + let patch_file = patch.patch_file.as_path(); +- let pid_list = process::find_target_process(target_elf)?; +- sys::deactive_patch(&patch_uuid, target_elf, patch_file, &pid_list)?; ++ let process_list = process::find_target_process(target_elf)?; + +- let mut active_patch_map = self.active_patch_map.lock(); +- let active_patch = active_patch_map +- .entry(target_elf.to_path_buf()) +- .or_default(); +- let patch_list = &mut active_patch.patch_list; ++ let mut patch_map = self.elf_patch_map.lock(); ++ let patch_record = patch_map ++ .get_mut(target_elf) ++ .context("Failed to find elf patch record")?; + +- patch_list.pop(); +- if patch_list.is_empty() { +- self.patch_monitor.ignore_file(target_elf)?; +- active_patch_map.remove(target_elf); ++ let need_deactive = process_list ++ .intersection(&patch_record.processes) ++ .copied() ++ .collect::>(); ++ let need_removed = patch_record ++ .processes ++ .difference(&process_list) ++ .copied() ++ .collect::>(); ++ let mut need_stop_watch = false; ++ ++ // Deactive patch ++ if !need_deactive.is_empty() { ++ debug!( ++ "Upatch: Deactivating patch '{}' ({}) of process {:?}", ++ uuid, ++ target_elf.display(), ++ need_deactive, ++ ); ++ } ++ for pid in need_deactive { ++ sys::deactive_patch(&uuid, pid, target_elf, patch_file)?; ++ patch_record.processes.remove(&pid); // remove process from record + } + +- drop(active_patch_map); ++ // Remove process no longer exists ++ for pid in need_removed { ++ patch_record.processes.remove(&pid); ++ } + +- self.set_patch_status(patch_uuid, PatchStatus::Deactived)?; ++ // Remove patch from elf patch record ++ patch_record.patch_map.remove(&uuid); ++ ++ // If elf has no more patch, stop watching it & remove the entry ++ if patch_record.patch_map.is_empty() { ++ patch_map.remove(target_elf); ++ need_stop_watch = true; ++ } ++ ++ drop(patch_map); ++ ++ if need_stop_watch { ++ self.patch_monitor.ignore_file(target_elf)?; ++ } ++ self.set_patch_status(uuid, PatchStatus::Deactived)?; + self.remove_patch_symbols(patch); + + Ok(()) +diff --git a/syscared/src/patch/driver/upatch/monitor.rs b/syscared/src/patch/driver/upatch/monitor.rs +index 0dd4088..1dbb513 100644 +--- a/syscared/src/patch/driver/upatch/monitor.rs ++++ b/syscared/src/patch/driver/upatch/monitor.rs +@@ -23,10 +23,10 @@ use std::{ + use anyhow::{bail, Context, Result}; + use indexmap::IndexMap; + use inotify::{EventMask, Inotify, WatchDescriptor, WatchMask}; +-use log::{error, info}; ++use log::info; + use parking_lot::{Mutex, RwLock}; + +-use super::ActivePatchMap; ++use super::ElfPatchMap; + + const MONITOR_THREAD_NAME: &str = "upatch_monitor"; + const MONITOR_CHECK_PERIOD: u64 = 100; +@@ -40,9 +40,9 @@ pub(super) struct UserPatchMonitor { + } + + impl UserPatchMonitor { +- pub fn new(active_patch_map: ActivePatchMap, callback: F) -> Result ++ pub fn new(elf_patch_map: ElfPatchMap, callback: F) -> Result + where +- F: Fn(ActivePatchMap, &Path) -> Result<()> + Send + 'static, ++ F: Fn(ElfPatchMap, &Path) + Send + Sync + 'static, + { + let inotify = Arc::new(Mutex::new(Some( + Inotify::init().context("Failed to initialize inotify")?, +@@ -52,7 +52,7 @@ impl UserPatchMonitor { + let monitor_thread = MonitorThread { + inotify: inotify.clone(), + target_map: target_map.clone(), +- active_patch_map, ++ elf_patch_map, + callback, + } + .run()?; +@@ -115,13 +115,13 @@ impl UserPatchMonitor { + struct MonitorThread { + inotify: Arc>>, + target_map: Arc>>, +- active_patch_map: ActivePatchMap, ++ elf_patch_map: ElfPatchMap, + callback: F, + } + + impl MonitorThread + where +- F: Fn(ActivePatchMap, &Path) -> Result<()> + Send + 'static, ++ F: Fn(ElfPatchMap, &Path) + Send + Sync + 'static, + { + fn run(self) -> Result> { + thread::Builder::new() +@@ -140,9 +140,7 @@ where + continue; + } + if let Some(patch_file) = self.target_map.read().get(&event.wd) { +- if let Err(e) = (self.callback)(self.active_patch_map.clone(), patch_file) { +- error!("{:?}", e); +- } ++ (self.callback)(self.elf_patch_map.clone(), patch_file); + } + } + } +diff --git a/syscared/src/patch/driver/upatch/process.rs b/syscared/src/patch/driver/upatch/process.rs +index 597fc0e..9b2f6de 100644 +--- a/syscared/src/patch/driver/upatch/process.rs ++++ b/syscared/src/patch/driver/upatch/process.rs +@@ -12,77 +12,89 @@ + * See the Mulan PSL v2 for more details. + */ + +-use std::{ +- ffi::OsStr, +- path::{Path, PathBuf}, +-}; ++use std::{ffi::OsStr, os::linux::fs::MetadataExt, path::Path}; + + use anyhow::Result; + use indexmap::IndexSet; + use syscare_common::fs; + +-use syscare_common::os::proc_maps::ProcMaps; ++const PROC_BLACK_LIST: [&str; 18] = [ ++ "/usr/lib/systemd/systemd-journald", ++ "/usr/lib/systemd/systemd-logind", ++ "/usr/lib/systemd/systemd-udevd", ++ "/usr/lib/systemd/systemd-hostnamed", ++ "/usr/bin/udevadm", ++ "/usr/sbin/auditd", ++ "/usr/bin/syscare", ++ "/usr/bin/syscared", ++ "/usr/bin/upatchd", ++ "/usr/libexec/syscare/as-hijacker", ++ "/usr/libexec/syscare/cc-hijacker", ++ "/usr/libexec/syscare/c++-hijacker", ++ "/usr/libexec/syscare/gcc-hijacker", ++ "/usr/libexec/syscare/g++-hijacker", ++ "/usr/libexec/syscare/syscare-build", ++ "/usr/libexec/syscare/upatch-build", ++ "/usr/libexec/syscare/upatch-diff", ++ "/usr/libexec/syscare/upatch-manage", ++]; + + #[inline] +-fn parse_process_id>(path: P) -> Option { +- path.as_ref() ++fn is_blacklisted(file_path: &Path) -> bool { ++ PROC_BLACK_LIST ++ .iter() ++ .map(Path::new) ++ .any(|blacklist_path| blacklist_path == file_path) ++} ++ ++#[inline] ++fn parse_process_id(proc_path: &Path) -> Option { ++ proc_path + .file_name() + .and_then(OsStr::to_str) + .map(str::parse) + .and_then(Result::ok) + } + +-#[inline] +-fn parse_process_path(pid: i32) -> Option<(i32, PathBuf)> { +- const PROC_BLACK_LIST: [&str; 18] = [ +- "/usr/lib/systemd/systemd-journald", +- "/usr/lib/systemd/systemd-logind", +- "/usr/lib/systemd/systemd-udevd", +- "/usr/lib/systemd/systemd-hostnamed", +- "/usr/bin/udevadm", +- "/usr/sbin/auditd", +- "/usr/bin/syscare", +- "/usr/bin/syscared", +- "/usr/bin/upatchd", +- "/usr/libexec/syscare/as-hijacker", +- "/usr/libexec/syscare/cc-hijacker", +- "/usr/libexec/syscare/c++-hijacker", +- "/usr/libexec/syscare/gcc-hijacker", +- "/usr/libexec/syscare/g++-hijacker", +- "/usr/libexec/syscare/syscare-build", +- "/usr/libexec/syscare/upatch-build", +- "/usr/libexec/syscare/upatch-diff", +- "/usr/libexec/syscare/upatch-manage", +- ]; +- +- fs::read_link(format!("/proc/{}/exe", pid)) +- .ok() +- .filter(|path| { +- !PROC_BLACK_LIST +- .iter() +- .any(|blacklist_path| path.as_os_str() == *blacklist_path) +- }) +- .map(|path| (pid, path)) +-} +- + pub fn find_target_process>(target_elf: P) -> Result> { +- let target_file = fs::canonicalize(target_elf.as_ref())?; +- let target_path = target_file.as_path(); +- let target_pids = fs::list_dirs("/proc", fs::TraverseOptions { recursive: false })? +- .into_iter() +- .filter_map(self::parse_process_id) +- .filter_map(self::parse_process_path) +- .filter(|(pid, bin_path)| { +- if bin_path == target_path { +- return true; +- } +- if let Ok(mut mappings) = ProcMaps::new(*pid) { +- return mappings.any(|map| map.path_name == target_path); +- } +- false +- }) +- .map(|(pid, _)| pid) +- .collect(); ++ let mut target_pids = IndexSet::new(); ++ let target_path = target_elf.as_ref(); ++ let target_inode = target_path.metadata()?.st_ino(); ++ ++ for proc_path in fs::list_dirs("/proc", fs::TraverseOptions { recursive: false })? { ++ let pid = match self::parse_process_id(&proc_path) { ++ Some(pid) => pid, ++ None => continue, ++ }; ++ let exec_path = match fs::read_link(format!("/proc/{}/exe", pid)) { ++ Ok(file_path) => file_path, ++ Err(_) => continue, ++ }; ++ if is_blacklisted(&exec_path) { ++ continue; ++ } ++ // Try to match binary path ++ if exec_path == target_path { ++ target_pids.insert(pid); ++ continue; ++ } ++ // Try to match mapped files ++ let map_files = fs::list_symlinks( ++ format!("/proc/{}/map_files", pid), ++ fs::TraverseOptions { recursive: false }, ++ )?; ++ for mapped_file in map_files { ++ if let Ok(mapped_inode) = mapped_file ++ .read_link() ++ .and_then(|file_path| Ok(file_path.metadata()?.st_ino())) ++ { ++ if mapped_inode == target_inode { ++ target_pids.insert(pid); ++ break; ++ } ++ }; ++ } ++ } + + Ok(target_pids) + } +diff --git a/syscared/src/patch/driver/upatch/sys.rs b/syscared/src/patch/driver/upatch/sys.rs +index bab2974..f0745f0 100644 +--- a/syscared/src/patch/driver/upatch/sys.rs ++++ b/syscared/src/patch/driver/upatch/sys.rs +@@ -1,7 +1,7 @@ + use std::path::Path; + + use anyhow::{bail, Result}; +-use log::{debug, Level}; ++use log::Level; + use nix::libc::EEXIST; + use uuid::Uuid; + +@@ -9,80 +9,48 @@ use syscare_common::process::Command; + + const UPATCH_MANAGE_BIN: &str = "/usr/libexec/syscare/upatch-manage"; + +-pub fn active_patch<'a, I>( +- uuid: &Uuid, +- target_elf: &Path, +- patch_file: &Path, +- pid_list: I, +-) -> Result<()> +-where +- I: IntoIterator, +-{ +- debug!( +- "Patching '{}' to {}", +- patch_file.display(), +- target_elf.display() +- ); +- +- for pid in pid_list { +- let exit_code = Command::new(UPATCH_MANAGE_BIN) +- .arg("patch") +- .arg("--uuid") +- .arg(uuid.to_string()) +- .arg("--pid") +- .arg(pid.to_string()) +- .arg("--binary") +- .arg(target_elf) +- .arg("--upatch") +- .arg(patch_file) +- .stdout(Level::Debug) +- .run_with_output()? +- .exit_code(); +- +- match exit_code { +- 0 => {} +- EEXIST => {} +- _ => bail!("Upatch: {}", std::io::Error::from_raw_os_error(exit_code)), +- } ++pub fn active_patch(uuid: &Uuid, pid: i32, target_elf: &Path, patch_file: &Path) -> Result<()> { ++ let exit_code = Command::new(UPATCH_MANAGE_BIN) ++ .arg("patch") ++ .arg("--uuid") ++ .arg(uuid.to_string()) ++ .arg("--pid") ++ .arg(pid.to_string()) ++ .arg("--binary") ++ .arg(target_elf) ++ .arg("--upatch") ++ .arg(patch_file) ++ .stdout(Level::Debug) ++ .run_with_output()? ++ .exit_code(); ++ ++ match exit_code { ++ 0 => {} ++ EEXIST => {} ++ _ => bail!("Upatch: {}", std::io::Error::from_raw_os_error(exit_code)), + } + + Ok(()) + } + +-pub fn deactive_patch<'a, I>( +- uuid: &Uuid, +- target_elf: &Path, +- patch_file: &Path, +- pid_list: I, +-) -> Result<()> +-where +- I: IntoIterator, +-{ +- debug!( +- "Unpatching '{}' from {}", +- patch_file.display(), +- target_elf.display() +- ); +- +- for pid in pid_list { +- let exit_code = Command::new(UPATCH_MANAGE_BIN) +- .arg("unpatch") +- .arg("--uuid") +- .arg(uuid.to_string()) +- .arg("--pid") +- .arg(pid.to_string()) +- .arg("--binary") +- .arg(target_elf) +- .arg("--upatch") +- .arg(patch_file) +- .stdout(Level::Debug) +- .run_with_output()? +- .exit_code(); +- +- match exit_code { +- 0 => {} +- _ => bail!("Upatch: {}", std::io::Error::from_raw_os_error(exit_code)), +- } ++pub fn deactive_patch(uuid: &Uuid, pid: i32, target_elf: &Path, patch_file: &Path) -> Result<()> { ++ let exit_code = Command::new(UPATCH_MANAGE_BIN) ++ .arg("unpatch") ++ .arg("--uuid") ++ .arg(uuid.to_string()) ++ .arg("--pid") ++ .arg(pid.to_string()) ++ .arg("--binary") ++ .arg(target_elf) ++ .arg("--upatch") ++ .arg(patch_file) ++ .stdout(Level::Debug) ++ .run_with_output()? ++ .exit_code(); ++ ++ match exit_code { ++ 0 => {} ++ _ => bail!("Upatch: {}", std::io::Error::from_raw_os_error(exit_code)), + } + + Ok(()) +-- +2.34.1 + diff --git a/0005-syscared-optimize-patch-error-logic.patch b/0005-syscared-optimize-patch-error-logic.patch new file mode 100644 index 0000000000000000000000000000000000000000..3f6ab07f744c5b191bb0960085949b3708840f54 --- /dev/null +++ b/0005-syscared-optimize-patch-error-logic.patch @@ -0,0 +1,103 @@ +From a61958c837b70c0c530d32ee58b616ab9ad01f4b Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 12 Apr 2024 11:35:57 +0800 +Subject: [PATCH] syscared: optimize patch error logic + +Signed-off-by: renoseven +--- + syscared/src/patch/driver/upatch/mod.rs | 21 +++++++++++---------- + syscared/src/patch/driver/upatch/sys.rs | 4 ++-- + 2 files changed, 13 insertions(+), 12 deletions(-) + +diff --git a/syscared/src/patch/driver/upatch/mod.rs b/syscared/src/patch/driver/upatch/mod.rs +index a7fa154..0b82db9 100644 +--- a/syscared/src/patch/driver/upatch/mod.rs ++++ b/syscared/src/patch/driver/upatch/mod.rs +@@ -56,8 +56,7 @@ pub struct UserPatchDriver { + impl UserPatchDriver { + pub fn new() -> Result { + let elf_patch_map = Arc::new(Mutex::new(IndexMap::new())); +- let patch_monitor = +- UserPatchMonitor::new(elf_patch_map.clone(), Self::patch_new_process)?; ++ let patch_monitor = UserPatchMonitor::new(elf_patch_map.clone(), Self::patch_new_process)?; + + let instance = Self { + patch_target_map: IndexMap::new(), +@@ -196,8 +195,10 @@ impl UserPatchDriver { + ); + } + for pid in &need_active { +- if let Err(e) = sys::active_patch(uuid, *pid, target_elf, patch_file) { +- error!("{:?}", e); ++ if let Err(e) = sys::active_patch(uuid, *pid, target_elf, patch_file) ++ .with_context(|| format!("Failed to patch process, pid={}", pid)) ++ { ++ error!("{}", e); + continue; + } + patch_record.processes.insert(*pid); +@@ -262,7 +263,7 @@ impl UserPatchDriver { + ); + + debug!( +- "Upatch: Applying patch '{}', patch_file: {}", ++ "Upatch: Applying patch '{}' ({})", + patch_uuid, + patch.patch_file.display() + ); +@@ -281,7 +282,7 @@ impl UserPatchDriver { + ); + + debug!( +- "Upatch: Removing patch '{}', patch_file: {}", ++ "Upatch: Removing patch '{}' ({})", + patch_uuid, + patch.patch_file.display() + ); +@@ -326,9 +327,8 @@ impl UserPatchDriver { + ); + } + for pid in need_active { +- if let Err(e) = sys::active_patch(&uuid, pid, target_elf, patch_file) { +- error!("{:?}", e); +- } ++ sys::active_patch(&uuid, pid, target_elf, patch_file) ++ .with_context(|| format!("Failed to patch process, pid={}", pid))?; + patch_record.processes.insert(pid); + } + +@@ -394,7 +394,8 @@ impl UserPatchDriver { + ); + } + for pid in need_deactive { +- sys::deactive_patch(&uuid, pid, target_elf, patch_file)?; ++ sys::deactive_patch(&uuid, pid, target_elf, patch_file) ++ .with_context(|| format!("Failed to unpatch process, pid={}", pid))?; + patch_record.processes.remove(&pid); // remove process from record + } + +diff --git a/syscared/src/patch/driver/upatch/sys.rs b/syscared/src/patch/driver/upatch/sys.rs +index f0745f0..1908520 100644 +--- a/syscared/src/patch/driver/upatch/sys.rs ++++ b/syscared/src/patch/driver/upatch/sys.rs +@@ -20,7 +20,7 @@ pub fn active_patch(uuid: &Uuid, pid: i32, target_elf: &Path, patch_file: &Path) + .arg(target_elf) + .arg("--upatch") + .arg(patch_file) +- .stdout(Level::Debug) ++ .stdout(Level::Info) + .run_with_output()? + .exit_code(); + +@@ -44,7 +44,7 @@ pub fn deactive_patch(uuid: &Uuid, pid: i32, target_elf: &Path, patch_file: &Pat + .arg(target_elf) + .arg("--upatch") + .arg(patch_file) +- .stdout(Level::Debug) ++ .stdout(Level::Info) + .run_with_output()? + .exit_code(); + +-- +2.34.1 + diff --git a/0006-syscared-optimize-transaction-creation-logic.patch b/0006-syscared-optimize-transaction-creation-logic.patch new file mode 100644 index 0000000000000000000000000000000000000000..b43053aa5195d364e43a82458762f127d382d9a2 --- /dev/null +++ b/0006-syscared-optimize-transaction-creation-logic.patch @@ -0,0 +1,112 @@ +From 211e4549324a9209dc982b7426af8b832410b619 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 12 Apr 2024 11:40:25 +0800 +Subject: [PATCH] syscared: optimize transaction creation logic + +Signed-off-by: renoseven +--- + syscared/src/patch/driver/upatch/sys.rs | 4 ++-- + syscared/src/patch/transaction.rs | 9 +++------ + syscared/src/rpc/skeleton_impl/patch.rs | 10 +++++----- + 3 files changed, 10 insertions(+), 13 deletions(-) + +diff --git a/syscared/src/patch/driver/upatch/sys.rs b/syscared/src/patch/driver/upatch/sys.rs +index 1908520..f0745f0 100644 +--- a/syscared/src/patch/driver/upatch/sys.rs ++++ b/syscared/src/patch/driver/upatch/sys.rs +@@ -20,7 +20,7 @@ pub fn active_patch(uuid: &Uuid, pid: i32, target_elf: &Path, patch_file: &Path) + .arg(target_elf) + .arg("--upatch") + .arg(patch_file) +- .stdout(Level::Info) ++ .stdout(Level::Debug) + .run_with_output()? + .exit_code(); + +@@ -44,7 +44,7 @@ pub fn deactive_patch(uuid: &Uuid, pid: i32, target_elf: &Path, patch_file: &Pat + .arg(target_elf) + .arg("--upatch") + .arg(patch_file) +- .stdout(Level::Info) ++ .stdout(Level::Debug) + .run_with_output()? + .exit_code(); + +diff --git a/syscared/src/patch/transaction.rs b/syscared/src/patch/transaction.rs +index a3c5dda..695532c 100644 +--- a/syscared/src/patch/transaction.rs ++++ b/syscared/src/patch/transaction.rs +@@ -43,18 +43,15 @@ where + action: F, + flag: PatchOpFlag, + identifier: String, +- ) -> Result { +- let instance = Self { ++ ) -> Self { ++ Self { + name, + patch_manager, + action, + identifier, + flag, + finish_list: Vec::new(), +- }; +- +- debug!("{} is created", instance); +- Ok(instance) ++ } + } + } + +diff --git a/syscared/src/rpc/skeleton_impl/patch.rs b/syscared/src/rpc/skeleton_impl/patch.rs +index 98494b1..b009d46 100644 +--- a/syscared/src/rpc/skeleton_impl/patch.rs ++++ b/syscared/src/rpc/skeleton_impl/patch.rs +@@ -101,7 +101,7 @@ impl PatchSkeleton for PatchSkeletonImpl { + true => PatchOpFlag::Force, + }, + identifier, +- )? ++ ) + .invoke() + }) + } +@@ -115,7 +115,7 @@ impl PatchSkeleton for PatchSkeletonImpl { + PatchManager::remove_patch, + PatchOpFlag::Normal, + identifier, +- )? ++ ) + .invoke() + }) + } +@@ -136,7 +136,7 @@ impl PatchSkeleton for PatchSkeletonImpl { + true => PatchOpFlag::Force, + }, + identifier, +- )? ++ ) + .invoke() + }) + } +@@ -150,7 +150,7 @@ impl PatchSkeleton for PatchSkeletonImpl { + PatchManager::deactive_patch, + PatchOpFlag::Normal, + identifier, +- )? ++ ) + .invoke() + }) + } +@@ -164,7 +164,7 @@ impl PatchSkeleton for PatchSkeletonImpl { + PatchManager::accept_patch, + PatchOpFlag::Normal, + identifier, +- )? ++ ) + .invoke() + }) + } +-- +2.34.1 + diff --git a/0007-upatch-manage-optimize-output.patch b/0007-upatch-manage-optimize-output.patch new file mode 100644 index 0000000000000000000000000000000000000000..a97c04720001188e181e8f29134d502539711058 --- /dev/null +++ b/0007-upatch-manage-optimize-output.patch @@ -0,0 +1,136 @@ +From a32e9f39965579064dbd504246f13c6431ffed33 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 12 Apr 2024 11:50:59 +0800 +Subject: [PATCH] upatch-manage: optimize output + +Signed-off-by: renoseven +--- + upatch-manage/upatch-manage.c | 2 +- + upatch-manage/upatch-patch.c | 10 +++++----- + upatch-manage/upatch-process.c | 23 ++++++++++++----------- + 3 files changed, 18 insertions(+), 17 deletions(-) + +diff --git a/upatch-manage/upatch-manage.c b/upatch-manage/upatch-manage.c +index a5973e4..e33eeb3 100644 +--- a/upatch-manage/upatch-manage.c ++++ b/upatch-manage/upatch-manage.c +@@ -152,7 +152,7 @@ int patch_upatch(const char *uuid, const char *binary_path, const char *upatch_p + + ret = process_patch(pid, &uelf, &relf, uuid, binary_path); + if (ret) { +- log_error("Failed to patch process, pid=%d ret=%d\n", pid, ret); ++ log_error("Failed to patch process, pid=%d, ret=%d\n", pid, ret); + goto out; + } + log_normal("SUCCESS\n"); +diff --git a/upatch-manage/upatch-patch.c b/upatch-manage/upatch-patch.c +index bda4e10..5e16002 100644 +--- a/upatch-manage/upatch-patch.c ++++ b/upatch-manage/upatch-patch.c +@@ -712,6 +712,7 @@ int process_patch(int pid, struct upatch_elf *uelf, struct running_elf *relf, co + goto out; + } + ++ printf("Patch "); + upatch_process_print_short(&proc); + + ret = upatch_process_mem_open(&proc, MEM_READ); +@@ -768,8 +769,7 @@ out: + if (is_calc_time) { + gettimeofday(&end_tv, NULL); + frozen_time = GET_MICROSECONDS(end_tv, start_tv); +- log_normal( +- "PID '%d' process patch frozen_time is %ld microsecond\n", ++ log_normal("Process %d frozen time is %ld microsecond(s)\n", + pid, frozen_time); + } + return ret; +@@ -831,10 +831,11 @@ int process_unpatch(int pid, const char *uuid) + // 查看process的信息,pid: maps, mem, cmdline, exe + ret = upatch_process_init(&proc, pid); + if (ret < 0) { +- log_error("cannot init process %d\n", pid); ++ log_error("Failed to init process %d, ret=%d\n", pid, ret); + goto out; + } + ++ printf("Unpatch "); + upatch_process_print_short(&proc); + + ret = upatch_process_mem_open(&proc, MEM_READ); +@@ -880,8 +881,7 @@ out: + if (is_calc_time) { + gettimeofday(&end_tv, NULL); + frozen_time = GET_MICROSECONDS(end_tv, start_tv); +- log_normal( +- "PID '%d' process patch frozen_time is %ld microsecond\n", ++ log_normal("Process %d frozen time is %ld microsecond(s)\n", + pid, frozen_time); + } + return ret; +diff --git a/upatch-manage/upatch-process.c b/upatch-manage/upatch-process.c +index 0d57238..cd3f7e0 100644 +--- a/upatch-manage/upatch-process.c ++++ b/upatch-manage/upatch-process.c +@@ -204,30 +204,31 @@ static void process_print_cmdline(struct upatch_process *proc) + snprintf(buf, PATH_MAX, "/proc/%d/cmdline", proc->pid); + int fd = open(buf, O_RDONLY); + if (fd == -1) { +- log_error("open\n"); ++ log_error("Failed to open %s", buf); + return; + } + + while (1) { + rv = read(fd, buf, sizeof(buf)); + +- if (rv == -1 && errno == EINTR) +- continue; +- + if (rv == -1) { +- log_error("read\n"); ++ if (errno == EINTR) { ++ continue; ++ } ++ log_error("Failed to read cmdline\n"); + goto err_close; + } + +- if (rv == 0) ++ if (rv == 0) { + break; ++ } + + for (i = 0; i < rv; i++) { +- if (buf[i] != '\n' && isprint(buf[i])) { +- putchar(buf[i]); ++ if (isprint(buf[i])) { ++ printf("%c", buf[i]); + } + else { +- printf("\\x%02x", (unsigned char)buf[i]); ++ printf(" "); + } + } + } +@@ -238,7 +239,7 @@ err_close: + + void upatch_process_print_short(struct upatch_process *proc) + { +- printf("upatch target pid %d, cmdline:", proc->pid); ++ printf("process %d, cmdline: ", proc->pid); + process_print_cmdline(proc); + printf("\n"); + } +@@ -254,7 +255,7 @@ int upatch_process_mem_open(struct upatch_process *proc, int mode) + snprintf(path, sizeof(path), "/proc/%d/mem", proc->pid); + proc->memfd = open(path, mode == MEM_WRITE ? O_RDWR : O_RDONLY); + if (proc->memfd < 0) { +- log_error("can't open /proc/%d/mem", proc->pid); ++ log_error("Failed to open %s", path); + return -1; + } + +-- +2.34.1 + diff --git a/0008-common-impl-CStr-from_bytes_with_next_nul.patch b/0008-common-impl-CStr-from_bytes_with_next_nul.patch new file mode 100644 index 0000000000000000000000000000000000000000..932255659e0bb7d370df0987a34c7e7b042d1840 --- /dev/null +++ b/0008-common-impl-CStr-from_bytes_with_next_nul.patch @@ -0,0 +1,47 @@ +From cc090b31139bb9aa0158e50a8a620fc41b23231c Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Tue, 16 Apr 2024 12:44:11 +0800 +Subject: [PATCH] common: impl CStr::from_bytes_with_next_nul() + +Signed-off-by: renoseven +--- + syscare-common/src/ffi/c_str.rs | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/syscare-common/src/ffi/c_str.rs b/syscare-common/src/ffi/c_str.rs +index 060149a..4f3f26d 100644 +--- a/syscare-common/src/ffi/c_str.rs ++++ b/syscare-common/src/ffi/c_str.rs +@@ -13,7 +13,7 @@ + */ + + use std::{ +- ffi::{CStr, OsStr, OsString}, ++ ffi::{CStr, CString, FromBytesWithNulError, OsStr, OsString}, + os::unix::{ffi::OsStringExt, prelude::OsStrExt}, + path::{Path, PathBuf}, + }; +@@ -34,9 +34,19 @@ pub trait CStrExt: AsRef { + fn to_path_buf(&self) -> PathBuf { + PathBuf::from(self.to_os_string()) + } ++ ++ fn from_bytes_with_next_nul(bytes: &[u8]) -> Result<&CStr, FromBytesWithNulError> { ++ let nul_pos = bytes.iter().position(|b| b == &b'\0').unwrap_or(0); ++ let cstr_bytes = &bytes[..=nul_pos]; ++ ++ CStr::from_bytes_with_nul(cstr_bytes) ++ } + } + +-impl> CStrExt for T {} ++impl CStrExt for CStr {} ++impl CStrExt for &CStr {} ++impl CStrExt for CString {} ++impl CStrExt for &CString {} + + #[test] + fn test_cstr() { +-- +2.34.1 + diff --git a/0009-syscared-improve-patch-management.patch b/0009-syscared-improve-patch-management.patch new file mode 100644 index 0000000000000000000000000000000000000000..3b49b3529e856720c2fc1a82432b7eb0884f18bd --- /dev/null +++ b/0009-syscared-improve-patch-management.patch @@ -0,0 +1,2319 @@ +From 354e0888188d4cabd9fff9912fa0935e4e1b4b52 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Tue, 16 Apr 2024 14:20:27 +0800 +Subject: [PATCH] syscared: improve patch management + +Signed-off-by: renoseven +--- + syscared/src/patch/driver/kpatch/mod.rs | 161 ++++-- + syscared/src/patch/driver/kpatch/sys.rs | 16 +- + syscared/src/patch/driver/kpatch/target.rs | 164 +++---- + syscared/src/patch/driver/mod.rs | 18 +- + syscared/src/patch/driver/upatch/entity.rs | 74 +++ + syscared/src/patch/driver/upatch/mod.rs | 511 +++++++++++--------- + syscared/src/patch/driver/upatch/monitor.rs | 72 +-- + syscared/src/patch/driver/upatch/process.rs | 100 ---- + syscared/src/patch/driver/upatch/sys.rs | 14 +- + syscared/src/patch/driver/upatch/target.rs | 138 +++--- + syscared/src/patch/entity/kpatch.rs | 20 +- + syscared/src/patch/entity/symbol.rs | 10 +- + syscared/src/patch/entity/upatch.rs | 12 +- + syscared/src/patch/resolver/kpatch.rs | 141 +++--- + syscared/src/patch/resolver/upatch.rs | 98 ++-- + 15 files changed, 833 insertions(+), 716 deletions(-) + create mode 100644 syscared/src/patch/driver/upatch/entity.rs + delete mode 100644 syscared/src/patch/driver/upatch/process.rs + +diff --git a/syscared/src/patch/driver/kpatch/mod.rs b/syscared/src/patch/driver/kpatch/mod.rs +index e4509d8..45dc719 100644 +--- a/syscared/src/patch/driver/kpatch/mod.rs ++++ b/syscared/src/patch/driver/kpatch/mod.rs +@@ -19,12 +19,12 @@ use std::{ + + use anyhow::{ensure, Result}; + use indexmap::{indexset, IndexMap, IndexSet}; +-use log::debug; ++use log::{debug, info}; + + use syscare_abi::PatchStatus; + use syscare_common::{concat_os, os, util::digest}; + +-use crate::patch::entity::KernelPatch; ++use crate::patch::entity::{KernelPatch, KernelPatchFunction}; + + mod sys; + mod target; +@@ -32,21 +32,84 @@ mod target; + use target::PatchTarget; + + pub struct KernelPatchDriver { +- patch_target_map: IndexMap, ++ target_map: IndexMap, + } + + impl KernelPatchDriver { + pub fn new() -> Result { + Ok(Self { +- patch_target_map: IndexMap::new(), ++ target_map: IndexMap::new(), + }) + } + } + ++impl KernelPatchDriver { ++ fn group_patch_targets(patch: &KernelPatch) -> IndexSet<&OsStr> { ++ let mut patch_targets = IndexSet::new(); ++ ++ for function in &patch.functions { ++ patch_targets.insert(function.object.as_os_str()); ++ } ++ patch_targets ++ } ++ ++ pub fn group_patch_functions( ++ patch: &KernelPatch, ++ ) -> IndexMap<&OsStr, Vec<&KernelPatchFunction>> { ++ let mut patch_function_map: IndexMap<&OsStr, Vec<&KernelPatchFunction>> = IndexMap::new(); ++ ++ for function in &patch.functions { ++ patch_function_map ++ .entry(function.object.as_os_str()) ++ .or_default() ++ .push(function); ++ } ++ patch_function_map ++ } ++} ++ ++impl KernelPatchDriver { ++ fn add_patch_target(&mut self, patch: &KernelPatch) { ++ for target_name in Self::group_patch_targets(patch) { ++ if !self.target_map.contains_key(target_name) { ++ self.target_map.insert( ++ target_name.to_os_string(), ++ PatchTarget::new(target_name.to_os_string()), ++ ); ++ } ++ } ++ } ++ ++ fn remove_patch_target(&mut self, patch: &KernelPatch) { ++ for target_name in Self::group_patch_targets(patch) { ++ if let Some(target) = self.target_map.get_mut(target_name) { ++ if !target.has_function() { ++ self.target_map.remove(target_name); ++ } ++ } ++ } ++ } ++ ++ fn add_patch_functions(&mut self, patch: &KernelPatch) { ++ for (target_name, functions) in Self::group_patch_functions(patch) { ++ if let Some(target) = self.target_map.get_mut(target_name) { ++ target.add_functions(patch.uuid, functions); ++ } ++ } ++ } ++ ++ fn remove_patch_functions(&mut self, patch: &KernelPatch) { ++ for (target_name, functions) in Self::group_patch_functions(patch) { ++ if let Some(target) = self.target_map.get_mut(target_name) { ++ target.remove_functions(&patch.uuid, functions); ++ } ++ } ++ } ++} ++ + impl KernelPatchDriver { + fn check_consistency(patch: &KernelPatch) -> Result<()> { +- let patch_file = patch.patch_file.as_path(); +- let real_checksum = digest::file(patch_file)?; ++ let real_checksum = digest::file(&patch.patch_file)?; + debug!("Target checksum: '{}'", patch.checksum); + debug!("Expected checksum: '{}'", real_checksum); + +@@ -78,7 +141,7 @@ impl KernelPatchDriver { + let mut non_exist_kmod = IndexSet::new(); + + let kmod_list = sys::list_kernel_modules()?; +- for kmod_name in Self::parse_target_modules(patch) { ++ for kmod_name in Self::group_patch_targets(patch) { + if kmod_name == VMLINUX_MODULE_NAME { + continue; + } +@@ -102,15 +165,15 @@ impl KernelPatchDriver { + Ok(()) + } + +- pub fn check_conflict_symbols(&self, patch: &KernelPatch) -> Result<()> { ++ pub fn check_conflict_functions(&self, patch: &KernelPatch) -> Result<()> { + let mut conflict_patches = indexset! {}; + +- let target_symbols = PatchTarget::classify_symbols(&patch.symbols); +- for (target_name, symbols) in target_symbols { +- if let Some(target) = self.patch_target_map.get(target_name) { ++ let target_functions = Self::group_patch_functions(patch); ++ for (target_name, functions) in target_functions { ++ if let Some(target) = self.target_map.get(target_name) { + conflict_patches.extend( + target +- .get_conflicts(symbols) ++ .get_conflicts(functions) + .into_iter() + .map(|record| record.uuid), + ); +@@ -131,15 +194,15 @@ impl KernelPatchDriver { + Ok(()) + } + +- pub fn check_override_symbols(&self, patch: &KernelPatch) -> Result<()> { ++ pub fn check_override_functions(&self, patch: &KernelPatch) -> Result<()> { + let mut override_patches = indexset! {}; + +- let target_symbols = PatchTarget::classify_symbols(&patch.symbols); +- for (target_name, symbols) in target_symbols { +- if let Some(target) = self.patch_target_map.get(target_name) { ++ let target_functions = Self::group_patch_functions(patch); ++ for (target_name, functions) in target_functions { ++ if let Some(target) = self.target_map.get(target_name) { + override_patches.extend( + target +- .get_overrides(&patch.uuid, symbols) ++ .get_overrides(&patch.uuid, functions) + .into_iter() + .map(|record| record.uuid), + ); +@@ -161,35 +224,6 @@ impl KernelPatchDriver { + } + } + +-impl KernelPatchDriver { +- fn parse_target_modules(patch: &KernelPatch) -> impl IntoIterator { +- patch.symbols.iter().map(|symbol| symbol.target.as_os_str()) +- } +- +- fn add_patch_symbols(&mut self, patch: &KernelPatch) { +- let target_symbols = PatchTarget::classify_symbols(&patch.symbols); +- +- for (target_name, symbols) in target_symbols { +- let target = self +- .patch_target_map +- .entry(target_name.to_os_string()) +- .or_insert_with(|| PatchTarget::new(target_name)); +- +- target.add_symbols(patch.uuid, symbols); +- } +- } +- +- fn remove_patch_symbols(&mut self, patch: &KernelPatch) { +- let target_symbols = PatchTarget::classify_symbols(&patch.symbols); +- +- for (target_name, symbols) in target_symbols { +- if let Some(target) = self.patch_target_map.get_mut(target_name) { +- target.remove_symbols(&patch.uuid, symbols); +- } +- } +- } +-} +- + impl KernelPatchDriver { + pub fn status(&self, patch: &KernelPatch) -> Result { + sys::read_patch_status(patch) +@@ -204,24 +238,51 @@ impl KernelPatchDriver { + } + + pub fn apply(&mut self, patch: &KernelPatch) -> Result<()> { ++ info!( ++ "Kpatch: Applying patch '{}' ({})", ++ patch.uuid, ++ patch.patch_file.display() ++ ); ++ + sys::selinux_relable_patch(patch)?; +- sys::apply_patch(patch) ++ sys::apply_patch(patch)?; ++ self.add_patch_target(patch); ++ ++ Ok(()) + } + + pub fn remove(&mut self, patch: &KernelPatch) -> Result<()> { +- sys::remove_patch(patch) ++ info!( ++ "Kpatch: Removing patch '{}' ({})", ++ patch.uuid, ++ patch.patch_file.display() ++ ); ++ sys::remove_patch(patch)?; ++ self.remove_patch_target(patch); ++ ++ Ok(()) + } + + pub fn active(&mut self, patch: &KernelPatch) -> Result<()> { ++ info!( ++ "Kpatch: Activating patch '{}' ({})", ++ patch.uuid, ++ patch.patch_file.display() ++ ); + sys::active_patch(patch)?; +- self.add_patch_symbols(patch); ++ self.add_patch_functions(patch); + + Ok(()) + } + + pub fn deactive(&mut self, patch: &KernelPatch) -> Result<()> { ++ info!( ++ "Kpatch: Deactivating patch '{}' ({})", ++ patch.uuid, ++ patch.patch_file.display() ++ ); + sys::deactive_patch(patch)?; +- self.remove_patch_symbols(patch); ++ self.remove_patch_functions(patch); + + Ok(()) + } +diff --git a/syscared/src/patch/driver/kpatch/sys.rs b/syscared/src/patch/driver/kpatch/sys.rs +index 5035d06..ea6b68f 100644 +--- a/syscared/src/patch/driver/kpatch/sys.rs ++++ b/syscared/src/patch/driver/kpatch/sys.rs +@@ -61,17 +61,11 @@ pub fn read_patch_status(patch: &KernelPatch) -> Result { + debug!("Reading {}", sys_file.display()); + + let status = match fs::read_to_string(sys_file) { +- Ok(str) => { +- let status = str.trim(); +- let patch_status = match status { +- KPATCH_STATUS_DISABLED => PatchStatus::Deactived, +- KPATCH_STATUS_ENABLED => PatchStatus::Actived, +- _ => { +- bail!("Kpatch: Invalid patch status"); +- } +- }; +- Ok(patch_status) +- } ++ Ok(str) => match str.trim() { ++ KPATCH_STATUS_DISABLED => Ok(PatchStatus::Deactived), ++ KPATCH_STATUS_ENABLED => Ok(PatchStatus::Actived), ++ _ => bail!("Kpatch: Invalid patch status"), ++ }, + Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(PatchStatus::NotApplied), + Err(e) => Err(e), + } +diff --git a/syscared/src/patch/driver/kpatch/target.rs b/syscared/src/patch/driver/kpatch/target.rs +index 0b01f2f..beab803 100644 +--- a/syscared/src/patch/driver/kpatch/target.rs ++++ b/syscared/src/patch/driver/kpatch/target.rs +@@ -12,69 +12,106 @@ + * See the Mulan PSL v2 for more details. + */ + +-use std::ffi::{OsStr, OsString}; ++use std::ffi::OsString; + + use indexmap::IndexMap; + use uuid::Uuid; + +-use crate::patch::entity::KernelPatchSymbol; ++use crate::patch::entity::KernelPatchFunction; + +-#[derive(Debug, PartialEq)] +-pub struct PatchTargetRecord { ++#[derive(Debug)] ++pub struct PatchFunction { + pub uuid: Uuid, + pub name: OsString, + pub size: u64, + } + ++impl PatchFunction { ++ fn new(uuid: Uuid, function: &KernelPatchFunction) -> Self { ++ Self { ++ uuid, ++ name: function.name.to_os_string(), ++ size: function.new_size, ++ } ++ } ++ ++ fn is_same_function(&self, uuid: &Uuid, function: &KernelPatchFunction) -> bool { ++ (self.uuid == *uuid) && (self.name == function.name) && (self.size == function.new_size) ++ } ++} ++ ++#[derive(Debug)] + pub struct PatchTarget { + name: OsString, +- symbol_map: IndexMap>, // symbol addr -> symbol collision list ++ function_map: IndexMap>, // function addr -> function collision list + } + + impl PatchTarget { +- fn match_record(record: &PatchTargetRecord, uuid: &Uuid, symbol: &KernelPatchSymbol) -> bool { +- (record.uuid == *uuid) && (record.name == symbol.name) && (record.size == symbol.new_size) ++ pub fn new(name: OsString) -> Self { ++ Self { ++ name, ++ function_map: IndexMap::new(), ++ } + } + } + + impl PatchTarget { +- pub fn new>(name: S) -> Self { +- Self { +- name: name.as_ref().to_os_string(), +- symbol_map: IndexMap::new(), +- } ++ pub fn has_function(&self) -> bool { ++ self.function_map.is_empty() + } + +- pub fn classify_symbols( +- symbols: &[KernelPatchSymbol], +- ) -> IndexMap<&OsStr, Vec<&KernelPatchSymbol>> { +- let mut symbol_map = IndexMap::new(); +- +- for symbol in symbols { +- let target_name = symbol.target.as_os_str(); +- +- symbol_map +- .entry(target_name) +- .or_insert_with(Vec::new) +- .push(symbol); ++ pub fn add_functions<'a, I>(&mut self, uuid: Uuid, functions: I) ++ where ++ I: IntoIterator, ++ { ++ for function in functions { ++ if self.name != function.object { ++ continue; ++ } ++ self.function_map ++ .entry(function.old_addr) ++ .or_default() ++ .push(PatchFunction::new(uuid, function)); + } ++ } + +- symbol_map ++ pub fn remove_functions<'a, I>(&mut self, uuid: &Uuid, functions: I) ++ where ++ I: IntoIterator, ++ { ++ for function in functions { ++ if self.name != function.object { ++ continue; ++ } ++ if let Some(collision_list) = self.function_map.get_mut(&function.old_addr) { ++ if let Some(index) = collision_list ++ .iter() ++ .position(|patch_function| patch_function.is_same_function(uuid, function)) ++ { ++ collision_list.remove(index); ++ if collision_list.is_empty() { ++ self.function_map.remove(&function.old_addr); ++ } ++ } ++ } ++ } + } ++} + ++impl PatchTarget { + pub fn get_conflicts<'a, I>( + &'a self, +- symbols: I, +- ) -> impl IntoIterator ++ functions: I, ++ ) -> impl IntoIterator + where +- I: IntoIterator, ++ I: IntoIterator, + { +- symbols.into_iter().filter_map(move |symbol| { +- if self.name != symbol.target { ++ functions.into_iter().filter_map(move |function| { ++ if self.name != function.object { + return None; + } +- self.symbol_map +- .get(&symbol.old_addr) ++ self.function_map ++ .get(&function.old_addr) + .and_then(|list| list.last()) + }) + } +@@ -82,66 +119,19 @@ impl PatchTarget { + pub fn get_overrides<'a, I>( + &'a self, + uuid: &'a Uuid, +- symbols: I, +- ) -> impl IntoIterator ++ functions: I, ++ ) -> impl IntoIterator + where +- I: IntoIterator, ++ I: IntoIterator, + { +- symbols.into_iter().filter_map(move |symbol| { +- if self.name != symbol.target { ++ functions.into_iter().filter_map(move |function| { ++ if self.name != function.object { + return None; + } +- self.symbol_map +- .get(&symbol.old_addr) ++ self.function_map ++ .get(&function.old_addr) + .and_then(|list| list.last()) +- .filter(|record| !Self::match_record(record, uuid, symbol)) ++ .filter(|patch_function| !patch_function.is_same_function(uuid, function)) + }) + } +- +- pub fn add_symbols<'a, I>(&mut self, uuid: Uuid, symbols: I) +- where +- I: IntoIterator, +- { +- for symbol in symbols { +- if self.name != symbol.target { +- continue; +- } +- +- let symbol_addr = symbol.old_addr; +- let symbol_record = PatchTargetRecord { +- uuid, +- name: symbol.name.to_os_string(), +- size: symbol.new_size, +- }; +- +- self.symbol_map +- .entry(symbol_addr) +- .or_default() +- .push(symbol_record); +- } +- } +- +- pub fn remove_symbols<'a, I>(&mut self, uuid: &Uuid, symbols: I) +- where +- I: IntoIterator, +- { +- for symbol in symbols { +- if self.name != symbol.target { +- continue; +- } +- +- let symbol_addr = symbol.old_addr; +- if let Some(collision_list) = self.symbol_map.get_mut(&symbol_addr) { +- if let Some(index) = collision_list +- .iter() +- .position(|record| Self::match_record(record, uuid, symbol)) +- { +- collision_list.remove(index); +- if collision_list.is_empty() { +- self.symbol_map.remove(&symbol_addr); +- } +- } +- } +- } +- } + } +diff --git a/syscared/src/patch/driver/mod.rs b/syscared/src/patch/driver/mod.rs +index e6dab94..d64c2d4 100644 +--- a/syscared/src/patch/driver/mod.rs ++++ b/syscared/src/patch/driver/mod.rs +@@ -37,17 +37,17 @@ pub struct PatchDriver { + } + + impl PatchDriver { +- fn check_conflict_symbols(&self, patch: &Patch) -> Result<()> { ++ fn check_conflict_functions(&self, patch: &Patch) -> Result<()> { + match patch { +- Patch::KernelPatch(patch) => self.kpatch.check_conflict_symbols(patch), +- Patch::UserPatch(patch) => self.upatch.check_conflict_symbols(patch), ++ Patch::KernelPatch(patch) => self.kpatch.check_conflict_functions(patch), ++ Patch::UserPatch(patch) => self.upatch.check_conflict_functions(patch), + } + } + +- fn check_override_symbols(&self, patch: &Patch) -> Result<()> { ++ fn check_override_functions(&self, patch: &Patch) -> Result<()> { + match patch { +- Patch::KernelPatch(patch) => self.kpatch.check_override_symbols(patch), +- Patch::UserPatch(patch) => self.upatch.check_override_symbols(patch), ++ Patch::KernelPatch(patch) => self.kpatch.check_override_functions(patch), ++ Patch::UserPatch(patch) => self.upatch.check_override_functions(patch), + } + } + } +@@ -96,7 +96,7 @@ impl PatchDriver { + if flag == PatchOpFlag::Force { + return Ok(()); + } +- self.check_conflict_symbols(patch) ++ self.check_conflict_functions(patch) + .with_context(|| format!("Patch '{}' is conflicted", patch)) + } + +@@ -124,7 +124,7 @@ impl PatchDriver { + /// After this action, the patch status would be changed to 'ACTIVED'. + pub fn active_patch(&mut self, patch: &Patch, flag: PatchOpFlag) -> Result<()> { + if flag != PatchOpFlag::Force { +- self.check_conflict_symbols(patch)?; ++ self.check_conflict_functions(patch)?; + } + match patch { + Patch::KernelPatch(patch) => self.kpatch.active(patch), +@@ -137,7 +137,7 @@ impl PatchDriver { + /// After this action, the patch status would be changed to 'DEACTIVED'. + pub fn deactive_patch(&mut self, patch: &Patch, flag: PatchOpFlag) -> Result<()> { + if flag != PatchOpFlag::Force { +- self.check_override_symbols(patch)?; ++ self.check_override_functions(patch)?; + } + match patch { + Patch::KernelPatch(patch) => self.kpatch.deactive(patch), +diff --git a/syscared/src/patch/driver/upatch/entity.rs b/syscared/src/patch/driver/upatch/entity.rs +new file mode 100644 +index 0000000..80932c4 +--- /dev/null ++++ b/syscared/src/patch/driver/upatch/entity.rs +@@ -0,0 +1,74 @@ ++// SPDX-License-Identifier: Mulan PSL v2 ++/* ++ * Copyright (c) 2024 Huawei Technologies Co., Ltd. ++ * syscared is licensed under Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, ++ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, ++ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++ ++use std::path::PathBuf; ++ ++use indexmap::{indexset, IndexSet}; ++ ++#[derive(Debug)] ++pub struct PatchEntity { ++ pub patch_file: PathBuf, ++ process_list: IndexSet, ++ ignored_list: IndexSet, ++} ++ ++impl PatchEntity { ++ pub fn new(patch_file: PathBuf) -> Self { ++ Self { ++ patch_file, ++ process_list: indexset! {}, ++ ignored_list: indexset! {}, ++ } ++ } ++} ++ ++impl PatchEntity { ++ pub fn add_process(&mut self, pid: i32) { ++ self.process_list.insert(pid); ++ } ++ ++ pub fn remove_process(&mut self, pid: i32) { ++ self.process_list.remove(&pid); ++ } ++ ++ pub fn ignore_process(&mut self, pid: i32) { ++ self.ignored_list.insert(pid); ++ } ++ ++ pub fn clean_dead_process(&mut self, process_list: &IndexSet) { ++ self.process_list.retain(|pid| process_list.contains(pid)); ++ self.ignored_list.retain(|pid| process_list.contains(pid)); ++ } ++ ++ pub fn need_ignored(&self, process_list: &IndexSet) -> IndexSet { ++ process_list ++ .intersection(&self.ignored_list) ++ .copied() ++ .collect() ++ } ++ ++ pub fn need_actived(&self, process_list: &IndexSet) -> IndexSet { ++ process_list ++ .difference(&self.process_list) ++ .copied() ++ .collect() ++ } ++ ++ pub fn need_deactived(&self, process_list: &IndexSet) -> IndexSet { ++ process_list ++ .intersection(&self.process_list) ++ .copied() ++ .collect() ++ } ++} +diff --git a/syscared/src/patch/driver/upatch/mod.rs b/syscared/src/patch/driver/upatch/mod.rs +index 0b82db9..dd07e9b 100644 +--- a/syscared/src/patch/driver/upatch/mod.rs ++++ b/syscared/src/patch/driver/upatch/mod.rs +@@ -13,65 +13,97 @@ + */ + + use std::{ +- ffi::OsString, ++ ffi::OsStr, + fmt::Write, ++ os::linux::fs::MetadataExt, + path::{Path, PathBuf}, + sync::Arc, + }; + +-use anyhow::{ensure, Context, Result}; ++use anyhow::{bail, ensure, Context, Result}; + use indexmap::{indexset, IndexMap, IndexSet}; +-use log::{debug, error}; +-use parking_lot::Mutex; ++use log::{debug, info, warn}; ++use parking_lot::RwLock; + use uuid::Uuid; + + use syscare_abi::PatchStatus; +-use syscare_common::util::digest; ++use syscare_common::{fs, util::digest}; + +-use crate::patch::entity::UserPatch; ++use crate::patch::{driver::upatch::entity::PatchEntity, entity::UserPatch}; + ++mod entity; + mod monitor; +-mod process; + mod sys; + mod target; + + use monitor::UserPatchMonitor; + use target::PatchTarget; + +-type ElfPatchMap = Arc>>; +- +-#[derive(Default)] +-struct ElfPatchRecord { +- patch_map: IndexMap, // Patch applied to target elf (uuid and patch file) +- processes: IndexSet, // Target elf process list +-} +- + pub struct UserPatchDriver { +- patch_target_map: IndexMap, +- patch_status_map: IndexMap, +- elf_patch_map: ElfPatchMap, +- patch_monitor: UserPatchMonitor, ++ status_map: IndexMap, ++ target_map: Arc>>, ++ monitor: UserPatchMonitor, + } + + impl UserPatchDriver { + pub fn new() -> Result { +- let elf_patch_map = Arc::new(Mutex::new(IndexMap::new())); +- let patch_monitor = UserPatchMonitor::new(elf_patch_map.clone(), Self::patch_new_process)?; +- ++ let status_map = IndexMap::new(); ++ let target_map = Arc::new(RwLock::new(IndexMap::new())); ++ let monitor = UserPatchMonitor::new(target_map.clone(), Self::patch_new_process)?; + let instance = Self { +- patch_target_map: IndexMap::new(), +- patch_status_map: IndexMap::new(), +- elf_patch_map, +- patch_monitor, ++ status_map, ++ target_map, ++ monitor, + }; ++ + Ok(instance) + } + } + ++impl UserPatchDriver { ++ #[inline] ++ fn get_patch_status(&self, uuid: &Uuid) -> PatchStatus { ++ self.status_map ++ .get(uuid) ++ .copied() ++ .unwrap_or(PatchStatus::NotApplied) ++ } ++ ++ #[inline] ++ fn set_patch_status(&mut self, uuid: &Uuid, value: PatchStatus) { ++ *self.status_map.entry(*uuid).or_default() = value; ++ } ++ ++ fn remove_patch_status(&mut self, uuid: &Uuid) { ++ self.status_map.remove(uuid); ++ } ++} ++ ++impl UserPatchDriver { ++ fn add_patch_target(&mut self, patch: &UserPatch) { ++ let target_elf = patch.target_elf.as_path(); ++ let mut target_map = self.target_map.write(); ++ ++ if !target_map.contains_key(target_elf) { ++ target_map.insert(target_elf.to_path_buf(), PatchTarget::default()); ++ } ++ } ++ ++ fn remove_patch_target(&mut self, patch: &UserPatch) { ++ let target_elf = patch.target_elf.as_path(); ++ let mut target_map = self.target_map.write(); ++ ++ if let Some(target) = target_map.get_mut(target_elf) { ++ if !target.is_patched() { ++ target_map.remove(target_elf); ++ } ++ } ++ } ++} ++ + impl UserPatchDriver { + fn check_consistency(patch: &UserPatch) -> Result<()> { +- let patch_file = patch.patch_file.as_path(); +- let real_checksum = digest::file(patch_file)?; ++ let real_checksum = digest::file(&patch.patch_file)?; + debug!("Target checksum: '{}'", patch.checksum); + debug!("Expected checksum: '{}'", real_checksum); + +@@ -86,12 +118,10 @@ impl UserPatchDriver { + Ok(()) + } + +- pub fn check_conflict_symbols(&self, patch: &UserPatch) -> Result<()> { +- let patch_symbols = patch.symbols.as_slice(); +- let target_name = patch.target_elf.as_os_str(); +- let conflict_patches = match self.patch_target_map.get(target_name) { ++ pub fn check_conflict_functions(&self, patch: &UserPatch) -> Result<()> { ++ let conflict_patches = match self.target_map.read().get(&patch.target_elf) { + Some(target) => target +- .get_conflicts(patch_symbols) ++ .get_conflicts(&patch.functions) + .into_iter() + .map(|record| record.uuid) + .collect(), +@@ -112,13 +142,10 @@ impl UserPatchDriver { + Ok(()) + } + +- pub fn check_override_symbols(&self, patch: &UserPatch) -> Result<()> { +- let patch_uuid = patch.uuid; +- let patch_symbols = patch.symbols.as_slice(); +- let target_name = patch.target_elf.as_os_str(); +- let override_patches = match self.patch_target_map.get(target_name) { ++ pub fn check_override_functions(&self, patch: &UserPatch) -> Result<()> { ++ let override_patches = match self.target_map.read().get(&patch.target_elf) { + Some(target) => target +- .get_overrides(&patch_uuid, patch_symbols) ++ .get_overrides(&patch.uuid, &patch.functions) + .into_iter() + .map(|record| record.uuid) + .collect(), +@@ -142,110 +169,109 @@ impl UserPatchDriver { + } + + impl UserPatchDriver { +- fn add_patch_symbols(&mut self, patch: &UserPatch) { +- let target_name = patch.target_elf.as_os_str(); +- +- let patch_uuid = patch.uuid; +- let patch_target = self +- .patch_target_map +- .entry(target_name.to_os_string()) +- .or_insert_with(PatchTarget::new); +- let patch_symbols = patch.symbols.as_slice(); +- +- patch_target.add_symbols(patch_uuid, patch_symbols); ++ #[inline] ++ fn parse_process_id(proc_path: &Path) -> Option { ++ proc_path ++ .file_name() ++ .and_then(OsStr::to_str) ++ .map(str::parse) ++ .and_then(Result::ok) + } + +- fn remove_patch_symbols(&mut self, patch: &UserPatch) { +- let patch_uuid = patch.uuid; +- let patch_symbols = patch.symbols.as_slice(); +- let target_name = patch.target_elf.as_os_str(); +- +- if let Some(patch_target) = self.patch_target_map.get_mut(target_name) { +- patch_target.remove_symbols(&patch_uuid, patch_symbols); ++ fn find_target_process>(target_elf: P) -> Result> { ++ let mut target_pids = IndexSet::new(); ++ let target_path = target_elf.as_ref(); ++ let target_inode = target_path.metadata()?.st_ino(); ++ ++ for proc_path in fs::list_dirs("/proc", fs::TraverseOptions { recursive: false })? { ++ let pid = match Self::parse_process_id(&proc_path) { ++ Some(pid) => pid, ++ None => continue, ++ }; ++ let exec_path = match fs::read_link(format!("/proc/{}/exe", pid)) { ++ Ok(file_path) => file_path, ++ Err(_) => continue, ++ }; ++ // Try to match binary path ++ if exec_path == target_path { ++ target_pids.insert(pid); ++ continue; ++ } ++ // Try to match mapped files ++ let map_files = fs::list_symlinks( ++ format!("/proc/{}/map_files", pid), ++ fs::TraverseOptions { recursive: false }, ++ )?; ++ for mapped_file in map_files { ++ if let Ok(mapped_inode) = mapped_file ++ .read_link() ++ .and_then(|file_path| Ok(file_path.metadata()?.st_ino())) ++ { ++ if mapped_inode == target_inode { ++ target_pids.insert(pid); ++ break; ++ } ++ }; ++ } + } ++ ++ Ok(target_pids) + } +-} + +-impl UserPatchDriver { +- fn patch_new_process(elf_patch_map: ElfPatchMap, target_elf: &Path) { +- let process_list = match process::find_target_process(target_elf) { +- Ok(processes) => processes, ++ fn patch_new_process( ++ target_map: Arc>>, ++ target_elf: &Path, ++ ) { ++ let process_list = match Self::find_target_process(target_elf) { ++ Ok(pids) => pids, + Err(_) => return, + }; + +- let mut patch_map = elf_patch_map.lock(); +- let patch_record = match patch_map.get_mut(target_elf) { +- Some(record) => record, ++ let mut target_map = target_map.write(); ++ let patch_target = match target_map.get_mut(target_elf) { ++ Some(target) => target, + None => return, + }; + +- let need_active = process_list +- .difference(&patch_record.processes) +- .copied() +- .collect::>(); ++ for (patch_uuid, patch_entity) in patch_target.all_patches() { ++ patch_entity.clean_dead_process(&process_list); + +- // Active patch +- for (uuid, patch_file) in &patch_record.patch_map { +- if !need_active.is_empty() { ++ // Active patch ++ let need_actived = patch_entity.need_actived(&process_list); ++ if !need_actived.is_empty() { + debug!( +- "Upatch: Activating patch '{}' ({}) to process {:?}", +- uuid, ++ "Upatch: Activating patch '{}' ({}) for process {:?}", ++ patch_uuid, + target_elf.display(), +- need_active, ++ need_actived, + ); + } +- for pid in &need_active { +- if let Err(e) = sys::active_patch(uuid, *pid, target_elf, patch_file) +- .with_context(|| format!("Failed to patch process, pid={}", pid)) +- { +- error!("{}", e); ++ ++ let ignore_list = patch_entity.need_ignored(&process_list); ++ for pid in need_actived { ++ if ignore_list.contains(&pid) { + continue; + } +- patch_record.processes.insert(*pid); ++ match sys::active_patch(patch_uuid, pid, target_elf, &patch_entity.patch_file) { ++ Ok(_) => patch_entity.add_process(pid), ++ Err(e) => { ++ warn!( ++ "Upatch: Failed to active patch '{}' for process {}, {}", ++ patch_uuid, ++ pid, ++ e.to_string().to_lowercase(), ++ ); ++ patch_entity.ignore_process(pid) ++ } ++ } + } + } +- +- // Remove process no longer exists +- let need_remove = patch_record +- .processes +- .difference(&process_list) +- .copied() +- .collect::>(); +- for pid in need_remove { +- patch_record.processes.remove(&pid); +- } +- } +-} +- +-impl UserPatchDriver { +- #[inline] +- fn get_patch_status(&self, uuid: Uuid) -> Result { +- let patch_status = self +- .patch_status_map +- .get(&uuid) +- .copied() +- .context("Upatch: Patch does not exist")?; +- +- Ok(patch_status) +- } +- +- #[inline] +- fn set_patch_status(&mut self, uuid: Uuid, value: PatchStatus) -> Result<()> { +- let patch_status = self +- .patch_status_map +- .get_mut(&uuid) +- .context("Upatch: Patch does not exist")?; +- +- *patch_status = value; +- Ok(()) + } + } + + impl UserPatchDriver { + pub fn status(&self, patch: &UserPatch) -> Result { +- Ok(self +- .get_patch_status(patch.uuid) +- .unwrap_or(PatchStatus::NotApplied)) ++ Ok(self.get_patch_status(&patch.uuid)) + } + + pub fn check(&self, patch: &UserPatch) -> Result<()> { +@@ -256,170 +282,189 @@ impl UserPatchDriver { + } + + pub fn apply(&mut self, patch: &UserPatch) -> Result<()> { +- let patch_uuid = patch.uuid; +- ensure!( +- self.get_patch_status(patch_uuid).is_err(), +- "Upatch: Patch already exists" +- ); +- +- debug!( ++ info!( + "Upatch: Applying patch '{}' ({})", +- patch_uuid, ++ patch.uuid, + patch.patch_file.display() + ); +- self.patch_status_map +- .insert(patch_uuid, PatchStatus::Deactived); ++ ++ self.add_patch_target(patch); ++ self.set_patch_status(&patch.uuid, PatchStatus::Deactived); + + Ok(()) + } + + pub fn remove(&mut self, patch: &UserPatch) -> Result<()> { +- let patch_uuid = patch.uuid; +- let patch_status = self.get_patch_status(patch_uuid)?; +- ensure!( +- patch_status == PatchStatus::Deactived, +- "Upatch: Invalid patch status" +- ); +- +- debug!( ++ info!( + "Upatch: Removing patch '{}' ({})", +- patch_uuid, ++ patch.uuid, + patch.patch_file.display() + ); +- self.patch_status_map.remove(&patch_uuid); ++ ++ self.remove_patch_target(patch); ++ self.remove_patch_status(&patch.uuid); + + Ok(()) + } + + pub fn active(&mut self, patch: &UserPatch) -> Result<()> { +- let uuid = patch.uuid; +- let patch_status = self.get_patch_status(uuid)?; +- ensure!( +- patch_status == PatchStatus::Deactived, +- "Upatch: Invalid patch status" +- ); +- +- let target_elf = patch.target_elf.as_path(); ++ let patch_uuid = &patch.uuid; + let patch_file = patch.patch_file.as_path(); +- let process_list = process::find_target_process(target_elf)?; ++ let patch_functions = patch.functions.as_slice(); ++ let target_elf = patch.target_elf.as_path(); + +- let mut patch_map = self.elf_patch_map.lock(); +- let patch_record = patch_map.entry(target_elf.to_path_buf()).or_default(); ++ let process_list = Self::find_target_process(target_elf)?; + +- let need_active = process_list +- .difference(&patch_record.processes) +- .copied() +- .collect::>(); +- let need_remove = patch_record +- .processes +- .difference(&process_list) +- .copied() +- .collect::>(); +- let mut need_start_watch = false; ++ let mut target_map = self.target_map.write(); ++ let patch_target = target_map ++ .get_mut(target_elf) ++ .context("Upatch: Cannot find patch target")?; ++ let mut patch_entity = match patch_target.get_patch(patch_uuid) { ++ Some(_) => bail!("Upatch: Patch is already exist"), ++ None => PatchEntity::new(patch_file.to_path_buf()), ++ }; + + // Active patch +- if !need_active.is_empty() { +- debug!( +- "Upatch: Activating patch '{}' ({}) to process {:?}", +- uuid, +- target_elf.display(), +- need_active, +- ); +- } +- for pid in need_active { +- sys::active_patch(&uuid, pid, target_elf, patch_file) +- .with_context(|| format!("Failed to patch process, pid={}", pid))?; +- patch_record.processes.insert(pid); ++ info!( ++ "Upatch: Activating patch '{}' ({}) for {}", ++ patch_uuid, ++ patch_file.display(), ++ target_elf.display(), ++ ); ++ let mut results = Vec::new(); ++ for pid in patch_entity.need_actived(&process_list) { ++ let result = sys::active_patch(patch_uuid, pid, target_elf, patch_file); ++ match result { ++ Ok(_) => patch_entity.add_process(pid), ++ Err(_) => patch_entity.ignore_process(pid), ++ } ++ results.push((pid, result)); + } + +- // Remove process no longer exists +- for pid in need_remove { +- patch_record.processes.remove(&pid); ++ // Check results, return error if all process fails ++ match results.iter().any(|(_, result)| result.is_ok()) { ++ true => { ++ for (pid, result) in &results { ++ if let Err(e) = result { ++ warn!( ++ "Upatch: Failed to active patch '{}' for process {}, {}", ++ patch_uuid, ++ pid, ++ e.to_string().to_lowercase(), ++ ); ++ } ++ } ++ } ++ false => { ++ let mut err_msg = String::new(); ++ ++ writeln!(err_msg, "Upatch: Failed to active patch")?; ++ for (pid, result) in &results { ++ if let Err(e) = result { ++ writeln!(err_msg, "* Process {}: {}", pid, e)?; ++ } ++ } ++ bail!(err_msg); ++ } + } + +- // If elf is not patched before, start watching it & add a new entry +- if !patch_record.patch_map.contains_key(&uuid) { +- patch_record +- .patch_map +- .insert(uuid, patch_file.to_path_buf()); +- need_start_watch = true; +- } ++ // If target is no patched before, start watching it ++ let need_start_watch = !patch_target.is_patched(); + +- drop(patch_map); ++ // Apply patch to target ++ patch_target.add_patch(*patch_uuid, patch_entity); ++ patch_target.add_functions(*patch_uuid, patch_functions); ++ ++ // Drop the lock ++ drop(target_map); + + if need_start_watch { +- self.patch_monitor.watch_file(target_elf)?; ++ self.monitor.watch_file(target_elf)?; + } +- self.set_patch_status(uuid, PatchStatus::Actived)?; +- self.add_patch_symbols(patch); ++ self.set_patch_status(patch_uuid, PatchStatus::Actived); + + Ok(()) + } + + pub fn deactive(&mut self, patch: &UserPatch) -> Result<()> { +- let uuid = patch.uuid; +- let patch_status = self.get_patch_status(uuid)?; +- ensure!( +- patch_status == PatchStatus::Actived, +- "Upatch: Invalid patch status" +- ); +- +- let target_elf = patch.target_elf.as_path(); ++ let patch_uuid = &patch.uuid; + let patch_file = patch.patch_file.as_path(); +- let process_list = process::find_target_process(target_elf)?; ++ let patch_functions = patch.functions.as_slice(); ++ let target_elf = patch.target_elf.as_path(); ++ ++ let process_list = Self::find_target_process(target_elf)?; + +- let mut patch_map = self.elf_patch_map.lock(); +- let patch_record = patch_map ++ let mut target_map = self.target_map.write(); ++ let patch_target = target_map + .get_mut(target_elf) +- .context("Failed to find elf patch record")?; ++ .context("Upatch: Cannot find patch target")?; ++ let patch_entity = patch_target ++ .get_patch(patch_uuid) ++ .context("Upatch: Cannot find patch entity")?; + +- let need_deactive = process_list +- .intersection(&patch_record.processes) +- .copied() +- .collect::>(); +- let need_removed = patch_record +- .processes +- .difference(&process_list) +- .copied() +- .collect::>(); +- let mut need_stop_watch = false; ++ // Remove dead process ++ patch_entity.clean_dead_process(&process_list); + + // Deactive patch +- if !need_deactive.is_empty() { +- debug!( +- "Upatch: Deactivating patch '{}' ({}) of process {:?}", +- uuid, +- target_elf.display(), +- need_deactive, +- ); +- } +- for pid in need_deactive { +- sys::deactive_patch(&uuid, pid, target_elf, patch_file) +- .with_context(|| format!("Failed to unpatch process, pid={}", pid))?; +- patch_record.processes.remove(&pid); // remove process from record ++ info!( ++ "Upatch: Deactivating patch '{}' ({}) for {}", ++ patch_uuid, ++ patch_file.display(), ++ target_elf.display(), ++ ); ++ let mut results = Vec::new(); ++ let ignore_list = patch_entity.need_ignored(&process_list); ++ for pid in patch_entity.need_deactived(&process_list) { ++ if ignore_list.contains(&pid) { ++ continue; ++ } ++ let result = sys::deactive_patch(patch_uuid, pid, target_elf, patch_file); ++ if result.is_ok() { ++ patch_entity.remove_process(pid) ++ } ++ results.push((pid, result)); + } + +- // Remove process no longer exists +- for pid in need_removed { +- patch_record.processes.remove(&pid); ++ // Check results, return error if any process failes ++ match results.iter().any(|(_, result)| result.is_err()) { ++ true => { ++ let mut err_msg = String::new(); ++ ++ writeln!(err_msg, "Upatch: Failed to deactive patch")?; ++ for (pid, result) in &results { ++ if let Err(e) = result { ++ writeln!(err_msg, "* Process {}: {}", pid, e)?; ++ } ++ } ++ bail!(err_msg) ++ } ++ false => { ++ for (pid, result) in &results { ++ if let Err(e) = result { ++ warn!( ++ "Upatch: Failed to deactive patch '{}' for process {}, {}", ++ patch_uuid, ++ pid, ++ e.to_string().to_lowercase(), ++ ); ++ } ++ } ++ } + } + +- // Remove patch from elf patch record +- patch_record.patch_map.remove(&uuid); ++ // Remove patch functions from target ++ patch_target.remove_patch(patch_uuid); ++ patch_target.remove_functions(patch_uuid, patch_functions); + +- // If elf has no more patch, stop watching it & remove the entry +- if patch_record.patch_map.is_empty() { +- patch_map.remove(target_elf); +- need_stop_watch = true; +- } ++ // If target is no longer patched, stop watching it ++ let need_stop_watch = !patch_target.is_patched(); + +- drop(patch_map); ++ drop(target_map); + + if need_stop_watch { +- self.patch_monitor.ignore_file(target_elf)?; ++ self.monitor.ignore_file(target_elf)?; + } +- self.set_patch_status(uuid, PatchStatus::Deactived)?; +- self.remove_patch_symbols(patch); ++ self.set_patch_status(patch_uuid, PatchStatus::Deactived); + + Ok(()) + } +diff --git a/syscared/src/patch/driver/upatch/monitor.rs b/syscared/src/patch/driver/upatch/monitor.rs +index 1dbb513..09df2a2 100644 +--- a/syscared/src/patch/driver/upatch/monitor.rs ++++ b/syscared/src/patch/driver/upatch/monitor.rs +@@ -21,12 +21,13 @@ use std::{ + }; + + use anyhow::{bail, Context, Result}; +-use indexmap::IndexMap; +-use inotify::{EventMask, Inotify, WatchDescriptor, WatchMask}; ++use indexmap::{IndexMap, IndexSet}; ++use inotify::{Inotify, WatchDescriptor, WatchMask}; + use log::info; + use parking_lot::{Mutex, RwLock}; ++use syscare_common::ffi::OsStrExt; + +-use super::ElfPatchMap; ++use super::target::PatchTarget; + + const MONITOR_THREAD_NAME: &str = "upatch_monitor"; + const MONITOR_CHECK_PERIOD: u64 = 100; +@@ -34,33 +35,36 @@ const MONITOR_EVENT_BUFFER_CAPACITY: usize = 16 * 64; // inotify event size: 16 + + pub(super) struct UserPatchMonitor { + inotify: Arc>>, +- watch_map: Arc>>, +- target_map: Arc>>, ++ watch_wd_map: Arc>>, ++ watch_file_map: Arc>>, + monitor_thread: Option>, + } + + impl UserPatchMonitor { +- pub fn new(elf_patch_map: ElfPatchMap, callback: F) -> Result ++ pub fn new( ++ patch_target_map: Arc>>, ++ callback: F, ++ ) -> Result + where +- F: Fn(ElfPatchMap, &Path) + Send + Sync + 'static, ++ F: Fn(Arc>>, &Path) + Send + Sync + 'static, + { + let inotify = Arc::new(Mutex::new(Some( + Inotify::init().context("Failed to initialize inotify")?, + ))); +- let watch_map = Arc::new(Mutex::new(IndexMap::new())); +- let target_map = Arc::new(RwLock::new(IndexMap::new())); ++ let watch_wd_map = Arc::new(Mutex::new(IndexMap::new())); ++ let watch_file_map = Arc::new(RwLock::new(IndexMap::new())); + let monitor_thread = MonitorThread { + inotify: inotify.clone(), +- target_map: target_map.clone(), +- elf_patch_map, ++ watch_file_map: watch_file_map.clone(), ++ patch_target_map, + callback, + } + .run()?; + + Ok(Self { + inotify, +- target_map, +- watch_map, ++ watch_wd_map, ++ watch_file_map, + monitor_thread: Some(monitor_thread), + }) + } +@@ -69,7 +73,7 @@ impl UserPatchMonitor { + impl UserPatchMonitor { + pub fn watch_file>(&self, file_path: P) -> Result<()> { + let watch_file = file_path.as_ref(); +- if self.watch_map.lock().contains_key(watch_file) { ++ if self.watch_wd_map.lock().contains_key(watch_file) { + return Ok(()); + } + +@@ -79,10 +83,10 @@ impl UserPatchMonitor { + .add_watch(watch_file, WatchMask::OPEN) + .with_context(|| format!("Failed to watch file {}", watch_file.display()))?; + +- self.target_map ++ self.watch_file_map + .write() + .insert(wd.clone(), watch_file.to_owned()); +- self.watch_map.lock().insert(watch_file.to_owned(), wd); ++ self.watch_wd_map.lock().insert(watch_file.to_owned(), wd); + info!("Start watching file {}", watch_file.display()); + } + None => bail!("Inotify does not exist"), +@@ -94,10 +98,10 @@ impl UserPatchMonitor { + pub fn ignore_file>(&self, file_path: P) -> Result<()> { + let ignore_file = file_path.as_ref(); + +- if let Some(wd) = self.watch_map.lock().remove(ignore_file) { ++ if let Some(wd) = self.watch_wd_map.lock().remove(ignore_file) { + match self.inotify.lock().as_mut() { + Some(inotify) => { +- self.target_map.write().remove(&wd); ++ self.watch_file_map.write().remove(&wd); + + inotify.rm_watch(wd).with_context(|| { + format!("Failed to stop watch file {}", ignore_file.display()) +@@ -114,14 +118,14 @@ impl UserPatchMonitor { + + struct MonitorThread { + inotify: Arc>>, +- target_map: Arc>>, +- elf_patch_map: ElfPatchMap, ++ watch_file_map: Arc>>, ++ patch_target_map: Arc>>, + callback: F, + } + + impl MonitorThread + where +- F: Fn(ElfPatchMap, &Path) + Send + Sync + 'static, ++ F: Fn(Arc>>, &Path) + Send + Sync + 'static, + { + fn run(self) -> Result> { + thread::Builder::new() +@@ -130,18 +134,30 @@ where + .with_context(|| format!("Failed to create thread '{}'", MONITOR_THREAD_NAME)) + } + ++ #[inline] ++ fn filter_blacklist_path(path: &Path) -> bool { ++ const BLACKLIST_KEYWORDS: [&str; 2] = ["syscare", "upatch"]; ++ ++ for keyword in BLACKLIST_KEYWORDS { ++ if path.contains(keyword) { ++ return false; ++ } ++ } ++ true ++ } ++ + fn thread_main(self) { + while let Some(inotify) = self.inotify.lock().as_mut() { + let mut buffer = [0; MONITOR_EVENT_BUFFER_CAPACITY]; + + if let Ok(events) = inotify.read_events(&mut buffer) { +- for event in events { +- if !event.mask.contains(EventMask::OPEN) { +- continue; +- } +- if let Some(patch_file) = self.target_map.read().get(&event.wd) { +- (self.callback)(self.elf_patch_map.clone(), patch_file); +- } ++ let watch_file_map = self.watch_file_map.read(); ++ let target_elfs = events ++ .filter_map(|event| watch_file_map.get(&event.wd)) ++ .filter(|path| Self::filter_blacklist_path(path)) ++ .collect::>(); ++ for target_elf in target_elfs { ++ (self.callback)(self.patch_target_map.clone(), target_elf); + } + } + +diff --git a/syscared/src/patch/driver/upatch/process.rs b/syscared/src/patch/driver/upatch/process.rs +deleted file mode 100644 +index 9b2f6de..0000000 +--- a/syscared/src/patch/driver/upatch/process.rs ++++ /dev/null +@@ -1,100 +0,0 @@ +-// SPDX-License-Identifier: Mulan PSL v2 +-/* +- * Copyright (c) 2024 Huawei Technologies Co., Ltd. +- * syscared is licensed under Mulan PSL v2. +- * You can use this software according to the terms and conditions of the Mulan PSL v2. +- * You may obtain a copy of Mulan PSL v2 at: +- * http://license.coscl.org.cn/MulanPSL2 +- * +- * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +- * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +- * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +- * See the Mulan PSL v2 for more details. +- */ +- +-use std::{ffi::OsStr, os::linux::fs::MetadataExt, path::Path}; +- +-use anyhow::Result; +-use indexmap::IndexSet; +-use syscare_common::fs; +- +-const PROC_BLACK_LIST: [&str; 18] = [ +- "/usr/lib/systemd/systemd-journald", +- "/usr/lib/systemd/systemd-logind", +- "/usr/lib/systemd/systemd-udevd", +- "/usr/lib/systemd/systemd-hostnamed", +- "/usr/bin/udevadm", +- "/usr/sbin/auditd", +- "/usr/bin/syscare", +- "/usr/bin/syscared", +- "/usr/bin/upatchd", +- "/usr/libexec/syscare/as-hijacker", +- "/usr/libexec/syscare/cc-hijacker", +- "/usr/libexec/syscare/c++-hijacker", +- "/usr/libexec/syscare/gcc-hijacker", +- "/usr/libexec/syscare/g++-hijacker", +- "/usr/libexec/syscare/syscare-build", +- "/usr/libexec/syscare/upatch-build", +- "/usr/libexec/syscare/upatch-diff", +- "/usr/libexec/syscare/upatch-manage", +-]; +- +-#[inline] +-fn is_blacklisted(file_path: &Path) -> bool { +- PROC_BLACK_LIST +- .iter() +- .map(Path::new) +- .any(|blacklist_path| blacklist_path == file_path) +-} +- +-#[inline] +-fn parse_process_id(proc_path: &Path) -> Option { +- proc_path +- .file_name() +- .and_then(OsStr::to_str) +- .map(str::parse) +- .and_then(Result::ok) +-} +- +-pub fn find_target_process>(target_elf: P) -> Result> { +- let mut target_pids = IndexSet::new(); +- let target_path = target_elf.as_ref(); +- let target_inode = target_path.metadata()?.st_ino(); +- +- for proc_path in fs::list_dirs("/proc", fs::TraverseOptions { recursive: false })? { +- let pid = match self::parse_process_id(&proc_path) { +- Some(pid) => pid, +- None => continue, +- }; +- let exec_path = match fs::read_link(format!("/proc/{}/exe", pid)) { +- Ok(file_path) => file_path, +- Err(_) => continue, +- }; +- if is_blacklisted(&exec_path) { +- continue; +- } +- // Try to match binary path +- if exec_path == target_path { +- target_pids.insert(pid); +- continue; +- } +- // Try to match mapped files +- let map_files = fs::list_symlinks( +- format!("/proc/{}/map_files", pid), +- fs::TraverseOptions { recursive: false }, +- )?; +- for mapped_file in map_files { +- if let Ok(mapped_inode) = mapped_file +- .read_link() +- .and_then(|file_path| Ok(file_path.metadata()?.st_ino())) +- { +- if mapped_inode == target_inode { +- target_pids.insert(pid); +- break; +- } +- }; +- } +- } +- +- Ok(target_pids) +-} +diff --git a/syscared/src/patch/driver/upatch/sys.rs b/syscared/src/patch/driver/upatch/sys.rs +index f0745f0..bfeb1b8 100644 +--- a/syscared/src/patch/driver/upatch/sys.rs ++++ b/syscared/src/patch/driver/upatch/sys.rs +@@ -25,12 +25,10 @@ pub fn active_patch(uuid: &Uuid, pid: i32, target_elf: &Path, patch_file: &Path) + .exit_code(); + + match exit_code { +- 0 => {} +- EEXIST => {} +- _ => bail!("Upatch: {}", std::io::Error::from_raw_os_error(exit_code)), ++ 0 => Ok(()), ++ EEXIST => Ok(()), ++ _ => bail!(std::io::Error::from_raw_os_error(exit_code)), + } +- +- Ok(()) + } + + pub fn deactive_patch(uuid: &Uuid, pid: i32, target_elf: &Path, patch_file: &Path) -> Result<()> { +@@ -49,9 +47,7 @@ pub fn deactive_patch(uuid: &Uuid, pid: i32, target_elf: &Path, patch_file: &Pat + .exit_code(); + + match exit_code { +- 0 => {} +- _ => bail!("Upatch: {}", std::io::Error::from_raw_os_error(exit_code)), ++ 0 => Ok(()), ++ _ => bail!(std::io::Error::from_raw_os_error(exit_code)), + } +- +- Ok(()) + } +diff --git a/syscared/src/patch/driver/upatch/target.rs b/syscared/src/patch/driver/upatch/target.rs +index df1e075..26c3ed3 100644 +--- a/syscared/src/patch/driver/upatch/target.rs ++++ b/syscared/src/patch/driver/upatch/target.rs +@@ -17,98 +17,120 @@ use std::ffi::OsString; + use indexmap::IndexMap; + use uuid::Uuid; + +-use crate::patch::entity::UserPatchSymbol; ++use crate::patch::entity::UserPatchFunction; + +-#[derive(Debug, PartialEq)] +-pub struct PatchTargetRecord { ++use super::entity::PatchEntity; ++ ++#[derive(Debug)] ++pub struct PatchFunction { + pub uuid: Uuid, + pub name: OsString, + pub size: u64, + } + ++impl PatchFunction { ++ pub fn new(uuid: Uuid, function: &UserPatchFunction) -> Self { ++ Self { ++ uuid, ++ name: function.name.to_os_string(), ++ size: function.new_size, ++ } ++ } ++ ++ pub fn is_same_function(&self, uuid: &Uuid, function: &UserPatchFunction) -> bool { ++ (self.uuid == *uuid) && (self.name == function.name) && (self.size == function.new_size) ++ } ++} ++ ++#[derive(Debug, Default)] + pub struct PatchTarget { +- symbol_map: IndexMap>, // symbol addr -> symbol collision list ++ patch_map: IndexMap, // patched file data ++ function_map: IndexMap>, // function addr -> function collision list + } + + impl PatchTarget { +- fn match_record(record: &PatchTargetRecord, uuid: &Uuid, symbol: &UserPatchSymbol) -> bool { +- (record.uuid == *uuid) && (record.name == symbol.name) && (record.size == symbol.new_size) ++ pub fn is_patched(&self) -> bool { ++ !self.patch_map.is_empty() + } +-} + +-impl PatchTarget { +- pub fn new() -> Self { +- Self { +- symbol_map: IndexMap::new(), +- } ++ pub fn add_patch(&mut self, uuid: Uuid, entity: PatchEntity) { ++ self.patch_map.insert(uuid, entity); + } + +- pub fn get_conflicts<'a, I>( +- &'a self, +- symbols: I, +- ) -> impl IntoIterator +- where +- I: IntoIterator, +- { +- symbols.into_iter().filter_map(move |symbol| { +- self.symbol_map +- .get(&symbol.old_addr) +- .and_then(|list| list.last()) +- }) ++ pub fn remove_patch(&mut self, uuid: &Uuid) { ++ self.patch_map.remove(uuid); + } + +- pub fn get_overrides<'a, I>( +- &'a self, +- uuid: &'a Uuid, +- symbols: I, +- ) -> impl IntoIterator +- where +- I: IntoIterator, +- { +- symbols.into_iter().filter_map(move |symbol| { +- self.symbol_map +- .get(&symbol.old_addr) +- .and_then(|list| list.last()) +- .filter(|record| !Self::match_record(record, uuid, symbol)) +- }) ++ pub fn get_patch(&mut self, uuid: &Uuid) -> Option<&mut PatchEntity> { ++ self.patch_map.get_mut(uuid) ++ } ++ ++ pub fn all_patches(&mut self) -> impl IntoIterator { ++ self.patch_map.iter_mut() + } ++} + +- pub fn add_symbols<'a, I>(&mut self, uuid: Uuid, symbols: I) ++impl PatchTarget { ++ pub fn add_functions<'a, I>(&mut self, uuid: Uuid, functions: I) + where +- I: IntoIterator, ++ I: IntoIterator, + { +- for symbol in symbols { +- let symbol_addr = symbol.old_addr; +- let symbol_record = PatchTargetRecord { +- uuid, +- name: symbol.name.to_os_string(), +- size: symbol.new_size, +- }; +- +- self.symbol_map +- .entry(symbol_addr) ++ for function in functions { ++ self.function_map ++ .entry(function.old_addr) + .or_default() +- .push(symbol_record); ++ .push(PatchFunction::new(uuid, function)); + } + } + +- pub fn remove_symbols<'a, I>(&mut self, uuid: &Uuid, symbols: I) ++ pub fn remove_functions<'a, I>(&mut self, uuid: &Uuid, functions: I) + where +- I: IntoIterator, ++ I: IntoIterator, + { +- for symbol in symbols { +- let symbol_addr = symbol.old_addr; +- if let Some(collision_list) = self.symbol_map.get_mut(&symbol_addr) { ++ for function in functions { ++ if let Some(collision_list) = self.function_map.get_mut(&function.old_addr) { + if let Some(index) = collision_list + .iter() +- .position(|record| Self::match_record(record, uuid, symbol)) ++ .position(|patch_function| patch_function.is_same_function(uuid, function)) + { + collision_list.remove(index); + if collision_list.is_empty() { +- self.symbol_map.remove(&symbol_addr); ++ self.function_map.remove(&function.old_addr); + } + } + } + } + } + } ++ ++impl PatchTarget { ++ pub fn get_conflicts<'a, I>( ++ &'a self, ++ functions: I, ++ ) -> impl IntoIterator ++ where ++ I: IntoIterator, ++ { ++ functions.into_iter().filter_map(move |function| { ++ self.function_map ++ .get(&function.old_addr) ++ .and_then(|list| list.last()) ++ }) ++ } ++ ++ pub fn get_overrides<'a, I>( ++ &'a self, ++ uuid: &'a Uuid, ++ functions: I, ++ ) -> impl IntoIterator ++ where ++ I: IntoIterator, ++ { ++ functions.into_iter().filter_map(move |function| { ++ self.function_map ++ .get(&function.old_addr) ++ .and_then(|list| list.last()) ++ .filter(|patch_function| !patch_function.is_same_function(uuid, function)) ++ }) ++ } ++} +diff --git a/syscared/src/patch/entity/kpatch.rs b/syscared/src/patch/entity/kpatch.rs +index 9399920..ab2c8b2 100644 +--- a/syscared/src/patch/entity/kpatch.rs ++++ b/syscared/src/patch/entity/kpatch.rs +@@ -17,22 +17,22 @@ use std::{ffi::OsString, path::PathBuf, sync::Arc}; + use syscare_abi::{PatchInfo, PatchType}; + use uuid::Uuid; + +-/// Kernel patch symbol definition ++/// Kernel patch function definition + #[derive(Clone)] +-pub struct KernelPatchSymbol { ++pub struct KernelPatchFunction { + pub name: OsString, +- pub target: OsString, ++ pub object: OsString, + pub old_addr: u64, + pub old_size: u64, + pub new_addr: u64, + pub new_size: u64, + } + +-impl std::fmt::Debug for KernelPatchSymbol { ++impl std::fmt::Debug for KernelPatchFunction { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +- f.debug_struct("KernelPatchSymbol") ++ f.debug_struct("KernelPatchFunction") + .field("name", &self.name) +- .field("target", &self.target) ++ .field("object", &self.object) + .field("old_addr", &format!("{:#x}", self.old_addr)) + .field("old_size", &format!("{:#x}", self.old_size)) + .field("new_addr", &format!("{:#x}", self.new_addr)) +@@ -41,13 +41,13 @@ impl std::fmt::Debug for KernelPatchSymbol { + } + } + +-impl std::fmt::Display for KernelPatchSymbol { ++impl std::fmt::Display for KernelPatchFunction { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, +- "name: {}, target: {}, old_addr: {:#x}, old_size: {:#x}, new_addr: {:#x}, new_size: {:#x}", ++ "name: {}, object: {}, old_addr: {:#x}, old_size: {:#x}, new_addr: {:#x}, new_size: {:#x}", + self.name.to_string_lossy(), +- self.target.to_string_lossy(), ++ self.object.to_string_lossy(), + self.old_addr, + self.old_size, + self.new_addr, +@@ -65,7 +65,7 @@ pub struct KernelPatch { + pub info: Arc, + pub pkg_name: String, + pub module_name: OsString, +- pub symbols: Vec, ++ pub functions: Vec, + pub patch_file: PathBuf, + pub sys_file: PathBuf, + pub checksum: String, +diff --git a/syscared/src/patch/entity/symbol.rs b/syscared/src/patch/entity/symbol.rs +index 300775a..c7845aa 100644 +--- a/syscared/src/patch/entity/symbol.rs ++++ b/syscared/src/patch/entity/symbol.rs +@@ -14,9 +14,9 @@ + + use std::ffi::OsString; + +-/// Patch symbol definiation ++/// Patch function definiation + #[derive(Clone)] +-pub struct PatchSymbol { ++pub struct PatchFunction { + pub name: OsString, + pub target: OsString, + pub old_addr: u64, +@@ -25,9 +25,9 @@ pub struct PatchSymbol { + pub new_size: u64, + } + +-impl std::fmt::Debug for PatchSymbol { ++impl std::fmt::Debug for PatchFunction { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +- f.debug_struct("PatchSymbol") ++ f.debug_struct("PatchFunction") + .field("name", &self.name) + .field("target", &self.target) + .field("old_addr", &format!("0x{}", self.old_addr)) +@@ -38,7 +38,7 @@ impl std::fmt::Debug for PatchSymbol { + } + } + +-impl std::fmt::Display for PatchSymbol { ++impl std::fmt::Display for PatchFunction { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, +diff --git a/syscared/src/patch/entity/upatch.rs b/syscared/src/patch/entity/upatch.rs +index 4e62431..ef24866 100644 +--- a/syscared/src/patch/entity/upatch.rs ++++ b/syscared/src/patch/entity/upatch.rs +@@ -17,9 +17,9 @@ use std::{ffi::OsString, path::PathBuf, sync::Arc}; + use syscare_abi::{PatchInfo, PatchType}; + use uuid::Uuid; + +-/// User patch symbol definition ++/// User patch function definition + #[derive(Clone)] +-pub struct UserPatchSymbol { ++pub struct UserPatchFunction { + pub name: OsString, + pub old_addr: u64, + pub old_size: u64, +@@ -27,9 +27,9 @@ pub struct UserPatchSymbol { + pub new_size: u64, + } + +-impl std::fmt::Debug for UserPatchSymbol { ++impl std::fmt::Debug for UserPatchFunction { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +- f.debug_struct("UserPatchSymbol") ++ f.debug_struct("UserPatchFunction") + .field("name", &self.name) + .field("old_addr", &format!("0x{}", self.old_addr)) + .field("old_size", &format!("0x{}", self.old_size)) +@@ -39,7 +39,7 @@ impl std::fmt::Debug for UserPatchSymbol { + } + } + +-impl std::fmt::Display for UserPatchSymbol { ++impl std::fmt::Display for UserPatchFunction { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, +@@ -61,7 +61,7 @@ pub struct UserPatch { + pub kind: PatchType, + pub info: Arc, + pub pkg_name: String, +- pub symbols: Vec, ++ pub functions: Vec, + pub patch_file: PathBuf, + pub target_elf: PathBuf, + pub checksum: String, +diff --git a/syscared/src/patch/resolver/kpatch.rs b/syscared/src/patch/resolver/kpatch.rs +index 7de81b3..8738225 100644 +--- a/syscared/src/patch/resolver/kpatch.rs ++++ b/syscared/src/patch/resolver/kpatch.rs +@@ -13,8 +13,7 @@ + */ + + use std::{ +- ffi::OsString, +- os::unix::ffi::OsStringExt, ++ ffi::{CStr, OsString}, + path::{Path, PathBuf}, + str::FromStr, + sync::Arc, +@@ -25,10 +24,14 @@ use object::{NativeFile, Object, ObjectSection}; + use uuid::Uuid; + + use syscare_abi::{PatchEntity, PatchInfo, PatchType}; +-use syscare_common::{concat_os, ffi::OsStrExt, fs}; ++use syscare_common::{ ++ concat_os, ++ ffi::{CStrExt, OsStrExt}, ++ fs, ++}; + + use super::PatchResolverImpl; +-use crate::patch::entity::{KernelPatch, KernelPatchSymbol, Patch}; ++use crate::patch::entity::{KernelPatch, KernelPatchFunction, Patch}; + + const KPATCH_SUFFIX: &str = ".ko"; + const KPATCH_SYS_DIR: &str = "/sys/kernel/livepatch"; +@@ -37,7 +40,10 @@ const KPATCH_SYS_FILE_NAME: &str = "enabled"; + mod ffi { + use std::os::raw::{c_char, c_long, c_ulong}; + +- use object::Pod; ++ use object::{ ++ read::elf::{ElfSectionRelocationIterator, FileHeader}, ++ Pod, Relocation, ++ }; + + #[repr(C)] + #[derive(Debug, Clone, Copy)] +@@ -54,9 +60,9 @@ mod ffi { + pub ref_offset: c_long, + } + +- pub const KPATCH_FUNC_SIZE: usize = std::mem::size_of::(); +- pub const KPATCH_FUNC_NAME_OFFSET: usize = 40; +- pub const KPATCH_OBJECT_NAME_OFFSET: usize = 48; ++ pub const KPATCH_FUNCTION_SIZE: usize = std::mem::size_of::(); ++ pub const KPATCH_FUNCTION_OFFSET: usize = 40; ++ pub const KPATCH_OBJECT_OFFSET: usize = 48; + + /* + * SAFETY: This struct is +@@ -66,24 +72,34 @@ mod ffi { + */ + unsafe impl Pod for KpatchFunction {} + +- pub enum KpatchRelocation { +- NewAddr = 0, +- Name = 1, +- ObjName = 2, ++ pub struct KpatchRelocation { ++ pub addr: (u64, Relocation), ++ pub name: (u64, Relocation), ++ pub object: (u64, Relocation), + } + +- impl From for KpatchRelocation { +- fn from(value: usize) -> Self { +- match value { +- 0 => KpatchRelocation::NewAddr, +- 1 => KpatchRelocation::Name, +- 2 => KpatchRelocation::ObjName, +- _ => unreachable!(), +- } ++ pub struct KpatchRelocationIterator<'data, 'file, Elf: FileHeader>( ++ ElfSectionRelocationIterator<'data, 'file, Elf, &'data [u8]>, ++ ); ++ ++ impl<'data, 'file, Elf: FileHeader> KpatchRelocationIterator<'data, 'file, Elf> { ++ pub fn new(relocations: ElfSectionRelocationIterator<'data, 'file, Elf>) -> Self { ++ Self(relocations) + } + } + +- pub const KPATCH_FUNC_RELA_TYPE_NUM: usize = 3; ++ impl<'data, 'file, Elf: FileHeader> Iterator for KpatchRelocationIterator<'data, 'file, Elf> { ++ type Item = KpatchRelocation; ++ ++ fn next(&mut self) -> Option { ++ if let (Some(addr), Some(name), Some(object)) = ++ (self.0.next(), self.0.next(), self.0.next()) ++ { ++ return Some(KpatchRelocation { addr, name, object }); ++ } ++ None ++ } ++ } + } + + use ffi::*; +@@ -115,19 +131,19 @@ impl KpatchResolverImpl { + .with_context(|| format!("Failed to read section '{}'", KPATCH_FUNCS_SECTION))?; + + // Resolve patch functions +- let patch_symbols = &mut patch.symbols; +- let patch_functions = object::slice_from_bytes::( ++ let patch_functions = &mut patch.functions; ++ let kpatch_function_slice = object::slice_from_bytes::( + function_data, +- function_data.len() / KPATCH_FUNC_SIZE, ++ function_data.len() / KPATCH_FUNCTION_SIZE, + ) + .map(|(f, _)| f) + .map_err(|_| anyhow!("Invalid data format")) + .context("Failed to resolve patch functions")?; + +- for function in patch_functions { +- patch_symbols.push(KernelPatchSymbol { ++ for function in kpatch_function_slice { ++ patch_functions.push(KernelPatchFunction { + name: OsString::new(), +- target: OsString::new(), ++ object: OsString::new(), + old_addr: function.old_addr, + old_size: function.old_size, + new_addr: function.new_addr, +@@ -136,44 +152,35 @@ impl KpatchResolverImpl { + } + + // Relocate patch functions +- for (index, (offset, relocation)) in function_section.relocations().enumerate() { +- match KpatchRelocation::from(index % KPATCH_FUNC_RELA_TYPE_NUM) { +- KpatchRelocation::Name => { +- let symbol_index = +- (offset as usize - KPATCH_FUNC_NAME_OFFSET) / KPATCH_FUNC_SIZE; +- let patch_symbol = patch_symbols +- .get_mut(symbol_index) +- .context("Failed to find patch symbol")?; +- +- let name_offset = relocation.addend() as usize; +- let mut name_bytes = &string_data[name_offset..]; +- let string_end = name_bytes +- .iter() +- .position(|b| b == &b'\0') +- .context("Failed to find termination char")?; +- name_bytes = &name_bytes[..string_end]; +- +- patch_symbol.name = OsString::from_vec(name_bytes.to_vec()); +- } +- KpatchRelocation::ObjName => { +- let symbol_index = +- (offset as usize - KPATCH_OBJECT_NAME_OFFSET) / KPATCH_FUNC_SIZE; +- let patch_symbol = patch_symbols +- .get_mut(symbol_index) +- .context("Failed to find patch symbol")?; +- +- let name_offset = relocation.addend() as usize; +- let mut name_bytes = &string_data[name_offset..]; +- let string_end = name_bytes +- .iter() +- .position(|b| b == &b'\0') +- .context("Failed to find termination char")?; +- name_bytes = &name_bytes[..string_end]; +- +- patch_symbol.target = OsString::from_vec(name_bytes.to_vec()); +- } +- _ => {} +- }; ++ for relocation in KpatchRelocationIterator::new(function_section.relocations()) { ++ let (name_reloc_offset, name_reloc) = relocation.name; ++ let (object_reloc_offset, obj_reloc) = relocation.object; ++ ++ // Relocate patch function name ++ let name_index = ++ (name_reloc_offset as usize - KPATCH_FUNCTION_OFFSET) / KPATCH_FUNCTION_SIZE; ++ let name_function = patch_functions ++ .get_mut(name_index) ++ .context("Failed to find patch function")?; ++ let name_offset = name_reloc.addend() as usize; ++ let name_string = CStr::from_bytes_with_next_nul(&string_data[name_offset..]) ++ .context("Failed to parse patch object name")? ++ .to_os_string(); ++ ++ name_function.name = name_string; ++ ++ // Relocate patch function object ++ let object_index = ++ (object_reloc_offset as usize - KPATCH_OBJECT_OFFSET) / KPATCH_FUNCTION_SIZE; ++ let object_function = patch_functions ++ .get_mut(object_index) ++ .context("Failed to find patch function")?; ++ let object_offset = obj_reloc.addend() as usize; ++ let object_string = CStr::from_bytes_with_next_nul(&string_data[object_offset..]) ++ .context("Failed to parse patch function name")? ++ .to_os_string(); ++ ++ object_function.object = object_string; + } + + Ok(()) +@@ -208,10 +215,10 @@ impl PatchResolverImpl for KpatchResolverImpl { + module_name, + patch_file, + sys_file, +- symbols: Vec::new(), ++ functions: Vec::new(), + checksum: patch_entity.checksum.clone(), + }; +- Self::resolve_patch_file(&mut patch).context("Failed to resolve patch elf")?; ++ Self::resolve_patch_file(&mut patch).context("Failed to resolve patch")?; + + Ok(Patch::KernelPatch(patch)) + } +diff --git a/syscared/src/patch/resolver/upatch.rs b/syscared/src/patch/resolver/upatch.rs +index 507bf8e..985b8f1 100644 +--- a/syscared/src/patch/resolver/upatch.rs ++++ b/syscared/src/patch/resolver/upatch.rs +@@ -12,22 +12,30 @@ + * See the Mulan PSL v2 for more details. + */ + +-use std::{ffi::OsString, os::unix::ffi::OsStringExt, path::Path, str::FromStr, sync::Arc}; ++use std::{ ++ ffi::{CStr, OsString}, ++ path::Path, ++ str::FromStr, ++ sync::Arc, ++}; + + use anyhow::{anyhow, Context, Result}; + use object::{NativeFile, Object, ObjectSection}; + use uuid::Uuid; + + use syscare_abi::{PatchEntity, PatchInfo, PatchType}; +-use syscare_common::{concat_os, fs}; ++use syscare_common::{concat_os, ffi::CStrExt, fs}; + + use super::PatchResolverImpl; +-use crate::patch::entity::{Patch, UserPatch, UserPatchSymbol}; ++use crate::patch::entity::{Patch, UserPatch, UserPatchFunction}; + + mod ffi { + use std::os::raw::{c_char, c_ulong}; + +- use object::Pod; ++ use object::{ ++ read::elf::{ElfSectionRelocationIterator, FileHeader}, ++ Pod, Relocation, ++ }; + + #[repr(C)] + #[derive(Debug, Clone, Copy)] +@@ -49,25 +57,34 @@ mod ffi { + */ + unsafe impl Pod for UpatchFunction {} + +- pub const UPATCH_FUNC_SIZE: usize = std::mem::size_of::(); +- pub const UPATCH_FUNC_NAME_OFFSET: usize = 40; ++ pub const UPATCH_FUNCTION_SIZE: usize = std::mem::size_of::(); ++ pub const UPATCH_FUNCTION_OFFSET: usize = 40; + +- pub enum UpatchRelocation { +- NewAddr = 0, +- Name = 1, ++ pub struct UpatchRelocation { ++ pub addr: (u64, Relocation), ++ pub name: (u64, Relocation), + } + +- impl From for UpatchRelocation { +- fn from(value: usize) -> Self { +- match value { +- 0 => UpatchRelocation::NewAddr, +- 1 => UpatchRelocation::Name, +- _ => unreachable!(), +- } ++ pub struct UpatchRelocationIterator<'data, 'file, Elf: FileHeader>( ++ ElfSectionRelocationIterator<'data, 'file, Elf, &'data [u8]>, ++ ); ++ ++ impl<'data, 'file, Elf: FileHeader> UpatchRelocationIterator<'data, 'file, Elf> { ++ pub fn new(relocations: ElfSectionRelocationIterator<'data, 'file, Elf>) -> Self { ++ Self(relocations) + } + } + +- pub const UPATCH_FUNC_RELA_TYPE_NUM: usize = 2; ++ impl<'data, 'file, Elf: FileHeader> Iterator for UpatchRelocationIterator<'data, 'file, Elf> { ++ type Item = UpatchRelocation; ++ ++ fn next(&mut self) -> Option { ++ if let (Some(addr), Some(name)) = (self.0.next(), self.0.next()) { ++ return Some(UpatchRelocation { addr, name }); ++ } ++ None ++ } ++ } + } + + use ffi::*; +@@ -99,17 +116,17 @@ impl UpatchResolverImpl { + .with_context(|| format!("Failed to read section '{}'", UPATCH_FUNCS_SECTION))?; + + // Resolve patch functions +- let patch_symbols = &mut patch.symbols; +- let patch_functions = object::slice_from_bytes::( ++ let patch_functions = &mut patch.functions; ++ let upatch_function_slice = object::slice_from_bytes::( + function_data, +- function_data.len() / UPATCH_FUNC_SIZE, ++ function_data.len() / UPATCH_FUNCTION_SIZE, + ) + .map(|(f, _)| f) + .map_err(|_| anyhow!("Invalid data format")) + .context("Failed to resolve patch functions")?; + +- for function in patch_functions { +- patch_symbols.push(UserPatchSymbol { ++ for function in upatch_function_slice { ++ patch_functions.push(UserPatchFunction { + name: OsString::new(), + old_addr: function.old_addr, + old_size: function.old_size, +@@ -119,25 +136,20 @@ impl UpatchResolverImpl { + } + + // Relocate patch functions +- for (index, (offset, relocation)) in function_section.relocations().enumerate() { +- if let UpatchRelocation::Name = +- UpatchRelocation::from(index % UPATCH_FUNC_RELA_TYPE_NUM) +- { +- let symbol_index = (offset as usize - UPATCH_FUNC_NAME_OFFSET) / UPATCH_FUNC_SIZE; +- let patch_symbol = patch_symbols +- .get_mut(symbol_index) +- .context("Failed to find patch symbol")?; +- +- let name_offset = relocation.addend() as usize; +- let mut name_bytes = &string_data[name_offset..]; +- let string_end = name_bytes +- .iter() +- .position(|b| b == &b'\0') +- .context("Failed to find termination char")?; +- name_bytes = &name_bytes[..string_end]; +- +- patch_symbol.name = OsString::from_vec(name_bytes.to_vec()); +- } ++ for relocation in UpatchRelocationIterator::new(function_section.relocations()) { ++ let (name_reloc_offset, name_reloc) = relocation.name; ++ ++ let name_index = ++ (name_reloc_offset as usize - UPATCH_FUNCTION_OFFSET) / UPATCH_FUNCTION_SIZE; ++ let name_function = patch_functions ++ .get_mut(name_index) ++ .context("Failed to find patch function")?; ++ let name_offset = name_reloc.addend() as usize; ++ let name_string = CStr::from_bytes_with_next_nul(&string_data[name_offset..]) ++ .context("Failed to parse patch function name")? ++ .to_os_string(); ++ ++ name_function.name = name_string; + } + + Ok(()) +@@ -165,10 +177,10 @@ impl PatchResolverImpl for UpatchResolverImpl { + pkg_name: patch_info.target.full_name(), + patch_file: patch_root.join(&patch_entity.patch_name), + target_elf: patch_entity.patch_target.clone(), +- symbols: Vec::new(), ++ functions: Vec::new(), + checksum: patch_entity.checksum.clone(), + }; +- Self::resolve_patch_elf(&mut patch).context("Failed to resolve patch elf")?; ++ Self::resolve_patch_elf(&mut patch).context("Failed to resolve patch")?; + + Ok(Patch::UserPatch(patch)) + } +-- +2.34.1 + diff --git a/0010-syscared-stop-activating-ignored-process-on-new-proc.patch b/0010-syscared-stop-activating-ignored-process-on-new-proc.patch new file mode 100644 index 0000000000000000000000000000000000000000..4c41fc0f1b4e0956430b6e914d3a8abd4bb02a56 --- /dev/null +++ b/0010-syscared-stop-activating-ignored-process-on-new-proc.patch @@ -0,0 +1,237 @@ +From a83410a74713c4f191aeb31bc9ea87b9e9f4bcc6 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Wed, 17 Apr 2024 19:14:19 +0800 +Subject: [PATCH] syscared: stop activating ignored process on new process + start + +Signed-off-by: renoseven +--- + syscared/src/patch/driver/kpatch/mod.rs | 8 +- + syscared/src/patch/driver/upatch/mod.rs | 109 ++++++++++++------------ + 2 files changed, 58 insertions(+), 59 deletions(-) + +diff --git a/syscared/src/patch/driver/kpatch/mod.rs b/syscared/src/patch/driver/kpatch/mod.rs +index 45dc719..307efb5 100644 +--- a/syscared/src/patch/driver/kpatch/mod.rs ++++ b/syscared/src/patch/driver/kpatch/mod.rs +@@ -239,7 +239,7 @@ impl KernelPatchDriver { + + pub fn apply(&mut self, patch: &KernelPatch) -> Result<()> { + info!( +- "Kpatch: Applying patch '{}' ({})", ++ "Applying patch '{}' ({})", + patch.uuid, + patch.patch_file.display() + ); +@@ -253,7 +253,7 @@ impl KernelPatchDriver { + + pub fn remove(&mut self, patch: &KernelPatch) -> Result<()> { + info!( +- "Kpatch: Removing patch '{}' ({})", ++ "Removing patch '{}' ({})", + patch.uuid, + patch.patch_file.display() + ); +@@ -265,7 +265,7 @@ impl KernelPatchDriver { + + pub fn active(&mut self, patch: &KernelPatch) -> Result<()> { + info!( +- "Kpatch: Activating patch '{}' ({})", ++ "Activating patch '{}' ({})", + patch.uuid, + patch.patch_file.display() + ); +@@ -277,7 +277,7 @@ impl KernelPatchDriver { + + pub fn deactive(&mut self, patch: &KernelPatch) -> Result<()> { + info!( +- "Kpatch: Deactivating patch '{}' ({})", ++ "Deactivating patch '{}' ({})", + patch.uuid, + patch.patch_file.display() + ); +diff --git a/syscared/src/patch/driver/upatch/mod.rs b/syscared/src/patch/driver/upatch/mod.rs +index dd07e9b..66eecf5 100644 +--- a/syscared/src/patch/driver/upatch/mod.rs ++++ b/syscared/src/patch/driver/upatch/mod.rs +@@ -237,21 +237,20 @@ impl UserPatchDriver { + patch_entity.clean_dead_process(&process_list); + + // Active patch +- let need_actived = patch_entity.need_actived(&process_list); ++ let need_ignored = patch_entity.need_ignored(&process_list); ++ ++ let mut need_actived = patch_entity.need_actived(&process_list); ++ need_actived.retain(|pid| !need_ignored.contains(pid)); + if !need_actived.is_empty() { + debug!( +- "Upatch: Activating patch '{}' ({}) for process {:?}", ++ "Activating patch '{}' ({}) for process {:?}", + patch_uuid, + target_elf.display(), + need_actived, + ); + } + +- let ignore_list = patch_entity.need_ignored(&process_list); + for pid in need_actived { +- if ignore_list.contains(&pid) { +- continue; +- } + match sys::active_patch(patch_uuid, pid, target_elf, &patch_entity.patch_file) { + Ok(_) => patch_entity.add_process(pid), + Err(e) => { +@@ -283,7 +282,7 @@ impl UserPatchDriver { + + pub fn apply(&mut self, patch: &UserPatch) -> Result<()> { + info!( +- "Upatch: Applying patch '{}' ({})", ++ "Applying patch '{}' ({})", + patch.uuid, + patch.patch_file.display() + ); +@@ -296,7 +295,7 @@ impl UserPatchDriver { + + pub fn remove(&mut self, patch: &UserPatch) -> Result<()> { + info!( +- "Upatch: Removing patch '{}' ({})", ++ "Removing patch '{}' ({})", + patch.uuid, + patch.patch_file.display() + ); +@@ -326,7 +325,7 @@ impl UserPatchDriver { + + // Active patch + info!( +- "Upatch: Activating patch '{}' ({}) for {}", ++ "Activating patch '{}' ({}) for {}", + patch_uuid, + patch_file.display(), + target_elf.display(), +@@ -342,29 +341,28 @@ impl UserPatchDriver { + } + + // Check results, return error if all process fails +- match results.iter().any(|(_, result)| result.is_ok()) { +- true => { +- for (pid, result) in &results { +- if let Err(e) = result { +- warn!( +- "Upatch: Failed to active patch '{}' for process {}, {}", +- patch_uuid, +- pid, +- e.to_string().to_lowercase(), +- ); +- } ++ if !results.is_empty() && results.iter().all(|(_, result)| result.is_err()) { ++ let mut err_msg = String::new(); ++ ++ writeln!(err_msg, "Upatch: Failed to active patch")?; ++ for (pid, result) in &results { ++ if let Err(e) = result { ++ writeln!(err_msg, "* Process {}: {}", pid, e)?; + } + } +- false => { +- let mut err_msg = String::new(); ++ err_msg.pop(); ++ bail!(err_msg); ++ } + +- writeln!(err_msg, "Upatch: Failed to active patch")?; +- for (pid, result) in &results { +- if let Err(e) = result { +- writeln!(err_msg, "* Process {}: {}", pid, e)?; +- } +- } +- bail!(err_msg); ++ // Print failure results ++ for (pid, result) in &results { ++ if let Err(e) = result { ++ warn!( ++ "Upatch: Failed to active patch '{}' for process {}, {}", ++ patch_uuid, ++ pid, ++ e.to_string().to_lowercase(), ++ ); + } + } + +@@ -407,17 +405,19 @@ impl UserPatchDriver { + + // Deactive patch + info!( +- "Upatch: Deactivating patch '{}' ({}) for {}", ++ "Deactivating patch '{}' ({}) for {}", + patch_uuid, + patch_file.display(), + target_elf.display(), + ); ++ ++ let need_ignored = patch_entity.need_ignored(&process_list); ++ ++ let mut need_deactived = patch_entity.need_deactived(&process_list); ++ need_deactived.retain(|pid| need_ignored.contains(pid)); ++ + let mut results = Vec::new(); +- let ignore_list = patch_entity.need_ignored(&process_list); + for pid in patch_entity.need_deactived(&process_list) { +- if ignore_list.contains(&pid) { +- continue; +- } + let result = sys::deactive_patch(patch_uuid, pid, target_elf, patch_file); + if result.is_ok() { + patch_entity.remove_process(pid) +@@ -426,29 +426,28 @@ impl UserPatchDriver { + } + + // Check results, return error if any process failes +- match results.iter().any(|(_, result)| result.is_err()) { +- true => { +- let mut err_msg = String::new(); +- +- writeln!(err_msg, "Upatch: Failed to deactive patch")?; +- for (pid, result) in &results { +- if let Err(e) = result { +- writeln!(err_msg, "* Process {}: {}", pid, e)?; +- } ++ if !results.is_empty() && results.iter().any(|(_, result)| result.is_err()) { ++ let mut err_msg = String::new(); ++ ++ writeln!(err_msg, "Upatch: Failed to deactive patch")?; ++ for (pid, result) in &results { ++ if let Err(e) = result { ++ writeln!(err_msg, "* Process {}: {}", pid, e)?; + } +- bail!(err_msg) + } +- false => { +- for (pid, result) in &results { +- if let Err(e) = result { +- warn!( +- "Upatch: Failed to deactive patch '{}' for process {}, {}", +- patch_uuid, +- pid, +- e.to_string().to_lowercase(), +- ); +- } +- } ++ err_msg.pop(); ++ bail!(err_msg); ++ } ++ ++ // Print failure results ++ for (pid, result) in &results { ++ if let Err(e) = result { ++ warn!( ++ "Upatch: Failed to deactive patch '{}' for process {}, {}", ++ patch_uuid, ++ pid, ++ e.to_string().to_lowercase(), ++ ); + } + } + +-- +2.34.1 + diff --git a/0011-syscared-adapt-upatch-manage-exit-code-change.patch b/0011-syscared-adapt-upatch-manage-exit-code-change.patch new file mode 100644 index 0000000000000000000000000000000000000000..d3cb308caf147f5ce20222884d2c44ac72f49743 --- /dev/null +++ b/0011-syscared-adapt-upatch-manage-exit-code-change.patch @@ -0,0 +1,35 @@ +From 4ad0b0369cd039b64635d2c405fa244b6c6afb59 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 19 Apr 2024 12:02:23 +0800 +Subject: [PATCH] syscared: adapt upatch-manage exit code change + +1. upatch driver treats EEXIST as an error + +Signed-off-by: renoseven +--- + syscared/src/patch/driver/upatch/sys.rs | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/syscared/src/patch/driver/upatch/sys.rs b/syscared/src/patch/driver/upatch/sys.rs +index bfeb1b8..a388bc6 100644 +--- a/syscared/src/patch/driver/upatch/sys.rs ++++ b/syscared/src/patch/driver/upatch/sys.rs +@@ -2,7 +2,6 @@ use std::path::Path; + + use anyhow::{bail, Result}; + use log::Level; +-use nix::libc::EEXIST; + use uuid::Uuid; + + use syscare_common::process::Command; +@@ -26,7 +25,6 @@ pub fn active_patch(uuid: &Uuid, pid: i32, target_elf: &Path, patch_file: &Path) + + match exit_code { + 0 => Ok(()), +- EEXIST => Ok(()), + _ => bail!(std::io::Error::from_raw_os_error(exit_code)), + } + } +-- +2.34.1 + diff --git a/0012-upatch-manage-change-exit-code.patch b/0012-upatch-manage-change-exit-code.patch new file mode 100644 index 0000000000000000000000000000000000000000..ef8f232a57f0dea831705dd37a6b1f5b5fad701d --- /dev/null +++ b/0012-upatch-manage-change-exit-code.patch @@ -0,0 +1,446 @@ +From e04ce4a7539a469091fef8c1566a85fe6050f728 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 19 Apr 2024 12:01:38 +0800 +Subject: [PATCH] upatch-manage: change exit code + +1. return more specific exit code +2. change exit code from EEXIST to 0 when patching existing patch (uuid) + +Signed-off-by: renoseven +--- + upatch-manage/log.h | 2 +- + upatch-manage/upatch-elf.c | 10 ++--- + upatch-manage/upatch-manage.c | 7 ++-- + upatch-manage/upatch-patch.c | 70 ++++++++++++++++++++-------------- + upatch-manage/upatch-process.c | 15 ++------ + upatch-manage/upatch-ptrace.c | 1 + + 6 files changed, 56 insertions(+), 49 deletions(-) + +diff --git a/upatch-manage/log.h b/upatch-manage/log.h +index a41bfc8..32e9c56 100644 +--- a/upatch-manage/log.h ++++ b/upatch-manage/log.h +@@ -52,7 +52,7 @@ enum exit_status { + /* it is time cost */ + #define log_debug(format, ...) log(DEBUG, format, ##__VA_ARGS__) + #define log_normal(format, ...) log(NORMAL, format, ##__VA_ARGS__) +-#define log_warn(format, ...) log(WARN, "%s: " format, logprefix, ##__VA_ARGS__) ++#define log_warn(format, ...) log(WARN, format, ##__VA_ARGS__) + #define log_error(format, ...) log(ERR, format, ##__VA_ARGS__) + + #define log(level, format, ...) \ +diff --git a/upatch-manage/upatch-elf.c b/upatch-manage/upatch-elf.c +index 165f0cf..02444eb 100644 +--- a/upatch-manage/upatch-elf.c ++++ b/upatch-manage/upatch-elf.c +@@ -54,20 +54,20 @@ static int open_elf(struct elf_info *einfo, const char *name) + fd = open(name, O_RDONLY); + if (fd == -1) { + ret = -errno; +- log_error("Failed to open file '%s', ret=%d\n", name, ret); ++ log_error("Failed to open file '%s'\n", name); + goto out; + } + + ret = stat(name, &st); + if (ret != 0) { + ret = -errno; +- log_error("Failed to stat file '%s', ret=%d\n", name, ret); ++ log_error("Failed to stat file '%s'\n", name); + goto out; + } + + ret = read_from_offset(fd, (void **)&einfo->patch_buff, st.st_size, 0); + if (ret != 0) { +- log_error("Failed to read file '%s', ret=%d\n", name, ret); ++ log_error("Failed to read file '%s'\n", name); + goto out; + } + +@@ -112,7 +112,7 @@ int upatch_init(struct upatch_elf *uelf, const char *name) + { + int ret = open_elf(&uelf->info, name); + if (ret) { +- log_error("Failed to open elf '%s', ret=%d\n", name, ret); ++ log_error("Failed to open file '%s'\n", name); + return ret; + } + +@@ -136,7 +136,7 @@ int binary_init(struct running_elf *relf, const char *name) + { + int ret = open_elf(&relf->info, name); + if (ret) { +- log_error("Failed to open elf '%s', ret=%d\n", name, ret); ++ log_error("Failed to open file '%s'\n", name); + return ret; + } + +diff --git a/upatch-manage/upatch-manage.c b/upatch-manage/upatch-manage.c +index e33eeb3..8a7ba60 100644 +--- a/upatch-manage/upatch-manage.c ++++ b/upatch-manage/upatch-manage.c +@@ -146,7 +146,7 @@ int patch_upatch(const char *uuid, const char *binary_path, const char *upatch_p + + int ret = upatch_init(&uelf, upatch_path); + if (ret) { +- log_error("Failed to initialize patch, ret=%d\n", ret); ++ log_error("Failed to initialize patch, pid=%d, ret=%d\n", pid, ret); + goto out; + } + +@@ -155,7 +155,6 @@ int patch_upatch(const char *uuid, const char *binary_path, const char *upatch_p + log_error("Failed to patch process, pid=%d, ret=%d\n", pid, ret); + goto out; + } +- log_normal("SUCCESS\n"); + + out: + upatch_close(&uelf); +@@ -173,7 +172,6 @@ int unpatch_upatch(const char *uuid, const char *binary_path, const char *upatch + log_error("Failed to unpatch process, pid=%d, ret=%d\n", pid, ret); + return ret; + } +- log_normal("SUCCESS\n"); + + return 0; + } +@@ -185,7 +183,6 @@ int info_upatch(const char *binary_path, const char *upatch_path, int pid) + log_error("Failed to get patch info, pid=%d, ret=%d\n", pid, ret); + return ret; + } +- log_normal("SUCCESS\n"); + + return 0; + } +@@ -207,6 +204,7 @@ int main(int argc, char *argv[]) + log_debug("Patch: %s\n", args.upatch); + log_debug("Binary: %s\n", args.binary); + ++ args.pid = args.pid & INT32_MAX; + switch (args.cmd) { + case PATCH: + ret = patch_upatch(args.uuid, args.binary, args.upatch, args.pid); +@@ -223,5 +221,6 @@ int main(int argc, char *argv[]) + break; + } + ++ (ret == 0) ? log_normal("SUCCESS\n\n") : log_error("FAILED\n\n"); + return abs(ret); + } +diff --git a/upatch-manage/upatch-patch.c b/upatch-manage/upatch-patch.c +index 5e16002..5a8f927 100644 +--- a/upatch-manage/upatch-patch.c ++++ b/upatch-manage/upatch-patch.c +@@ -291,7 +291,6 @@ static void *upatch_alloc(struct object_file *obj, size_t sz) + MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, + 0); + if (addr == 0) { +- log_error("Failed to alloc remote patch memory\n"); + return NULL; + } + +@@ -308,7 +307,7 @@ static void *upatch_alloc(struct object_file *obj, size_t sz) + return (void *)addr; + } + +-static void __upatch_memfree(struct object_file *obj, void *base, ++static void upatch_free(struct object_file *obj, void *base, + unsigned int size) + { + log_debug("Free patch memory %p\n", base); +@@ -323,14 +322,13 @@ static int __alloc_memory(struct object_file *obj_file, + /* Do the allocs. */ + layout->base = upatch_alloc(obj_file, layout->size); + if (!layout->base) { +- log_error("Failed to alloc patch core layout %p\n", layout->base); +- return -ENOMEM; ++ return -errno; + } + + layout->kbase = malloc(layout->size); + if (!layout->kbase) { +- __upatch_memfree(obj_file, layout->base, layout->size); +- return -ENOMEM; ++ upatch_free(obj_file, layout->base, layout->size); ++ return -errno; + } + + memset(layout->kbase, 0, layout->size); +@@ -345,7 +343,6 @@ static int alloc_memory(struct upatch_elf *uelf, struct object_file *obj) + /* Do the allocs. */ + ret = __alloc_memory(obj, &uelf->core_layout); + if (ret) { +- log_error("Failed to alloc patch memory, ret=%d\n", ret); + return ret; + } + +@@ -634,11 +631,13 @@ static int upatch_apply_patches(struct upatch_process *proc, + */ + ret = alloc_memory(uelf, obj); + if (ret) { ++ log_error("Failed to alloc patch memory\n"); + goto free; + } + + ret = upatch_mprotect(uelf, obj); + if (ret) { ++ log_error("Failed to set patch memory permission\n"); + goto free; + } + +@@ -675,7 +674,7 @@ static int upatch_apply_patches(struct upatch_process *proc, + + // TODO: clear + free: +- __upatch_memfree(obj, uelf->core_layout.base, uelf->core_layout.size); ++ upatch_free(obj, uelf->core_layout.base, uelf->core_layout.size); + out: + return ret; + } +@@ -708,15 +707,16 @@ int process_patch(int pid, struct upatch_elf *uelf, struct running_elf *relf, co + // 查看process的信息,pid: maps, mem, cmdline, exe + ret = upatch_process_init(&proc, pid); + if (ret < 0) { +- log_error("Failed to init process %d, ret=%d\n", pid, ret); ++ log_error("Failed to init process\n"); + goto out; + } + +- printf("Patch "); ++ printf("Patch '%s' to ", uuid); + upatch_process_print_short(&proc); + + ret = upatch_process_mem_open(&proc, MEM_READ); + if (ret < 0) { ++ log_error("Failed to open process memory\n"); + goto out_free; + } + +@@ -731,15 +731,19 @@ int process_patch(int pid, struct upatch_elf *uelf, struct running_elf *relf, co + */ + // 解析process的mem-maps,获得各个块的内存映射以及phdr + ret = upatch_process_map_object_files(&proc, NULL); +- if (ret < 0) ++ if (ret < 0) { ++ log_error("Failed to read process memory mapping\n"); + goto out_free; ++ } + ret = upatch_process_uuid_exist(&proc, uuid); + if (ret != 0) { ++ ret = 0; ++ log_error("Patch '%s' already exists\n", uuid); + goto out_free; + } + ret = binary_init(relf, binary_path); + if (ret) { +- log_error("Failed to load binary, ret=%d\n", ret); ++ log_error("Failed to load binary\n"); + goto out_free; + } + +@@ -750,24 +754,27 @@ int process_patch(int pid, struct upatch_elf *uelf, struct running_elf *relf, co + + /* Finally, attach to process */ + ret = upatch_process_attach(&proc); +- if (ret < 0) ++ if (ret < 0) { ++ log_error("Failed to attach process\n"); + goto out_free; ++ } + + // TODO: 栈解析 + // 应用 + ret = upatch_apply_patches(&proc, uelf, uuid); +- if (ret < 0) ++ if (ret < 0) { ++ log_error("Failed to apply patch\n"); + goto out_free; +- +- ret = 0; ++ } + + out_free: + upatch_process_detach(&proc); ++ gettimeofday(&end_tv, NULL); ++ + upatch_process_destroy(&proc); + + out: + if (is_calc_time) { +- gettimeofday(&end_tv, NULL); + frozen_time = GET_MICROSECONDS(end_tv, start_tv); + log_normal("Process %d frozen time is %ld microsecond(s)\n", + pid, frozen_time); +@@ -800,7 +807,7 @@ static int upatch_unapply_patches(struct upatch_process *proc, const char *uuid) + } + + log_debug("munmap upatch layout core:\n"); +- __upatch_memfree(obj, ++ upatch_free(obj, + (void *)patch->uinfo->start, + patch->uinfo->end - patch->uinfo->start + ); +@@ -810,7 +817,7 @@ static int upatch_unapply_patches(struct upatch_process *proc, const char *uuid) + } + + if (!found) { +- log_debug("can't found patch info memory\n"); ++ log_warn("Patch '%s' is not found\n", uuid); + goto out; + } + +@@ -831,16 +838,18 @@ int process_unpatch(int pid, const char *uuid) + // 查看process的信息,pid: maps, mem, cmdline, exe + ret = upatch_process_init(&proc, pid); + if (ret < 0) { +- log_error("Failed to init process %d, ret=%d\n", pid, ret); ++ log_error("Failed to init process\n"); + goto out; + } + +- printf("Unpatch "); ++ printf("Unpatch '%s' from ", uuid); + upatch_process_print_short(&proc); + + ret = upatch_process_mem_open(&proc, MEM_READ); +- if (ret < 0) ++ if (ret < 0) { ++ log_error("Failed to open process memory\n"); + goto out_free; ++ } + + // use uprobe to hack function. the program has been executed to the entry + // point +@@ -853,8 +862,10 @@ int process_unpatch(int pid, const char *uuid) + */ + // 解析process的mem-maps,获得各个块的内存映射以及phdr + ret = upatch_process_map_object_files(&proc, NULL); +- if (ret < 0) ++ if (ret < 0) { ++ log_error("Failed to read process memory mapping\n"); + goto out_free; ++ } + + is_calc_time = true; + gettimeofday(&start_tv, NULL); +@@ -862,24 +873,25 @@ int process_unpatch(int pid, const char *uuid) + /* Finally, attach to process */ + ret = upatch_process_attach(&proc); + if (ret < 0) { ++ log_error("Failed to attach process\n"); + goto out_free; + } + + // 应用 + ret = upatch_unapply_patches(&proc, uuid); + if (ret < 0) { ++ log_error("Failed to remove patch\n"); + goto out_free; + } + +- ret = 0; +- + out_free: + upatch_process_detach(&proc); ++ gettimeofday(&end_tv, NULL); ++ + upatch_process_destroy(&proc); + + out: + if (is_calc_time) { +- gettimeofday(&end_tv, NULL); + frozen_time = GET_MICROSECONDS(end_tv, start_tv); + log_normal("Process %d frozen time is %ld microsecond(s)\n", + pid, frozen_time); +@@ -924,23 +936,25 @@ int process_info(int pid) + // 查看process的信息,pid: maps, mem, cmdline, exe + ret = upatch_process_init(&proc, pid); + if (ret < 0) { +- log_error("Failed to init process %d, ret=%d\n", pid, ret); ++ log_error("Failed to init process\n"); + goto out; + } + + ret = upatch_process_mem_open(&proc, MEM_READ); + if (ret < 0) { ++ log_error("Failed to open process memory\n"); + goto out_free; + } + + ret = upatch_process_map_object_files(&proc, NULL); + if (ret < 0) { ++ log_error("Failed to read process memory mapping\n"); + goto out_free; + } + + ret = upatch_info(&proc); + if (ret) { +- status = "active"; ++ status = "actived"; + } + else { + status = "removed"; +diff --git a/upatch-manage/upatch-process.c b/upatch-manage/upatch-process.c +index cd3f7e0..c368165 100644 +--- a/upatch-manage/upatch-process.c ++++ b/upatch-manage/upatch-process.c +@@ -57,7 +57,7 @@ static int lock_process(int pid) + + fd = open(path, O_RDONLY); + if (fd < 0) { +- log_error("Failed to open '%s'\n", path); ++ log_error("Failed to open file '%s'\n", path); + return -1; + } + log_debug("OK\n"); +@@ -204,7 +204,7 @@ static void process_print_cmdline(struct upatch_process *proc) + snprintf(buf, PATH_MAX, "/proc/%d/cmdline", proc->pid); + int fd = open(buf, O_RDONLY); + if (fd == -1) { +- log_error("Failed to open %s", buf); ++ log_error("Failed to open file '%s'\n", buf); + return; + } + +@@ -255,7 +255,7 @@ int upatch_process_mem_open(struct upatch_process *proc, int mode) + snprintf(path, sizeof(path), "/proc/%d/mem", proc->pid); + proc->memfd = open(path, mode == MEM_WRITE ? O_RDWR : O_RDONLY); + if (proc->memfd < 0) { +- log_error("Failed to open %s", path); ++ log_error("Failed to open file '%s'\n", path); + return -1; + } + +@@ -560,16 +560,9 @@ error: + int upatch_process_map_object_files(struct upatch_process *proc, + const char *patch_id) + { +- int ret; +- +- ret = upatch_process_parse_proc_maps(proc); +- if (ret < 0) +- return -1; +- + // we can get plt/got table from mem's elf_segments + // Now we read them from the running file +- +- return ret; ++ return upatch_process_parse_proc_maps(proc); + } + + // static int process_has_thread_pid(struct upatch_proces *proc, int pid) +diff --git a/upatch-manage/upatch-ptrace.c b/upatch-manage/upatch-ptrace.c +index 39e8f59..1309a6e 100644 +--- a/upatch-manage/upatch-ptrace.c ++++ b/upatch-manage/upatch-ptrace.c +@@ -19,6 +19,7 @@ + */ + + #include ++#include + #include + #include + #include +-- +2.34.1 + diff --git a/0013-upatch-manage-change-the-way-to-calculate-frozen-tim.patch b/0013-upatch-manage-change-the-way-to-calculate-frozen-tim.patch new file mode 100644 index 0000000000000000000000000000000000000000..06ac67ca5effa69b564aef9777bea2ccab5df31e --- /dev/null +++ b/0013-upatch-manage-change-the-way-to-calculate-frozen-tim.patch @@ -0,0 +1,140 @@ +From ff07e664cb475fa74b4f6531d8e709a5dd9b55dd Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 19 Apr 2024 14:19:27 +0800 +Subject: [PATCH] upatch-manage: change the way to calculate frozen time + +Signed-off-by: renoseven +--- + upatch-manage/upatch-patch.c | 58 +++++++++++++++++++----------------- + 1 file changed, 31 insertions(+), 27 deletions(-) + +diff --git a/upatch-manage/upatch-patch.c b/upatch-manage/upatch-patch.c +index 5a8f927..ab972ac 100644 +--- a/upatch-manage/upatch-patch.c ++++ b/upatch-manage/upatch-patch.c +@@ -679,6 +679,31 @@ out: + return ret; + } + ++static void upatch_time_tick(int pid) { ++ static struct timeval start_tv; ++ static struct timeval end_tv; ++ ++ if ((end_tv.tv_sec != 0) || (end_tv.tv_usec != 0)) { ++ memset(&start_tv, 0, sizeof(struct timeval)); ++ memset(&end_tv, 0, sizeof(struct timeval)); ++ } ++ ++ if ((start_tv.tv_sec == 0) && (start_tv.tv_usec == 0)) { ++ gettimeofday(&start_tv, NULL); ++ } else { ++ gettimeofday(&end_tv, NULL); ++ } ++ ++ if ((start_tv.tv_sec == 0) || (start_tv.tv_usec == 0) || ++ (end_tv.tv_sec == 0) || (end_tv.tv_usec == 0)) { ++ return; ++ } ++ ++ unsigned long frozen_time = GET_MICROSECONDS(end_tv, start_tv); ++ log_normal("Process %d frozen time is %ld microsecond(s)\n", ++ pid, frozen_time); ++} ++ + int upatch_process_uuid_exist(struct upatch_process *proc, const char *uuid) + { + struct object_file *obj; +@@ -698,14 +723,10 @@ int upatch_process_uuid_exist(struct upatch_process *proc, const char *uuid) + + int process_patch(int pid, struct upatch_elf *uelf, struct running_elf *relf, const char *uuid, const char *binary_path) + { +- int ret; +- bool is_calc_time = false; +- struct timeval start_tv, end_tv; +- unsigned long frozen_time; + struct upatch_process proc; + + // 查看process的信息,pid: maps, mem, cmdline, exe +- ret = upatch_process_init(&proc, pid); ++ int ret = upatch_process_init(&proc, pid); + if (ret < 0) { + log_error("Failed to init process\n"); + goto out; +@@ -748,9 +769,7 @@ int process_patch(int pid, struct upatch_elf *uelf, struct running_elf *relf, co + } + + uelf->relf = relf; +- +- is_calc_time = true; +- gettimeofday(&start_tv, NULL); ++ upatch_time_tick(pid); + + /* Finally, attach to process */ + ret = upatch_process_attach(&proc); +@@ -769,16 +788,11 @@ int process_patch(int pid, struct upatch_elf *uelf, struct running_elf *relf, co + + out_free: + upatch_process_detach(&proc); +- gettimeofday(&end_tv, NULL); ++ upatch_time_tick(pid); + + upatch_process_destroy(&proc); + + out: +- if (is_calc_time) { +- frozen_time = GET_MICROSECONDS(end_tv, start_tv); +- log_normal("Process %d frozen time is %ld microsecond(s)\n", +- pid, frozen_time); +- } + return ret; + } + +@@ -827,16 +841,12 @@ out: + + int process_unpatch(int pid, const char *uuid) + { +- int ret; +- bool is_calc_time = false; +- struct timeval start_tv, end_tv; +- unsigned long frozen_time; + struct upatch_process proc; + + // TODO: check build id + // TODO: 栈解析 + // 查看process的信息,pid: maps, mem, cmdline, exe +- ret = upatch_process_init(&proc, pid); ++ int ret = upatch_process_init(&proc, pid); + if (ret < 0) { + log_error("Failed to init process\n"); + goto out; +@@ -867,8 +877,7 @@ int process_unpatch(int pid, const char *uuid) + goto out_free; + } + +- is_calc_time = true; +- gettimeofday(&start_tv, NULL); ++ upatch_time_tick(pid); + + /* Finally, attach to process */ + ret = upatch_process_attach(&proc); +@@ -886,16 +895,11 @@ int process_unpatch(int pid, const char *uuid) + + out_free: + upatch_process_detach(&proc); +- gettimeofday(&end_tv, NULL); ++ upatch_time_tick(pid); + + upatch_process_destroy(&proc); + + out: +- if (is_calc_time) { +- frozen_time = GET_MICROSECONDS(end_tv, start_tv); +- log_normal("Process %d frozen time is %ld microsecond(s)\n", +- pid, frozen_time); +- } + return ret; + } + +-- +2.34.1 + diff --git a/0014-upatch-build-fix-file-detection-cause-build-failure-.patch b/0014-upatch-build-fix-file-detection-cause-build-failure-.patch new file mode 100644 index 0000000000000000000000000000000000000000..e19f4704b9b79666965c7c3a4def68549ddae2e1 --- /dev/null +++ b/0014-upatch-build-fix-file-detection-cause-build-failure-.patch @@ -0,0 +1,556 @@ +From 35ee9283c60a2d3e7d5ae2bcb9db31c71856d645 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Thu, 9 May 2024 18:49:29 +0800 +Subject: [PATCH] upatch-build: fix 'file detection cause build failure' issue + + File relation detection does not work as we expected sometimes. +We changed the way to parse file relations from parsing dwarf info +to reading symlink, which is generated by hijacker. + + This method would list all generated symlinks after each build, +finding the file it points to and create a file map. Because of build results +are same, we can use the symlink path as a KEY to find the relationship +between patched objects and original objects, which is the previous step for +comparing difference of each build. + + Sometimes, the directory of generated objects may be different than source +directory. Thus, we provide a new argument '--object-dir', which would be +same as '--source-dir' by default. + +Signed-off-by: renoseven +--- + upatch-build/src/args.rs | 19 ++++- + upatch-build/src/build_root.rs | 8 +- + upatch-build/src/compiler.rs | 4 +- + upatch-build/src/dwarf/mod.rs | 22 +---- + upatch-build/src/file_relation.rs | 133 +++++++++++++++++------------- + upatch-build/src/main.rs | 33 ++++---- + upatch-build/src/project.rs | 2 +- + upatch-build/src/rpc/remote.rs | 2 +- + 8 files changed, 119 insertions(+), 104 deletions(-) + +diff --git a/upatch-build/src/args.rs b/upatch-build/src/args.rs +index 9f5fa15..c3b6f48 100644 +--- a/upatch-build/src/args.rs ++++ b/upatch-build/src/args.rs +@@ -23,6 +23,8 @@ use super::{CLI_ABOUT, CLI_NAME, CLI_VERSION}; + + const DEFAULT_WORK_DIR: &str = "/var/run/syscare"; + const DEFAULT_BUILD_ROOT: &str = "./upatch"; ++const DEFAULT_ELF_DIR: &str = ""; ++const DEFAULT_OBJECT_DIR: &str = ""; + const DEFAULT_CMD: &str = ""; + const DEFAULT_COMPILERS: &str = "cc"; + const DEFAULT_OUTPUT_DIR: &str = "."; +@@ -66,10 +68,14 @@ pub struct Arguments { + #[clap(short, long, multiple = true, required = true)] + pub debuginfo: Vec, + +- /// Specify the directory of searching elf [default: ] +- #[clap(long, default_value = "", hide_default_value = true)] ++ /// Specify the directory for searching elf [default: ] ++ #[clap(long, default_value = DEFAULT_ELF_DIR, hide_default_value = true)] + pub elf_dir: PathBuf, + ++ /// Specify the directory for searching object [default: ] ++ #[clap(long, default_value = DEFAULT_OBJECT_DIR, hide_default_value = true)] ++ pub object_dir: PathBuf, ++ + /// Specify elf's relative path relate to 'elf' or absolute patch list + #[clap(long, multiple = true, required = true)] + pub elf: Vec, +@@ -111,6 +117,10 @@ impl Arguments { + false => fs::normalize(&args.elf_dir)?, + true => args.source_dir.clone(), + }; ++ args.object_dir = match args.object_dir.as_os_str().is_empty() { ++ false => fs::normalize(&args.object_dir)?, ++ true => args.source_dir.clone(), ++ }; + + for elf_path in &mut args.elf { + *elf_path = args.elf_dir.join(&elf_path); +@@ -124,6 +134,7 @@ impl Arguments { + self.build_root = fs::normalize(self.build_root)?; + self.source_dir = fs::normalize(&self.source_dir)?; + self.elf_dir = fs::normalize(&self.elf_dir)?; ++ self.object_dir = fs::normalize(&self.object_dir)?; + self.output_dir = fs::normalize(&self.output_dir)?; + + for debuginfo in &mut self.debuginfo { +@@ -149,6 +160,10 @@ impl Arguments { + self.elf_dir.is_dir(), + format!("Cannot find elf directory {}", self.elf_dir.display()) + ); ++ ensure!( ++ self.object_dir.is_dir(), ++ format!("Cannot find object directory {}", self.object_dir.display()) ++ ); + for debuginfo in &self.debuginfo { + ensure!( + debuginfo.is_file(), +diff --git a/upatch-build/src/build_root.rs b/upatch-build/src/build_root.rs +index 0d703a7..556231d 100644 +--- a/upatch-build/src/build_root.rs ++++ b/upatch-build/src/build_root.rs +@@ -21,7 +21,7 @@ pub struct BuildRoot { + pub path: PathBuf, + pub original_dir: PathBuf, + pub patched_dir: PathBuf, +- pub output_dir: PathBuf, ++ pub temp_dir: PathBuf, + pub log_file: PathBuf, + } + +@@ -30,19 +30,19 @@ impl BuildRoot { + let path = path.as_ref().to_path_buf(); + let original_dir = path.join("original"); + let patched_dir = path.join("patched"); +- let output_dir = path.join("output"); ++ let temp_dir = path.join("temp"); + let log_file = path.join("build.log"); + + fs::create_dir_all(&path)?; + fs::create_dir_all(&original_dir)?; + fs::create_dir_all(&patched_dir)?; +- fs::create_dir_all(&output_dir)?; ++ fs::create_dir_all(&temp_dir)?; + + Ok(Self { + path, + original_dir, + patched_dir, +- output_dir, ++ temp_dir, + log_file, + }) + } +diff --git a/upatch-build/src/compiler.rs b/upatch-build/src/compiler.rs +index 9c282e2..7778f0b 100644 +--- a/upatch-build/src/compiler.rs ++++ b/upatch-build/src/compiler.rs +@@ -169,7 +169,7 @@ impl Compiler { + } + + impl Compiler { +- pub fn parse(compilers: I, build_dir: Q) -> Result> ++ pub fn parse(compilers: I, temp_dir: Q) -> Result> + where + I: IntoIterator, + P: AsRef, +@@ -183,7 +183,7 @@ impl Compiler { + .file_name() + .context("Failed to parse compiler name")?; + +- let output_dir = build_dir.as_ref().join(compiler_name); ++ let output_dir = temp_dir.as_ref().join(compiler_name); + fs::create_dir_all(&output_dir)?; + + debug!("- Checking {}", compiler.display()); +diff --git a/upatch-build/src/dwarf/mod.rs b/upatch-build/src/dwarf/mod.rs +index aded143..35f359e 100644 +--- a/upatch-build/src/dwarf/mod.rs ++++ b/upatch-build/src/dwarf/mod.rs +@@ -22,7 +22,7 @@ use std::{ + path::{Path, PathBuf}, + }; + +-use anyhow::{bail, Context, Result}; ++use anyhow::{Context, Result}; + use gimli::{ + constants, Attribute, AttributeValue, EndianSlice, Endianity, Reader, RunTimeEndian, SectionId, + }; +@@ -65,26 +65,6 @@ impl Dwarf { + Self::get_files(&object, endian) + } + +- pub fn parse_source_file>(object: P) -> Result { +- let source_files = Dwarf::parse(&object) +- .with_context(|| format!("Failed to read dwarf of {}", object.as_ref().display()))? +- .into_iter() +- .filter_map(|dwarf| { +- let file_path = dwarf.compile_dir.join(&dwarf.file_name); +- match file_path.exists() { +- true => Some(file_path), +- false => None, +- } +- }) +- .collect::>(); +- +- match source_files.len() { +- 1 => Ok(source_files[0].clone()), +- 0 => bail!("Object does not contain source file"), +- _ => bail!("Object contains to too many source files"), +- } +- } +- + pub fn parse_compiler_versions>(object: P) -> Result> { + let compiler_versions = Dwarf::parse(&object) + .with_context(|| format!("Failed to read dwarf of {}", object.as_ref().display()))? +diff --git a/upatch-build/src/file_relation.rs b/upatch-build/src/file_relation.rs +index ef67af1..5a58d04 100644 +--- a/upatch-build/src/file_relation.rs ++++ b/upatch-build/src/file_relation.rs +@@ -21,7 +21,6 @@ use indexmap::{IndexMap, IndexSet}; + use syscare_common::{ffi::OsStrExt, fs}; + + use super::{ +- dwarf::Dwarf, + elf::{check_elf, read}, + pattern_path::glob, + }; +@@ -29,25 +28,32 @@ use super::{ + const UPATCH_SYM_PREFIX: &str = ".upatch_"; + const OBJECT_EXTENSION: &str = "o"; + ++/* ++ * The task of this class is to find out: ++ * 1. relationship between binary and debuginfo ++ * 2. relationship between output binaries and objects ++ * 3. relationship between original objects and patched objects ++ */ ++ + #[derive(Debug)] + pub struct FileRelation { +- binary_debug_map: IndexMap, // Binary -> Debuginfo +- source_origin_map: IndexMap, // Source file -> Original object +- binary_patched_map: IndexMap>, // Binary -> Patched objects +- patched_original_map: IndexMap, // Patched object -> Original object ++ debuginfo_map: IndexMap, // Binary -> Debuginfo ++ symlink_map: IndexMap, // Symlink object -> Orignal object ++ patch_objects_map: IndexMap>, // Binary -> Patched objects ++ original_object_map: IndexMap, // Patched object -> Original object + } + + impl FileRelation { + pub fn new() -> Self { + Self { +- binary_debug_map: IndexMap::new(), +- binary_patched_map: IndexMap::new(), +- source_origin_map: IndexMap::new(), +- patched_original_map: IndexMap::new(), ++ debuginfo_map: IndexMap::new(), ++ symlink_map: IndexMap::new(), ++ patch_objects_map: IndexMap::new(), ++ original_object_map: IndexMap::new(), + } + } + +- pub fn collect_outputs(&mut self, binaries: I, debuginfos: J) -> Result<()> ++ pub fn collect_debuginfo(&mut self, binaries: I, debuginfos: J) -> Result<()> + where + I: IntoIterator, + J: IntoIterator, +@@ -61,86 +67,99 @@ impl FileRelation { + let binary = Self::find_binary_file(binary)?; + let debuginfo = debuginfo.as_ref().to_path_buf(); + +- self.binary_debug_map.insert(binary, debuginfo); ++ self.debuginfo_map.insert(binary, debuginfo); + } + + Ok(()) + } + +- pub fn collect_original_build>(&mut self, object_dir: P) -> Result<()> { +- for (binary, _) in &self.binary_debug_map { +- let upatch_ids = Self::parse_upatch_ids(binary) +- .with_context(|| format!("Failed to parse upatch id of {}", binary.display()))?; +- +- for upatch_id in upatch_ids { +- let original_object = Self::find_object_file(&object_dir, &upatch_id) +- .with_context(|| { +- format!("Failed to find object of {}", upatch_id.to_string_lossy()) +- })?; +- let source_file = +- Dwarf::parse_source_file(&original_object).with_context(|| { +- format!( +- "Failed to parse source file of {}", +- original_object.display() +- ) +- })?; +- +- self.source_origin_map.insert(source_file, original_object); ++ pub fn collect_original_build(&mut self, object_dir: P, expected_dir: Q) -> Result<()> ++ where ++ P: AsRef, ++ Q: AsRef, ++ { ++ let symlinks = fs::list_symlinks(&object_dir, fs::TraverseOptions { recursive: true })?; ++ for symlink in symlinks { ++ let object = fs::read_link(&symlink)?; ++ if !object.starts_with(expected_dir.as_ref().as_os_str()) { ++ continue; + } ++ self.symlink_map.insert(symlink, object); + } ++ ensure!( ++ !self.symlink_map.is_empty(), ++ "Cannot find any valid objects in {}", ++ object_dir.as_ref().display() ++ ); + + Ok(()) + } + +- pub fn collect_patched_build>(&mut self, object_dir: P) -> Result<()> { +- for (binary, _) in &self.binary_debug_map { ++ pub fn collect_patched_build(&mut self, object_dir: P, expected_dir: Q) -> Result<()> ++ where ++ P: AsRef, ++ Q: AsRef, ++ { ++ let mut symlink_map = IndexMap::new(); ++ let symlinks = fs::list_symlinks(&object_dir, fs::TraverseOptions { recursive: true })?; ++ for symlink in symlinks { ++ let object = fs::read_link(&symlink)?; ++ if !object.starts_with(expected_dir.as_ref().as_os_str()) { ++ continue; ++ } ++ symlink_map.insert(object, symlink); ++ } ++ ensure!( ++ !self.symlink_map.is_empty(), ++ "Cannot find any valid objects in {}", ++ object_dir.as_ref().display() ++ ); ++ ++ for (binary, _) in &self.debuginfo_map { ++ let mut objects = IndexSet::new(); ++ + let upatch_ids = Self::parse_upatch_ids(binary) + .with_context(|| format!("Failed to parse upatch id of {}", binary.display()))?; +- +- let mut patched_objects = IndexSet::new(); + for upatch_id in upatch_ids { +- let patched_object = +- Self::find_object_file(&object_dir, &upatch_id).with_context(|| { +- format!("Failed to find object of {}", upatch_id.to_string_lossy()) ++ let patched_object = Self::get_object_file(&expected_dir, &upatch_id) ++ .with_context(|| { ++ format!("Failed to get object of {}", upatch_id.to_string_lossy()) + })?; +- let source_file = Dwarf::parse_source_file(&patched_object).with_context(|| { +- format!( +- "Failed to parse source file of {}", +- patched_object.display() +- ) +- })?; +- let original_object = +- self.source_origin_map.get(&source_file).with_context(|| { ++ let original_object = symlink_map ++ .get(&patched_object) ++ .and_then(|path| self.symlink_map.get(path)) ++ .with_context(|| { + format!( +- "Failed to find original object of {}", ++ "failed to find original object of {}", + patched_object.display() + ) +- })?; ++ }) ++ .cloned()?; + +- patched_objects.insert(patched_object.clone()); +- self.patched_original_map +- .insert(patched_object, original_object.to_path_buf()); ++ // Update object relations ++ self.original_object_map ++ .insert(patched_object.to_owned(), original_object); ++ objects.insert(patched_object); + } +- +- self.binary_patched_map +- .insert(binary.to_path_buf(), patched_objects); ++ self.patch_objects_map.insert(binary.to_owned(), objects); + } ++ self.symlink_map.clear(); // clear useless records + + Ok(()) + } + + pub fn get_files(&self) -> impl IntoIterator { +- self.binary_debug_map ++ self.debuginfo_map + .iter() + .map(|(binary, debuginfo)| (binary.as_path(), debuginfo.as_path())) + } + + pub fn get_patched_objects>(&self, binary: P) -> Option<&IndexSet> { +- self.binary_patched_map.get(binary.as_ref()) ++ self.patch_objects_map.get(binary.as_ref()) + } + + pub fn get_original_object>(&self, object: P) -> Option<&Path> { +- self.patched_original_map ++ self.original_object_map + .get(object.as_ref()) + .map(|p| p.as_path()) + } +@@ -166,7 +185,7 @@ impl FileRelation { + } + } + +- fn find_object_file(object_dir: P, upatch_id: S) -> Result ++ fn get_object_file(object_dir: P, upatch_id: S) -> Result + where + P: AsRef, + S: AsRef, +diff --git a/upatch-build/src/main.rs b/upatch-build/src/main.rs +index 99de581..b5c14a8 100644 +--- a/upatch-build/src/main.rs ++++ b/upatch-build/src/main.rs +@@ -49,7 +49,7 @@ use file_relation::FileRelation; + use hijacker::Hijacker; + use project::Project; + +-const CLI_NAME: &str = "syscare build"; ++const CLI_NAME: &str = "upatch build"; + const CLI_VERSION: &str = env!("CARGO_PKG_VERSION"); + const CLI_ABOUT: &str = env!("CARGO_PKG_DESCRIPTION"); + const CLI_UMASK: u32 = 0o022; +@@ -59,7 +59,7 @@ const LOG_FILE_NAME: &str = "build"; + struct BuildInfo { + files: FileRelation, + linker: PathBuf, +- build_dir: PathBuf, ++ temp_dir: PathBuf, + output_dir: PathBuf, + verbose: bool, + } +@@ -256,11 +256,11 @@ impl UpatchBuild { + let debuginfo_name = debuginfo + .file_name() + .context("Failed to parse debuginfo name")?; +- let output_dir = build_info.build_dir.join(binary_name); +- let new_debuginfo = output_dir.join(debuginfo_name); ++ let temp_dir = build_info.temp_dir.join(binary_name); ++ let new_debuginfo = temp_dir.join(debuginfo_name); + + debug!("- Preparing to build patch"); +- fs::create_dir_all(&output_dir)?; ++ fs::create_dir_all(&temp_dir)?; + fs::copy(debuginfo, &new_debuginfo)?; + fs::set_permissions(&new_debuginfo, Permissions::from_mode(0o644))?; + +@@ -288,7 +288,7 @@ impl UpatchBuild { + original_object, + patched_object, + &new_debuginfo, +- &output_dir, ++ &temp_dir, + build_info.verbose, + ) + .with_context(|| format!("Failed to create diff objects for {}", binary.display()))?; +@@ -296,7 +296,7 @@ impl UpatchBuild { + + debug!("- Collecting changes"); + let mut changed_objects = fs::list_files_by_ext( +- &output_dir, ++ &temp_dir, + OBJECT_EXTENSION, + fs::TraverseOptions { recursive: false }, + )?; +@@ -306,7 +306,7 @@ impl UpatchBuild { + } + + debug!("- Creating patch notes"); +- let notes_object = output_dir.join(NOTES_OBJECT_NAME); ++ let notes_object = temp_dir.join(NOTES_OBJECT_NAME); + Self::create_note(&new_debuginfo, ¬es_object).context("Failed to create patch notes")?; + changed_objects.push(notes_object); + +@@ -332,10 +332,10 @@ impl UpatchBuild { + }; + let output_file = build_info.output_dir.join(&patch_name); + +- info!("Generating patch {}", patch_name.to_string_lossy()); ++ info!("Generating patch for '{}'", patch_name.to_string_lossy()); + self.build_patch(&build_info, binary, debuginfo, &output_file) + .with_context(|| { +- format!("Failed to build patch {}", patch_name.to_string_lossy()) ++ format!("Failed to build patch '{}'", patch_name.to_string_lossy()) + })?; + } + +@@ -346,11 +346,12 @@ impl UpatchBuild { + let work_dir = self.args.work_dir.as_path(); + let name = self.args.name.as_os_str(); + let output_dir = self.args.output_dir.as_path(); ++ let object_dir = self.args.object_dir.as_path(); + let binaries = self.args.elf.as_slice(); + let debuginfos = self.args.debuginfo.as_slice(); + let verbose = self.args.verbose; + +- let build_dir = self.build_root.output_dir.as_path(); ++ let temp_dir = self.build_root.temp_dir.as_path(); + let original_dir = self.build_root.original_dir.as_path(); + let patched_dir = self.build_root.patched_dir.as_path(); + +@@ -359,7 +360,7 @@ impl UpatchBuild { + info!("=============================="); + info!("Checking compiler(s)"); + +- let compilers = Compiler::parse(&self.args.compiler, build_dir)?; ++ let compilers = Compiler::parse(&self.args.compiler, temp_dir)?; + let linker = compilers + .iter() + .map(|c| c.linker.clone()) +@@ -406,8 +407,8 @@ impl UpatchBuild { + .with_context(|| format!("Failed to build {}", project))?; + + info!("Collecting file relations"); +- files.collect_outputs(binaries, debuginfos)?; +- files.collect_original_build(original_dir)?; ++ files.collect_debuginfo(binaries, debuginfos)?; ++ files.collect_original_build(object_dir, original_dir)?; + + info!("Preparing {}", project); + project +@@ -425,7 +426,7 @@ impl UpatchBuild { + .with_context(|| format!("Failed to rebuild {}", project))?; + + info!("Collecting file relations"); +- files.collect_patched_build(patched_dir)?; ++ files.collect_patched_build(object_dir, patched_dir)?; + + // Unhack compilers + drop(hijacker); +@@ -433,7 +434,7 @@ impl UpatchBuild { + let build_info = BuildInfo { + linker, + files, +- build_dir: build_dir.to_path_buf(), ++ temp_dir: temp_dir.to_path_buf(), + output_dir: output_dir.to_path_buf(), + verbose, + }; +diff --git a/upatch-build/src/project.rs b/upatch-build/src/project.rs +index b2f8230..b36c26b 100644 +--- a/upatch-build/src/project.rs ++++ b/upatch-build/src/project.rs +@@ -46,7 +46,7 @@ pub struct Project<'a> { + impl<'a> Project<'a> { + pub fn new(args: &'a Arguments, build_root: &'a BuildRoot) -> Self { + let root_dir = args.source_dir.as_path(); +- let build_dir = build_root.output_dir.as_path(); ++ let build_dir = build_root.temp_dir.as_path(); + let original_dir = build_root.original_dir.as_path(); + let patched_dir = build_root.patched_dir.as_path(); + +diff --git a/upatch-build/src/rpc/remote.rs b/upatch-build/src/rpc/remote.rs +index a34f713..9927ece 100644 +--- a/upatch-build/src/rpc/remote.rs ++++ b/upatch-build/src/rpc/remote.rs +@@ -56,7 +56,7 @@ impl RpcRemote { + match error { + Error::Transport(e) => { + anyhow!( +- "Cannot connect to syscare daemon at unix://{}, {}", ++ "Cannot connect to upatch daemon at unix://{}, {}", + self.socket.display(), + e.source() + .map(|e| e.to_string()) +-- +2.34.1 + diff --git a/0015-upatch-diff-optimize-log-output.patch b/0015-upatch-diff-optimize-log-output.patch new file mode 100644 index 0000000000000000000000000000000000000000..cdfa3bf5a4cf9ec729fdb4b79e15c828879cdf46 --- /dev/null +++ b/0015-upatch-diff-optimize-log-output.patch @@ -0,0 +1,469 @@ +From 2a4df8e1c7418c49fbad06e20b2a6af100b1ed16 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Sat, 11 May 2024 08:26:33 +0800 +Subject: [PATCH] upatch-diff: optimize log output + +Signed-off-by: renoseven +--- + upatch-diff/create-diff-object.c | 177 ++++++++++++++++++------------- + upatch-diff/elf-compare.c | 2 +- + upatch-diff/elf-correlate.c | 4 +- + upatch-diff/log.h | 18 ++-- + upatch-diff/running-elf.c | 6 +- + upatch-diff/running-elf.h | 6 +- + upatch-diff/upatch-elf.c | 2 +- + upatch-diff/upatch-elf.h | 4 +- + 8 files changed, 122 insertions(+), 97 deletions(-) + +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index 5dc7522..01c58b8 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -62,9 +62,10 @@ + + #define PROG_VERSION "upatch-diff "BUILD_VERSION + +-enum loglevel loglevel = NORMAL; +-char *logprefix; +-char *upatch_elf_name; ++enum LogLevel g_loglevel = NORMAL; ++char *g_logprefix; ++char *g_uelf_name; ++char *g_relf_name; + + struct arguments { + char *source_obj; +@@ -334,72 +335,87 @@ enum LOCAL_MATCH { + EMPTY, + }; + +-static enum LOCAL_MATCH locals_match(struct running_elf *relf, int idx, +- struct symbol *file_sym, struct list_head *sym_list) ++static enum LOCAL_MATCH locals_match( ++ struct upatch_elf *uelf, struct running_elf *relf, ++ struct symbol *file_sym, int file_sym_idx) + { +- struct symbol *sym; +- struct object_symbol *running_sym; +- int i; ++ struct symbol *uelf_sym = NULL; ++ struct debug_symbol *relf_sym = NULL; + enum LOCAL_MATCH found = EMPTY; + +- for (i = idx + 1; i < relf->obj_nr; ++i) { +- running_sym = &relf->obj_syms[i]; +- if (running_sym->type == STT_FILE) +- break; +- if (running_sym->bind != STB_LOCAL) ++ for (int i = file_sym_idx + 1; i < relf->obj_nr; i++) { ++ relf_sym = &relf->obj_syms[i]; ++ ++ if (relf_sym->type == STT_FILE) { ++ break; // find until next file ++ } ++ if (relf_sym->bind != STB_LOCAL) { + continue; +- if (running_sym->type != STT_FUNC && running_sym->type != STT_OBJECT) ++ } ++ if ((relf_sym->type != STT_FUNC) && ++ (relf_sym->type != STT_OBJECT)) { + continue; ++ } + + found = NOT_FOUND; +- sym = file_sym; +- list_for_each_entry_continue(sym, sym_list, list) { +- if (sym->type == STT_FILE) +- break; +- if(sym->bind != STB_LOCAL) ++ uelf_sym = file_sym; ++ list_for_each_entry_continue(uelf_sym, &uelf->symbols, list) { ++ if (uelf_sym->type == STT_FILE) { ++ break; // find until next file ++ } ++ if(uelf_sym->bind != STB_LOCAL) { + continue; +- +- if (sym->type == running_sym->type && +- !strcmp(sym->name, running_sym->name)) { +- found = FOUND; +- break; ++ } ++ if ((uelf_sym->type == relf_sym->type) && ++ (strcmp(uelf_sym->name, relf_sym->name) == 0)) { ++ found = FOUND; ++ break; + } + } + + if (found == NOT_FOUND) { +- log_warn("Cannot find symbol '%s' in running binary\n", running_sym->name); ++ log_warn("Cannot find symbol '%s' in %s\n", ++ relf_sym->name, g_relf_name); + return NOT_FOUND; + } + } + +- sym = file_sym; +- list_for_each_entry_continue(sym, sym_list, list) { +- if (sym->type == STT_FILE) +- break; +- if(sym->bind != STB_LOCAL) ++ uelf_sym = file_sym; ++ list_for_each_entry_continue(uelf_sym, &uelf->symbols, list) { ++ if (uelf_sym->type == STT_FILE) { ++ break; // find until next file ++ } ++ if(uelf_sym->bind != STB_LOCAL) { + continue; +- if (sym->type != STT_FUNC && sym->type != STT_OBJECT) ++ } ++ if ((relf_sym->type != STT_FUNC) && ++ (relf_sym->type != STT_OBJECT)) { + continue; +- if (discarded_sym(relf, sym)) ++ } ++ if (discarded_sym(relf, uelf_sym)) { + continue; ++ } + + found = NOT_FOUND; +- for (i = idx + 1; i < relf->obj_nr; ++i) { +- running_sym = &relf->obj_syms[i]; +- if (running_sym->type == STT_FILE) +- break; +- if (running_sym->bind != STB_LOCAL) +- continue; ++ for (int i = file_sym_idx + 1; i < relf->obj_nr; i++) { ++ relf_sym = &relf->obj_syms[i]; + +- if (sym->type == running_sym->type && +- !strcmp(sym->name, running_sym->name)) { +- found = FOUND; +- break; ++ if (relf_sym->type == STT_FILE) { ++ break; // find until next file ++ } ++ if (relf_sym->bind != STB_LOCAL) { ++ continue; ++ } ++ if ((uelf_sym->type == relf_sym->type) && ++ (strcmp(uelf_sym->name, relf_sym->name) == 0)) { ++ found = FOUND; ++ break; + } + } + +- if (found == NOT_FOUND){ +- log_warn("Cannot find symbol '%s' in object\n", sym->name); ++ if (found == NOT_FOUND) { ++ log_warn("Cannot find symbol '%s' in %s\n", ++ uelf_sym->name, g_uelf_name); + return NOT_FOUND; + } + } +@@ -407,41 +423,48 @@ static enum LOCAL_MATCH locals_match(struct running_elf *relf, int idx, + return found; + } + +-static void find_local_syms(struct running_elf *relf, struct symbol *file_sym, +- struct list_head *sym_list) ++static void find_local_syms(struct upatch_elf *uelf, struct running_elf *relf, ++ struct symbol *file_sym) + { +- struct object_symbol *running_sym; +- struct object_symbol *lookup_running_file_sym = NULL; +- int i; ++ struct debug_symbol *relf_sym = NULL; ++ struct debug_symbol *found_sym = NULL; + enum LOCAL_MATCH found; + +- for (i = 0; i < relf->obj_nr; ++i) { +- running_sym = &relf->obj_syms[i]; +- if (running_sym->type != STT_FILE) ++ for (int i = 0; i < relf->obj_nr; i++) { ++ relf_sym = &relf->obj_syms[i]; ++ ++ if (relf_sym->type != STT_FILE) { + continue; +- if (strcmp(file_sym->name, running_sym->name)) ++ } ++ if (strcmp(file_sym->name, relf_sym->name)) { + continue; +- found = locals_match(relf, i, file_sym, sym_list); ++ } ++ ++ found = locals_match(uelf, relf, file_sym, i); + if (found == NOT_FOUND) { + continue; +- } else if (found == EMPTY) { +- lookup_running_file_sym = running_sym; ++ } ++ else if (found == EMPTY) { ++ found_sym = relf_sym; + break; +- } else { +- if (lookup_running_file_sym) +- ERROR("Found duplicate local symbols in '%s'", file_sym->name); +- +- lookup_running_file_sym = running_sym; ++ } ++ else { ++ if (found_sym) { ++ ERROR("Found duplicate local symbols in '%s'", g_relf_name); ++ } ++ found_sym = relf_sym; + } + } + +- if (!lookup_running_file_sym) +- ERROR("Cannot find a local symbol in '%s'", file_sym->name); ++ if (!found_sym) { ++ ERROR("Cannot find local symbol in '%s'", g_relf_name); ++ } + +- list_for_each_entry_continue(file_sym, sym_list, list) { +- if (file_sym->type == STT_FILE) ++ list_for_each_entry_continue(file_sym, &uelf->symbols, list) { ++ if (file_sym->type == STT_FILE) { + break; +- file_sym->lookup_running_file_sym = lookup_running_file_sym; ++ } ++ file_sym->relf_sym = found_sym; + } + } + +@@ -453,13 +476,14 @@ static void find_local_syms(struct running_elf *relf, struct symbol *file_sym, + * We then compare local symbol lists from both blocks and store the pointer + * to STT_FILE symbol in running elf for later using. + */ +-static void find_file_symbol(struct upatch_elf *uelf, struct running_elf *relf) ++static void find_debug_symbol(struct upatch_elf *uelf, struct running_elf *relf) + { +- struct symbol *sym; ++ struct symbol *file_sym = NULL; + +- list_for_each_entry(sym, &uelf->symbols, list) { +- if (sym->type == STT_FILE) +- find_local_syms(relf, sym, &uelf->symbols); ++ list_for_each_entry(file_sym, &uelf->symbols, list) { ++ if (file_sym->type == STT_FILE) { ++ find_local_syms(uelf, relf, file_sym); ++ } + } + } + +@@ -735,7 +759,7 @@ static int include_changed_functions(struct upatch_elf *uelf) + if (sym->status == CHANGED && + sym->type == STT_SECTION && + sym->sec && is_except_section(sym->sec)) { +- log_warn("Exeception section '%s' is changed\n", sym->sec->name); ++ log_warn("Exception section '%s' is changed\n", sym->sec->name); + changed_nr++; + include_symbol(sym); + } +@@ -886,15 +910,16 @@ int main(int argc, char*argv[]) + argp_parse(&argp, argc, argv, 0, NULL, &arguments); + + if (arguments.debug) +- loglevel = DEBUG; +- logprefix = basename(arguments.source_obj); ++ g_loglevel = DEBUG; ++ g_logprefix = basename(arguments.source_obj); + show_program_info(&arguments); + + if (elf_version(EV_CURRENT) == EV_NONE) + ERROR("ELF library initialization failed"); + + /* TODO: with debug info, this may changed */ +- upatch_elf_name = arguments.running_elf; ++ g_uelf_name = arguments.source_obj; ++ g_relf_name = arguments.running_elf; + + /* check error in log, since errno may be from libelf */ + upatch_elf_open(&uelf_source, arguments.source_obj); +@@ -912,7 +937,7 @@ int main(int argc, char*argv[]) + detect_child_functions(&uelf_source); + detect_child_functions(&uelf_patched); + +- find_file_symbol(&uelf_source, &relf); ++ find_debug_symbol(&uelf_source, &relf); + + mark_grouped_sections(&uelf_patched); + +diff --git a/upatch-diff/elf-compare.c b/upatch-diff/elf-compare.c +index 054f16a..9b857b1 100644 +--- a/upatch-diff/elf-compare.c ++++ b/upatch-diff/elf-compare.c +@@ -177,7 +177,7 @@ bool upatch_handle_redis_line(const char *symname) + /* TODO: let user support this list or generate by the compiler ? */ + bool check_line_func(struct upatch_elf *uelf, const char *symname) + { +- if (!strncmp(basename(upatch_elf_name), "redis-server", 12)) ++ if (!strncmp(basename(g_relf_name), "redis-server", 12)) + return upatch_handle_redis_line(symname); + + return false; +diff --git a/upatch-diff/elf-correlate.c b/upatch-diff/elf-correlate.c +index f25f252..a0fe669 100644 +--- a/upatch-diff/elf-correlate.c ++++ b/upatch-diff/elf-correlate.c +@@ -40,8 +40,8 @@ static void correlate_symbol(struct symbol *sym_orig, struct symbol *sym_patched + if (!sym_patched->name) + ERROR("strdup"); + } +- if (sym_orig->lookup_running_file_sym && !sym_patched->lookup_running_file_sym) +- sym_patched->lookup_running_file_sym = sym_orig->lookup_running_file_sym; ++ if (sym_orig->relf_sym && !sym_patched->relf_sym) ++ sym_patched->relf_sym = sym_orig->relf_sym; + } + + void upatch_correlate_symbols(struct upatch_elf *uelf_source, struct upatch_elf *uelf_patched) +diff --git a/upatch-diff/log.h b/upatch-diff/log.h +index 5af3e34..34b58bf 100644 +--- a/upatch-diff/log.h ++++ b/upatch-diff/log.h +@@ -28,9 +28,9 @@ + #include + #include + +-/* Files that include log.h must define loglevel and logprefix */ +-extern enum loglevel loglevel; +-extern char *logprefix; ++/* Files that include log.h must define g_loglevel and g_logprefix */ ++extern enum LogLevel g_loglevel; ++extern char *g_logprefix; + + enum exit_status{ + EXIT_STATUS_SUCCESS = 0, +@@ -41,19 +41,19 @@ enum exit_status{ + + /* Since upatch-build is an one-shot program, we do not care about failure handler */ + #define ERROR(format, ...) \ +- error(EXIT_STATUS_ERROR, 0, "ERROR: %s: %s: %d: " format, logprefix, __FUNCTION__, __LINE__, ##__VA_ARGS__) ++ error(EXIT_STATUS_ERROR, 0, "ERROR: %s: %s: %d: " format, g_logprefix, __FUNCTION__, __LINE__, ##__VA_ARGS__) + + #define DIFF_FATAL(format, ...) \ +- error(EXIT_STATUS_DIFF_FATAL, 0, "ERROR: %s: %s: %d: " format, logprefix, __FUNCTION__, __LINE__, ##__VA_ARGS__) ++ error(EXIT_STATUS_DIFF_FATAL, 0, "ERROR: %s: %s: %d: " format, g_logprefix, __FUNCTION__, __LINE__, ##__VA_ARGS__) + + /* it is time cost */ + #define log_debug(format, ...) log(DEBUG, format, ##__VA_ARGS__) +-#define log_normal(format, ...) log(NORMAL, "%s: " format, logprefix, ##__VA_ARGS__) +-#define log_warn(format, ...) log(WARN, "%s: " format, logprefix, ##__VA_ARGS__) ++#define log_normal(format, ...) log(NORMAL, "%s: " format, g_logprefix, ##__VA_ARGS__) ++#define log_warn(format, ...) log(WARN, "%s: " format, g_logprefix, ##__VA_ARGS__) + + #define log(level, format, ...) \ + ({ \ +- if (loglevel <= (level)) \ ++ if (g_loglevel <= (level)) \ + printf(format, ##__VA_ARGS__); \ + }) + +@@ -63,7 +63,7 @@ enum exit_status{ + ERROR(message); \ + while (0) + +-enum loglevel { ++enum LogLevel { + DEBUG, + NORMAL, + WARN, +diff --git a/upatch-diff/running-elf.c b/upatch-diff/running-elf.c +index e190691..037f5fc 100644 +--- a/upatch-diff/running-elf.c ++++ b/upatch-diff/running-elf.c +@@ -84,7 +84,7 @@ void relf_init(char *elf_name, struct running_elf *relf) + ERROR("elf_getdata with error %s", elf_errmsg(0)); + + relf->obj_nr = shdr.sh_size / shdr.sh_entsize; +- relf->obj_syms = calloc(relf->obj_nr, sizeof(struct object_symbol)); ++ relf->obj_syms = calloc(relf->obj_nr, sizeof(struct debug_symbol)); + if (!relf->obj_syms) + ERROR("calloc with errno = %d", errno); + +@@ -117,7 +117,7 @@ bool lookup_relf(struct running_elf *relf, struct symbol *lookup_sym, + struct lookup_result *result) + { + int i; +- struct object_symbol *sym; ++ struct debug_symbol *sym; + unsigned long sympos = 0; + bool in_file = false; + +@@ -128,7 +128,7 @@ bool lookup_relf(struct running_elf *relf, struct symbol *lookup_sym, + if (sym->bind == STB_LOCAL && !strcmp(sym->name, lookup_sym->name)) + sympos ++; + +- if (lookup_sym->lookup_running_file_sym == sym) { ++ if (lookup_sym->relf_sym == sym) { + in_file = true; + continue; + } +diff --git a/upatch-diff/running-elf.h b/upatch-diff/running-elf.h +index 0eb5c70..0646780 100644 +--- a/upatch-diff/running-elf.h ++++ b/upatch-diff/running-elf.h +@@ -35,12 +35,12 @@ + struct symbol; + + struct lookup_result { +- struct object_symbol *symbol; ++ struct debug_symbol *symbol; + unsigned long sympos; + bool global; + }; + +-struct object_symbol { ++struct debug_symbol { + char *name; + unsigned char type, bind; + unsigned int shndx; +@@ -50,7 +50,7 @@ struct object_symbol { + + struct running_elf { + int obj_nr; +- struct object_symbol *obj_syms; ++ struct debug_symbol *obj_syms; + int fd; + Elf *elf; + bool is_exec; +diff --git a/upatch-diff/upatch-elf.c b/upatch-diff/upatch-elf.c +index e39fb6a..fc4396a 100644 +--- a/upatch-diff/upatch-elf.c ++++ b/upatch-diff/upatch-elf.c +@@ -206,7 +206,7 @@ static void create_rela_list(struct upatch_elf *uelf, struct section *relasec) + if (skip) + continue; + +- log_debug("offset %d, type %d, %s %s %ld \n", rela->offset, ++ log_debug("offset %d, type %d, %s %s %ld", rela->offset, + rela->type, rela->sym->name, + (rela->addend < 0) ? "-" : "+", labs(rela->addend)); + if (rela->string) // rela->string is not utf8 +diff --git a/upatch-diff/upatch-elf.h b/upatch-diff/upatch-elf.h +index 2f7c777..b2d038b 100644 +--- a/upatch-diff/upatch-elf.h ++++ b/upatch-diff/upatch-elf.h +@@ -32,7 +32,7 @@ + #include "list.h" + #include "running-elf.h" + +-extern char *upatch_elf_name; ++extern char *g_relf_name; + + // these data structs contain each other + struct section; +@@ -102,7 +102,7 @@ struct symbol { + struct section *sec; + GElf_Sym sym; + char *name; +- struct object_symbol *lookup_running_file_sym; ++ struct debug_symbol *relf_sym; + unsigned int index; + unsigned char bind; + unsigned char type; +-- +2.34.1 + diff --git a/0016-security-change-directory-permission.patch b/0016-security-change-directory-permission.patch new file mode 100644 index 0000000000000000000000000000000000000000..a651dd03f4bc8165df058c4b663eb40e975a8b8e --- /dev/null +++ b/0016-security-change-directory-permission.patch @@ -0,0 +1,99 @@ +From 4626c401b541c46debd18e1a326a323f4f85f69d Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Sat, 11 May 2024 08:28:48 +0800 +Subject: [PATCH] security: change directory permission + +1. config_dir /etc/syscare drwx------. +2. data_dir /usr/lib/syscare drwx------. +3. log_dir /var/log/syscare drwx------. +4. work_dir /var/run/syscare drwxr-xr-x. + +Signed-off-by: renoseven +--- + syscared/src/main.rs | 9 +++++++-- + upatchd/src/args.rs | 2 +- + upatchd/src/main.rs | 13 +++++++++---- + 3 files changed, 17 insertions(+), 7 deletions(-) + +diff --git a/syscared/src/main.rs b/syscared/src/main.rs +index 74bd488..22f01df 100644 +--- a/syscared/src/main.rs ++++ b/syscared/src/main.rs +@@ -47,7 +47,9 @@ const DAEMON_VERSION: &str = env!("CARGO_PKG_VERSION"); + const DAEMON_ABOUT: &str = env!("CARGO_PKG_DESCRIPTION"); + const DAEMON_UMASK: u32 = 0o077; + +-const WORK_DIR_PERMISSION: u32 = 0o755; ++const DATA_DIR_PERM: u32 = 0o700; ++const WORK_DIR_PERM: u32 = 0o755; ++const LOG_DIR_PERM: u32 = 0o700; + const PID_FILE_NAME: &str = "syscared.pid"; + const SOCKET_FILE_NAME: &str = "syscared.sock"; + +@@ -102,7 +104,10 @@ impl SyscareDaemon { + fs::create_dir_all(&args.data_dir)?; + fs::create_dir_all(&args.work_dir)?; + fs::create_dir_all(&args.log_dir)?; +- fs::set_permissions(&args.work_dir, Permissions::from_mode(WORK_DIR_PERMISSION))?; ++ fs::set_permissions(&args.data_dir, Permissions::from_mode(DATA_DIR_PERM))?; ++ fs::set_permissions(&args.work_dir, Permissions::from_mode(WORK_DIR_PERM))?; ++ fs::set_permissions(&args.log_dir, Permissions::from_mode(LOG_DIR_PERM))?; ++ + std::env::set_current_dir(&args.work_dir).with_context(|| { + format!( + "Failed to change current directory to {}", +diff --git a/upatchd/src/args.rs b/upatchd/src/args.rs +index 9311047..0b9029b 100644 +--- a/upatchd/src/args.rs ++++ b/upatchd/src/args.rs +@@ -22,8 +22,8 @@ use syscare_common::fs; + + use super::{DAEMON_ABOUT, DAEMON_NAME, DAEMON_VERSION}; + +-const DEFAULT_WORK_DIR: &str = "/var/run/syscare"; + const DEFAULT_CONFIG_DIR: &str = "/etc/syscare"; ++const DEFAULT_WORK_DIR: &str = "/var/run/syscare"; + const DEFAULT_LOG_DIR: &str = "/var/log/syscare"; + const DEFAULT_LOG_LEVEL: &str = "info"; + +diff --git a/upatchd/src/main.rs b/upatchd/src/main.rs +index 86e2052..1007ebb 100644 +--- a/upatchd/src/main.rs ++++ b/upatchd/src/main.rs +@@ -43,8 +43,10 @@ const CONFIG_FILE_NAME: &str = "upatchd.yaml"; + const PID_FILE_NAME: &str = "upatchd.pid"; + const SOCKET_FILE_NAME: &str = "upatchd.sock"; + +-const WORK_DIR_PERMISSION: u32 = 0o755; +-const SOCKET_FILE_PERMISSION: u32 = 0o666; ++const CONFIG_DIR_PERM: u32 = 0o700; ++const WORK_DIR_PERM: u32 = 0o755; ++const LOG_DIR_PERM: u32 = 0o700; ++const SOCKET_FILE_PERM: u32 = 0o666; + + const MAIN_THREAD_NAME: &str = "main"; + const UNNAMED_THREAD_NAME: &str = ""; +@@ -97,7 +99,10 @@ impl UpatchDaemon { + fs::create_dir_all(&args.config_dir)?; + fs::create_dir_all(&args.work_dir)?; + fs::create_dir_all(&args.log_dir)?; +- fs::set_permissions(&args.work_dir, Permissions::from_mode(WORK_DIR_PERMISSION))?; ++ fs::set_permissions(&args.config_dir, Permissions::from_mode(CONFIG_DIR_PERM))?; ++ fs::set_permissions(&args.work_dir, Permissions::from_mode(WORK_DIR_PERM))?; ++ fs::set_permissions(&args.log_dir, Permissions::from_mode(LOG_DIR_PERM))?; ++ + std::env::set_current_dir(&args.work_dir).with_context(|| { + format!( + "Failed to change current directory to {}", +@@ -168,7 +173,7 @@ impl UpatchDaemon { + .context("Failed to convert socket path to string")?, + )?; + +- fs::set_permissions(&socket_file, Permissions::from_mode(SOCKET_FILE_PERMISSION))?; ++ fs::set_permissions(&socket_file, Permissions::from_mode(SOCKET_FILE_PERM))?; + + Ok(server) + } +-- +2.34.1 + diff --git a/0017-security-change-daemon-socket-permission.patch b/0017-security-change-daemon-socket-permission.patch new file mode 100644 index 0000000000000000000000000000000000000000..3cda7987e864ba596cfaa08f69b9e979817de0c5 --- /dev/null +++ b/0017-security-change-daemon-socket-permission.patch @@ -0,0 +1,826 @@ +From bb21560c6ab6217c06533ea85dd7db5a40379e5b Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Sat, 11 May 2024 10:21:58 +0800 +Subject: [PATCH] security: change daemon socket permission + +1. add socket uid & gid to config file + default uid: 0 + default gid: 0 + +2. set socket permission by its uid & gid + uid == gid: 0600 + uid != gid: 0660 + +Signed-off-by: renoseven +--- + Cargo.lock | 2 + + syscared/Cargo.toml | 1 + + syscared/src/args.rs | 8 ++- + syscared/src/config.rs | 88 ++++++++++++++++++++++++++++++ + syscared/src/main.rs | 70 ++++++++++++++++++------ + upatchd/Cargo.toml | 2 +- + upatchd/src/config.rs | 91 ++++++++++++++++++++++++++++++++ + upatchd/src/hijacker/config.rs | 85 +++++------------------------ + upatchd/src/hijacker/mod.rs | 47 +++-------------- + upatchd/src/main.rs | 55 ++++++++++++++----- + upatchd/src/rpc/skeleton_impl.rs | 8 +-- + 11 files changed, 310 insertions(+), 147 deletions(-) + create mode 100644 syscared/src/config.rs + create mode 100644 upatchd/src/config.rs + +diff --git a/Cargo.lock b/Cargo.lock +index 1d13df6..3e920ab 100644 +--- a/Cargo.lock ++++ b/Cargo.lock +@@ -511,6 +511,7 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" + dependencies = [ + "autocfg", + "hashbrown", ++ "serde", + ] + + [[package]] +@@ -1184,6 +1185,7 @@ dependencies = [ + "object", + "parking_lot", + "serde", ++ "serde_yaml", + "signal-hook", + "syscare-abi", + "syscare-common", +diff --git a/syscared/Cargo.toml b/syscared/Cargo.toml +index 2b148e7..27f27e2 100644 +--- a/syscared/Cargo.toml ++++ b/syscared/Cargo.toml +@@ -26,5 +26,6 @@ nix = { version = "0.26" } + object = { version = "0.29" } + parking_lot = { version = "0.11" } + serde = { version = "1.0", features = ["derive"] } ++serde_yaml = { version = "0.8" } + signal-hook = { version = "0.3" } + uuid = { version = "0.8", features = ["v4", "serde"] } +diff --git a/syscared/src/args.rs b/syscared/src/args.rs +index 71cdf95..4c28dff 100644 +--- a/syscared/src/args.rs ++++ b/syscared/src/args.rs +@@ -22,6 +22,7 @@ use syscare_common::fs; + + use super::{DAEMON_ABOUT, DAEMON_NAME, DAEMON_VERSION}; + ++const DEFAULT_CONFIG_DIR: &str = "/etc/syscare"; + const DEFAULT_DATA_ROOT: &str = "/usr/lib/syscare"; + const DEFAULT_WORK_DIR: &str = "/var/run/syscare"; + const DEFAULT_LOG_DIR: &str = "/var/log/syscare"; +@@ -42,6 +43,10 @@ pub struct Arguments { + #[clap(short, long)] + pub daemon: bool, + ++ /// Daemon config directory ++ #[clap(long, default_value=DEFAULT_CONFIG_DIR)] ++ pub config_dir: PathBuf, ++ + /// Daemon data directory + #[clap(long, default_value = DEFAULT_DATA_ROOT)] + pub data_dir: PathBuf, +@@ -65,8 +70,9 @@ impl Arguments { + } + + fn normalize_path(mut self) -> Result { +- self.work_dir = fs::normalize(&self.work_dir)?; ++ self.config_dir = fs::normalize(&self.config_dir)?; + self.data_dir = fs::normalize(&self.data_dir)?; ++ self.work_dir = fs::normalize(&self.work_dir)?; + self.log_dir = fs::normalize(&self.log_dir)?; + + Ok(self) +diff --git a/syscared/src/config.rs b/syscared/src/config.rs +new file mode 100644 +index 0000000..af98a51 +--- /dev/null ++++ b/syscared/src/config.rs +@@ -0,0 +1,88 @@ ++// SPDX-License-Identifier: Mulan PSL v2 ++/* ++ * Copyright (c) 2024 Huawei Technologies Co., Ltd. ++ * upatchd is licensed under Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, ++ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, ++ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++ ++use std::path::Path; ++ ++use anyhow::{anyhow, Result}; ++use serde::{Deserialize, Serialize}; ++use syscare_common::fs; ++ ++const DEFAULT_SOCKET_UID: u32 = 0; ++const DEFAULT_SOCKET_GID: u32 = 0; ++ ++#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] ++pub struct SocketConfig { ++ pub uid: u32, ++ pub gid: u32, ++} ++ ++impl Default for SocketConfig { ++ fn default() -> Self { ++ Self { ++ uid: DEFAULT_SOCKET_UID, ++ gid: DEFAULT_SOCKET_GID, ++ } ++ } ++} ++ ++#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] ++pub struct DaemonConfig { ++ pub socket: SocketConfig, ++} ++ ++#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] ++pub struct Config { ++ pub daemon: DaemonConfig, ++} ++ ++impl Config { ++ pub fn parse>(path: P) -> Result { ++ let config_path = path.as_ref(); ++ let instance = serde_yaml::from_reader(fs::open_file(config_path)?) ++ .map_err(|_| anyhow!("Failed to parse config {}", config_path.display()))?; ++ ++ Ok(instance) ++ } ++ ++ pub fn write>(&self, path: P) -> Result<()> { ++ let config_path = path.as_ref(); ++ let config_file = fs::create_file(config_path)?; ++ serde_yaml::to_writer(config_file, self) ++ .map_err(|_| anyhow!("Failed to write config {}", config_path.display()))?; ++ ++ Ok(()) ++ } ++} ++ ++#[test] ++fn test() -> Result<()> { ++ use anyhow::{ensure, Context}; ++ use std::path::PathBuf; ++ ++ let tmp_file = PathBuf::from("/tmp/syscared.yaml"); ++ ++ let orig_cfg = Config::default(); ++ println!("{:#?}", orig_cfg); ++ ++ orig_cfg ++ .write(&tmp_file) ++ .context("Failed to write config")?; ++ ++ let new_cfg = Config::parse(tmp_file).context("Failed to read config")?; ++ println!("{:#?}", new_cfg); ++ ++ ensure!(orig_cfg == new_cfg, "Config does not match"); ++ ++ Ok(()) ++} +diff --git a/syscared/src/main.rs b/syscared/src/main.rs +index 22f01df..b840abf 100644 +--- a/syscared/src/main.rs ++++ b/syscared/src/main.rs +@@ -22,7 +22,8 @@ use flexi_logger::{ + }; + use jsonrpc_core::IoHandler; + use jsonrpc_ipc_server::{Server, ServerBuilder}; +-use log::{error, info, LevelFilter, Record}; ++use log::{debug, error, info, warn, LevelFilter, Record}; ++use nix::unistd::{chown, Gid, Uid}; + use parking_lot::RwLock; + use patch::manager::PatchManager; + use signal_hook::{consts::TERM_SIGNALS, iterator::Signals, low_level::signal_name}; +@@ -30,38 +31,45 @@ use signal_hook::{consts::TERM_SIGNALS, iterator::Signals, low_level::signal_nam + use syscare_common::{fs, os}; + + mod args; ++mod config; + mod fast_reboot; + mod patch; + mod rpc; + + use args::Arguments; ++use config::Config; ++use patch::monitor::PatchMonitor; + use rpc::{ + skeleton::{FastRebootSkeleton, PatchSkeleton}, + skeleton_impl::{FastRebootSkeletonImpl, PatchSkeletonImpl}, + }; + +-use crate::patch::monitor::PatchMonitor; +- + const DAEMON_NAME: &str = env!("CARGO_PKG_NAME"); + const DAEMON_VERSION: &str = env!("CARGO_PKG_VERSION"); + const DAEMON_ABOUT: &str = env!("CARGO_PKG_DESCRIPTION"); + const DAEMON_UMASK: u32 = 0o077; + ++const CONFIG_FILE_NAME: &str = "syscared.yaml"; ++const PID_FILE_NAME: &str = "syscared.pid"; ++const SOCKET_FILE_NAME: &str = "syscared.sock"; ++ ++const CONFIG_DIR_PERM: u32 = 0o700; + const DATA_DIR_PERM: u32 = 0o700; + const WORK_DIR_PERM: u32 = 0o755; + const LOG_DIR_PERM: u32 = 0o700; +-const PID_FILE_NAME: &str = "syscared.pid"; +-const SOCKET_FILE_NAME: &str = "syscared.sock"; ++const SOCKET_FILE_PERM: u32 = 0o660; ++const SOCKET_FILE_PERM_STRICT: u32 = 0o600; + + const MAIN_THREAD_NAME: &str = "main"; + const UNNAMED_THREAD_NAME: &str = ""; + const LOG_FORMAT: &str = "%Y-%m-%d %H:%M:%S%.6f"; + +-struct SyscareDaemon { ++struct Daemon { + args: Arguments, ++ config: Config, + } + +-impl SyscareDaemon { ++impl Daemon { + fn format_log( + w: &mut dyn std::io::Write, + now: &mut DeferredNow, +@@ -101,9 +109,11 @@ impl SyscareDaemon { + os::umask::set_umask(DAEMON_UMASK); + + let args = Arguments::new()?; ++ fs::create_dir_all(&args.config_dir)?; + fs::create_dir_all(&args.data_dir)?; + fs::create_dir_all(&args.work_dir)?; + fs::create_dir_all(&args.log_dir)?; ++ fs::set_permissions(&args.config_dir, Permissions::from_mode(CONFIG_DIR_PERM))?; + fs::set_permissions(&args.data_dir, Permissions::from_mode(DATA_DIR_PERM))?; + fs::set_permissions(&args.work_dir, Permissions::from_mode(WORK_DIR_PERM))?; + fs::set_permissions(&args.log_dir, Permissions::from_mode(LOG_DIR_PERM))?; +@@ -138,14 +148,29 @@ impl SyscareDaemon { + .start() + .context("Failed to initialize logger")?; + ++ // Initialize config ++ debug!("Initializing configuation..."); ++ let config_file = args.config_dir.join(CONFIG_FILE_NAME); ++ let config = match Config::parse(&config_file) { ++ Ok(config) => config, ++ Err(e) => { ++ warn!("{:?}", e); ++ info!("Using default configuration..."); ++ let config = Config::default(); ++ config.write(&config_file)?; ++ ++ config ++ } ++ }; ++ + // Print panic to log incase it really happens + panic::set_hook(Box::new(|info| error!("{}", info))); + +- Ok(Self { args }) ++ Ok(Self { args, config }) + } + } + +-impl SyscareDaemon { ++impl Daemon { + fn daemonize(&self) -> Result<()> { + if !self.args.daemon { + return Ok(()); +@@ -171,13 +196,24 @@ impl SyscareDaemon { + + fn start_rpc_server(&self, io_handler: IoHandler) -> Result { + let socket_file = self.args.work_dir.join(SOCKET_FILE_NAME); +- let server = ServerBuilder::new(io_handler) +- .set_client_buffer_size(1) +- .start( +- socket_file +- .to_str() +- .context("Failed to convert socket path to string")?, +- )?; ++ let builder = ServerBuilder::new(io_handler).set_client_buffer_size(1); ++ let server = builder.start( ++ socket_file ++ .to_str() ++ .context("Failed to convert socket path to string")?, ++ )?; ++ ++ let socket_owner = Uid::from_raw(self.config.daemon.socket.uid); ++ let socket_group = Gid::from_raw(self.config.daemon.socket.gid); ++ chown(&socket_file, Some(socket_owner), Some(socket_group))?; ++ ++ fs::set_permissions( ++ &socket_file, ++ match socket_owner.as_raw() == socket_group.as_raw() { ++ true => Permissions::from_mode(SOCKET_FILE_PERM_STRICT), ++ false => Permissions::from_mode(SOCKET_FILE_PERM), ++ }, ++ )?; + + Ok(server) + } +@@ -227,7 +263,7 @@ impl SyscareDaemon { + } + + fn main() { +- let daemon = match SyscareDaemon::new() { ++ let daemon = match Daemon::new() { + Ok(instance) => instance, + Err(e) => { + eprintln!("Error: {:?}", e); +diff --git a/upatchd/Cargo.toml b/upatchd/Cargo.toml +index dd9f5ca..fea0859 100644 +--- a/upatchd/Cargo.toml ++++ b/upatchd/Cargo.toml +@@ -14,7 +14,7 @@ anyhow = { version = "1.0" } + clap = { version = "3.2", features = ["cargo", "derive"] } + daemonize = { version = "0.5" } + flexi_logger = { version = "0.24", features = ["compress"] } +-indexmap = { version = "1.9" } ++indexmap = { version = "1.9", features = ["serde"] } + jsonrpc-core = { version = "18.0" } + jsonrpc-derive = { version = "18.0" } + jsonrpc-ipc-server = { version = "18.0" } +diff --git a/upatchd/src/config.rs b/upatchd/src/config.rs +new file mode 100644 +index 0000000..125770d +--- /dev/null ++++ b/upatchd/src/config.rs +@@ -0,0 +1,91 @@ ++// SPDX-License-Identifier: Mulan PSL v2 ++/* ++ * Copyright (c) 2024 Huawei Technologies Co., Ltd. ++ * upatchd is licensed under Mulan PSL v2. ++ * You can use this software according to the terms and conditions of the Mulan PSL v2. ++ * You may obtain a copy of Mulan PSL v2 at: ++ * http://license.coscl.org.cn/MulanPSL2 ++ * ++ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, ++ * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, ++ * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. ++ * See the Mulan PSL v2 for more details. ++ */ ++ ++use std::path::Path; ++ ++use anyhow::{anyhow, Result}; ++use serde::{Deserialize, Serialize}; ++use syscare_common::fs; ++ ++use crate::hijacker::HijackerConfig; ++ ++const DEFAULT_SOCKET_UID: u32 = 0; ++const DEFAULT_SOCKET_GID: u32 = 0; ++ ++#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] ++pub struct SocketConfig { ++ pub uid: u32, ++ pub gid: u32, ++} ++ ++impl Default for SocketConfig { ++ fn default() -> Self { ++ Self { ++ uid: DEFAULT_SOCKET_UID, ++ gid: DEFAULT_SOCKET_GID, ++ } ++ } ++} ++ ++#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] ++pub struct DaemonConfig { ++ pub socket: SocketConfig, ++} ++ ++#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] ++pub struct Config { ++ pub daemon: DaemonConfig, ++ pub hijacker: HijackerConfig, ++} ++ ++impl Config { ++ pub fn parse>(path: P) -> Result { ++ let config_path = path.as_ref(); ++ let instance = serde_yaml::from_reader(fs::open_file(config_path)?) ++ .map_err(|_| anyhow!("Failed to parse config {}", config_path.display()))?; ++ ++ Ok(instance) ++ } ++ ++ pub fn write>(&self, path: P) -> Result<()> { ++ let config_path = path.as_ref(); ++ let config_file = fs::create_file(config_path)?; ++ serde_yaml::to_writer(config_file, self) ++ .map_err(|_| anyhow!("Failed to write config {}", config_path.display()))?; ++ ++ Ok(()) ++ } ++} ++ ++#[test] ++fn test() -> Result<()> { ++ use anyhow::{ensure, Context}; ++ use std::path::PathBuf; ++ ++ let tmp_file = PathBuf::from("/tmp/upatchd.yaml"); ++ ++ let orig_cfg = Config::default(); ++ println!("{:#?}", orig_cfg); ++ ++ orig_cfg ++ .write(&tmp_file) ++ .context("Failed to write config")?; ++ ++ let new_cfg = Config::parse(tmp_file).context("Failed to read config")?; ++ println!("{:#?}", new_cfg); ++ ++ ensure!(orig_cfg == new_cfg, "Config does not match"); ++ ++ Ok(()) ++} +diff --git a/upatchd/src/hijacker/config.rs b/upatchd/src/hijacker/config.rs +index f96cc05..5f97fb1 100644 +--- a/upatchd/src/hijacker/config.rs ++++ b/upatchd/src/hijacker/config.rs +@@ -12,15 +12,10 @@ + * See the Mulan PSL v2 for more details. + */ + +-use std::{ +- collections::HashMap, +- ops::Deref, +- path::{Path, PathBuf}, +-}; ++use std::path::PathBuf; + +-use anyhow::{anyhow, Result}; ++use indexmap::{indexmap, IndexMap}; + use serde::{Deserialize, Serialize}; +-use syscare_common::fs; + + const CC_BINARY: &str = "/usr/bin/cc"; + const CXX_BINARY: &str = "/usr/bin/c++"; +@@ -34,73 +29,21 @@ const GCC_HIJACKER: &str = "/usr/libexec/syscare/gcc-hijacker"; + const GXX_HIJACKER: &str = "/usr/libexec/syscare/g++-hijacker"; + const AS_HIJACKER: &str = "/usr/libexec/syscare/as-hijacker"; + +-#[derive(Debug, PartialEq, Eq, Serialize, Deserialize)] +-pub struct HijackerConfig(HashMap); +- +-impl HijackerConfig { +- pub fn parse_from>(path: P) -> Result { +- let config_path = path.as_ref(); +- let config_file = fs::open_file(config_path)?; +- let instance: Self = serde_yaml::from_reader(config_file) +- .map_err(|_| anyhow!("Failed to parse config {}", config_path.display()))?; +- +- Ok(instance) +- } +- +- pub fn write_to>(&self, path: P) -> Result<()> { +- let config_path = path.as_ref(); +- let config_file = fs::create_file(config_path)?; +- serde_yaml::to_writer(config_file, self) +- .map_err(|_| anyhow!("Failed to write config {}", config_path.display()))?; +- +- Ok(()) +- } +-} +- +-impl Deref for HijackerConfig { +- type Target = HashMap; +- +- fn deref(&self) -> &Self::Target { +- &self.0 +- } ++#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] ++pub struct HijackerConfig { ++ pub mapping: IndexMap, + } + + impl Default for HijackerConfig { + fn default() -> Self { +- let mut map = HashMap::new(); +- map.insert(PathBuf::from(CC_BINARY), PathBuf::from(CC_HIJACKER)); +- map.insert(PathBuf::from(CXX_BINARY), PathBuf::from(CXX_HIJACKER)); +- map.insert(PathBuf::from(GCC_BINARY), PathBuf::from(GCC_HIJACKER)); +- map.insert(PathBuf::from(GXX_BINARY), PathBuf::from(GXX_HIJACKER)); +- map.insert(PathBuf::from(AS_BINARY), PathBuf::from(AS_HIJACKER)); +- +- Self(map) ++ Self { ++ mapping: indexmap! { ++ PathBuf::from(CC_BINARY) => PathBuf::from(CC_HIJACKER), ++ PathBuf::from(CXX_BINARY) => PathBuf::from(CXX_HIJACKER), ++ PathBuf::from(GCC_BINARY) => PathBuf::from(GCC_HIJACKER), ++ PathBuf::from(GXX_BINARY) => PathBuf::from(GXX_HIJACKER), ++ PathBuf::from(AS_BINARY) => PathBuf::from(AS_HIJACKER), ++ }, ++ } + } + } +- +-impl std::fmt::Display for HijackerConfig { +- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +- f.write_fmt(format_args!("{:#?}", &self.0)) +- } +-} +- +-#[test] +-fn test() -> Result<()> { +- use anyhow::{ensure, Context}; +- +- let tmp_file = PathBuf::from("/tmp/upatch_hijacker_config.yaml"); +- +- let orig_cfg = HijackerConfig::default(); +- println!("{}", orig_cfg); +- +- orig_cfg +- .write_to(&tmp_file) +- .context("Failed to write config")?; +- +- let new_cfg = HijackerConfig::parse_from(tmp_file).context("Failed to read config")?; +- println!("{}", new_cfg); +- +- ensure!(orig_cfg == new_cfg, "Config does not match"); +- +- Ok(()) +-} +diff --git a/upatchd/src/hijacker/mod.rs b/upatchd/src/hijacker/mod.rs +index 8ac12e7..d0f2c4d 100644 +--- a/upatchd/src/hijacker/mod.rs ++++ b/upatchd/src/hijacker/mod.rs +@@ -12,7 +12,6 @@ + * See the Mulan PSL v2 for more details. + */ + +-use std::os::unix::prelude::MetadataExt; + use std::path::{Path, PathBuf}; + + use anyhow::{bail, Context, Result}; +@@ -25,14 +24,14 @@ mod elf_resolver; + mod ioctl; + mod kmod; + +-use config::HijackerConfig; ++pub use config::HijackerConfig; + use elf_resolver::ElfResolver; + use ioctl::HijackerIoctl; + use kmod::HijackerKmodGuard; + + const KMOD_NAME: &str = "upatch_hijacker"; + const KMOD_DEV_PATH: &str = "/dev/upatch-hijacker"; +-const KMOD_FILE_PATH: &str = "/usr/libexec/syscare/upatch_hijacker.ko"; ++const KMOD_PATH: &str = "/usr/libexec/syscare/upatch_hijacker.ko"; + + const HIJACK_SYMBOL_NAME: &str = "execve"; + +@@ -43,36 +42,6 @@ pub struct Hijacker { + } + + impl Hijacker { +- fn initialize_config>(config_path: P) -> Result { +- const MODE_EXEC_MASK: u32 = 0o111; +- +- let config = match config_path.as_ref().exists() { +- true => HijackerConfig::parse_from(config_path)?, +- false => { +- info!("Generating default configuration..."); +- let config = HijackerConfig::default(); +- config.write_to(config_path)?; +- +- config +- } +- }; +- +- for hijacker in config.values() { +- let is_executable_file = hijacker +- .symlink_metadata() +- .map(|m| m.is_file() && (m.mode() & MODE_EXEC_MASK != 0)) +- .with_context(|| format!("Failed to read {} metadata", hijacker.display()))?; +- if !is_executable_file { +- bail!( +- "Hijack program {} is not an executable file", +- hijacker.display() +- ); +- } +- } +- +- Ok(config) +- } +- + fn find_symbol_addr(symbol_name: &str) -> Result<(PathBuf, u64)> { + let exec_file = MappedFile::open(os::process::path())?; + let exec_resolver = ElfResolver::new(exec_file.as_bytes())?; +@@ -91,14 +60,9 @@ impl Hijacker { + } + + impl Hijacker { +- pub fn new>(config_path: P) -> Result { +- debug!("Initializing hijacker configuation..."); +- let config = Self::initialize_config(config_path) +- .context("Failed to initialize hijacker configuration")?; +- info!("Using elf mapping: {}", config); +- ++ pub fn new(config: HijackerConfig) -> Result { + debug!("Initializing hijacker kernel module..."); +- let kmod = HijackerKmodGuard::new(KMOD_NAME, KMOD_FILE_PATH)?; ++ let kmod = HijackerKmodGuard::new(KMOD_NAME, KMOD_PATH)?; + + debug!("Initializing hijacker ioctl channel..."); + let ioctl = HijackerIoctl::new(KMOD_DEV_PATH)?; +@@ -113,9 +77,9 @@ impl Hijacker { + ioctl.enable_hijacker(lib_path, offset)?; + + Ok(Self { ++ config, + _kmod: kmod, + ioctl, +- config, + }) + } + } +@@ -124,6 +88,7 @@ impl Hijacker { + fn get_hijacker>(&self, exec_path: P) -> Result<&Path> { + let hijacker = self + .config ++ .mapping + .get(exec_path.as_ref()) + .with_context(|| format!("Cannot find hijacker for {}", exec_path.as_ref().display()))? + .as_path(); +diff --git a/upatchd/src/main.rs b/upatchd/src/main.rs +index 1007ebb..066e53e 100644 +--- a/upatchd/src/main.rs ++++ b/upatchd/src/main.rs +@@ -22,16 +22,19 @@ use flexi_logger::{ + }; + use jsonrpc_core::IoHandler; + use jsonrpc_ipc_server::{Server, ServerBuilder}; +-use log::{error, info, LevelFilter, Record}; ++use log::{debug, error, info, warn, LevelFilter, Record}; ++use nix::unistd::{chown, Gid, Uid}; + use signal_hook::{consts::TERM_SIGNALS, iterator::Signals, low_level::signal_name}; + + use syscare_common::{fs, os}; + + mod args; ++mod config; + mod hijacker; + mod rpc; + + use args::Arguments; ++use config::Config; + use rpc::{Skeleton, SkeletonImpl}; + + const DAEMON_NAME: &str = env!("CARGO_PKG_NAME"); +@@ -46,17 +49,19 @@ const SOCKET_FILE_NAME: &str = "upatchd.sock"; + const CONFIG_DIR_PERM: u32 = 0o700; + const WORK_DIR_PERM: u32 = 0o755; + const LOG_DIR_PERM: u32 = 0o700; +-const SOCKET_FILE_PERM: u32 = 0o666; ++const SOCKET_FILE_PERM: u32 = 0o660; ++const SOCKET_FILE_PERM_STRICT: u32 = 0o600; + + const MAIN_THREAD_NAME: &str = "main"; + const UNNAMED_THREAD_NAME: &str = ""; + const LOG_FORMAT: &str = "%Y-%m-%d %H:%M:%S%.6f"; + +-struct UpatchDaemon { ++struct Daemon { + args: Arguments, ++ config: Config, + } + +-impl UpatchDaemon { ++impl Daemon { + fn format_log( + w: &mut dyn std::io::Write, + now: &mut DeferredNow, +@@ -133,14 +138,28 @@ impl UpatchDaemon { + .start() + .context("Failed to initialize logger")?; + ++ // Initialize config ++ debug!("Initializing configuation..."); ++ let config_file = args.config_dir.join(CONFIG_FILE_NAME); ++ let config = match Config::parse(&config_file) { ++ Ok(config) => config, ++ Err(e) => { ++ warn!("{:?}", e); ++ info!("Using default configuration..."); ++ let config = Config::default(); ++ config.write(&config_file)?; ++ ++ config ++ } ++ }; ++ + // Print panic to log incase it really happens + panic::set_hook(Box::new(|info| error!("{}", info))); +- +- Ok(Self { args }) ++ Ok(Self { args, config }) + } + } + +-impl UpatchDaemon { ++impl Daemon { + fn daemonize(&self) -> Result<()> { + if !self.args.daemon { + return Ok(()); +@@ -156,10 +175,11 @@ impl UpatchDaemon { + } + + fn initialize_skeleton(&self) -> Result { +- let mut io_handler = IoHandler::new(); ++ let config = self.config.hijacker.clone(); ++ let methods = SkeletonImpl::new(config)?.to_delegate(); + +- let config_file = self.args.config_dir.join(CONFIG_FILE_NAME); +- io_handler.extend_with(SkeletonImpl::new(config_file)?.to_delegate()); ++ let mut io_handler = IoHandler::new(); ++ io_handler.extend_with(methods); + + Ok(io_handler) + } +@@ -173,7 +193,17 @@ impl UpatchDaemon { + .context("Failed to convert socket path to string")?, + )?; + +- fs::set_permissions(&socket_file, Permissions::from_mode(SOCKET_FILE_PERM))?; ++ let socket_owner = Uid::from_raw(self.config.daemon.socket.uid); ++ let socket_group = Gid::from_raw(self.config.daemon.socket.gid); ++ chown(&socket_file, Some(socket_owner), Some(socket_group))?; ++ ++ fs::set_permissions( ++ &socket_file, ++ match socket_owner.as_raw() == socket_group.as_raw() { ++ true => Permissions::from_mode(SOCKET_FILE_PERM_STRICT), ++ false => Permissions::from_mode(SOCKET_FILE_PERM), ++ }, ++ )?; + + Ok(server) + } +@@ -183,6 +213,7 @@ impl UpatchDaemon { + info!("Upatch Daemon - {}", DAEMON_VERSION); + info!("================================"); + info!("Start with {:#?}", self.args); ++ info!("Using {:#?}", self.config); + self.daemonize()?; + + info!("Initializing skeleton..."); +@@ -213,7 +244,7 @@ impl UpatchDaemon { + } + + fn main() { +- let daemon = match UpatchDaemon::new() { ++ let daemon = match Daemon::new() { + Ok(instance) => instance, + Err(e) => { + eprintln!("Error: {:?}", e); +diff --git a/upatchd/src/rpc/skeleton_impl.rs b/upatchd/src/rpc/skeleton_impl.rs +index a334120..d725166 100644 +--- a/upatchd/src/rpc/skeleton_impl.rs ++++ b/upatchd/src/rpc/skeleton_impl.rs +@@ -12,12 +12,12 @@ + * See the Mulan PSL v2 for more details. + */ + +-use std::path::{Path, PathBuf}; ++use std::path::PathBuf; + + use anyhow::{Context, Result}; + use log::{debug, info}; + +-use crate::hijacker::Hijacker; ++use crate::hijacker::{Hijacker, HijackerConfig}; + + use super::{ + function::{RpcFunction, RpcResult}, +@@ -29,10 +29,10 @@ pub struct SkeletonImpl { + } + + impl SkeletonImpl { +- pub fn new>(config_path: P) -> Result { ++ pub fn new(config: HijackerConfig) -> Result { + debug!("Initializing hijacker..."); + Ok(Self { +- hijacker: Hijacker::new(config_path).context("Failed to initialize hijacker")?, ++ hijacker: Hijacker::new(config).context("Failed to initialize hijacker")?, + }) + } + } +-- +2.34.1 + diff --git a/0018-upatch-manage-Fixed-the-core-dump-issue-after-applyi.patch b/0018-upatch-manage-Fixed-the-core-dump-issue-after-applyi.patch new file mode 100644 index 0000000000000000000000000000000000000000..434a1b5fb194d5b534ac07bd48a5b52b900d63ad --- /dev/null +++ b/0018-upatch-manage-Fixed-the-core-dump-issue-after-applyi.patch @@ -0,0 +1,132 @@ +From 270b6e91dc659aa52bde54facbc744d35fc67de4 Mon Sep 17 00:00:00 2001 +From: ningyu +Date: Sat, 11 May 2024 08:06:58 +0000 +Subject: [PATCH] upatch-manage: Fixed the core dump issue after applying hot + patches to nginx on x86_64 architecture. + +For non-dynamic library elf, do not place the global variables in the GOT table +--- + upatch-manage/arch/x86_64/resolve.c | 16 ++++++++++++--- + upatch-manage/upatch-elf.c | 32 +++++++++++++++++++++++++++-- + upatch-manage/upatch-elf.h | 5 ++++- + 3 files changed, 47 insertions(+), 6 deletions(-) + +diff --git a/upatch-manage/arch/x86_64/resolve.c b/upatch-manage/arch/x86_64/resolve.c +index 45261dd..5432b20 100644 +--- a/upatch-manage/arch/x86_64/resolve.c ++++ b/upatch-manage/arch/x86_64/resolve.c +@@ -123,10 +123,20 @@ unsigned long insert_got_table(struct upatch_elf *uelf, struct object_file *obj, + goto out; + } + +- elf_addr = setup_got_table(uelf, jmp_addr, tls_addr); ++ if (uelf->relf->info.is_dyn && !uelf->relf->info.is_pie) { ++ elf_addr = setup_got_table(uelf, jmp_addr, tls_addr); ++ ++ log_debug("0x%lx: jmp_addr=0x%lx\n", elf_addr, jmp_addr); ++ ++ } else { ++ /* ++ * For non-dynamic library files, global variables are not placed in the GOT table ++ */ ++ elf_addr = jmp_addr; ++ log_debug("For non-dynamic library: jmp_addr=0x%lx\n", jmp_addr); ++ } + +- log_debug("0x%lx: jmp_addr=0x%lx\n", elf_addr, jmp_addr); + + out: + return elf_addr; +-} +\ No newline at end of file ++} +diff --git a/upatch-manage/upatch-elf.c b/upatch-manage/upatch-elf.c +index 02444eb..c79637d 100644 +--- a/upatch-manage/upatch-elf.c ++++ b/upatch-manage/upatch-elf.c +@@ -132,6 +132,31 @@ int upatch_init(struct upatch_elf *uelf, const char *name) + return 0; + } + ++static bool is_pie_elf(struct running_elf *relf) ++{ ++ GElf_Shdr *shdr = &relf->info.shdrs[relf->index.dynamic]; ++ GElf_Dyn *dyns = (void *)relf->info.hdr + shdr->sh_offset; ++ if (relf->index.dynamic == 0) { ++ return false; ++ } ++ for (Elf64_Xword i = 0; i < shdr->sh_size / sizeof(GElf_Dyn); i++) { ++ log_debug("Syminfo %lx, %lx\n", dyns[i].d_tag, dyns[i].d_un.d_val); ++ if (dyns[i].d_tag == DT_FLAGS_1) { ++ if ((dyns[i].d_un.d_val & DF_1_PIE) != 0) ++ return true; ++ break; ++ } ++ } ++ return false; ++} ++ ++static bool is_dyn_elf(struct running_elf *relf) ++{ ++ GElf_Ehdr *ehdr = relf->info.hdr; ++ ++ return ehdr->e_type == ET_DYN; ++} ++ + int binary_init(struct running_elf *relf, const char *name) + { + int ret = open_elf(&relf->info, name); +@@ -156,7 +181,8 @@ int binary_init(struct running_elf *relf, const char *name) + relf->dynstrtab = (char *)relf->info.hdr + + relf->info.shdrs[relf->info.shdrs[i].sh_link].sh_offset; + } else if (relf->info.shdrs[i].sh_type == SHT_DYNAMIC) { +- /* Currently, we don't utilize it */ ++ log_debug("Found section '%s', idx=%d\n", DYNAMIC_NAME, i); ++ relf->index.dynamic = i; + } else if (streql(sec_name, PLT_RELA_NAME) && + relf->info.shdrs[i].sh_type == SHT_RELA) { + log_debug("Found section '%s', idx=%d\n", PLT_RELA_NAME, i); +@@ -177,7 +203,9 @@ int binary_init(struct running_elf *relf, const char *name) + break; + } + } +- ++ ++ relf->info.is_pie = is_pie_elf(relf); ++ relf->info.is_dyn = is_dyn_elf(relf); + return 0; + } + +diff --git a/upatch-manage/upatch-elf.h b/upatch-manage/upatch-elf.h +index fe68b7e..481fec9 100644 +--- a/upatch-manage/upatch-elf.h ++++ b/upatch-manage/upatch-elf.h +@@ -30,6 +30,7 @@ + + #define SYMTAB_NAME ".symtab" + #define DYNSYM_NAME ".dynsym" ++#define DYNAMIC_NAME ".dynamic" + #define GOT_RELA_NAME ".rela.dyn" + #define PLT_RELA_NAME ".rela.plt" + #define BUILD_ID_NAME ".note.gnu.build-id" +@@ -95,6 +96,8 @@ struct elf_info { + char *shstrtab; + + unsigned int num_build_id; ++ bool is_pie; ++ bool is_dyn; + }; + + struct running_elf { +@@ -111,7 +114,7 @@ struct running_elf { + struct { + unsigned int sym, str; + unsigned int rela_dyn, rela_plt; +- unsigned int dynsym, dynstr; ++ unsigned int dynsym, dynstr, dynamic; + } index; + + /* load bias, used to handle ASLR */ +-- +2.34.1 + diff --git a/0019-upatch-diff-fix-lookup_relf-failed-issue.patch b/0019-upatch-diff-fix-lookup_relf-failed-issue.patch new file mode 100644 index 0000000000000000000000000000000000000000..eebc8e7b95cfdedd54bb9e9c13c20249f2972695 --- /dev/null +++ b/0019-upatch-diff-fix-lookup_relf-failed-issue.patch @@ -0,0 +1,144 @@ +From e7baf4fef5dfa7ccbb0d639628a910a8099735ec Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Sat, 11 May 2024 17:31:46 +0800 +Subject: [PATCH] upatch-diff: fix 'lookup_relf failed' issue + +Signed-off-by: renoseven +--- + upatch-diff/elf-create.c | 24 ++++++++++------- + upatch-diff/running-elf.c | 57 +++++++++++++-------------------------- + 2 files changed, 32 insertions(+), 49 deletions(-) + +diff --git a/upatch-diff/elf-create.c b/upatch-diff/elf-create.c +index de4cb57..873b3a9 100644 +--- a/upatch-diff/elf-create.c ++++ b/upatch-diff/elf-create.c +@@ -135,8 +135,9 @@ void upatch_create_patches_sections(struct upatch_elf *uelf, struct running_elf + + /* find changed func */ + list_for_each_entry(sym, &uelf->symbols, list) { +- if (sym->type != STT_FUNC || sym->status != CHANGED || sym->parent) ++ if (sym->type != STT_FUNC || sym->status != CHANGED || sym->parent) { + continue; ++ } + nr++; + } + +@@ -146,24 +147,27 @@ void upatch_create_patches_sections(struct upatch_elf *uelf, struct running_elf + funcs = sec->data->d_buf; + + strsym = find_symbol_by_name(&uelf->symbols, ".upatch.strings"); +- if (!strsym) +- ERROR("can't find .upatch.strings symbol."); ++ if (!strsym) { ++ ERROR("Cannot find symbol '.upatch.strings'"); ++ } + + list_for_each_entry(sym, &uelf->symbols, list) { +- if (sym->type != STT_FUNC || sym->status != CHANGED || sym->parent) ++ if (sym->type != STT_FUNC || sym->status != CHANGED || sym->parent) { + continue; ++ } + +- if (!lookup_relf(relf, sym, &symbol)) +- ERROR("lookup_relf failed."); ++ if (!lookup_relf(relf, sym, &symbol)) { ++ ERROR("Cannot find symbol '%s' in %s", sym->name, g_relf_name); ++ } + +- if (sym->bind == STB_LOCAL && symbol.global) +- ERROR("can't find local symbol '%s' in symbol table.", sym->name); ++ if (sym->bind == STB_LOCAL && symbol.global) { ++ ERROR("Cannot find local symbol '%s' in symbol table.", sym->name); ++ } + +- log_debug("lookup for %s: symbol name %s sympos=%lu size=%lu .\n", ++ log_debug("lookup for %s: symbol name %s sympos=%lu size=%lu.\n", + sym->name, symbol.symbol->name, symbol.sympos, symbol.symbol->size); + + /* ATTENTION: kpatch convert global symbols to local symbols here. */ +- + funcs[index].old_addr = symbol.symbol->addr; + funcs[index].old_size = symbol.symbol->size; + funcs[index].new_size = sym->sym.st_size; +diff --git a/upatch-diff/running-elf.c b/upatch-diff/running-elf.c +index 037f5fc..3bb35e7 100644 +--- a/upatch-diff/running-elf.c ++++ b/upatch-diff/running-elf.c +@@ -113,55 +113,34 @@ int relf_destroy(struct running_elf *relf) + return 0; + } + +-bool lookup_relf(struct running_elf *relf, struct symbol *lookup_sym, +- struct lookup_result *result) ++bool lookup_relf(struct running_elf *relf, ++ struct symbol *lookup_sym, struct lookup_result *result) + { +- int i; +- struct debug_symbol *sym; ++ struct debug_symbol *symbol = NULL; + unsigned long sympos = 0; +- bool in_file = false; + ++ log_debug("looking up symbol '%s'\n", lookup_sym->name); + memset(result, 0, sizeof(*result)); + +- for (i = 0; i < relf->obj_nr; i ++) { +- sym = &relf->obj_syms[i]; +- if (sym->bind == STB_LOCAL && !strcmp(sym->name, lookup_sym->name)) +- sympos ++; ++ for (int i = 0; i < relf->obj_nr; i++) { ++ symbol = &relf->obj_syms[i]; ++ sympos++; + +- if (lookup_sym->relf_sym == sym) { +- in_file = true; ++ if (strcmp(symbol->name, lookup_sym->name) != 0) { + continue; + } +- +- if (!in_file) +- continue; +- +- if (sym->type == STT_FILE) +- break; +- +- if (sym->bind == STB_LOCAL && !strcmp(sym->name, lookup_sym->name)) { +- if (result->symbol) +- ERROR("duplicate local symbol found for %s", lookup_sym->name); +- +- result->symbol = sym; +- result->sympos = sympos; +- result->global = false; ++ if ((result->symbol != NULL) && ++ (result->symbol->bind == symbol->bind)) { ++ ERROR("Found duplicate symbol '%s' in %s", ++ lookup_sym->name, g_relf_name); + } +- } +- +- if (!!result->symbol) +- return !!result->symbol; + +- for (i = 0; i < relf->obj_nr; i ++) { +- sym = &relf->obj_syms[i]; +- if ((sym->bind == STB_GLOBAL || sym->bind == STB_WEAK) && +- !strcmp(sym->name, lookup_sym->name)) { +- if (result->symbol) +- ERROR("duplicated global symbol for %s \n", lookup_sym->name); +- result->symbol = sym; +- result->global = true; +- } ++ result->symbol = symbol; ++ result->sympos = sympos; ++ result->global = ++ ((symbol->bind == STB_GLOBAL) || (symbol->bind == STB_WEAK)); ++ log_normal("found symbol '%s'\n", lookup_sym->name); + } + +- return !!result->symbol; ++ return (result->symbol != NULL); + } +-- +2.34.1 + diff --git a/0020-upatch-diff-only-check-changed-file-symbols.patch b/0020-upatch-diff-only-check-changed-file-symbols.patch new file mode 100644 index 0000000000000000000000000000000000000000..073f6ecffdc4374994e8ad198ad83e3e078f82d5 --- /dev/null +++ b/0020-upatch-diff-only-check-changed-file-symbols.patch @@ -0,0 +1,165 @@ +From d3a4f6a47f2151e9828bdfd805ff2af927c80ed9 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Mon, 13 May 2024 21:27:13 +0800 +Subject: [PATCH] upatch-diff: only check changed file symbols + +1. sync compare results (SAME/NEW/CHANGED) to correlated objects +2. mark file changes by looking up symbol changes +3. check orignal object & debuginfo when file changes were detected +4. defer symbol check until after calculation changes + +Signed-off-by: renoseven +--- + upatch-diff/create-diff-object.c | 26 +++++++++++++-- + upatch-diff/elf-compare.c | 57 ++++++++++++++++++-------------- + upatch-diff/running-elf.c | 2 +- + 3 files changed, 56 insertions(+), 29 deletions(-) + +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index 01c58b8..1a05869 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -481,12 +481,32 @@ static void find_debug_symbol(struct upatch_elf *uelf, struct running_elf *relf) + struct symbol *file_sym = NULL; + + list_for_each_entry(file_sym, &uelf->symbols, list) { +- if (file_sym->type == STT_FILE) { ++ if ((file_sym->type == STT_FILE) && (file_sym->status == CHANGED)) { ++ log_debug("file '%s' is CHANGED\n", file_sym->name); + find_local_syms(uelf, relf, file_sym); + } + } + } + ++static void mark_file_symbols(struct upatch_elf *uelf) ++{ ++ struct symbol *curr_sym = NULL; ++ struct symbol *file_sym = NULL; ++ ++ list_for_each_entry(curr_sym, &uelf->symbols, list) { ++ if (curr_sym->type == STT_FILE) { ++ file_sym = curr_sym; ++ continue; ++ } ++ if ((file_sym == NULL) || (file_sym->status == CHANGED)) { ++ continue; ++ } ++ if (curr_sym->status == CHANGED) { ++ file_sym->status = CHANGED; ++ } ++ } ++} ++ + static void mark_grouped_sections(struct upatch_elf *uelf) + { + struct section *groupsec, *sec; +@@ -937,8 +957,6 @@ int main(int argc, char*argv[]) + detect_child_functions(&uelf_source); + detect_child_functions(&uelf_patched); + +- find_debug_symbol(&uelf_source, &relf); +- + mark_grouped_sections(&uelf_patched); + + replace_section_syms(&uelf_source); +@@ -952,6 +970,8 @@ int main(int argc, char*argv[]) + mark_ignored_sections(&uelf_patched); + + upatch_compare_correlated_elements(&uelf_patched); ++ mark_file_symbols(&uelf_source); ++ find_debug_symbol(&uelf_source, &relf); + + mark_ignored_functions_same(&uelf_patched); + mark_ignored_sections_same(&uelf_patched); +diff --git a/upatch-diff/elf-compare.c b/upatch-diff/elf-compare.c +index 9b857b1..ef8dd23 100644 +--- a/upatch-diff/elf-compare.c ++++ b/upatch-diff/elf-compare.c +@@ -336,38 +336,45 @@ static bool line_macro_change_only(struct upatch_elf *uelf, struct section *sec) + return false; + } + ++static inline void update_section_status(struct section *sec, enum status status) ++{ ++ if (sec == NULL) { ++ return; ++ } ++ if (sec->twin != NULL) { ++ sec->twin->status = status; ++ } ++ if (is_rela_section(sec)) { ++ if ((sec->base != NULL) && ++ (sec->base->sym != NULL)) { ++ sec->base->sym->status = status; ++ } ++ } ++ else { ++ if (sec->sym != NULL) { ++ sec->sym->status = status; ++ } ++ } ++} ++ + void upatch_compare_sections(struct upatch_elf *uelf) + { +- struct section *sec; +- struct list_head *seclist = &uelf->sections; ++ struct section *sec = NULL; + +- /* compare all sections */ +- list_for_each_entry(sec, seclist, list) { +- if (sec->twin) +- compare_correlated_section(sec, sec->twin); +- else ++ list_for_each_entry(sec, &uelf->sections, list) { ++ if (sec->twin == NULL) { + sec->status = NEW; +- } +- +- /* exclude WARN-only, might_sleep changes */ +- list_for_each_entry(sec, seclist, list) { ++ } ++ else { ++ compare_correlated_section(sec, sec->twin); ++ } ++ /* exclude WARN-only, might_sleep changes */ + if (line_macro_change_only(uelf, sec)) { + log_debug("reverting macro / line number section %s status to SAME\n", sec->name); + sec->status = SAME; + } +- } +- +- /* sync symbol status */ +- list_for_each_entry(sec, seclist, list) { +- if (is_rela_section(sec)) { +- /* sync bundleable symbol for relocation section */ +- if (sec->base->sym && sec->base->sym->status != CHANGED) +- sec->base->sym->status = sec->status; +- } else { +- struct symbol *sym = sec->sym; +- if (sym && sym->status != CHANGED) +- sym->status = sec->status; +- /* TODO: handle child func */ +- } ++ /* sync status */ ++ update_section_status(sec, sec->status); ++ update_section_status(sec->twin, sec->status); + } + } +\ No newline at end of file +diff --git a/upatch-diff/running-elf.c b/upatch-diff/running-elf.c +index 3bb35e7..676880f 100644 +--- a/upatch-diff/running-elf.c ++++ b/upatch-diff/running-elf.c +@@ -139,7 +139,7 @@ bool lookup_relf(struct running_elf *relf, + result->sympos = sympos; + result->global = + ((symbol->bind == STB_GLOBAL) || (symbol->bind == STB_WEAK)); +- log_normal("found symbol '%s'\n", lookup_sym->name); ++ log_debug("found symbol '%s'\n", lookup_sym->name); + } + + return (result->symbol != NULL); +-- +2.34.1 + diff --git a/0021-upatch-diff-remove-rela-check-while-build-rebuilding.patch b/0021-upatch-diff-remove-rela-check-while-build-rebuilding.patch new file mode 100644 index 0000000000000000000000000000000000000000..a8f7dc18587d417ec5772b855843319cb7386038 --- /dev/null +++ b/0021-upatch-diff-remove-rela-check-while-build-rebuilding.patch @@ -0,0 +1,27 @@ +From 8103b361db40350131bdb7b01124ce1d0f23e09a Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Tue, 14 May 2024 14:10:05 +0800 +Subject: [PATCH] upatch-diff: remove rela check while build rebuilding + .eh_frame + +Signed-off-by: renoseven +--- + upatch-diff/elf-debug.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/upatch-diff/elf-debug.c b/upatch-diff/elf-debug.c +index 6b5fc53..f9c5327 100644 +--- a/upatch-diff/elf-debug.c ++++ b/upatch-diff/elf-debug.c +@@ -181,8 +181,6 @@ void upatch_rebuild_eh_frame(struct section *sec) + if (found_rela) + break; + } +- if (!found_rela) +- ERROR("No FDE found for relocation at 0x%x \n", offset); + } + + /* +-- +2.34.1 + diff --git a/0022-syscared-fix-apply-kernel-module-patch-failure-issue.patch b/0022-syscared-fix-apply-kernel-module-patch-failure-issue.patch new file mode 100644 index 0000000000000000000000000000000000000000..f4bf6bb11e43301f8482e6755c1500206cfff485 --- /dev/null +++ b/0022-syscared-fix-apply-kernel-module-patch-failure-issue.patch @@ -0,0 +1,27 @@ +From 5f9ef3e5d565fc31c809f57635c3619b4a2e6582 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 17 May 2024 14:46:30 +0800 +Subject: [PATCH] syscared: fix 'apply kernel module patch failure' issue + +Signed-off-by: renoseven +--- + syscared/src/patch/driver/kpatch/mod.rs | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/syscared/src/patch/driver/kpatch/mod.rs b/syscared/src/patch/driver/kpatch/mod.rs +index 307efb5..970da92 100644 +--- a/syscared/src/patch/driver/kpatch/mod.rs ++++ b/syscared/src/patch/driver/kpatch/mod.rs +@@ -128,6 +128,9 @@ impl KernelPatchDriver { + debug!("Patch target: '{}'", patch_target); + debug!("Current kernel: '{}'", current_kernel.to_string_lossy()); + ++ if !patch_target.starts_with("KERNEL_NAME_PREFIX") { ++ return Ok(()); ++ } + ensure!( + current_kernel == patch_target, + "Kpatch: Patch is incompatible", +-- +2.34.1 + diff --git a/0023-all-finding-executable-from-environment-variables.patch b/0023-all-finding-executable-from-environment-variables.patch new file mode 100644 index 0000000000000000000000000000000000000000..374b91c4662b4e8d4c6fd955510f94902494f48b --- /dev/null +++ b/0023-all-finding-executable-from-environment-variables.patch @@ -0,0 +1,241 @@ +From c0c8df3bdb7986925570279f3085425d9e6a87cc Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Wed, 29 May 2024 22:06:09 +0800 +Subject: [PATCH] all: finding executable from environment variables + +Signed-off-by: renoseven +--- + syscare-build/src/main.rs | 10 ++++++++-- + syscare-build/src/patch/user_patch/upatch_builder.rs | 2 +- + syscare/src/executor/build.rs | 7 +++---- + syscare/src/main.rs | 10 ++++++++-- + syscared/src/main.rs | 10 ++++++++-- + syscared/src/patch/driver/upatch/sys.rs | 2 +- + upatch-build/src/main.rs | 9 ++++++++- + 7 files changed, 37 insertions(+), 13 deletions(-) + +diff --git a/syscare-build/src/main.rs b/syscare-build/src/main.rs +index 8928218..1faa803 100644 +--- a/syscare-build/src/main.rs ++++ b/syscare-build/src/main.rs +@@ -12,7 +12,7 @@ + * See the Mulan PSL v2 for more details. + */ + +-use std::{process, sync::Arc}; ++use std::{env, process, sync::Arc}; + + use anyhow::{bail, ensure, Context, Result}; + use flexi_logger::{ +@@ -22,7 +22,7 @@ use lazy_static::lazy_static; + use log::{error, info, LevelFilter, Record}; + + use syscare_abi::{PackageInfo, PackageType, PatchInfo, PatchType}; +-use syscare_common::{fs, os}; ++use syscare_common::{concat_os, fs, os}; + + mod args; + mod build_params; +@@ -44,6 +44,9 @@ const CLI_VERSION: &str = env!("CARGO_PKG_VERSION"); + const CLI_ABOUT: &str = env!("CARGO_PKG_DESCRIPTION"); + const CLI_UMASK: u32 = 0o022; + ++const PATH_ENV_NAME: &str = "PATH"; ++const PATH_ENV_VALUE: &str = "/usr/libexec/syscare"; ++ + const LOG_FILE_NAME: &str = "build"; + const KERNEL_PKG_NAME: &str = "kernel"; + +@@ -70,6 +73,9 @@ impl SyscareBuild { + fn new() -> Result { + // Initialize arguments & prepare environments + os::umask::set_umask(CLI_UMASK); ++ if let Some(path_env) = env::var_os(PATH_ENV_NAME) { ++ env::set_var(PATH_ENV_NAME, concat_os!(PATH_ENV_VALUE, ":", path_env)); ++ } + + let args = Arguments::new()?; + let build_root = BuildRoot::new(&args.build_root)?; +diff --git a/syscare-build/src/patch/user_patch/upatch_builder.rs b/syscare-build/src/patch/user_patch/upatch_builder.rs +index ad8710b..ca56515 100644 +--- a/syscare-build/src/patch/user_patch/upatch_builder.rs ++++ b/syscare-build/src/patch/user_patch/upatch_builder.rs +@@ -34,7 +34,7 @@ use crate::{build_params::BuildParameters, package::PackageImpl, patch::PatchBui + + use super::{elf_relation::ElfRelation, DEBUGINFO_FILE_EXT}; + +-const UPATCH_BUILD_BIN: &str = "/usr/libexec/syscare/upatch-build"; ++const UPATCH_BUILD_BIN: &str = "upatch-build"; + const RPMBUILD_BIN: &str = "rpmbuild"; + + struct UBuildParameters { +diff --git a/syscare/src/executor/build.rs b/syscare/src/executor/build.rs +index f9027c7..6d3866f 100644 +--- a/syscare/src/executor/build.rs ++++ b/syscare/src/executor/build.rs +@@ -19,22 +19,21 @@ use anyhow::{bail, Context, Result}; + use super::CommandExecutor; + use crate::args::SubCommand; + +-const SYSCARE_BUILD_PATH: &str = "/usr/libexec/syscare/syscare-build"; ++const SYSCARE_BUILD_BIN: &str = "syscare-build"; + + pub struct BuildCommandExecutor; + + impl CommandExecutor for BuildCommandExecutor { + fn invoke(&self, command: &SubCommand) -> Result> { + if let SubCommand::Build { args } = command { +- let e = Command::new(SYSCARE_BUILD_PATH).args(args).exec(); ++ let e = Command::new(SYSCARE_BUILD_BIN).args(args).exec(); + + match e.kind() { + std::io::ErrorKind::NotFound => { + bail!("Package syscare-build is not installed"); + } + _ => { +- return Err(e) +- .with_context(|| format!("Failed to start {}", SYSCARE_BUILD_PATH)) ++ return Err(e).with_context(|| format!("Failed to start {}", SYSCARE_BUILD_BIN)) + } + } + } +diff --git a/syscare/src/main.rs b/syscare/src/main.rs +index c709f6a..dea5717 100644 +--- a/syscare/src/main.rs ++++ b/syscare/src/main.rs +@@ -12,7 +12,7 @@ + * See the Mulan PSL v2 for more details. + */ + +-use std::{process, rc::Rc}; ++use std::{env, process, rc::Rc}; + + use anyhow::{Context, Result}; + use flexi_logger::{DeferredNow, LogSpecification, Logger, LoggerHandle, WriteMode}; +@@ -25,13 +25,16 @@ mod rpc; + use args::Arguments; + use executor::{build::BuildCommandExecutor, patch::PatchCommandExecutor, CommandExecutor}; + use rpc::{RpcProxy, RpcRemote}; +-use syscare_common::os; ++use syscare_common::{concat_os, os}; + + pub const CLI_NAME: &str = env!("CARGO_PKG_NAME"); + pub const CLI_VERSION: &str = env!("CARGO_PKG_VERSION"); + pub const CLI_ABOUT: &str = env!("CARGO_PKG_DESCRIPTION"); + const CLI_UMASK: u32 = 0o077; + ++const PATH_ENV_NAME: &str = "PATH"; ++const PATH_ENV_VALUE: &str = "/usr/libexec/syscare"; ++ + const SOCKET_FILE_NAME: &str = "syscared.sock"; + const PATCH_OP_LOCK_NAME: &str = "patch_op.lock"; + +@@ -52,6 +55,9 @@ impl SyscareCLI { + fn new() -> Result { + // Initialize arguments & prepare environments + os::umask::set_umask(CLI_UMASK); ++ if let Some(path_env) = env::var_os(PATH_ENV_NAME) { ++ env::set_var(PATH_ENV_NAME, concat_os!(PATH_ENV_VALUE, ":", path_env)); ++ } + + let args = Arguments::new()?; + +diff --git a/syscared/src/main.rs b/syscared/src/main.rs +index b840abf..5c60ecf 100644 +--- a/syscared/src/main.rs ++++ b/syscared/src/main.rs +@@ -12,7 +12,7 @@ + * See the Mulan PSL v2 for more details. + */ + +-use std::{fs::Permissions, os::unix::fs::PermissionsExt, panic, process, sync::Arc}; ++use std::{env, fs::Permissions, os::unix::fs::PermissionsExt, panic, process, sync::Arc}; + + use anyhow::{ensure, Context, Result}; + use daemonize::Daemonize; +@@ -28,7 +28,7 @@ use parking_lot::RwLock; + use patch::manager::PatchManager; + use signal_hook::{consts::TERM_SIGNALS, iterator::Signals, low_level::signal_name}; + +-use syscare_common::{fs, os}; ++use syscare_common::{concat_os, fs, os}; + + mod args; + mod config; +@@ -49,6 +49,9 @@ const DAEMON_VERSION: &str = env!("CARGO_PKG_VERSION"); + const DAEMON_ABOUT: &str = env!("CARGO_PKG_DESCRIPTION"); + const DAEMON_UMASK: u32 = 0o077; + ++const PATH_ENV_NAME: &str = "PATH"; ++const PATH_ENV_VALUE: &str = "/usr/libexec/syscare"; ++ + const CONFIG_FILE_NAME: &str = "syscared.yaml"; + const PID_FILE_NAME: &str = "syscared.pid"; + const SOCKET_FILE_NAME: &str = "syscared.sock"; +@@ -107,6 +110,9 @@ impl Daemon { + + // Initialize arguments & prepare environments + os::umask::set_umask(DAEMON_UMASK); ++ if let Some(path_env) = env::var_os(PATH_ENV_NAME) { ++ env::set_var(PATH_ENV_NAME, concat_os!(PATH_ENV_VALUE, ":", path_env)); ++ } + + let args = Arguments::new()?; + fs::create_dir_all(&args.config_dir)?; +diff --git a/syscared/src/patch/driver/upatch/sys.rs b/syscared/src/patch/driver/upatch/sys.rs +index a388bc6..1990289 100644 +--- a/syscared/src/patch/driver/upatch/sys.rs ++++ b/syscared/src/patch/driver/upatch/sys.rs +@@ -6,7 +6,7 @@ use uuid::Uuid; + + use syscare_common::process::Command; + +-const UPATCH_MANAGE_BIN: &str = "/usr/libexec/syscare/upatch-manage"; ++const UPATCH_MANAGE_BIN: &str = "upatch-manage"; + + pub fn active_patch(uuid: &Uuid, pid: i32, target_elf: &Path, patch_file: &Path) -> Result<()> { + let exit_code = Command::new(UPATCH_MANAGE_BIN) +diff --git a/upatch-build/src/main.rs b/upatch-build/src/main.rs +index b5c14a8..473b0a7 100644 +--- a/upatch-build/src/main.rs ++++ b/upatch-build/src/main.rs +@@ -13,6 +13,7 @@ + */ + + use std::{ ++ env, + ffi::OsStr, + fs::Permissions, + os::unix::fs::PermissionsExt, +@@ -54,6 +55,9 @@ const CLI_VERSION: &str = env!("CARGO_PKG_VERSION"); + const CLI_ABOUT: &str = env!("CARGO_PKG_DESCRIPTION"); + const CLI_UMASK: u32 = 0o022; + ++const PATH_ENV_NAME: &str = "PATH"; ++const PATH_ENV_VALUE: &str = "/usr/libexec/syscare"; ++ + const LOG_FILE_NAME: &str = "build"; + + struct BuildInfo { +@@ -83,6 +87,9 @@ impl UpatchBuild { + fn new() -> Result { + // Initialize arguments & prepare environments + os::umask::set_umask(CLI_UMASK); ++ if let Some(path_env) = env::var_os(PATH_ENV_NAME) { ++ env::set_var(PATH_ENV_NAME, concat_os!(PATH_ENV_VALUE, ":", path_env)); ++ } + + let args = Arguments::new()?; + let build_root = BuildRoot::new(&args.build_root)?; +@@ -196,7 +203,7 @@ impl UpatchBuild { + output_dir: &Path, + verbose: bool, + ) -> Result<()> { +- const UPATCH_DIFF_BIN: &str = "/usr/libexec/syscare/upatch-diff"; ++ const UPATCH_DIFF_BIN: &str = "upatch-diff"; + + let ouput_name = original_object.file_name().with_context(|| { + format!( +-- +2.34.1 + diff --git a/0024-all-remove-redundant-code.patch b/0024-all-remove-redundant-code.patch new file mode 100644 index 0000000000000000000000000000000000000000..66a30cf6b2a50234c03a21e94185d74616478235 --- /dev/null +++ b/0024-all-remove-redundant-code.patch @@ -0,0 +1,901 @@ +From 5956424c9bc00a722dd6227de1b85e65a5e23b25 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Tue, 21 May 2024 15:01:48 +0800 +Subject: [PATCH] all: remove redundant code + +Signed-off-by: renoseven +--- + syscare-build/src/build_root/mod.rs | 20 +- + syscare-build/src/build_root/package_root.rs | 6 - + syscare-build/src/build_root/patch_root.rs | 6 - + syscare-build/src/package/dependency.rs | 10 - + syscare-build/src/package/mod.rs | 1 - + syscare-build/src/package/rpm/mod.rs | 4 - + syscare-common/src/os/disk.rs | 64 ---- + syscare-common/src/os/grub.rs | 312 ------------------ + syscare-common/src/os/kernel.rs | 43 +-- + syscare-common/src/os/mod.rs | 2 - + syscare-common/src/util/digest.rs | 7 - + syscared/src/fast_reboot/manager.rs | 123 ------- + syscared/src/fast_reboot/mod.rs | 17 - + syscared/src/main.rs | 7 +- + syscared/src/rpc/skeleton/fast_reboot.rs | 21 -- + syscared/src/rpc/skeleton/mod.rs | 2 - + syscared/src/rpc/skeleton_impl/fast_reboot.rs | 42 --- + syscared/src/rpc/skeleton_impl/mod.rs | 2 - + 18 files changed, 3 insertions(+), 686 deletions(-) + delete mode 100644 syscare-build/src/package/dependency.rs + delete mode 100644 syscare-common/src/os/disk.rs + delete mode 100644 syscare-common/src/os/grub.rs + delete mode 100644 syscared/src/fast_reboot/manager.rs + delete mode 100644 syscared/src/fast_reboot/mod.rs + delete mode 100644 syscared/src/rpc/skeleton/fast_reboot.rs + delete mode 100644 syscared/src/rpc/skeleton_impl/fast_reboot.rs + +diff --git a/syscare-build/src/build_root/mod.rs b/syscare-build/src/build_root/mod.rs +index 81de6b2..6a12788 100644 +--- a/syscare-build/src/build_root/mod.rs ++++ b/syscare-build/src/build_root/mod.rs +@@ -12,11 +12,7 @@ + * See the Mulan PSL v2 for more details. + */ + +-use std::{ +- ffi::OsStr, +- ops::Deref, +- path::{Path, PathBuf}, +-}; ++use std::path::{Path, PathBuf}; + + use anyhow::Result; + use syscare_common::fs; +@@ -61,17 +57,3 @@ impl BuildRoot { + Ok(()) + } + } +- +-impl Deref for BuildRoot { +- type Target = Path; +- +- fn deref(&self) -> &Self::Target { +- &self.path +- } +-} +- +-impl AsRef for BuildRoot { +- fn as_ref(&self) -> &OsStr { +- self.as_os_str() +- } +-} +diff --git a/syscare-build/src/build_root/package_root.rs b/syscare-build/src/build_root/package_root.rs +index abb7a86..724a42b 100644 +--- a/syscare-build/src/build_root/package_root.rs ++++ b/syscare-build/src/build_root/package_root.rs +@@ -50,9 +50,3 @@ impl PackageRoot { + }) + } + } +- +-impl AsRef for PackageRoot { +- fn as_ref(&self) -> &Path { +- &self.path +- } +-} +diff --git a/syscare-build/src/build_root/patch_root.rs b/syscare-build/src/build_root/patch_root.rs +index b780e32..af8ec6b 100644 +--- a/syscare-build/src/build_root/patch_root.rs ++++ b/syscare-build/src/build_root/patch_root.rs +@@ -44,9 +44,3 @@ impl PatchRoot { + }) + } + } +- +-impl AsRef for PatchRoot { +- fn as_ref(&self) -> &Path { +- &self.path +- } +-} +diff --git a/syscare-build/src/package/dependency.rs b/syscare-build/src/package/dependency.rs +deleted file mode 100644 +index 37bdf92..0000000 +--- a/syscare-build/src/package/dependency.rs ++++ /dev/null +@@ -1,10 +0,0 @@ +-pub struct PackageDependency { +- requires: HashSet, +- conflicts: HashSet, +- suggests: HashSet, +- recommends: HashSet, +-} +- +-impl PackageDependency { +- +-} +\ No newline at end of file +diff --git a/syscare-build/src/package/mod.rs b/syscare-build/src/package/mod.rs +index 9ba29a1..72b555a 100644 +--- a/syscare-build/src/package/mod.rs ++++ b/syscare-build/src/package/mod.rs +@@ -33,7 +33,6 @@ pub use spec_writer::*; + pub use tar::*; + + trait Package { +- fn extension(&self) -> &'static str; + fn parse_package_info(&self, pkg_path: &Path) -> Result; + fn query_package_files(&self, pkg_path: &Path) -> Result>; + fn extract_package(&self, pkg_path: &Path, output_dir: &Path) -> Result<()>; +diff --git a/syscare-build/src/package/rpm/mod.rs b/syscare-build/src/package/rpm/mod.rs +index 5b4bf07..0e9f77c 100644 +--- a/syscare-build/src/package/rpm/mod.rs ++++ b/syscare-build/src/package/rpm/mod.rs +@@ -60,10 +60,6 @@ impl RpmPackage { + } + + impl Package for RpmPackage { +- fn extension(&self) -> &'static str { +- PKG_FILE_EXT +- } +- + fn parse_package_info(&self, pkg_path: &Path) -> Result { + let query_result = Self::query_package_info( + pkg_path, +diff --git a/syscare-common/src/os/disk.rs b/syscare-common/src/os/disk.rs +deleted file mode 100644 +index 7ace804..0000000 +--- a/syscare-common/src/os/disk.rs ++++ /dev/null +@@ -1,64 +0,0 @@ +-// SPDX-License-Identifier: Mulan PSL v2 +-/* +- * Copyright (c) 2024 Huawei Technologies Co., Ltd. +- * syscare-common is licensed under Mulan PSL v2. +- * You can use this software according to the terms and conditions of the Mulan PSL v2. +- * You may obtain a copy of Mulan PSL v2 at: +- * http://license.coscl.org.cn/MulanPSL2 +- * +- * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +- * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +- * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +- * See the Mulan PSL v2 for more details. +- */ +- +-use std::ffi::OsStr; +-use std::path::{Path, PathBuf}; +- +-use crate::fs; +- +-#[inline(always)] +-fn find_disk, S: AsRef>(directory: P, name: S) -> std::io::Result { +- #[inline(always)] +- fn __find_disk(directory: &Path, name: &OsStr) -> std::io::Result { +- let dev = fs::find_symlink( +- directory, +- name, +- fs::FindOptions { +- fuzz: false, +- recursive: false, +- }, +- )?; +- fs::canonicalize(dev) +- } +- +- __find_disk(directory.as_ref(), name.as_ref()).map_err(|_| { +- std::io::Error::new( +- std::io::ErrorKind::NotFound, +- format!( +- "Cannot find block device by label \"{}\"", +- name.as_ref().to_string_lossy() +- ), +- ) +- }) +-} +- +-pub fn find_by_id>(name: S) -> std::io::Result { +- find_disk("/dev/disk/by-id", name) +-} +- +-pub fn find_by_label>(name: S) -> std::io::Result { +- find_disk("/dev/disk/by-label", name) +-} +- +-pub fn find_by_uuid>(name: S) -> std::io::Result { +- find_disk("/dev/disk/by-uuid", name) +-} +- +-pub fn find_by_partuuid>(name: S) -> std::io::Result { +- find_disk("/dev/disk/by-partuuid", name) +-} +- +-pub fn find_by_path>(name: S) -> std::io::Result { +- find_disk("/dev/disk/by-path", name) +-} +diff --git a/syscare-common/src/os/grub.rs b/syscare-common/src/os/grub.rs +deleted file mode 100644 +index 54299d8..0000000 +--- a/syscare-common/src/os/grub.rs ++++ /dev/null +@@ -1,312 +0,0 @@ +-// SPDX-License-Identifier: Mulan PSL v2 +-/* +- * Copyright (c) 2024 Huawei Technologies Co., Ltd. +- * syscare-common is licensed under Mulan PSL v2. +- * You can use this software according to the terms and conditions of the Mulan PSL v2. +- * You may obtain a copy of Mulan PSL v2 at: +- * http://license.coscl.org.cn/MulanPSL2 +- * +- * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +- * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +- * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +- * See the Mulan PSL v2 for more details. +- */ +- +-use std::collections::HashMap; +-use std::ffi::{OsStr, OsString}; +-use std::io::{BufRead, BufReader}; +-use std::os::unix::prelude::OsStrExt as StdOsStrExt; +-use std::path::{Path, PathBuf}; +- +-use lazy_static::lazy_static; +-use log::debug; +-use regex::bytes::Regex; +- +-use super::{disk, proc_mounts}; +-use crate::{ +- ffi::OsStrExt, +- fs, +- io::{BufReadOsLines, OsLines}, +-}; +- +-#[derive(Debug, Clone, Copy)] +-enum BootType { +- Csm, +- Uefi, +-} +- +-#[derive(Debug)] +-pub struct GrubMenuEntry { +- name: OsString, +- root: PathBuf, +- kernel: PathBuf, +- initrd: PathBuf, +-} +- +-impl GrubMenuEntry { +- pub fn get_name(&self) -> &OsStr { +- &self.name +- } +- +- pub fn get_root(&self) -> &Path { +- &self.root +- } +- +- pub fn get_kernel(&self) -> PathBuf { +- // Path is stripped by regular expression, thus, it would always start with '/' +- self.root.join(self.kernel.strip_prefix("/").unwrap()) +- } +- +- pub fn get_initrd(&self) -> PathBuf { +- // Path is stripped by regular expression, thus, it would always start with '/' +- self.root.join(self.initrd.strip_prefix("/").unwrap()) +- } +-} +- +-struct GrubConfigParser { +- lines: OsLines, +- is_matching: bool, +- entry_name: Option, +- entry_root: Option, +- entry_kernel: Option, +- entry_initrd: Option, +-} +- +-impl GrubConfigParser { +- pub fn new(buf: R) -> Self { +- Self { +- lines: buf.os_lines(), +- is_matching: false, +- entry_name: None, +- entry_root: None, +- entry_kernel: None, +- entry_initrd: None, +- } +- } +- +- #[inline(always)] +- fn parse_name(str: &OsStr) -> Option { +- lazy_static! { +- static ref RE: Regex = Regex::new(r"'([^']*)'").unwrap(); +- } +- RE.captures(str.as_bytes()) +- .and_then(|captures| captures.get(1)) +- .map(|matched| OsStr::from_bytes(matched.as_bytes()).to_os_string()) +- } +- +- #[inline(always)] +- fn parse_uuid(str: &OsStr) -> Option { +- str.split_whitespace() +- .filter_map(|str| { +- let arg = str.trim(); +- if arg != OsStr::new("search") && !arg.starts_with("--") { +- return Some(arg.to_os_string()); +- } +- None +- }) +- .next() +- } +- +- #[inline(always)] +- fn parse_path(str: &OsStr) -> Option { +- lazy_static! { +- static ref RE: Regex = Regex::new(r"/\.?\w+([\w\-\.])*").unwrap(); +- } +- RE.find(str.as_bytes()) +- .map(|matched| PathBuf::from(OsStr::from_bytes(matched.as_bytes()))) +- } +- +- #[inline(always)] +- fn parse_mount_point(str: &OsStr) -> Option { +- let find_dev = Self::parse_uuid(str).and_then(|uuid| disk::find_by_uuid(uuid).ok()); +- if let (Some(dev_name), Ok(mounts)) = (find_dev, proc_mounts::Mounts::new()) { +- for mount in mounts { +- if mount.mount_source == dev_name { +- return Some(mount.mount_point); +- } +- } +- } +- None +- } +-} +- +-impl Iterator for GrubConfigParser { +- type Item = GrubMenuEntry; +- +- fn next(&mut self) -> Option { +- for line in (&mut self.lines).flatten() { +- if line.starts_with("#") { +- continue; +- } +- +- let str = line.trim(); +- if str.is_empty() { +- continue; +- } +- +- if !self.is_matching { +- if str.starts_with("menuentry '") { +- self.entry_name = Self::parse_name(str); +- self.is_matching = true; +- } +- continue; +- } +- if str.starts_with("search") { +- self.entry_root = Self::parse_mount_point(str); +- } else if str.starts_with("linux") { +- self.entry_kernel = Self::parse_path(str); +- } else if str.starts_with("initrd") { +- self.entry_initrd = Self::parse_path(str); +- } else if str.starts_with("}") { +- let entry = match ( +- &self.entry_name, +- &self.entry_root, +- &self.entry_kernel, +- &self.entry_initrd, +- ) { +- (Some(name), Some(root), Some(kernel), Some(initrd)) => Some(GrubMenuEntry { +- name: name.to_os_string(), +- root: root.to_path_buf(), +- kernel: kernel.to_path_buf(), +- initrd: initrd.to_path_buf(), +- }), +- _ => None, +- }; +- self.is_matching = false; +- self.entry_name = None; +- self.entry_root = None; +- self.entry_kernel = None; +- self.entry_initrd = None; +- +- return entry; +- } +- } +- None +- } +-} +- +-struct GrubEnvParser { +- lines: OsLines, +-} +- +-impl GrubEnvParser { +- pub fn new(buf: R) -> Self { +- Self { +- lines: buf.os_lines(), +- } +- } +-} +- +-impl Iterator for GrubEnvParser { +- type Item = (OsString, OsString); +- +- fn next(&mut self) -> Option { +- for line in (&mut self.lines).flatten() { +- if line.starts_with("#") { +- continue; +- } +- +- let str = line.trim(); +- if str.is_empty() { +- continue; +- } +- +- let mut kv = line.split('='); +- if let (Some(key), Some(value)) = (kv.next(), kv.next()) { +- return Some((key.trim().to_os_string(), value.trim().to_os_string())); +- } +- } +- +- None +- } +-} +- +-fn get_boot_type() -> BootType { +- const UEFI_SYS_INTERFACE: &str = "/sys/firmware/efi"; +- +- match fs::metadata(UEFI_SYS_INTERFACE) { +- Ok(_) => BootType::Uefi, +- Err(_) => BootType::Csm, +- } +-} +- +-fn get_grub_path(boot_type: BootType) -> PathBuf { +- const CSM_GRUB_PATH: &str = "/boot/grub2"; +- const UEFI_GRUB_PATH: &str = "/boot/efi/EFI"; +- +- match boot_type { +- BootType::Csm => PathBuf::from(CSM_GRUB_PATH), +- BootType::Uefi => PathBuf::from(UEFI_GRUB_PATH), +- } +-} +- +-fn find_grub_config>(grub_root: P) -> std::io::Result { +- const GRUB_CFG_NAME: &str = "grub.cfg"; +- +- fs::find_file( +- grub_root, +- GRUB_CFG_NAME, +- fs::FindOptions { +- fuzz: false, +- recursive: true, +- }, +- ) +-} +- +-fn find_grub_env>(grub_root: P) -> std::io::Result { +- const GRUB_ENV_NAME: &str = "grubenv"; +- +- fs::find_file( +- grub_root, +- GRUB_ENV_NAME, +- fs::FindOptions { +- fuzz: false, +- recursive: true, +- }, +- ) +-} +- +-pub fn read_menu_entries>(grub_root: P) -> std::io::Result> { +- let grub_config = find_grub_config(grub_root)?; +- +- let result = GrubConfigParser::new(BufReader::new(fs::open_file(grub_config)?)).collect(); +- +- Ok(result) +-} +- +-pub fn read_grub_env>(grub_root: P) -> std::io::Result> { +- let grub_env = find_grub_env(grub_root).unwrap(); +- +- let result = GrubEnvParser::new(BufReader::new(fs::open_file(grub_env)?)).collect(); +- +- Ok(result) +-} +- +-pub fn get_boot_entry() -> std::io::Result { +- let boot_type = get_boot_type(); +- let grub_root = get_grub_path(boot_type); +- debug!("Boot type: {:?}", boot_type); +- +- let menu_entries = read_menu_entries(&grub_root)?; +- debug!("Boot entries: {:#?}", menu_entries); +- +- let grub_env = read_grub_env(&grub_root)?; +- let default_entry_name = grub_env.get(OsStr::new("saved_entry")).ok_or_else(|| { +- std::io::Error::new( +- std::io::ErrorKind::Other, +- "Cannot read grub default entry name", +- ) +- })?; +- debug!("Default entry: {:?}", default_entry_name); +- +- for entry in menu_entries { +- if entry.get_name() == default_entry_name { +- return Ok(entry); +- } +- } +- +- Err(std::io::Error::new( +- std::io::ErrorKind::Other, +- format!("Cannot find grub default entry {:?}", default_entry_name), +- )) +-} +diff --git a/syscare-common/src/os/kernel.rs b/syscare-common/src/os/kernel.rs +index b89850b..a29e663 100644 +--- a/syscare-common/src/os/kernel.rs ++++ b/syscare-common/src/os/kernel.rs +@@ -12,51 +12,10 @@ + * See the Mulan PSL v2 for more details. + */ + +-use std::{ffi::OsStr, path::Path}; +- +-use anyhow::Result; +- +-const KEXEC_PATH: &str = "kexec"; +-const SYSTEMCTL_PATH: &str = "systemctl"; ++use std::ffi::OsStr; + + use super::platform; +-use crate::{concat_os, process::Command}; + + pub fn version() -> &'static OsStr { + platform::release() + } +- +-pub fn load(kernel: P, initramfs: Q) -> Result<()> +-where +- P: AsRef, +- Q: AsRef, +-{ +- Command::new(KEXEC_PATH) +- .arg("--load") +- .arg(kernel.as_ref()) +- .arg(concat_os!("--initrd=", initramfs.as_ref())) +- .arg("--reuse-cmdline") +- .run_with_output()? +- .exit_ok() +-} +- +-pub fn unload() -> Result<()> { +- Command::new(KEXEC_PATH) +- .arg("--unload") +- .run_with_output()? +- .exit_ok() +-} +- +-pub fn systemd_exec() -> Result<()> { +- Command::new(SYSTEMCTL_PATH) +- .arg("kexec") +- .run_with_output()? +- .exit_ok() +-} +- +-pub fn force_exec() -> Result<()> { +- Command::new(KEXEC_PATH) +- .arg("--exec") +- .run_with_output()? +- .exit_ok() +-} +diff --git a/syscare-common/src/os/mod.rs b/syscare-common/src/os/mod.rs +index 8e6d5c1..6a93a20 100644 +--- a/syscare-common/src/os/mod.rs ++++ b/syscare-common/src/os/mod.rs +@@ -13,8 +13,6 @@ + */ + + pub mod cpu; +-pub mod disk; +-pub mod grub; + pub mod kernel; + pub mod platform; + pub mod proc_maps; +diff --git a/syscare-common/src/util/digest.rs b/syscare-common/src/util/digest.rs +index bb879cb..086b636 100644 +--- a/syscare-common/src/util/digest.rs ++++ b/syscare-common/src/util/digest.rs +@@ -45,10 +45,3 @@ where + + Ok(format!("{:#x}", hasher.finalize())) + } +- +-pub fn dir>(directory: P) -> std::io::Result { +- file_list(fs::list_files( +- directory, +- fs::TraverseOptions { recursive: true }, +- )?) +-} +diff --git a/syscared/src/fast_reboot/manager.rs b/syscared/src/fast_reboot/manager.rs +deleted file mode 100644 +index 8a4a928..0000000 +--- a/syscared/src/fast_reboot/manager.rs ++++ /dev/null +@@ -1,123 +0,0 @@ +-// SPDX-License-Identifier: Mulan PSL v2 +-/* +- * Copyright (c) 2024 Huawei Technologies Co., Ltd. +- * syscared is licensed under Mulan PSL v2. +- * You can use this software according to the terms and conditions of the Mulan PSL v2. +- * You may obtain a copy of Mulan PSL v2 at: +- * http://license.coscl.org.cn/MulanPSL2 +- * +- * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +- * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +- * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +- * See the Mulan PSL v2 for more details. +- */ +- +-use std::path::PathBuf; +- +-use anyhow::{Context, Result}; +-use lazy_static::lazy_static; +-use log::{error, info}; +- +-use syscare_common::{ +- fs, +- os::{grub, kernel}, +-}; +- +-lazy_static! { +- static ref BOOT_DIRECTORY: PathBuf = PathBuf::from("/boot"); +-} +- +-pub enum RebootOption { +- Normal, +- Forced, +-} +- +-struct LoadKernelOption { +- name: String, +- kernel: PathBuf, +- initramfs: PathBuf, +-} +- +-pub struct KExecManager; +- +-impl KExecManager { +- fn find_kernel(kernel_version: &str) -> Result { +- info!("Finding kernel {}...", kernel_version); +- let kernel_file_name = format!("vmlinuz-{}", kernel_version); +- let kernel_file = fs::find_file( +- BOOT_DIRECTORY.as_path(), +- kernel_file_name, +- fs::FindOptions { +- fuzz: false, +- recursive: false, +- }, +- ) +- .with_context(|| format!("Cannot find kernel {}", kernel_version))?; +- +- info!("Finding initramfs..."); +- let initramfs_file_name = format!("initramfs-{}.img", kernel_version); +- let initramfs_file = fs::find_file( +- BOOT_DIRECTORY.as_path(), +- initramfs_file_name, +- fs::FindOptions { +- fuzz: false, +- recursive: false, +- }, +- ) +- .with_context(|| format!("Cannot find kernel {} initramfs", kernel_version))?; +- +- Ok(LoadKernelOption { +- name: kernel_version.to_owned(), +- kernel: kernel_file, +- initramfs: initramfs_file, +- }) +- } +- +- fn find_kernel_by_grub() -> Result { +- info!("Parsing grub configuration..."); +- let entry = grub::get_boot_entry().context("Failed to read grub boot entry")?; +- let entry_name = entry +- .get_name() +- .to_str() +- .context("Failed to parse grub entry name")?; +- +- Ok(LoadKernelOption { +- name: entry_name.to_owned(), +- kernel: entry.get_kernel(), +- initramfs: entry.get_initrd(), +- }) +- } +- +- pub fn load_kernel(kernel_version: Option) -> Result<()> { +- let load_option = match kernel_version { +- Some(version) => Self::find_kernel(&version), +- None => Self::find_kernel_by_grub().or_else(|e| { +- error!("{:?}", e); +- let version: &str = kernel::version() +- .to_str() +- .context("Failed to parse current kernel version")?; +- +- Self::find_kernel(version) +- }), +- }?; +- +- kernel::unload().context("Failed to unload kernel")?; +- +- let name = load_option.name; +- let kernel = load_option.kernel; +- let initramfs = load_option.initramfs; +- info!("Loading {:?}", name); +- info!("Using kernel: {:?}", kernel); +- info!("Using initrd: {:?}", initramfs); +- +- kernel::load(&kernel, &initramfs).context("Failed to load kernel") +- } +- +- pub fn execute(option: RebootOption) -> Result<()> { +- match option { +- RebootOption::Normal => kernel::systemd_exec(), +- RebootOption::Forced => kernel::force_exec(), +- } +- .context("Failed to execute kernel") +- } +-} +diff --git a/syscared/src/fast_reboot/mod.rs b/syscared/src/fast_reboot/mod.rs +deleted file mode 100644 +index 8c40eb9..0000000 +--- a/syscared/src/fast_reboot/mod.rs ++++ /dev/null +@@ -1,17 +0,0 @@ +-// SPDX-License-Identifier: Mulan PSL v2 +-/* +- * Copyright (c) 2024 Huawei Technologies Co., Ltd. +- * syscared is licensed under Mulan PSL v2. +- * You can use this software according to the terms and conditions of the Mulan PSL v2. +- * You may obtain a copy of Mulan PSL v2 at: +- * http://license.coscl.org.cn/MulanPSL2 +- * +- * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +- * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +- * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +- * See the Mulan PSL v2 for more details. +- */ +- +-mod manager; +- +-pub use manager::*; +diff --git a/syscared/src/main.rs b/syscared/src/main.rs +index 5c60ecf..f13a9f8 100644 +--- a/syscared/src/main.rs ++++ b/syscared/src/main.rs +@@ -32,17 +32,13 @@ use syscare_common::{concat_os, fs, os}; + + mod args; + mod config; +-mod fast_reboot; + mod patch; + mod rpc; + + use args::Arguments; + use config::Config; + use patch::monitor::PatchMonitor; +-use rpc::{ +- skeleton::{FastRebootSkeleton, PatchSkeleton}, +- skeleton_impl::{FastRebootSkeletonImpl, PatchSkeletonImpl}, +-}; ++use rpc::{skeleton::PatchSkeleton, skeleton_impl::PatchSkeletonImpl}; + + const DAEMON_NAME: &str = env!("CARGO_PKG_NAME"); + const DAEMON_VERSION: &str = env!("CARGO_PKG_VERSION"); +@@ -195,7 +191,6 @@ impl Daemon { + let mut io_handler = IoHandler::new(); + + io_handler.extend_with(PatchSkeletonImpl::new(patch_manager).to_delegate()); +- io_handler.extend_with(FastRebootSkeletonImpl.to_delegate()); + + Ok(io_handler) + } +diff --git a/syscared/src/rpc/skeleton/fast_reboot.rs b/syscared/src/rpc/skeleton/fast_reboot.rs +deleted file mode 100644 +index 1a7b496..0000000 +--- a/syscared/src/rpc/skeleton/fast_reboot.rs ++++ /dev/null +@@ -1,21 +0,0 @@ +-// SPDX-License-Identifier: Mulan PSL v2 +-/* +- * Copyright (c) 2024 Huawei Technologies Co., Ltd. +- * syscared is licensed under Mulan PSL v2. +- * You can use this software according to the terms and conditions of the Mulan PSL v2. +- * You may obtain a copy of Mulan PSL v2 at: +- * http://license.coscl.org.cn/MulanPSL2 +- * +- * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +- * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +- * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +- * See the Mulan PSL v2 for more details. +- */ +- +-use super::function::{rpc, RpcResult}; +- +-#[rpc(server)] +-pub trait FastRebootSkeleton { +- #[rpc(name = "fast_reboot")] +- fn fast_reboot(&self, kernel_version: Option, force: bool) -> RpcResult<()>; +-} +diff --git a/syscared/src/rpc/skeleton/mod.rs b/syscared/src/rpc/skeleton/mod.rs +index 74456ca..6fa6b60 100644 +--- a/syscared/src/rpc/skeleton/mod.rs ++++ b/syscared/src/rpc/skeleton/mod.rs +@@ -14,8 +14,6 @@ + + use super::function; + +-mod fast_reboot; + mod patch; + +-pub use fast_reboot::*; + pub use patch::*; +diff --git a/syscared/src/rpc/skeleton_impl/fast_reboot.rs b/syscared/src/rpc/skeleton_impl/fast_reboot.rs +deleted file mode 100644 +index aeab458..0000000 +--- a/syscared/src/rpc/skeleton_impl/fast_reboot.rs ++++ /dev/null +@@ -1,42 +0,0 @@ +-// SPDX-License-Identifier: Mulan PSL v2 +-/* +- * Copyright (c) 2024 Huawei Technologies Co., Ltd. +- * syscared is licensed under Mulan PSL v2. +- * You can use this software according to the terms and conditions of the Mulan PSL v2. +- * You may obtain a copy of Mulan PSL v2 at: +- * http://license.coscl.org.cn/MulanPSL2 +- * +- * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +- * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +- * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +- * See the Mulan PSL v2 for more details. +- */ +- +-use anyhow::{Context, Result}; +- +-use crate::fast_reboot::{KExecManager, RebootOption}; +-use log::info; +- +-use super::{ +- function::{RpcFunction, RpcResult}, +- skeleton::FastRebootSkeleton, +-}; +- +-pub struct FastRebootSkeletonImpl; +- +-impl FastRebootSkeleton for FastRebootSkeletonImpl { +- fn fast_reboot(&self, kernel_version: Option, force: bool) -> RpcResult<()> { +- RpcFunction::call(move || -> Result<()> { +- info!("Rebooting system..."); +- +- KExecManager::load_kernel(kernel_version) +- .and_then(|_| { +- KExecManager::execute(match force { +- true => RebootOption::Forced, +- false => RebootOption::Normal, +- }) +- }) +- .context("Failed to reboot system") +- }) +- } +-} +diff --git a/syscared/src/rpc/skeleton_impl/mod.rs b/syscared/src/rpc/skeleton_impl/mod.rs +index a238df4..7037946 100644 +--- a/syscared/src/rpc/skeleton_impl/mod.rs ++++ b/syscared/src/rpc/skeleton_impl/mod.rs +@@ -15,8 +15,6 @@ + use super::function; + use super::skeleton; + +-mod fast_reboot; + mod patch; + +-pub use fast_reboot::*; + pub use patch::*; +-- +2.34.1 + diff --git a/0025-all-add-c-rust-compilation-options.patch b/0025-all-add-c-rust-compilation-options.patch new file mode 100644 index 0000000000000000000000000000000000000000..0d87d3e934c1c770bca1c65933315d3778d5d443 --- /dev/null +++ b/0025-all-add-c-rust-compilation-options.patch @@ -0,0 +1,2283 @@ +From 85fced2e3cf1e6cf70beb86e8486454299971c3f Mon Sep 17 00:00:00 2001 +From: ningyu +Date: Wed, 5 Jun 2024 03:08:47 +0000 +Subject: [PATCH] all: add c & rust compilation options + +Signed-off-by: ningyu +--- + CMakeLists.txt | 13 ++- + upatch-diff/create-diff-object.c | 38 +++---- + upatch-diff/elf-common.c | 8 +- + upatch-diff/elf-common.h | 14 +-- + upatch-diff/elf-compare.c | 10 +- + upatch-diff/elf-correlate.c | 16 +-- + upatch-diff/elf-create.c | 22 ++--- + upatch-diff/elf-create.h | 4 +- + upatch-diff/elf-debug.c | 14 +-- + upatch-diff/elf-insn.c | 4 +- + upatch-diff/insn/asm/inat.h | 4 +- + upatch-diff/insn/asm/insn.h | 6 +- + upatch-diff/insn/insn.c | 4 +- + upatch-diff/list.h | 2 +- + upatch-diff/running-elf.c | 11 +-- + upatch-diff/upatch-elf.c | 6 +- + upatch-diff/upatch-elf.h | 2 +- + upatch-hijacker/hijacker/gnu-as-hijacker.c | 10 +- + .../hijacker/gnu-compiler-hijacker.c | 4 +- + upatch-hijacker/hijacker/hijacker.h | 4 +- + upatch-manage/arch/aarch64/insn.c | 12 +-- + upatch-manage/arch/aarch64/insn.h | 4 +- + upatch-manage/arch/aarch64/ptrace.c | 53 +++++----- + upatch-manage/arch/aarch64/relocation.c | 98 +++++++++---------- + upatch-manage/arch/x86_64/ptrace.c | 41 ++++---- + upatch-manage/arch/x86_64/relocation.c | 5 +- + upatch-manage/arch/x86_64/resolve.c | 3 +- + upatch-manage/upatch-common.h | 4 +- + upatch-manage/upatch-elf.c | 16 +-- + upatch-manage/upatch-elf.h | 12 +-- + upatch-manage/upatch-manage.c | 24 ++--- + upatch-manage/upatch-patch.c | 79 +++++++-------- + upatch-manage/upatch-process.c | 33 ++++--- + upatch-manage/upatch-process.h | 2 +- + upatch-manage/upatch-ptrace.c | 45 ++++----- + upatch-manage/upatch-ptrace.h | 25 ++--- + upatch-manage/upatch-resolve.c | 17 ++-- + upatch-manage/upatch-resolve.h | 2 +- + 38 files changed, 324 insertions(+), 347 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index c7838a8..4858ba5 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -54,8 +54,15 @@ message("---------------------------------------------------------") + + # Compile options + add_compile_options(-DBUILD_VERSION="${BUILD_VERSION}") +-add_compile_options(-g -Wall -O2 -fPIE) +- ++add_compile_options(-std=gnu99 -g -Wall -D_FORTIFY_SOURCE=2 -O2 -Werror -Wextra ++ -Wtrampolines -Wformat=2 -Wstrict-prototypes -Wdate-time -Wstack-usage=8192 ++ -Wfloat-equal -Wswitch-default -Wshadow -Wconversion -Wcast-qual -Wcast-align ++ -Wunused -Wundef -funsigned-char -fstack-protector-all -fpic -fpie -ftrapv ++ -fstack-check -freg-struct-return -fno-canonical-system-headers -pipe ++ -fdebug-prefix-map=old=new) ++set(LINK_FLAGS "-pie -Wl,-z,relro,-z,now -Wl,-z,noexecstack -rdynamic -Wl,-Bsymbolic -Wl,-no-undefined") ++set(CMAKE_SHARED_LINKER_FLAGS "${LINK_FLAGS}") ++set(CMAKE_EXE_LINKER_FLAGS "${LINK_FLAGS}") + # Subdirectories + add_subdirectory(upatch-diff) + add_subdirectory(upatch-manage) +@@ -67,7 +74,7 @@ add_custom_target(rust-executables ALL + COMMENT "Building rust executables..." + COMMAND ${CMAKE_COMMAND} -E env + "BUILD_VERSION=${BUILD_VERSION}" +- "RUSTFLAGS=--cfg unsound_local_offset" ++ "RUSTFLAGS=--cfg unsound_local_offset -C relocation_model=pic -D warnings -C link-arg=-s -C overflow_checks -W rust_2021_incompatible_closure_captures" + cargo build --release --target-dir ${CMAKE_CURRENT_BINARY_DIR} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + ) +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index 1a05869..6474b22 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -76,11 +76,11 @@ struct arguments { + }; + + static struct argp_option options[] = { +- {"debug", 'd', NULL, 0, "Show debug output"}, +- {"source", 's', "source", 0, "Source object"}, +- {"patched", 'p', "patched", 0, "Patched object"}, +- {"running", 'r', "running", 0, "Running binary file"}, +- {"output", 'o', "output", 0, "Output object"}, ++ {"debug", 'd', NULL, 0, "Show debug output", 0}, ++ {"source", 's', "source", 0, "Source object", 0}, ++ {"patched", 'p', "patched", 0, "Patched object", 0}, ++ {"running", 'r', "running", 0, "Running binary file", 0}, ++ {"output", 'o', "output", 0, "Output object", 0}, + {NULL} + }; + +@@ -136,7 +136,7 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) + return 0; + } + +-static struct argp argp = {options, parse_opt, args_doc, program_doc}; ++static struct argp argp = {options, parse_opt, args_doc, program_doc, NULL, NULL, NULL}; + + /* + * Key point for chreate-diff-object: +@@ -266,7 +266,7 @@ static void bundle_symbols(struct upatch_elf *uelf) + list_for_each_entry(sym, &uelf->symbols, list) { + if (is_bundleable(sym)) { + if (sym->sym.st_value != 0 && +- is_gcc6_localentry_bundled_sym(uelf, sym)) { ++ is_gcc6_localentry_bundled_sym(uelf)) { + ERROR("Symbol '%s' at offset %lu within section '%s', expected 0.", + sym->name, sym->sym.st_value, sym->sec->name); + } +@@ -301,7 +301,7 @@ static void detect_child_functions(struct upatch_elf *uelf) + if (!childstr) + continue; + +- pname = strndup(sym->name, childstr - sym->name); ++ pname = strndup(sym->name, (size_t)(childstr - sym->name)); + log_debug("symbol '%s', pname: '%s'\n", sym->name, pname); + if (!pname) + ERROR("detect_child_functions strndup failed."); +@@ -576,8 +576,8 @@ static void replace_section_syms(struct upatch_elf *uelf) + if (sym->type == STT_SECTION || sym->sec != rela->sym->sec) + continue; + +- start = sym->sym.st_value; +- end = sym->sym.st_value + sym->sym.st_size; ++ start = (long)sym->sym.st_value; ++ end = (long)(sym->sym.st_value + sym->sym.st_size); + + /* text section refer other sections */ + if (is_text_section(relasec->base) && +@@ -638,7 +638,7 @@ static void replace_section_syms(struct upatch_elf *uelf) + if (!found && !is_string_literal_section(rela->sym->sec) && + strncmp(rela->sym->name, ".rodata", strlen(".rodata")) && + strncmp(rela->sym->name, ".data", strlen(".data"))) { +- ERROR("%s+0x%x: Cannot find replacement symbol for '%s+%ld' reference.", ++ ERROR("%s+0x%lx: Cannot find replacement symbol for '%s+%ld' reference.", + relasec->base->name, rela->offset, rela->sym->name, rela->addend); + } + } +@@ -662,8 +662,8 @@ static void mark_ignored_sections(struct upatch_elf *uelf) + } + + /* TODO: we do not handle it now */ +-static void mark_ignored_functions_same(struct upatch_elf *uelf) {} +-static void mark_ignored_sections_same(struct upatch_elf *uelf) {} ++static void mark_ignored_functions_same(void) {} ++static void mark_ignored_sections_same(void) {} + + /* + * For a local symbol referenced in the rela list of a changing function, +@@ -845,7 +845,7 @@ static void include_debug_sections(struct upatch_elf *uelf) + } + + /* currently, there si no special section need to be handled */ +-static void process_special_sections(struct upatch_elf *uelf) {} ++static void process_special_sections(void) {} + + static void verify_patchability(struct upatch_elf *uelf) + { +@@ -973,8 +973,8 @@ int main(int argc, char*argv[]) + mark_file_symbols(&uelf_source); + find_debug_symbol(&uelf_source, &relf); + +- mark_ignored_functions_same(&uelf_patched); +- mark_ignored_sections_same(&uelf_patched); ++ mark_ignored_functions_same(); ++ mark_ignored_sections_same(); + + upatch_elf_teardown(&uelf_source); + upatch_elf_free(&uelf_source); +@@ -990,7 +990,7 @@ int main(int argc, char*argv[]) + + include_debug_sections(&uelf_patched); + +- process_special_sections(&uelf_patched); ++ process_special_sections(); + + upatch_print_changes(&uelf_patched); + +@@ -1011,7 +1011,7 @@ int main(int argc, char*argv[]) + + upatch_create_intermediate_sections(&uelf_out, &relf); + +- create_kpatch_arch_section(&uelf_out); ++ create_kpatch_arch_section(); + + upatch_build_strings_section_data(&uelf_out); + +@@ -1029,7 +1029,7 @@ int main(int argc, char*argv[]) + + upatch_rebuild_relocations(&uelf_out); + +- upatch_check_relocations(&uelf_out); ++ upatch_check_relocations(); + + upatch_create_shstrtab(&uelf_out); + +diff --git a/upatch-diff/elf-common.c b/upatch-diff/elf-common.c +index f895e9b..a74da3a 100644 +--- a/upatch-diff/elf-common.c ++++ b/upatch-diff/elf-common.c +@@ -74,8 +74,10 @@ bool is_normal_static_local(struct symbol *sym) + if (!strchr(sym->name, '.')) + return false; + +- if (is_special_static(sym)) +- return false; ++ /* ++ * TODO: Special static local variables should never be correlated and should always ++ * be included if they are referenced by an included function. ++ */ + + return true; + } +@@ -97,7 +99,7 @@ int offset_of_string(struct list_head *list, char *name) + } + + // no need for X86 +-bool is_gcc6_localentry_bundled_sym(struct upatch_elf *uelf, struct symbol *sym) ++bool is_gcc6_localentry_bundled_sym(struct upatch_elf *uelf) + { + switch(uelf->arch) { + case AARCH64: +diff --git a/upatch-diff/elf-common.h b/upatch-diff/elf-common.h +index 9e44a7c..f3d4308 100644 +--- a/upatch-diff/elf-common.h ++++ b/upatch-diff/elf-common.h +@@ -103,7 +103,7 @@ static inline bool is_debug_section(struct section *sec) + !strncmp(name, ".eh_frame", 9); + } + +-static inline struct symbol *find_symbol_by_index(struct list_head *list, size_t index) ++static inline struct symbol *find_symbol_by_index(struct list_head *list, unsigned int index) + { + struct symbol *sym; + +@@ -174,16 +174,6 @@ static inline bool has_digit_tail(char *tail) + */ + int mangled_strcmp(char *, char *); + +- +-/* +- * TODO: Special static local variables should never be correlated and should always +- * be included if they are referenced by an included function. +- */ +-static inline bool is_special_static(struct symbol *sym){ +- /* Not need it now. */ +- return false; +-} +- + bool is_normal_static_local(struct symbol *); + + static inline char *section_function_name(struct section *sec) +@@ -243,7 +233,7 @@ static inline bool is_local_sym(struct symbol *sym) + return sym->bind == STB_LOCAL; + } + +-bool is_gcc6_localentry_bundled_sym(struct upatch_elf *, struct symbol *); ++bool is_gcc6_localentry_bundled_sym(struct upatch_elf *); + + /* + * Mapping symbols are used to mark and label the transitions between code and +diff --git a/upatch-diff/elf-compare.c b/upatch-diff/elf-compare.c +index ef8dd23..851c25f 100644 +--- a/upatch-diff/elf-compare.c ++++ b/upatch-diff/elf-compare.c +@@ -175,7 +175,7 @@ bool upatch_handle_redis_line(const char *symname) + } + + /* TODO: let user support this list or generate by the compiler ? */ +-bool check_line_func(struct upatch_elf *uelf, const char *symname) ++bool check_line_func(const char *symname) + { + if (!strncmp(basename(g_relf_name), "redis-server", 12)) + return upatch_handle_redis_line(symname); +@@ -247,7 +247,7 @@ static bool _line_macro_change_only(struct upatch_elf *uelf, struct section *sec + continue; + + /* TODO: we may need black list ? */ +- if (check_line_func(uelf, rela->sym->name)) { ++ if (check_line_func(rela->sym->name)) { + found = true; + break; + } +@@ -292,8 +292,8 @@ static bool _line_macro_change_only_aarch64(struct upatch_elf *uelf, struct sect + continue; + + /* verify it's a mov immediate to w1 */ +- if ((*(int *)(start1 + offset) & ~mov_imm_mask) != +- (*(int *)(start2 + offset) & ~mov_imm_mask)) ++ if ((*(unsigned int *)(start1 + offset) & ~mov_imm_mask) != ++ (*(unsigned int *)(start2 + offset) & ~mov_imm_mask)) + return false; + + found = false; +@@ -304,7 +304,7 @@ static bool _line_macro_change_only_aarch64(struct upatch_elf *uelf, struct sect + continue; + + /* TODO: we may need black list ? */ +- if (check_line_func(uelf, rela->sym->name)) { ++ if (check_line_func(rela->sym->name)) { + found = true; + break; + } +diff --git a/upatch-diff/elf-correlate.c b/upatch-diff/elf-correlate.c +index a0fe669..3e3a536 100644 +--- a/upatch-diff/elf-correlate.c ++++ b/upatch-diff/elf-correlate.c +@@ -58,9 +58,10 @@ void upatch_correlate_symbols(struct upatch_elf *uelf_source, struct upatch_elf + sym_orig->type != sym_patched->type || sym_patched->twin) + continue; + +- if (is_special_static(sym_orig)) +- continue; +- ++ /* ++ * TODO: Special static local variables should never be correlated and should always ++ * be included if they are referenced by an included function. ++ */ + /* + * The .LCx symbols point to string literals in + * '.rodata..str1.*' sections. They get included +@@ -140,11 +141,10 @@ void upatch_correlate_sections(struct upatch_elf *uelf_source, struct upatch_elf + sec_patched->twin) + continue; + +- if (is_special_static(is_rela_section(sec_orig) ? +- sec_orig->base->secsym : +- sec_orig->secsym)) +- continue; +- ++ /* ++ * TODO: Special static local variables should never be correlated and should always ++ * be included if they are referenced by an included function. ++ */ + /* + * Group sections must match exactly to be correlated. + */ +diff --git a/upatch-diff/elf-create.c b/upatch-diff/elf-create.c +index 873b3a9..8ac212a 100644 +--- a/upatch-diff/elf-create.c ++++ b/upatch-diff/elf-create.c +@@ -37,7 +37,7 @@ + + /* create text and relocation sections */ + static struct section *create_section_pair(struct upatch_elf *uelf, char *name, +- int entsize, int nr) ++ unsigned int entsize, unsigned int nr) + { + char *relaname; + struct section *sec, *relasec; +@@ -131,7 +131,7 @@ void upatch_create_patches_sections(struct upatch_elf *uelf, struct running_elf + struct upatch_patch_func *funcs; + struct rela *rela; + struct lookup_result symbol; +- int nr = 0, index = 0; ++ unsigned int nr = 0, index = 0; + + /* find changed func */ + list_for_each_entry(sym, &uelf->symbols, list) { +@@ -197,7 +197,7 @@ void upatch_create_patches_sections(struct upatch_elf *uelf, struct running_elf + ERROR("sanity check failed in funcs sections. \n"); + } + +-static bool need_dynrela(struct upatch_elf *uelf, struct running_elf *relf, ++static bool need_dynrela(struct running_elf *relf, + struct section *relasec, struct rela *rela) + { + struct lookup_result symbol; +@@ -234,7 +234,7 @@ void upatch_create_intermediate_sections(struct upatch_elf *uelf, struct running + struct upatch_symbol *usyms; + struct upatch_relocation *urelas; + struct symbol *strsym, *usym_sec_sym; +- int nr = 0, index = 0; ++ unsigned int nr = 0, index = 0; + + list_for_each_entry(relasec, &uelf->sections, list) { + if (!is_rela_section(relasec)) +@@ -245,7 +245,7 @@ void upatch_create_intermediate_sections(struct upatch_elf *uelf, struct running + + list_for_each_entry(rela, &relasec->relas, list) { + nr++; +- if (need_dynrela(uelf, relf, relasec, rela)){ ++ if (need_dynrela(relf, relasec, rela)){ + rela->need_dynrela = 1; + } + } +@@ -401,7 +401,7 @@ static void rebuild_rela_section_data(struct section *sec) + struct rela *rela; + GElf_Rela *relas; + size_t size; +- int nr = 0, index = 0; ++ unsigned int nr = 0, index = 0; + + list_for_each_entry(rela, &sec->relas, list) + nr++; +@@ -438,13 +438,13 @@ void upatch_rebuild_relocations(struct upatch_elf *uelf) + list_for_each_entry(relasec, &uelf->sections, list) { + if (!is_rela_section(relasec)) + continue; +- relasec->sh.sh_link = symtab->index; +- relasec->sh.sh_info = relasec->base->index; ++ relasec->sh.sh_link = (Elf64_Word)symtab->index; ++ relasec->sh.sh_info = (Elf64_Word)relasec->base->index; + rebuild_rela_section_data(relasec); + } + } + +-void upatch_check_relocations(struct upatch_elf *uelf) ++void upatch_check_relocations(void) + { + log_debug("upatch_check_relocations does not work now.\n"); + return; +@@ -558,7 +558,7 @@ void upatch_create_symtab(struct upatch_elf *uelf) + struct symbol *sym; + size_t size; + char *buf; +- int nr = 0, nr_local = 0; ++ unsigned int nr = 0, nr_local = 0; + unsigned long offset = 0; + + symtab = find_section_by_name(&uelf->sections, ".symtab"); +@@ -591,7 +591,7 @@ void upatch_create_symtab(struct upatch_elf *uelf) + if (!strtab) + ERROR("missing .strtab section in create symtab."); + +- symtab->sh.sh_link = strtab->index; ++ symtab->sh.sh_link = (Elf64_Word)strtab->index; + symtab->sh.sh_info = nr_local; + } + +diff --git a/upatch-diff/elf-create.h b/upatch-diff/elf-create.h +index 1b4dc6c..ce7f263 100644 +--- a/upatch-diff/elf-create.h ++++ b/upatch-diff/elf-create.h +@@ -33,7 +33,7 @@ void upatch_create_patches_sections(struct upatch_elf *, struct running_elf *); + + void upatch_create_intermediate_sections(struct upatch_elf *, struct running_elf *); + +-static inline void create_kpatch_arch_section(struct upatch_elf *uelf) {} ++static inline void create_kpatch_arch_section(void) {} + + void upatch_build_strings_section_data(struct upatch_elf *); + +@@ -45,7 +45,7 @@ void upatch_reindex_elements(struct upatch_elf *); + + void upatch_rebuild_relocations(struct upatch_elf *); + +-void upatch_check_relocations(struct upatch_elf *); ++void upatch_check_relocations(void); + + void upatch_create_shstrtab(struct upatch_elf *); + +diff --git a/upatch-diff/elf-debug.c b/upatch-diff/elf-debug.c +index f9c5327..eaabfa1 100644 +--- a/upatch-diff/elf-debug.c ++++ b/upatch-diff/elf-debug.c +@@ -60,7 +60,7 @@ void upatch_dump_kelf(struct upatch_elf *uelf) + goto next; + log_debug("rela section expansion\n"); + list_for_each_entry(rela, &sec->relas, list) { +- log_debug("sym %d, offset %d, type %d, %s %s %ld \n", ++ log_debug("sym %d, offset %ld, type %d, %s %s %ld \n", + rela->sym->index, rela->offset, + rela->type, rela->sym->name, + (rela->addend < 0) ? "-" : "+", +@@ -107,7 +107,7 @@ void upatch_rebuild_eh_frame(struct section *sec) + struct rela *rela; + unsigned char *data, *data_end; + unsigned int hdr_length, hdr_id; +- unsigned int current_offset; ++ unsigned long current_offset; + unsigned int count = 0; + + /* sanity check */ +@@ -136,13 +136,13 @@ void upatch_rebuild_eh_frame(struct section *sec) + /* 8 is the offset of PC begin */ + current_offset = 8; + list_for_each_entry(rela, &sec->rela->relas, list) { +- unsigned int offset = rela->offset; ++ unsigned long offset = rela->offset; + bool found_rela = false; +- log_debug("handle relocaton offset at 0x%x \n", offset); ++ log_debug("handle relocaton offset at 0x%lx \n", offset); + while (data != data_end) { + void *__src = data; + +- log_debug("current handle offset is 0x%x \n", current_offset); ++ log_debug("current handle offset is 0x%lx \n", current_offset); + + REQUIRE(skip_bytes(&data, data_end, 4), "no length to be read"); + hdr_length = *(unsigned int *)(data - 4); +@@ -166,13 +166,13 @@ void upatch_rebuild_eh_frame(struct section *sec) + /* update rela offset to point to new offset, and also hdr_id */ + if (found_rela) { + /* 4 is the offset of hdr_id and 8 is the offset of PC begin */ +- *(unsigned int *)(eh_frame + frame_size + 4) = frame_size + 4; ++ *(unsigned long *)(eh_frame + frame_size + 4) = frame_size + 4; + rela->offset = frame_size + 8; + } + + frame_size += (hdr_length + 4); + } else { +- log_debug("remove FDE at 0x%x \n", current_offset); ++ log_debug("remove FDE at 0x%lx \n", current_offset); + } + + /* hdr_length(value) + hdr_length(body) */ +diff --git a/upatch-diff/elf-insn.c b/upatch-diff/elf-insn.c +index 41252fe..11380d0 100644 +--- a/upatch-diff/elf-insn.c ++++ b/upatch-diff/elf-insn.c +@@ -50,7 +50,7 @@ void rela_insn(const struct section *sec, const struct rela *rela, struct insn * + return; + } + +- ERROR("can't find instruction for rela at %s+0x%x", ++ ERROR("can't find instruction for rela at %s+0x%lx", + sec->name, rela->offset); + } + +@@ -75,7 +75,7 @@ long rela_target_offset(struct upatch_elf *uelf, struct section *relasec, struct + rela_insn(sec, rela, &insn); + add_off = (long)insn.next_byte - + (long)sec->data->d_buf - +- rela->offset; ++ (long)rela->offset; + } else { + ERROR("unable to handle rela type %d \n", rela->type); + } +diff --git a/upatch-diff/insn/asm/inat.h b/upatch-diff/insn/asm/inat.h +index 95811f3..f446ad8 100644 +--- a/upatch-diff/insn/asm/inat.h ++++ b/upatch-diff/insn/asm/inat.h +@@ -171,9 +171,9 @@ static inline int inat_group_id(insn_attr_t attr) + return (attr & INAT_GRP_MASK) >> INAT_GRP_OFFS; + } + +-static inline int inat_group_common_attribute(insn_attr_t attr) ++static inline insn_attr_t inat_group_common_attribute(insn_attr_t attr) + { +- return attr & ~INAT_GRP_MASK; ++ return attr & ~(insn_attr_t)INAT_GRP_MASK; + } + + static inline int inat_has_immediate(insn_attr_t attr) +diff --git a/upatch-diff/insn/asm/insn.h b/upatch-diff/insn/asm/insn.h +index 041b351..fc4ae40 100644 +--- a/upatch-diff/insn/asm/insn.h ++++ b/upatch-diff/insn/asm/insn.h +@@ -66,7 +66,7 @@ struct insn { + unsigned char x86_64; + + const insn_byte_t *kaddr; /* kernel address of insn to analyze */ +- const insn_byte_t *next_byte; ++ insn_byte_t *next_byte; + }; + + #define MAX_INSN_SIZE 16 +@@ -97,7 +97,7 @@ struct insn { + #define X86_VEX_P(vex) ((vex) & 0x03) /* VEX3 Byte2, VEX2 Byte1 */ + #define X86_VEX_M_MAX 0x1f /* VEX3.M Maximum value */ + +-extern void insn_init(struct insn *insn, const void *kaddr, int x86_64); ++extern void insn_init(struct insn *insn, void *kaddr, int x86_64); + extern void insn_get_prefixes(struct insn *insn); + extern void insn_get_opcode(struct insn *insn); + extern void insn_get_modrm(struct insn *insn); +@@ -116,7 +116,7 @@ static inline void insn_get_attribute(struct insn *insn) + extern int insn_rip_relative(struct insn *insn); + + /* Init insn for kernel text */ +-static inline void kernel_insn_init(struct insn *insn, const void *kaddr) ++static inline void kernel_insn_init(struct insn *insn, void *kaddr) + { + #ifdef CONFIG_X86_64 + insn_init(insn, kaddr, 1); +diff --git a/upatch-diff/insn/insn.c b/upatch-diff/insn/insn.c +index 6dfca32..d9a356b 100644 +--- a/upatch-diff/insn/insn.c ++++ b/upatch-diff/insn/insn.c +@@ -49,7 +49,7 @@ + * @kaddr: address (in kernel memory) of instruction (or copy thereof) + * @x86_64: !0 for 64-bit kernel or 64-bit app + */ +-void insn_init(struct insn *insn, const void *kaddr, int x86_64) ++void insn_init(struct insn *insn, void *kaddr, int x86_64) + { + memset(insn, 0, sizeof(*insn)); + insn->kaddr = kaddr; +@@ -250,7 +250,7 @@ void insn_get_modrm(struct insn *insn) + modrm->value = mod; + modrm->nbytes = 1; + if (inat_is_group(insn->attr)) { +- pfx_id = insn_last_prefix_id(insn); ++ pfx_id = (insn_byte_t)insn_last_prefix_id(insn); + insn->attr = inat_get_group_attribute(mod, pfx_id, + insn->attr); + if (insn_is_avx(insn) && !inat_accept_vex(insn->attr)) +diff --git a/upatch-diff/list.h b/upatch-diff/list.h +index 6205a72..b3b28e1 100644 +--- a/upatch-diff/list.h ++++ b/upatch-diff/list.h +@@ -49,7 +49,7 @@ + * + */ + #define container_of(ptr, type, member) ({ \ +- const typeof( ((type *)0)->member ) *__mptr = (ptr); \ ++ typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + + /** +diff --git a/upatch-diff/running-elf.c b/upatch-diff/running-elf.c +index 676880f..25b72b7 100644 +--- a/upatch-diff/running-elf.c ++++ b/upatch-diff/running-elf.c +@@ -38,7 +38,7 @@ + /* TODO: need to judge whether running_elf is a Position-Independent Executable file + * https://github.com/bminor/binutils-gdb/blob/master/binutils/readelf.c + */ +-static bool is_pie(struct Elf *elf) ++static bool is_pie(void) + { + return true; + } +@@ -50,7 +50,7 @@ static bool is_exec(struct Elf *elf) + if (!gelf_getehdr(elf, &ehdr)) + ERROR("gelf_getehdr running_file failed for %s.", elf_errmsg(0)); + +- return ehdr.e_type == ET_EXEC || (ehdr.e_type == ET_DYN && is_pie(elf)); ++ return ehdr.e_type == ET_EXEC || (ehdr.e_type == ET_DYN && is_pie()); + } + + void relf_init(char *elf_name, struct running_elf *relf) +@@ -59,7 +59,6 @@ void relf_init(char *elf_name, struct running_elf *relf) + Elf_Scn *scn = NULL; + Elf_Data *data; + GElf_Sym sym; +- unsigned int i; + + relf->fd = open(elf_name, O_RDONLY); + if (relf->fd == -1) +@@ -83,12 +82,12 @@ void relf_init(char *elf_name, struct running_elf *relf) + if (!data) + ERROR("elf_getdata with error %s", elf_errmsg(0)); + +- relf->obj_nr = shdr.sh_size / shdr.sh_entsize; +- relf->obj_syms = calloc(relf->obj_nr, sizeof(struct debug_symbol)); ++ relf->obj_nr = (int)(shdr.sh_size / shdr.sh_entsize); ++ relf->obj_syms = calloc((size_t)relf->obj_nr, sizeof(struct debug_symbol)); + if (!relf->obj_syms) + ERROR("calloc with errno = %d", errno); + +- for (i = 0; i < relf->obj_nr; i ++) { ++ for (int i = 0; i < relf->obj_nr; i ++) { + if (!gelf_getsym(data, i, &sym)) + ERROR("gelf_getsym with error %s", elf_errmsg(0)); + relf->obj_syms[i].name = elf_strptr(relf->elf, shdr.sh_link, sym.st_name); +diff --git a/upatch-diff/upatch-elf.c b/upatch-diff/upatch-elf.c +index fc4396a..ee38efc 100644 +--- a/upatch-diff/upatch-elf.c ++++ b/upatch-diff/upatch-elf.c +@@ -106,7 +106,7 @@ static void create_symbol_list(struct upatch_elf *uelf) + INIT_LIST_HEAD(&sym->children); + + sym->index = index; +- if (!gelf_getsym(symtab->data, index, &sym->sym)) ++ if (!gelf_getsym(symtab->data, (int)index, &sym->sym)) + ERROR("gelf_getsym with error %s", elf_errmsg(0)); + + index ++; +@@ -122,7 +122,7 @@ static void create_symbol_list(struct upatch_elf *uelf) + /* releated section located in extended header */ + if (shndx == SHN_XINDEX && + !gelf_getsymshndx(symtab->data, uelf->symtab_shndx, +- sym->index, &sym->sym, &shndx)) ++ (int)sym->index, &sym->sym, &shndx)) + ERROR("gelf_getsymshndx with error %s", elf_errmsg(0)); + + if ((sym->sym.st_shndx > SHN_UNDEF && sym->sym.st_shndx < SHN_LORESERVE) || +@@ -206,7 +206,7 @@ static void create_rela_list(struct upatch_elf *uelf, struct section *relasec) + if (skip) + continue; + +- log_debug("offset %d, type %d, %s %s %ld", rela->offset, ++ log_debug("offset %ld, type %d, %s %s %ld", rela->offset, + rela->type, rela->sym->name, + (rela->addend < 0) ? "-" : "+", labs(rela->addend)); + if (rela->string) // rela->string is not utf8 +diff --git a/upatch-diff/upatch-elf.h b/upatch-diff/upatch-elf.h +index b2d038b..3cbb59b 100644 +--- a/upatch-diff/upatch-elf.h ++++ b/upatch-diff/upatch-elf.h +@@ -87,7 +87,7 @@ struct rela { + GElf_Rela rela; + struct symbol *sym; + unsigned int type; +- unsigned int offset; ++ unsigned long offset; + long addend; + char *string; + bool need_dynrela; +diff --git a/upatch-hijacker/hijacker/gnu-as-hijacker.c b/upatch-hijacker/hijacker/gnu-as-hijacker.c +index 789ddc2..860a84f 100644 +--- a/upatch-hijacker/hijacker/gnu-as-hijacker.c ++++ b/upatch-hijacker/hijacker/gnu-as-hijacker.c +@@ -28,11 +28,9 @@ + + #define DEFSYM_MAX 64 + +-static const char *DEFSYM_FLAG = "--defsym"; +-static const char *DEFSYM_VALUE = ".upatch_0x%x="; ++static char *DEFSYM_FLAG = "--defsym"; + static const int APPEND_ARG_LEN = 2; + +-static const char *OUTPUT_PATH = "%s/0x%x.o"; + static const char *NULL_DEV_PATH = "/dev/null"; + + static char g_defsym[DEFSYM_MAX] = { 0 }; +@@ -81,7 +79,7 @@ int main(int argc, char *argv[], char *envp[]) + } + + int new_argc = argc + APPEND_ARG_LEN + 1; // include terminator NULL +- const char **new_argv = calloc(1, new_argc * sizeof(char *)); ++ char **new_argv = calloc(1, (unsigned long)new_argc * sizeof(char *)); + if (new_argv == NULL) { + return execve(filename, argv, envp); + } +@@ -100,13 +98,13 @@ int main(int argc, char *argv[], char *envp[]) + char *defsym_value = (char *)g_defsym; + char *new_output_file = (char *)g_new_output_file; + +- snprintf(defsym_value, DEFSYM_MAX, DEFSYM_VALUE, tid); ++ snprintf(defsym_value, DEFSYM_MAX, ".upatch_0x%x=", tid); + new_argv[new_argc++] = DEFSYM_FLAG; + new_argv[new_argc++] = defsym_value; + new_argv[new_argc] = NULL; + + // Handle output file +- snprintf(new_output_file, PATH_MAX, OUTPUT_PATH, output_dir, tid); ++ snprintf(new_output_file, PATH_MAX, "%s/0x%x.o", output_dir, tid); + new_argv[output_index] = new_output_file; + + if (access(output_file, F_OK) == 0) { +diff --git a/upatch-hijacker/hijacker/gnu-compiler-hijacker.c b/upatch-hijacker/hijacker/gnu-compiler-hijacker.c +index d0410a2..d868467 100644 +--- a/upatch-hijacker/hijacker/gnu-compiler-hijacker.c ++++ b/upatch-hijacker/hijacker/gnu-compiler-hijacker.c +@@ -16,7 +16,7 @@ + + #include "hijacker.h" + +-static const char* APPEND_ARGS[] = { ++static char* APPEND_ARGS[] = { + "-gdwarf", /* obatain debug information */ + "-ffunction-sections", + "-fdata-sections", +@@ -52,7 +52,7 @@ int main(int argc, char *argv[], char *envp[]) + } + + int new_argc = argc + APPEND_ARG_LEN + 1; // include terminator NULL +- const char **new_argv = calloc(1, new_argc * sizeof(char *)); ++ char **new_argv = calloc(1, (unsigned long)new_argc * sizeof(char *)); + if (new_argv == NULL) { + return execve(filename, argv, envp); + } +diff --git a/upatch-hijacker/hijacker/hijacker.h b/upatch-hijacker/hijacker/hijacker.h +index 2a41ab2..cc820ee 100644 +--- a/upatch-hijacker/hijacker/hijacker.h ++++ b/upatch-hijacker/hijacker/hijacker.h +@@ -28,7 +28,7 @@ static const char *OUTPUT_FLAG_NAME = "-o"; + + static char g_filename[PATH_MAX] = { 0 }; + +-static inline char* get_current_exec() ++static inline char* get_current_exec(void) + { + ssize_t path_len = readlink(EXEC_SELF_PATH, (char *)g_filename, PATH_MAX); + if (path_len == -1) { +@@ -39,7 +39,7 @@ static inline char* get_current_exec() + return (char *)g_filename; + } + +-static inline const char* get_hijacker_env() ++static inline const char* get_hijacker_env(void) + { + return getenv(UPATCH_ENV_NAME); + } +diff --git a/upatch-manage/arch/aarch64/insn.c b/upatch-manage/arch/aarch64/insn.c +index 8f78ae1..bb61f77 100644 +--- a/upatch-manage/arch/aarch64/insn.c ++++ b/upatch-manage/arch/aarch64/insn.c +@@ -97,17 +97,17 @@ u32 aarch64_insn_encode_immediate(enum aarch64_insn_imm_type type, u32 insn, + + /* Update the immediate field. */ + insn &= ~(mask << shift); +- insn |= (imm & mask) << shift; ++ insn |= (u32)(imm & mask) << shift; + + return insn; + } + +-u64 extract_insn_imm(s64 sval, int len, int lsb) ++s64 extract_insn_imm(s64 sval, int len, int lsb) + { +- u64 imm, imm_mask; ++ s64 imm, imm_mask; + + imm = sval >> lsb; +- imm_mask = (BIT(lsb + len) - 1) >> lsb; ++ imm_mask = (s64)((BIT(lsb + len) - 1) >> lsb); + imm = imm & imm_mask; + + log_debug("upatch: extract imm, X=0x%lx, X[%d:%d]=0x%lx\n", sval, +@@ -115,7 +115,7 @@ u64 extract_insn_imm(s64 sval, int len, int lsb) + return imm; + } + +-u32 insert_insn_imm(enum aarch64_insn_imm_type imm_type, void *place, u64 imm) ++s32 insert_insn_imm(enum aarch64_insn_imm_type imm_type, void *place, u64 imm) + { + u32 insn, new_insn; + +@@ -126,5 +126,5 @@ u32 insert_insn_imm(enum aarch64_insn_imm_type imm_type, void *place, u64 imm) + "upatch: insert imm, P=0x%lx, insn=0x%x, imm_type=%d, imm=0x%lx, " + "new_insn=0x%x\n", + (u64)place, insn, imm_type, imm, new_insn); +- return new_insn; ++ return (s32)new_insn; + } +diff --git a/upatch-manage/arch/aarch64/insn.h b/upatch-manage/arch/aarch64/insn.h +index 2b97e8d..76a9689 100644 +--- a/upatch-manage/arch/aarch64/insn.h ++++ b/upatch-manage/arch/aarch64/insn.h +@@ -64,8 +64,8 @@ enum aarch64_insn_imm_type { + u32 aarch64_insn_encode_immediate(enum aarch64_insn_imm_type type, u32 insn, + u64 imm); + +-u64 extract_insn_imm(s64, int, int); ++s64 extract_insn_imm(s64, int, int); + +-u32 insert_insn_imm(enum aarch64_insn_imm_type, void *, u64); ++s32 insert_insn_imm(enum aarch64_insn_imm_type, void *, u64); + + #endif /* _ARCH_AARCH64_INSN_H */ +diff --git a/upatch-manage/arch/aarch64/ptrace.c b/upatch-manage/arch/aarch64/ptrace.c +index c51a236..fdc7695 100644 +--- a/upatch-manage/arch/aarch64/ptrace.c ++++ b/upatch-manage/arch/aarch64/ptrace.c +@@ -21,13 +21,14 @@ + #include + #include + #include ++#include + + #include "insn.h" + #include "upatch-ptrace.h" + + #define ORIGIN_INSN_LEN 16 + +-int upatch_arch_syscall_remote(struct upatch_ptrace_ctx *pctx, int nr, ++long upatch_arch_syscall_remote(struct upatch_ptrace_ctx *pctx, int nr, + unsigned long arg1, unsigned long arg2, + unsigned long arg3, unsigned long arg4, + unsigned long arg5, unsigned long arg6, +@@ -38,10 +39,10 @@ int upatch_arch_syscall_remote(struct upatch_ptrace_ctx *pctx, int nr, + 0x01, 0x00, 0x00, 0xd4, // 0xd4000001 svc #0 = syscall + 0xa0, 0x00, 0x20, 0xd4, // 0xd42000a0 brk #5 = int3 + }; +- int ret; ++ long ret; + + log_debug("Executing syscall %d (pid %d)...\n", nr, pctx->pid); +- regs.regs[8] = (unsigned long)nr; ++ regs.regs[8] = (unsigned long long)nr; + regs.regs[0] = arg1; + regs.regs[1] = arg2; + regs.regs[2] = arg3; +@@ -56,39 +57,45 @@ int upatch_arch_syscall_remote(struct upatch_ptrace_ctx *pctx, int nr, + return ret; + } + +-int upatch_arch_execute_remote_func(struct upatch_ptrace_ctx *pctx, ++long upatch_arch_execute_remote_func(struct upatch_ptrace_ctx *pctx, + const unsigned char *code, size_t codelen, + struct user_regs_struct *pregs, + int (*func)(struct upatch_ptrace_ctx *pctx, + const void *data), + const void *data) + { ++ long ret; + struct user_regs_struct orig_regs, regs; + struct iovec orig_regs_iov, regs_iov; ++ struct upatch_process *proc = pctx->proc; ++ unsigned long libc_base = proc->libc_base; ++ unsigned char *orig_code = (unsigned char *)malloc(sizeof(*orig_code) * codelen); ++ ++ if (orig_code == NULL) { ++ log_error("Malloc orig_code failed\n"); ++ return -1; ++ } + + orig_regs_iov.iov_base = &orig_regs; + orig_regs_iov.iov_len = sizeof(orig_regs); + regs_iov.iov_base = ®s; + regs_iov.iov_len = sizeof(regs); + +- unsigned char orig_code[codelen]; +- int ret; +- struct upatch_process *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) { + log_error("can't get regs - %d\n", pctx->pid); ++ free(orig_code); + return -1; + } + ret = upatch_process_mem_read(proc, libc_base, + (unsigned long *)orig_code, codelen); + if (ret < 0) { + log_error("can't peek original code - %d\n", pctx->pid); ++ free(orig_code); + return -1; + } +- ret = upatch_process_mem_write(proc, (unsigned long *)code, libc_base, ++ ret = upatch_process_mem_write(proc, code, libc_base, + codelen); + if (ret < 0) { + log_error("can't poke syscall code - %d\n", pctx->pid); +@@ -132,6 +139,7 @@ int upatch_arch_execute_remote_func(struct upatch_ptrace_ctx *pctx, + poke_back: + upatch_process_mem_write(proc, (unsigned long *)orig_code, libc_base, + codelen); ++ free(orig_code); + return ret; + } + +@@ -162,41 +170,26 @@ void copy_regs(struct user_regs_struct *dst, struct user_regs_struct *src) + #undef COPY_REG + } + +-size_t get_origin_insn_len() ++size_t get_origin_insn_len(void) + { + return ORIGIN_INSN_LEN; + } + #define UPATCH_INSN_LEN 8 + #define UPATCH_ADDR_LEN 8 +-size_t get_upatch_insn_len() ++size_t get_upatch_insn_len(void) + { + return UPATCH_INSN_LEN; + } + +-size_t get_upatch_addr_len() ++size_t get_upatch_addr_len(void) + { + return UPATCH_ADDR_LEN; + } + + // for long jumper +-unsigned long get_new_insn(struct object_file *obj, unsigned long old_addr, +- unsigned long new_addr) ++unsigned long get_new_insn(void) + { + unsigned int insn0 = 0x58000051; // ldr x17, #8 + unsigned int insn4 = 0xd61f0220; // br x17 + return (unsigned long)(insn0 | ((unsigned long)insn4 << 32)); +-} +- +-#if 0 +-unsigned long get_new_insn(struct object_file *obj, unsigned long old_addr, +- unsigned long new_addr) +-{ +- unsigned char b_insn[] = { 0x00, 0x00, 0x00, 0x00 }; /* ins: b IMM */ +- +- *(unsigned int *)(b_insn) = (unsigned int)(new_addr - old_addr) / 4; +- b_insn[3] &= 0x3; +- b_insn[3] |= 0x14; +- +- return *(unsigned int *)b_insn; +-} +-#endif ++} +\ No newline at end of file +diff --git a/upatch-manage/arch/aarch64/relocation.c b/upatch-manage/arch/aarch64/relocation.c +index 0019388..3951135 100644 +--- a/upatch-manage/arch/aarch64/relocation.c ++++ b/upatch-manage/arch/aarch64/relocation.c +@@ -39,15 +39,15 @@ static inline s64 calc_reloc(enum aarch64_reloc_op op, void *place, u64 val) + switch (op) { + case RELOC_OP_ABS: + // S + A +- sval = val; ++ sval = (s64)val; + break; + case RELOC_OP_PREL: + // S + A - P +- sval = val - (u64)place; ++ sval = (s64)(val - (u64)place); + break; + case RELOC_OP_PAGE: + // Page(S + A) - Page(P) +- sval = (val & ~0xfff) - ((u64)place & ~0xfff); ++ sval = (s64)((val & ~(u64)0xfff) - ((u64)place & ~(u64)0xfff)); + break; + default: + log_error("upatch: unknown relocation operation %d\n", op); +@@ -92,7 +92,7 @@ int apply_relocate_add(struct upatch_elf *uelf, unsigned int symindex, + sym_name = uelf->strtab + sym->st_name; + + /* val corresponds to (S + A) */ +- val = (s64)(sym->st_value + rel[i].r_addend); ++ val = (unsigned long)sym->st_value + (unsigned long)rel[i].r_addend; + log_debug( + "upatch: reloc symbol, name=%s, k_addr=0x%lx, u_addr=0x%lx, " + "r_offset=0x%lx, st_value=0x%lx, r_addend=0x%lx \n", +@@ -113,13 +113,13 @@ int apply_relocate_add(struct upatch_elf *uelf, unsigned int symindex, + result = calc_reloc(RELOC_OP_ABS, uloc, val); + if (result < -(s64)BIT(31) || result >= (s64)BIT(32)) + goto overflow; +- *(s32 *)loc = result; ++ *(s32 *)loc = (s32)result; + break; + case R_AARCH64_ABS16: + result = calc_reloc(RELOC_OP_ABS, uloc, val); + if (result < -(s64)BIT(15) || result >= (s64)BIT(16)) + goto overflow; +- *(s16 *)loc = result; ++ *(s16 *)loc = (s16)result; + break; + case R_AARCH64_PREL64: + result = calc_reloc(RELOC_OP_PREL, uloc, val); +@@ -129,13 +129,13 @@ int apply_relocate_add(struct upatch_elf *uelf, unsigned int symindex, + result = calc_reloc(RELOC_OP_PREL, uloc, val); + if (result < -(s64)BIT(31) || result >= (s64)BIT(32)) + goto overflow; +- *(s32 *)loc = result; ++ *(s32 *)loc = (s32)result; + break; + case R_AARCH64_PREL16: + result = calc_reloc(RELOC_OP_PREL, uloc, val); + if (result < -(s64)BIT(15) || result >= (s64)BIT(16)) + goto overflow; +- *(s16 *)loc = result; ++ *(s16 *)loc = (s16)result; + break; + /* Immediate instruction relocations. */ + case R_AARCH64_LD_PREL_LO19: +@@ -144,8 +144,8 @@ int apply_relocate_add(struct upatch_elf *uelf, unsigned int symindex, + goto overflow; + result = extract_insn_imm(result, 19, 2); + result = insert_insn_imm(AARCH64_INSN_IMM_19, loc, +- result); +- *(__le32 *)loc = cpu_to_le32(result); ++ (unsigned long)result); ++ *(__le32 *)loc = cpu_to_le32((__le32)result); + break; + case R_AARCH64_ADR_PREL_LO21: + result = calc_reloc(RELOC_OP_PREL, uloc, val); +@@ -153,8 +153,8 @@ int apply_relocate_add(struct upatch_elf *uelf, unsigned int symindex, + goto overflow; + result = extract_insn_imm(result, 21, 0); + result = insert_insn_imm(AARCH64_INSN_IMM_ADR, loc, +- result); +- *(__le32 *)loc = cpu_to_le32(result); ++ (unsigned long)result); ++ *(__le32 *)loc = cpu_to_le32((__le32)result); + break; + case R_AARCH64_ADR_PREL_PG_HI21: + result = calc_reloc(RELOC_OP_PAGE, uloc, val); +@@ -162,51 +162,51 @@ int apply_relocate_add(struct upatch_elf *uelf, unsigned int symindex, + goto overflow; + result = extract_insn_imm(result, 21, 12); + result = insert_insn_imm(AARCH64_INSN_IMM_ADR, loc, +- result); +- *(__le32 *)loc = cpu_to_le32(result); ++ (unsigned long)result); ++ *(__le32 *)loc = cpu_to_le32((__le32)result); + break; + case R_AARCH64_ADR_PREL_PG_HI21_NC: + result = calc_reloc(RELOC_OP_PAGE, uloc, val); + result = extract_insn_imm(result, 21, 12); + result = insert_insn_imm(AARCH64_INSN_IMM_ADR, loc, +- result); +- *(__le32 *)loc = cpu_to_le32(result); ++ (unsigned long)result); ++ *(__le32 *)loc = cpu_to_le32((__le32)result); + break; + case R_AARCH64_ADD_ABS_LO12_NC: + case R_AARCH64_LDST8_ABS_LO12_NC: + result = calc_reloc(RELOC_OP_ABS, uloc, val); + result = extract_insn_imm(result, 12, 0); + result = insert_insn_imm(AARCH64_INSN_IMM_12, loc, +- result); +- *(__le32 *)loc = cpu_to_le32(result); ++ (unsigned long)result); ++ *(__le32 *)loc = cpu_to_le32((__le32)result); + break; + case R_AARCH64_LDST16_ABS_LO12_NC: + result = calc_reloc(RELOC_OP_ABS, uloc, val); + result = extract_insn_imm(result, 11, 1); + result = insert_insn_imm(AARCH64_INSN_IMM_12, loc, +- result); +- *(__le32 *)loc = cpu_to_le32(result); ++ (unsigned long)result); ++ *(__le32 *)loc = cpu_to_le32((__le32)result); + break; + case R_AARCH64_LDST32_ABS_LO12_NC: + result = calc_reloc(RELOC_OP_ABS, uloc, val); + result = extract_insn_imm(result, 10, 2); + result = insert_insn_imm(AARCH64_INSN_IMM_12, loc, +- result); +- *(__le32 *)loc = cpu_to_le32(result); ++ (unsigned long)result); ++ *(__le32 *)loc = cpu_to_le32((__le32)result); + break; + case R_AARCH64_LDST64_ABS_LO12_NC: + result = calc_reloc(RELOC_OP_ABS, uloc, val); + result = extract_insn_imm(result, 9, 3); + result = insert_insn_imm(AARCH64_INSN_IMM_12, loc, +- result); +- *(__le32 *)loc = cpu_to_le32(result); ++ (unsigned long)result); ++ *(__le32 *)loc = cpu_to_le32((__le32)result); + break; + case R_AARCH64_LDST128_ABS_LO12_NC: + result = calc_reloc(RELOC_OP_ABS, uloc, val); + result = extract_insn_imm(result, 8, 4); + result = insert_insn_imm(AARCH64_INSN_IMM_12, loc, +- result); +- *(__le32 *)loc = cpu_to_le32(result); ++ (unsigned long)result); ++ *(__le32 *)loc = cpu_to_le32((__le32)result); + break; + case R_AARCH64_TSTBR14: + result = calc_reloc(RELOC_OP_PREL, uloc, val); +@@ -214,15 +214,15 @@ int apply_relocate_add(struct upatch_elf *uelf, unsigned int symindex, + goto overflow; + result = extract_insn_imm(result, 14, 2); + result = insert_insn_imm(AARCH64_INSN_IMM_14, loc, +- result); +- *(__le32 *)loc = cpu_to_le32(result); ++ (unsigned long)result); ++ *(__le32 *)loc = cpu_to_le32((__le32)result); + break; + case R_AARCH64_CONDBR19: + result = calc_reloc(RELOC_OP_PREL, uloc, val); + result = extract_insn_imm(result, 19, 2); + result = insert_insn_imm(AARCH64_INSN_IMM_19, loc, +- result); +- *(__le32 *)loc = cpu_to_le32(result); ++ (unsigned long)result); ++ *(__le32 *)loc = cpu_to_le32((__le32)result); + break; + case R_AARCH64_JUMP26: + case R_AARCH64_CALL26: +@@ -243,8 +243,8 @@ int apply_relocate_add(struct upatch_elf *uelf, unsigned int symindex, + } + result = extract_insn_imm(result, 26, 2); + result = insert_insn_imm(AARCH64_INSN_IMM_26, loc, +- result); +- *(__le32 *)loc = cpu_to_le32(result); ++ (unsigned long)result); ++ *(__le32 *)loc = cpu_to_le32((__le32)result); + break; + case R_AARCH64_ADR_GOT_PAGE: + result = calc_reloc(RELOC_OP_PAGE, uloc, val); +@@ -252,8 +252,8 @@ int apply_relocate_add(struct upatch_elf *uelf, unsigned int symindex, + goto overflow; + result = extract_insn_imm(result, 21, 12); + result = insert_insn_imm(AARCH64_INSN_IMM_ADR, loc, +- result); +- *(__le32 *)loc = cpu_to_le32(result); ++ (unsigned long)result); ++ *(__le32 *)loc = cpu_to_le32((__le32)result); + break; + case R_AARCH64_LD64_GOT_LO12_NC: + result = calc_reloc(RELOC_OP_ABS, uloc, val); +@@ -261,24 +261,24 @@ int apply_relocate_add(struct upatch_elf *uelf, unsigned int symindex, + // sometimes, result & 7 != 0, it works fine. + result = extract_insn_imm(result, 9, 3); + result = insert_insn_imm(AARCH64_INSN_IMM_12, loc, +- result); +- *(__le32 *)loc = cpu_to_le32(result); ++ (unsigned long)result); ++ *(__le32 *)loc = cpu_to_le32((__le32)result); + break; + case R_AARCH64_TLSLE_ADD_TPREL_HI12: +- result = ALIGN(TCB_SIZE, uelf->relf->tls_align) + val; +- if (result < 0 || result >= BIT(24)) ++ result = (long)(ALIGN(TCB_SIZE, uelf->relf->tls_align) + val); ++ if (result < 0 || result >= (s64)BIT(24)) + goto overflow; + result = extract_insn_imm(result, 12, 12); + result = insert_insn_imm(AARCH64_INSN_IMM_12, loc, +- result); +- *(__le32 *)loc = cpu_to_le32(result); ++ (unsigned long)result); ++ *(__le32 *)loc = cpu_to_le32((__le32)result); + break; + case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: +- result = ALIGN(TCB_SIZE, uelf->relf->tls_align) + val; ++ result = (long)(ALIGN(TCB_SIZE, uelf->relf->tls_align) + val); + result = extract_insn_imm(result, 12, 0); + result = insert_insn_imm(AARCH64_INSN_IMM_12, loc, +- result); +- *(__le32 *)loc = cpu_to_le32(result); ++ (unsigned long)result); ++ *(__le32 *)loc = cpu_to_le32((__le32)result); + break; + case R_AARCH64_TLSDESC_ADR_PAGE21: + result = calc_reloc(RELOC_OP_PAGE, uloc, val); +@@ -286,23 +286,23 @@ int apply_relocate_add(struct upatch_elf *uelf, unsigned int symindex, + goto overflow; + result = extract_insn_imm(result, 21, 12); + result = insert_insn_imm(AARCH64_INSN_IMM_ADR, loc, +- result); +- *(__le32 *)loc = cpu_to_le32(result); ++ (unsigned long)result); ++ *(__le32 *)loc = cpu_to_le32((__le32)result); + break; + case R_AARCH64_TLSDESC_LD64_LO12: + result = calc_reloc(RELOC_OP_ABS, uloc, val); + // don't check result & 7 == 0. + result = extract_insn_imm(result, 9, 3); + result = insert_insn_imm(AARCH64_INSN_IMM_12, loc, +- result); +- *(__le32 *)loc = cpu_to_le32(result); ++ (unsigned long)result); ++ *(__le32 *)loc = cpu_to_le32((__le32)result); + break; + case R_AARCH64_TLSDESC_ADD_LO12: + result = calc_reloc(RELOC_OP_ABS, uloc, val); + result = extract_insn_imm(result, 12, 0); + result = insert_insn_imm(AARCH64_INSN_IMM_12, loc, +- result); +- *(__le32 *)loc = cpu_to_le32(result); ++ (unsigned long)result); ++ *(__le32 *)loc = cpu_to_le32((__le32)result); + break; + case R_AARCH64_TLSDESC_CALL: + // this is a blr instruction, don't need to modify +diff --git a/upatch-manage/arch/x86_64/ptrace.c b/upatch-manage/arch/x86_64/ptrace.c +index d824d92..3d6dd72 100644 +--- a/upatch-manage/arch/x86_64/ptrace.c ++++ b/upatch-manage/arch/x86_64/ptrace.c +@@ -19,6 +19,7 @@ + */ + + #include ++#include + + #include + #include +@@ -26,7 +27,7 @@ + + #include "upatch-ptrace.h" + +-int upatch_arch_syscall_remote(struct upatch_ptrace_ctx *pctx, int nr, ++long upatch_arch_syscall_remote(struct upatch_ptrace_ctx *pctx, int nr, + unsigned long arg1, unsigned long arg2, + unsigned long arg3, unsigned long arg4, + unsigned long arg5, unsigned long arg6, +@@ -38,11 +39,11 @@ int upatch_arch_syscall_remote(struct upatch_ptrace_ctx *pctx, int nr, + 0x0f, 0x05, /* syscall */ + 0xcc, /* int3 */ + }; +- int ret; ++ long ret; + + memset(®s, 0, sizeof(struct user_regs_struct)); + log_debug("Executing syscall %d (pid %d)...\n", nr, pctx->pid); +- regs.rax = (unsigned long)nr; ++ regs.rax = (unsigned long long)nr; + regs.rdi = arg1; + regs.rsi = arg2; + regs.rdx = arg3; +@@ -57,7 +58,7 @@ int upatch_arch_syscall_remote(struct upatch_ptrace_ctx *pctx, int nr, + return ret; + } + +-int upatch_arch_execute_remote_func(struct upatch_ptrace_ctx *pctx, ++long upatch_arch_execute_remote_func(struct upatch_ptrace_ctx *pctx, + const unsigned char *code, size_t codelen, + struct user_regs_struct *pregs, + int (*func)(struct upatch_ptrace_ctx *pctx, +@@ -65,23 +66,30 @@ int upatch_arch_execute_remote_func(struct upatch_ptrace_ctx *pctx, + const void *data) + { + struct user_regs_struct orig_regs, regs; +- unsigned char orig_code[codelen]; +- int ret; ++ long ret; + struct upatch_process *proc = pctx->proc; + unsigned long libc_base = proc->libc_base; + ++ unsigned char *orig_code = (unsigned char *)malloc(sizeof(*orig_code) * codelen); ++ ++ if (orig_code == NULL) { ++ log_error("Malloc orig_code failed\n"); ++ return -1; ++ } + ret = ptrace(PTRACE_GETREGS, pctx->pid, NULL, &orig_regs); + if (ret < 0) { + log_error("can't get regs - %d\n", pctx->pid); ++ free(orig_code); + return -1; + } + ret = upatch_process_mem_read(proc, libc_base, + (unsigned long *)orig_code, codelen); + if (ret < 0) { + log_error("can't peek original code - %d\n", pctx->pid); ++ free(orig_code); + return -1; + } +- ret = upatch_process_mem_write(proc, (unsigned long *)code, libc_base, ++ ret = upatch_process_mem_write(proc, code, libc_base, + codelen); + if (ret < 0) { + log_error("can't poke syscall code - %d\n", pctx->pid); +@@ -122,6 +130,7 @@ int upatch_arch_execute_remote_func(struct upatch_ptrace_ctx *pctx, + poke_back: + upatch_process_mem_write(proc, (unsigned long *)orig_code, libc_base, + codelen); ++ free(orig_code); + return ret; + } + +@@ -165,22 +174,8 @@ size_t get_upatch_addr_len() + } + + +-unsigned long get_new_insn(struct object_file *obj, unsigned long old_addr, +- unsigned long new_addr) ++unsigned long get_new_insn(void) + { + char jmp_insn[] = { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00}; + return *(unsigned long *)jmp_insn; +-} +- +-#if 0 +-unsigned long get_new_insn(struct object_file *obj, unsigned long old_addr, +- unsigned long new_addr) +-{ +- char jmp_insn[] = { 0xe9, 0x00, 0x00, 0x00, 0x00 }; /* jmp IMM */ +- +- *(unsigned int *)(jmp_insn + 1) = +- (unsigned int)(new_addr - old_addr - 5); +- +- return *(unsigned long *)jmp_insn; +-} +-#endif ++} +\ No newline at end of file +diff --git a/upatch-manage/arch/x86_64/relocation.c b/upatch-manage/arch/x86_64/relocation.c +index bb9cf32..657f014 100644 +--- a/upatch-manage/arch/x86_64/relocation.c ++++ b/upatch-manage/arch/x86_64/relocation.c +@@ -63,7 +63,7 @@ int apply_relocate_add(struct upatch_elf *uelf, unsigned int symindex, + (int)GELF_R_TYPE(rel[i].r_info), sym->st_value, + rel[i].r_addend, (u64)loc); + +- val = sym->st_value + rel[i].r_addend; ++ val = sym->st_value + (unsigned long)rel[i].r_addend; + switch (GELF_R_TYPE(rel[i].r_info)) { + case R_X86_64_NONE: + break; +@@ -95,7 +95,8 @@ int apply_relocate_add(struct upatch_elf *uelf, unsigned int symindex, + if (sym->st_value == 0) + goto overflow; + /* G + GOT + A*/ +- val = sym->st_value + rel[i].r_addend; ++ val = sym->st_value + (unsigned long)rel[i].r_addend; ++ /* fallthrough*/ + case R_X86_64_PC32: + case R_X86_64_PLT32: + if (*(u32 *)loc != 0) +diff --git a/upatch-manage/arch/x86_64/resolve.c b/upatch-manage/arch/x86_64/resolve.c +index 5432b20..0f8623d 100644 +--- a/upatch-manage/arch/x86_64/resolve.c ++++ b/upatch-manage/arch/x86_64/resolve.c +@@ -30,7 +30,7 @@ struct upatch_jmp_table_entry { + unsigned long addr; + }; + +-unsigned int get_jmp_table_entry() ++unsigned int get_jmp_table_entry(void) + { + return sizeof(struct upatch_jmp_table_entry); + } +@@ -84,6 +84,7 @@ unsigned long insert_plt_table(struct upatch_elf *uelf, struct object_file *obj, + unsigned long jmp_addr; + unsigned long elf_addr = 0; + ++ (void)r_type; + if (upatch_process_mem_read(obj->proc, addr, &jmp_addr, + sizeof(jmp_addr))) { + log_error("copy address failed\n"); +diff --git a/upatch-manage/upatch-common.h b/upatch-manage/upatch-common.h +index ab4084a..bc694d6 100644 +--- a/upatch-manage/upatch-common.h ++++ b/upatch-manage/upatch-common.h +@@ -33,7 +33,7 @@ + list_add(&(_new)->list, (_list)); \ + } + +-static inline int page_shift(int n) ++static inline int page_shift(long n) + { + int res = -1; + +@@ -52,7 +52,7 @@ static inline int page_shift(int n) + #endif + #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + #define ALIGN(x, a) (((x) + (a)-1) & (~((a)-1))) +-#define PAGE_ALIGN(x) ALIGN((x), PAGE_SIZE) ++#define PAGE_ALIGN(x) ALIGN((x), (unsigned long)PAGE_SIZE) + + #define ROUND_DOWN(x, m) ((x) & ~((m)-1)) + #define ROUND_UP(x, m) (((x) + (m)-1) & ~((m)-1)) +diff --git a/upatch-manage/upatch-elf.c b/upatch-manage/upatch-elf.c +index c79637d..3009a3d 100644 +--- a/upatch-manage/upatch-elf.c ++++ b/upatch-manage/upatch-elf.c +@@ -30,14 +30,14 @@ + #include "upatch-elf.h" + #include "upatch-ptrace.h" + +-static int read_from_offset(int fd, void **buf, int len, off_t offset) ++static int read_from_offset(int fd, void **buf, unsigned long len, off_t offset) + { + *buf = malloc(len); + if (*buf == NULL) { + return -errno; + } + +- int size = pread(fd, *buf, len, offset); ++ ssize_t size = pread(fd, *buf, len, offset); + if (size == -1) { + return -errno; + } +@@ -47,7 +47,7 @@ static int read_from_offset(int fd, void **buf, int len, off_t offset) + + static int open_elf(struct elf_info *einfo, const char *name) + { +- int ret = 0, fd = -1, i; ++ int ret = 0, fd = -1; + char *sec_name; + struct stat st; + +@@ -65,7 +65,7 @@ static int open_elf(struct elf_info *einfo, const char *name) + goto out; + } + +- ret = read_from_offset(fd, (void **)&einfo->patch_buff, st.st_size, 0); ++ ret = read_from_offset(fd, (void **)&einfo->patch_buff, (unsigned long)st.st_size, 0); + if (ret != 0) { + log_error("Failed to read file '%s'\n", name); + goto out; +@@ -73,7 +73,7 @@ static int open_elf(struct elf_info *einfo, const char *name) + + einfo->name = name; + einfo->inode = st.st_ino; +- einfo->patch_size = st.st_size; ++ einfo->patch_size = (unsigned long)st.st_size; + einfo->hdr = (void *)einfo->patch_buff; + einfo->shdrs = (void *)einfo->hdr + einfo->hdr->e_shoff; + einfo->shstrtab = (void *)einfo->hdr + einfo->shdrs[einfo->hdr->e_shstrndx].sh_offset; +@@ -85,7 +85,7 @@ static int open_elf(struct elf_info *einfo, const char *name) + goto out; + } + +- for (i = 0; i < einfo->hdr->e_shnum; ++i) { ++ for (unsigned int i = 0; i < einfo->hdr->e_shnum; ++i) { + sec_name = einfo->shstrtab + einfo->shdrs[i].sh_name; + if (streql(sec_name, BUILD_ID_NAME) && einfo->shdrs[i].sh_type == SHT_NOTE) { + einfo->num_build_id = i; +@@ -116,7 +116,7 @@ int upatch_init(struct upatch_elf *uelf, const char *name) + return ret; + } + +- for (int i = 1; i < uelf->info.hdr->e_shnum; ++i) { ++ for (unsigned int i = 1; i < uelf->info.hdr->e_shnum; ++i) { + char *sec_name = uelf->info.shstrtab + uelf->info.shdrs[i].sh_name; + if (uelf->info.shdrs[i].sh_type == SHT_SYMTAB) { + uelf->num_syms = uelf->info.shdrs[i].sh_size / sizeof(GElf_Sym); +@@ -165,7 +165,7 @@ int binary_init(struct running_elf *relf, const char *name) + return ret; + } + +- for (int i = 1; i < relf->info.hdr->e_shnum; i++) { ++ for (unsigned int i = 1; i < relf->info.hdr->e_shnum; i++) { + char *sec_name = relf->info.shstrtab + relf->info.shdrs[i].sh_name; + if (relf->info.shdrs[i].sh_type == SHT_SYMTAB) { + log_debug("Found section '%s', idx=%d\n", SYMTAB_NAME, i); +diff --git a/upatch-manage/upatch-elf.h b/upatch-manage/upatch-elf.h +index 481fec9..499287a 100644 +--- a/upatch-manage/upatch-elf.h ++++ b/upatch-manage/upatch-elf.h +@@ -56,7 +56,7 @@ struct upatch_info { + unsigned long size; // upatch_info and upatch_info_func size + unsigned long start; // upatch vma start + unsigned long end; // upatch vma end +- unsigned int changed_func_num; ++ unsigned long changed_func_num; + // upatch_header_func + }; + +@@ -65,15 +65,15 @@ struct upatch_layout { + void *kbase; + void *base; + /* Total size. */ +- unsigned int size; ++ unsigned long size; + /* The size of the executable code. */ +- unsigned int text_size; ++ unsigned long text_size; + /* Size of RO section of the module (text+rodata) */ +- unsigned int ro_size; ++ unsigned long ro_size; + /* Size of RO after init section, not use it now */ +- unsigned int ro_after_init_size; ++ unsigned long ro_after_init_size; + /* The size of the info. */ +- unsigned int info_size; ++ unsigned long info_size; + }; + + struct upatch_patch_func { +diff --git a/upatch-manage/upatch-manage.c b/upatch-manage/upatch-manage.c +index 8a7ba60..965af35 100644 +--- a/upatch-manage/upatch-manage.c ++++ b/upatch-manage/upatch-manage.c +@@ -54,14 +54,14 @@ struct arguments { + }; + + static struct argp_option options[] = { +- { "verbose", 'v', NULL, 0, "Show verbose output" }, +- { "uuid", 'U', "uuid", 0, "the uuid of the upatch" }, +- { "pid", 'p', "pid", 0, "the pid of the user-space process" }, +- { "upatch", 'u', "upatch", 0, "the upatch file" }, +- { "binary", 'b', "binary", 0, "the binary file" }, +- { "cmd", 0, "patch", 0, "Apply a upatch file to a user-space process" }, ++ { "verbose", 'v', NULL, 0, "Show verbose output", 0 }, ++ { "uuid", 'U', "uuid", 0, "the uuid of the upatch", 0 }, ++ { "pid", 'p', "pid", 0, "the pid of the user-space process", 0 }, ++ { "upatch", 'u', "upatch", 0, "the upatch file", 0 }, ++ { "binary", 'b', "binary", 0, "the binary file", 0 }, ++ { "cmd", 0, "patch", 0, "Apply a upatch file to a user-space process", 0 }, + { "cmd", 0, "unpatch", 0, +- "Unapply a upatch file to a user-space process" }, ++ "Unapply a upatch file to a user-space process", 0 }, + { NULL } + }; + +@@ -135,7 +135,7 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) + return 0; + } + +-static struct argp argp = { options, parse_opt, args_doc, program_doc }; ++static struct argp argp = { options, parse_opt, args_doc, program_doc, NULL, NULL, NULL }; + + int patch_upatch(const char *uuid, const char *binary_path, const char *upatch_path, int pid) + { +@@ -163,7 +163,7 @@ out: + return ret; + } + +-int unpatch_upatch(const char *uuid, const char *binary_path, const char *upatch_path, int pid) ++int unpatch_upatch(const char *uuid, int pid) + { + int ret = 0; + +@@ -176,7 +176,7 @@ int unpatch_upatch(const char *uuid, const char *binary_path, const char *upatch + return 0; + } + +-int info_upatch(const char *binary_path, const char *upatch_path, int pid) ++int info_upatch(int pid) + { + int ret = process_info(pid); + if (ret != 0) { +@@ -210,10 +210,10 @@ int main(int argc, char *argv[]) + ret = patch_upatch(args.uuid, args.binary, args.upatch, args.pid); + break; + case UNPATCH: +- ret = unpatch_upatch(args.uuid, args.binary, args.upatch, args.pid); ++ ret = unpatch_upatch(args.uuid, args.pid); + break; + case INFO: +- ret = info_upatch(args.binary, args.upatch, args.pid); ++ ret = info_upatch(args.pid); + break; + default: + ERROR("Unknown command"); +diff --git a/upatch-manage/upatch-patch.c b/upatch-manage/upatch-patch.c +index ab972ac..cbdbbe1 100644 +--- a/upatch-manage/upatch-patch.c ++++ b/upatch-manage/upatch-patch.c +@@ -51,7 +51,7 @@ static GElf_Off calculate_load_address(struct running_elf *relf, + bool check_code) + { + int i; +- GElf_Off min_addr = -1; ++ GElf_Off min_addr = (unsigned long)-1; + + /* TODO: for ET_DYN, consider check PIE */ + if (relf->info.hdr->e_type != ET_EXEC && +@@ -78,7 +78,7 @@ out: + static unsigned long calculate_mem_load(struct object_file *obj) + { + struct obj_vm_area *ovma; +- unsigned long load_addr = -1; ++ unsigned long load_addr = (unsigned long)-1; + + list_for_each_entry(ovma, &obj->vma, list) { + if (ovma->inmem.prot & PROT_EXEC) { +@@ -120,29 +120,20 @@ static int rewrite_section_headers(struct upatch_elf *uelf) + return 0; + } + +-/* Additional bytes needed by arch in front of individual sections */ +-unsigned int arch_mod_section_prepend(struct upatch_elf *uelf, +- unsigned int section) ++static unsigned long get_offset(unsigned long *size, ++ GElf_Shdr *sechdr) + { +- /* default implementation just returns zero */ +- return 0; +-} ++ unsigned long ret; + +-static long get_offset(struct upatch_elf *uelf, unsigned int *size, +- GElf_Shdr *sechdr, unsigned int section) +-{ +- long ret; +- +- *size += arch_mod_section_prepend(uelf, section); +- ret = ALIGN(*size, sechdr->sh_addralign ?: 1); +- *size = ret + sechdr->sh_size; ++ ret = ALIGN(*size, (unsigned long)(sechdr->sh_addralign ?: 1)); ++ *size = (unsigned long)ret + sechdr->sh_size; + return ret; + } + + static void layout_upatch_info(struct upatch_elf *uelf) + { + GElf_Shdr *upatch_func = uelf->info.shdrs + uelf->index.upatch_funcs; +- int num = upatch_func->sh_size / sizeof(struct upatch_patch_func); ++ unsigned long num = upatch_func->sh_size / sizeof(struct upatch_patch_func); + + uelf->core_layout.info_size = uelf->core_layout.size; + uelf->core_layout.size += sizeof(struct upatch_info) + +@@ -189,7 +180,7 @@ static void layout_sections(struct upatch_elf *uelf) + continue; + + s->sh_entsize = +- get_offset(uelf, &uelf->core_layout.size, s, i); ++ get_offset(&uelf->core_layout.size, s); + log_debug("\tm = %d; %s: sh_entsize: 0x%lx\n", m, sname, + s->sh_entsize); + } +@@ -214,13 +205,14 @@ static void layout_sections(struct upatch_elf *uelf) + uelf->core_layout.size = + PAGE_ALIGN(uelf->core_layout.size); + break; ++ default: ++ break; + } + } + } + + /* TODO: only included used symbol */ +-static bool is_upatch_symbol(const GElf_Sym *src, const GElf_Shdr *sechdrs, +- unsigned int shnum) ++static bool is_upatch_symbol(void) + { + return true; + } +@@ -237,12 +229,11 @@ static void layout_symtab(struct upatch_elf *uelf) + GElf_Shdr *strsect = uelf->info.shdrs + uelf->index.str; + /* TODO: only support same arch as kernel now */ + const GElf_Sym *src; +- unsigned int i, nsrc, ndst, strtab_size = 0; ++ unsigned long i, nsrc, ndst, strtab_size = 0; + + /* Put symbol section at end of init part of module. */ + symsect->sh_flags |= SHF_ALLOC; +- symsect->sh_entsize = get_offset(uelf, &uelf->core_layout.size, symsect, +- uelf->index.sym); ++ symsect->sh_entsize = get_offset(&uelf->core_layout.size, symsect); + log_debug("\t%s\n", uelf->info.shstrtab + symsect->sh_name); + + src = (void *)uelf->info.hdr + symsect->sh_offset; +@@ -250,8 +241,7 @@ static void layout_symtab(struct upatch_elf *uelf) + + /* Compute total space required for the symbols' strtab. */ + for (ndst = i = 0; i < nsrc; i++) { +- if (i == 0 || is_upatch_symbol(src + i, uelf->info.shdrs, +- uelf->info.hdr->e_shnum)) { ++ if (i == 0 || is_upatch_symbol()) { + strtab_size += + strlen(&uelf->strtab[src[i].st_name]) + 1; + ndst++; +@@ -270,8 +260,7 @@ static void layout_symtab(struct upatch_elf *uelf) + + /* Put string table section at end of init part of module. */ + strsect->sh_flags |= SHF_ALLOC; +- strsect->sh_entsize = get_offset(uelf, &uelf->core_layout.size, strsect, +- uelf->index.str); ++ strsect->sh_entsize = get_offset(&uelf->core_layout.size, strsect); + uelf->core_layout.size = PAGE_ALIGN(uelf->core_layout.size); + log_debug("\t%s\n", uelf->info.shstrtab + strsect->sh_name); + } +@@ -288,8 +277,8 @@ static void *upatch_alloc(struct object_file *obj, size_t sz) + + addr = upatch_mmap_remote(proc2pctx(obj->proc), addr, sz, + PROT_READ | PROT_WRITE | PROT_EXEC, +- MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, +- 0); ++ MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, ++ (unsigned long)-1, 0); + if (addr == 0) { + return NULL; + } +@@ -308,7 +297,7 @@ static void *upatch_alloc(struct object_file *obj, size_t sz) + } + + static void upatch_free(struct object_file *obj, void *base, +- unsigned int size) ++ unsigned long size) + { + log_debug("Free patch memory %p\n", base); + if (upatch_munmap_remote(proc2pctx(obj->proc), (unsigned long)base, size)) { +@@ -378,7 +367,7 @@ static int post_memory(struct upatch_elf *uelf, struct object_file *obj) + { + int ret = 0; + +- log_debug("Post kbase %lx(%x) to base %lx\n", ++ log_debug("Post kbase %lx(%lx) to base %lx\n", + (unsigned long)uelf->core_layout.kbase, + uelf->core_layout.size, + (unsigned long)uelf->core_layout.base); +@@ -396,7 +385,7 @@ out: + + static int complete_info(struct upatch_elf *uelf, struct object_file *obj, const char *uuid) + { +- int ret = 0, i; ++ int ret = 0; + struct upatch_info *uinfo = + (void *)uelf->core_layout.kbase + uelf->core_layout.info_size; + struct upatch_patch_func *upatch_funcs_addr = +@@ -414,7 +403,7 @@ static int complete_info(struct upatch_elf *uelf, struct object_file *obj, const + memcpy(uinfo->id, uuid, strlen(uuid)); + + log_normal("Changed insn:\n"); +- for (i = 0; i < uinfo->changed_func_num; ++i) { ++ for (unsigned int i = 0; i < uinfo->changed_func_num; ++i) { + struct upatch_info_func *upatch_func = + (void *)uelf->core_layout.kbase + + uelf->core_layout.info_size + +@@ -433,8 +422,7 @@ static int complete_info(struct upatch_elf *uelf, struct object_file *obj, const + goto out; + } + +- upatch_func->new_insn = get_new_insn(obj, upatch_func->old_addr, +- upatch_func->new_addr); ++ upatch_func->new_insn = get_new_insn(); + + log_normal("\t0x%lx(0x%lx -> 0x%lx)\n", upatch_func->old_addr, + upatch_func->old_insn[0], upatch_func->new_insn); +@@ -446,10 +434,10 @@ out: + + static int unapply_patch(struct object_file *obj, + struct upatch_info_func *funcs, +- unsigned int changed_func_num) ++ unsigned long changed_func_num) + { + log_normal("Changed insn:\n"); +- for (int i = 0; i < changed_func_num; ++i) { ++ for (unsigned int i = 0; i < changed_func_num; ++i) { + log_normal("\t0x%lx(0x%lx -> 0x%lx)\n", funcs[i].old_addr, + funcs[i].new_insn, funcs[i].old_insn[0]); + +@@ -467,7 +455,8 @@ static int unapply_patch(struct object_file *obj, + + static int apply_patch(struct upatch_elf *uelf, struct object_file *obj) + { +- int ret = 0, i; ++ int ret = 0; ++ unsigned int i; + struct upatch_info *uinfo = + (void *)uelf->core_layout.kbase + uelf->core_layout.info_size; + +@@ -617,10 +606,10 @@ static int upatch_apply_patches(struct upatch_process *proc, + layout_symtab(uelf); + layout_upatch_info(uelf); + +- log_debug("calculate core layout = %x\n", uelf->core_layout.size); ++ log_debug("calculate core layout = %lx\n", uelf->core_layout.size); + log_debug( +- "Core layout: text_size = %x, ro_size = %x, ro_after_init_size = " +- "%x, info = %x, size = %x\n", ++ "Core layout: text_size = %lx, ro_size = %lx, ro_after_init_size = " ++ "%lx, info = %lx, size = %lx\n", + uelf->core_layout.text_size, uelf->core_layout.ro_size, + uelf->core_layout.ro_after_init_size, + uelf->core_layout.info_size, uelf->core_layout.size); +@@ -699,7 +688,7 @@ static void upatch_time_tick(int pid) { + return; + } + +- unsigned long frozen_time = GET_MICROSECONDS(end_tv, start_tv); ++ long frozen_time = GET_MICROSECONDS(end_tv, start_tv); + log_normal("Process %d frozen time is %ld microsecond(s)\n", + pid, frozen_time); + } +@@ -751,7 +740,7 @@ int process_patch(int pid, struct upatch_elf *uelf, struct running_elf *relf, co + * stored in the patch are valid for the original object. + */ + // 解析process的mem-maps,获得各个块的内存映射以及phdr +- ret = upatch_process_map_object_files(&proc, NULL); ++ ret = upatch_process_map_object_files(&proc); + if (ret < 0) { + log_error("Failed to read process memory mapping\n"); + goto out_free; +@@ -871,7 +860,7 @@ int process_unpatch(int pid, const char *uuid) + * stored in the patch are valid for the original object. + */ + // 解析process的mem-maps,获得各个块的内存映射以及phdr +- ret = upatch_process_map_object_files(&proc, NULL); ++ ret = upatch_process_map_object_files(&proc); + if (ret < 0) { + log_error("Failed to read process memory mapping\n"); + goto out_free; +@@ -950,7 +939,7 @@ int process_info(int pid) + goto out_free; + } + +- ret = upatch_process_map_object_files(&proc, NULL); ++ ret = upatch_process_map_object_files(&proc); + if (ret < 0) { + log_error("Failed to read process memory mapping\n"); + goto out_free; +diff --git a/upatch-manage/upatch-process.c b/upatch-manage/upatch-process.c +index c368165..3b8db3b 100644 +--- a/upatch-manage/upatch-process.c ++++ b/upatch-manage/upatch-process.c +@@ -65,7 +65,7 @@ static int lock_process(int pid) + return fd; + } + +-static void unlock_process(int pid, int fdmaps) ++static void unlock_process(int fdmaps) + { + int errsv = errno; + close(fdmaps); +@@ -141,7 +141,7 @@ int upatch_process_init(struct upatch_process *proc, int pid) + return 0; + + out_unlock: +- unlock_process(pid, fdmaps); ++ unlock_process(fdmaps); + out_err: + return -1; + } +@@ -192,7 +192,7 @@ static void upatch_process_memfree(struct upatch_process *proc) + + void upatch_process_destroy(struct upatch_process *proc) + { +- unlock_process(proc->pid, proc->fdmaps); ++ unlock_process(proc->fdmaps); + upatch_process_memfree(proc); + } + +@@ -345,12 +345,12 @@ static int object_add_vm_area(struct object_file *o, struct vm_area *vma, + } + + static struct object_file * +-process_new_object(struct upatch_process *proc, dev_t dev, int inode, ++process_new_object(struct upatch_process *proc, dev_t dev, ino_t inode, + const char *name, struct vm_area *vma, struct vm_hole *hole) + { + struct object_file *o; + +- log_debug("Creating object file '%s' for %lx:%d...", name, dev, inode); ++ log_debug("Creating object file '%s' for %lx:%lu...", name, dev, inode); + + o = malloc(sizeof(*o)); + if (!o) { +@@ -389,7 +389,7 @@ process_new_object(struct upatch_process *proc, dev_t dev, int inode, + * Returns: 0 if everything is ok, -1 on error. + */ + static int process_add_object_vma(struct upatch_process *proc, dev_t dev, +- int inode, char *name, struct vm_area *vma, ++ ino_t inode, char *name, struct vm_area *vma, + struct vm_hole *hole) + { + int object_type; +@@ -407,7 +407,7 @@ static int process_add_object_vma(struct upatch_process *proc, dev_t dev, + */ + list_for_each_entry_reverse(o, &proc->objs, list) { + if ((dev && inode && o->dev == dev && +- o->inode == inode) || ++ o->inode == (ino_t)inode) || + (dev == 0 && !strcmp(o->name, name))) { + return object_add_vm_area(o, vma, hole); + } +@@ -512,9 +512,9 @@ int upatch_process_parse_proc_maps(struct upatch_process *proc) + vma.prot = perms2prot(perms); + + /* Hole must be at least 2 pages for guardians */ +- if (start - hole_start > 2 * PAGE_SIZE) { +- hole = process_add_vm_hole(proc, hole_start + PAGE_SIZE, +- start - PAGE_SIZE); ++ if (start - hole_start > (unsigned long)(2 * PAGE_SIZE)) { ++ hole = process_add_vm_hole(proc, hole_start + (unsigned long)PAGE_SIZE, ++ start - (unsigned long)PAGE_SIZE); + if (hole == NULL) { + log_error("Failed to add vma hole"); + goto error; +@@ -557,8 +557,7 @@ error: + return -1; + } + +-int upatch_process_map_object_files(struct upatch_process *proc, +- const char *patch_id) ++int upatch_process_map_object_files(struct upatch_process *proc) + { + // we can get plt/got table from mem's elf_segments + // Now we read them from the running file +@@ -618,7 +617,7 @@ static int process_list_threads(struct upatch_process *proc, int **ppids, + + *ppids = pids; + +- return *npids; ++ return (int)*npids; + + dealloc: + if (dir) { +@@ -761,8 +760,10 @@ static inline unsigned long hole_size(struct vm_hole *hole) + int vm_hole_split(struct vm_hole *hole, unsigned long alloc_start, + unsigned long alloc_end) + { +- alloc_start = ROUND_DOWN(alloc_start, PAGE_SIZE) - PAGE_SIZE; +- alloc_end = ROUND_UP(alloc_end, PAGE_SIZE) + PAGE_SIZE; ++ unsigned long page_size = (unsigned long)PAGE_SIZE; ++ ++ alloc_start = ROUND_DOWN(alloc_start, page_size) - page_size; ++ alloc_end = ROUND_UP(alloc_end, page_size) + page_size; + + if (alloc_start > hole->start) { + struct vm_hole *left = NULL; +@@ -856,7 +857,7 @@ unsigned long object_find_patch_region(struct object_file *obj, size_t memsize, + return -1UL; + } + +- region_start = (region_start >> PAGE_SHIFT) << PAGE_SHIFT; ++ region_start = (region_start >> (unsigned long)PAGE_SHIFT) << (unsigned long)PAGE_SHIFT; + log_debug("Found patch region for '%s' at 0x%lx\n", obj->name, + region_start); + +diff --git a/upatch-manage/upatch-process.h b/upatch-manage/upatch-process.h +index 39909db..be44cb5 100644 +--- a/upatch-manage/upatch-process.h ++++ b/upatch-manage/upatch-process.h +@@ -133,7 +133,7 @@ void upatch_process_print_short(struct upatch_process *); + + int upatch_process_mem_open(struct upatch_process *, int); + +-int upatch_process_map_object_files(struct upatch_process *, const char *); ++int upatch_process_map_object_files(struct upatch_process *); + + int upatch_process_attach(struct upatch_process *); + +diff --git a/upatch-manage/upatch-ptrace.c b/upatch-manage/upatch-ptrace.c +index 1309a6e..03296bc 100644 +--- a/upatch-manage/upatch-ptrace.c ++++ b/upatch-manage/upatch-ptrace.c +@@ -37,16 +37,16 @@ int upatch_process_mem_read(struct upatch_process *proc, unsigned long src, + { + ssize_t r = pread(proc->memfd, dst, size, (off_t)src); + +- return r != size ? -1 : 0; ++ return r != (ssize_t)size ? -1 : 0; + } + + static int upatch_process_mem_write_ptrace(struct upatch_process *proc, +- void *src, unsigned long dst, size_t size) ++ const void *src, unsigned long dst, size_t size) + { +- int ret; ++ long ret; + + while (ROUND_DOWN(size, sizeof(long)) != 0) { +- ret = ptrace(PTRACE_POKEDATA, proc->pid, dst, *(unsigned long *)src); ++ ret = ptrace(PTRACE_POKEDATA, proc->pid, dst, *(const unsigned long *)src); + if (ret) { + return -1; + } +@@ -56,10 +56,10 @@ static int upatch_process_mem_write_ptrace(struct upatch_process *proc, + } + + if (size) { +- unsigned long tmp; ++ long tmp; + + tmp = ptrace(PTRACE_PEEKDATA, proc->pid, dst, NULL); +- if (tmp == (unsigned long)-1 && errno) { ++ if (tmp == -1 && errno) { + return -1; + } + memcpy(&tmp, src, size); +@@ -73,7 +73,7 @@ static int upatch_process_mem_write_ptrace(struct upatch_process *proc, + return 0; + } + +-int upatch_process_mem_write(struct upatch_process *proc, void *src, ++int upatch_process_mem_write(struct upatch_process *proc, const void *src, + unsigned long dst, size_t size) + { + static int use_pwrite = 1; +@@ -87,7 +87,7 @@ int upatch_process_mem_write(struct upatch_process *proc, void *src, + return upatch_process_mem_write_ptrace(proc, src, dst, size); + } + +- return w != size ? -1 : 0; ++ return w != (ssize_t)size ? -1 : 0; + } + + static struct upatch_ptrace_ctx* upatch_ptrace_ctx_alloc( +@@ -168,19 +168,20 @@ int upatch_ptrace_attach_thread(struct upatch_process *proc, int tid) + + int wait_for_stop(struct upatch_ptrace_ctx *pctx, const void *data) + { +- int ret, status = 0, pid = (int)(uintptr_t)data ?: pctx->pid; ++ long ret; ++ int status = 0, pid = (int)(uintptr_t)data ?: pctx->pid; + log_debug("wait_for_stop(pctx->pid=%d, pid=%d)\n", pctx->pid, pid); + + while (1) { + ret = ptrace(PTRACE_CONT, pctx->pid, NULL, (void *)(uintptr_t)status); + if (ret < 0) { +- log_error("Cannot start tracee %d, ret=%d\n", pctx->pid, ret); ++ log_error("Cannot start tracee %d, ret=%ld\n", pctx->pid, ret); + return -1; + } + + ret = waitpid(pid, &status, __WALL); + if (ret < 0) { +- log_error("Cannot wait tracee %d, ret=%d\n", pid, ret); ++ log_error("Cannot wait tracee %d, ret=%ld\n", pid, ret); + return -1; + } + +@@ -217,7 +218,7 @@ int upatch_ptrace_detach(struct upatch_ptrace_ctx *pctx) + return 0; + } + +-int upatch_execute_remote(struct upatch_ptrace_ctx *pctx, ++long upatch_execute_remote(struct upatch_ptrace_ctx *pctx, + const unsigned char *code, size_t codelen, + struct user_regs_struct *pregs) + { +@@ -226,13 +227,13 @@ int upatch_execute_remote(struct upatch_ptrace_ctx *pctx, + } + + unsigned long upatch_mmap_remote(struct upatch_ptrace_ctx *pctx, +- unsigned long addr, size_t length, int prot, +- int flags, int fd, off_t offset) ++ unsigned long addr, size_t length, unsigned long prot, ++ unsigned long flags, unsigned long fd, unsigned long offset) + { +- int ret; ++ long ret; + unsigned long res = 0; + +- log_debug("mmap_remote: 0x%lx+%lx, %x, %x, %d, %lx\n", addr, length, ++ log_debug("mmap_remote: 0x%lx+%lx, %lx, %lx, %lu, %lx\n", addr, length, + prot, flags, fd, offset); + ret = upatch_arch_syscall_remote(pctx, __NR_mmap, (unsigned long)addr, + length, prot, flags, fd, offset, &res); +@@ -240,16 +241,16 @@ unsigned long upatch_mmap_remote(struct upatch_ptrace_ctx *pctx, + return 0; + } + if (ret == 0 && res >= (unsigned long)-MAX_ERRNO) { +- errno = -(long)res; ++ errno = -(int)res; + return 0; + } + return res; + } + + int upatch_mprotect_remote(struct upatch_ptrace_ctx *pctx, unsigned long addr, +- size_t length, int prot) ++ size_t length, unsigned long prot) + { +- int ret; ++ long ret; + unsigned long res; + + log_debug("mprotect_remote: 0x%lx+%lx\n", addr, length); +@@ -259,7 +260,7 @@ int upatch_mprotect_remote(struct upatch_ptrace_ctx *pctx, unsigned long addr, + if (ret < 0) + return -1; + if (ret == 0 && res >= (unsigned long)-MAX_ERRNO) { +- errno = -(long)res; ++ errno = -(int)res; + return -1; + } + +@@ -269,7 +270,7 @@ int upatch_mprotect_remote(struct upatch_ptrace_ctx *pctx, unsigned long addr, + int upatch_munmap_remote(struct upatch_ptrace_ctx *pctx, unsigned long addr, + size_t length) + { +- int ret; ++ long ret; + unsigned long res; + + log_debug("munmap_remote: 0x%lx+%lx\n", addr, length); +@@ -278,7 +279,7 @@ int upatch_munmap_remote(struct upatch_ptrace_ctx *pctx, unsigned long addr, + if (ret < 0) + return -1; + if (ret == 0 && res >= (unsigned long)-MAX_ERRNO) { +- errno = -(long)res; ++ errno = -(int)res; + return -1; + } + return 0; +diff --git a/upatch-manage/upatch-ptrace.h b/upatch-manage/upatch-ptrace.h +index 0c88434..b88c656 100644 +--- a/upatch-manage/upatch-ptrace.h ++++ b/upatch-manage/upatch-ptrace.h +@@ -43,7 +43,7 @@ struct upatch_ptrace_ctx { + int upatch_process_mem_read(struct upatch_process *proc, unsigned long src, + void *dst, size_t size); + +-int upatch_process_mem_write(struct upatch_process *, void *, unsigned long, ++int upatch_process_mem_write(struct upatch_process *, const void *, unsigned long, + size_t); + + int upatch_ptrace_attach_thread(struct upatch_process *, int); +@@ -54,31 +54,32 @@ int wait_for_stop(struct upatch_ptrace_ctx *, const void *); + + void copy_regs(struct user_regs_struct *, struct user_regs_struct *); + +-int upatch_arch_execute_remote_func(struct upatch_ptrace_ctx *pctx, ++long upatch_arch_execute_remote_func(struct upatch_ptrace_ctx *pctx, + const unsigned char *code, size_t codelen, + struct user_regs_struct *pregs, + int (*func)(struct upatch_ptrace_ctx *pctx, + const void *data), + const void *data); + +-int upatch_arch_syscall_remote(struct upatch_ptrace_ctx *, int, unsigned long, ++long upatch_arch_syscall_remote(struct upatch_ptrace_ctx *, int, unsigned long, + unsigned long, unsigned long, unsigned long, + unsigned long, unsigned long, unsigned long *); + +-unsigned long upatch_mmap_remote(struct upatch_ptrace_ctx *, unsigned long, +- size_t, int, int, int, off_t); ++unsigned long upatch_mmap_remote(struct upatch_ptrace_ctx *pctx, ++ unsigned long addr, size_t length, unsigned long prot, ++ unsigned long flags, unsigned long fd, unsigned long offset); + +-int upatch_mprotect_remote(struct upatch_ptrace_ctx *, unsigned long, size_t, +- int); ++int upatch_mprotect_remote(struct upatch_ptrace_ctx *pctx, unsigned long addr, ++ size_t length, unsigned long prot); + + int upatch_munmap_remote(struct upatch_ptrace_ctx *, unsigned long, size_t); + +-int upatch_execute_remote(struct upatch_ptrace_ctx *, const unsigned char *, ++long upatch_execute_remote(struct upatch_ptrace_ctx *, const unsigned char *, + size_t, struct user_regs_struct *); + +-size_t get_origin_insn_len(); +-size_t get_upatch_insn_len(); +-size_t get_upatch_addr_len(); +-unsigned long get_new_insn(struct object_file *, unsigned long, unsigned long); ++size_t get_origin_insn_len(void); ++size_t get_upatch_insn_len(void); ++size_t get_upatch_addr_len(void); ++unsigned long get_new_insn(void); + + #endif +diff --git a/upatch-manage/upatch-resolve.c b/upatch-manage/upatch-resolve.c +index 0e992da..197ea2f 100644 +--- a/upatch-manage/upatch-resolve.c ++++ b/upatch-manage/upatch-resolve.c +@@ -50,7 +50,7 @@ static unsigned long resolve_rela_dyn(struct upatch_elf *uelf, + * some rela don't have the symbol index, use the symbol's value and + * rela's addend to find the symbol. for example, R_X86_64_IRELATIVE. + */ +- if (rela_dyn[i].r_addend != patch_sym->st_value) { ++ if (rela_dyn[i].r_addend != (long)patch_sym->st_value) { + continue; + } + } +@@ -110,7 +110,7 @@ static unsigned long resolve_rela_plt(struct upatch_elf *uelf, + * some rela don't have the symbol index, use the symbol's value and + * rela's addend to find the symbol. for example, R_X86_64_IRELATIVE. + */ +- if (rela_plt[i].r_addend != patch_sym->st_value) { ++ if (rela_plt[i].r_addend != (long)patch_sym->st_value) { + continue; + } + } else { +@@ -140,7 +140,7 @@ static unsigned long resolve_rela_plt(struct upatch_elf *uelf, + } + + static unsigned long resolve_dynsym(struct upatch_elf *uelf, +- struct object_file *obj, const char *name, GElf_Sym *patch_sym) ++ struct object_file *obj, const char *name) + { + unsigned long elf_addr = 0; + struct running_elf *relf = uelf->relf; +@@ -178,8 +178,7 @@ static unsigned long resolve_dynsym(struct upatch_elf *uelf, + return elf_addr; + } + +-static unsigned long resolve_sym(struct upatch_elf *uelf, +- struct object_file *obj, const char *name, GElf_Sym *patch_sym) ++static unsigned long resolve_sym(struct upatch_elf *uelf, const char *name) + { + unsigned long elf_addr = 0; + struct running_elf *relf = uelf->relf; +@@ -217,7 +216,7 @@ static unsigned long resolve_sym(struct upatch_elf *uelf, + } + + static unsigned long resolve_patch_sym(struct upatch_elf *uelf, +- struct object_file *obj, const char *name, GElf_Sym *patch_sym) ++ const char *name, GElf_Sym *patch_sym) + { + unsigned long elf_addr = 0; + struct running_elf *relf = uelf->relf; +@@ -265,17 +264,17 @@ static unsigned long resolve_symbol(struct upatch_elf *uelf, + + /* resolve from dynsym */ + if (!elf_addr) { +- elf_addr = resolve_dynsym(uelf, obj, name, &patch_sym); ++ elf_addr = resolve_dynsym(uelf, obj, name); + } + + /* resolve from sym */ + if (!elf_addr) { +- elf_addr = resolve_sym(uelf, obj, name, &patch_sym); ++ elf_addr = resolve_sym(uelf, name); + } + + /* resolve from patch sym */ + if (!elf_addr) { +- elf_addr = resolve_patch_sym(uelf, obj, name, &patch_sym); ++ elf_addr = resolve_patch_sym(uelf, name, &patch_sym); + } + + if (!elf_addr) { +diff --git a/upatch-manage/upatch-resolve.h b/upatch-manage/upatch-resolve.h +index 324c49e..9b31dce 100644 +--- a/upatch-manage/upatch-resolve.h ++++ b/upatch-manage/upatch-resolve.h +@@ -29,7 +29,7 @@ + /* jmp table, solve limit for the jmp instruction, Used for both PLT/GOT */ + struct upatch_jmp_table_entry; + +-unsigned int get_jmp_table_entry(); ++unsigned int get_jmp_table_entry(void); + + unsigned long insert_plt_table(struct upatch_elf *, struct object_file *, + unsigned long, unsigned long); +-- +2.34.1 + diff --git a/0026-common-fix-failed-to-set-selinux-status-issue.patch b/0026-common-fix-failed-to-set-selinux-status-issue.patch new file mode 100644 index 0000000000000000000000000000000000000000..d4af0b3edd86bd2c1de117077a8a8bcc3ccafa78 --- /dev/null +++ b/0026-common-fix-failed-to-set-selinux-status-issue.patch @@ -0,0 +1,32 @@ +From 28eee5483aa283ee6e2ca50a3e141d21a0e9cb4b Mon Sep 17 00:00:00 2001 +From: liuxiaobo +Date: Wed, 5 Jun 2024 10:52:44 +0800 +Subject: [PATCH] common: fix 'failed to set selinux status' issue + +Signed-off-by: liuxiaobo +--- + syscare-common/src/os/selinux.rs | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/syscare-common/src/os/selinux.rs b/syscare-common/src/os/selinux.rs +index cf3b5b2..bb9864c 100644 +--- a/syscare-common/src/os/selinux.rs ++++ b/syscare-common/src/os/selinux.rs +@@ -59,7 +59,13 @@ pub fn set_status(value: Status) -> Result<()> { + if (value != Status::Permissive) && (value != Status::Enforcing) { + bail!("Status {} is invalid", value); + } +- fs::write(SELINUX_SYS_FILE, value.to_string())?; ++ fs::write( ++ SELINUX_SYS_FILE, ++ match value { ++ Status::Enforcing => "1", ++ _ => "0", ++ }, ++ )?; + + Ok(()) + } +-- +2.34.1 + diff --git a/0027-upatch-diff-exit-with-error-when-any-tls-var-include.patch b/0027-upatch-diff-exit-with-error-when-any-tls-var-include.patch new file mode 100644 index 0000000000000000000000000000000000000000..0430a7f917379dd12eed0095f5d3f9270f47ea76 --- /dev/null +++ b/0027-upatch-diff-exit-with-error-when-any-tls-var-include.patch @@ -0,0 +1,48 @@ +From ca2c36855f39d95d95f18024633e155a9cf220ff Mon Sep 17 00:00:00 2001 +From: ningyu +Date: Mon, 27 May 2024 10:34:00 +0000 +Subject: [PATCH] upatch-diff: exit with error when any tls var included + +Signed-off-by: ningyu +--- + upatch-diff/create-diff-object.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index 6474b22..5ec6f31 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -847,6 +847,19 @@ static void include_debug_sections(struct upatch_elf *uelf) + /* currently, there si no special section need to be handled */ + static void process_special_sections(void) {} + ++static bool has_tls_included(struct upatch_elf *uelf) ++{ ++ struct symbol *sym; ++ ++ list_for_each_entry(sym, &uelf->symbols, list) { ++ if (sym->include == 1 && sym->type == STT_TLS) { ++ log_normal("TLS symbol '%s' included, but it's not supported", sym->name); ++ return true; ++ } ++ } ++ return false; ++} ++ + static void verify_patchability(struct upatch_elf *uelf) + { + struct section *sec; +@@ -878,6 +891,10 @@ static void verify_patchability(struct upatch_elf *uelf) + + if (errs) + DIFF_FATAL("%d, Unsupported section changes", errs); ++ ++ if (has_tls_included(uelf)) { ++ DIFF_FATAL("Unsupported symbol included"); ++ } + } + + static void migrate_included_elements(struct upatch_elf *uelf_patched, struct upatch_elf *uelf_out) +-- +2.34.1 + diff --git a/0028-upatch-diff-fix-lookup_relf-duplicate-failure.patch b/0028-upatch-diff-fix-lookup_relf-duplicate-failure.patch new file mode 100644 index 0000000000000000000000000000000000000000..0649c604e9f6a6b225d9877f3ce9b3cebfba7a26 --- /dev/null +++ b/0028-upatch-diff-fix-lookup_relf-duplicate-failure.patch @@ -0,0 +1,34 @@ +From 598fcd5fc70ffb1f17c00ef03bcd67d8c42c06df Mon Sep 17 00:00:00 2001 +From: ningyu +Date: Mon, 27 May 2024 11:16:26 +0000 +Subject: [PATCH] upatch-diff: fix lookup_relf duplicate failure + +Signed-off-by: ningyu +--- + upatch-diff/running-elf.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/upatch-diff/running-elf.c b/upatch-diff/running-elf.c +index 25b72b7..18ff095 100644 +--- a/upatch-diff/running-elf.c ++++ b/upatch-diff/running-elf.c +@@ -125,9 +125,15 @@ bool lookup_relf(struct running_elf *relf, + symbol = &relf->obj_syms[i]; + sympos++; + +- if (strcmp(symbol->name, lookup_sym->name) != 0) { ++ if (result->symbol != NULL && symbol->type == STT_FILE) { ++ break; ++ } ++ ++ if (strcmp(symbol->name, lookup_sym->name) != 0 || ++ symbol->bind != lookup_sym->bind) { + continue; + } ++ + if ((result->symbol != NULL) && + (result->symbol->bind == symbol->bind)) { + ERROR("Found duplicate symbol '%s' in %s", +-- +2.34.1 + diff --git a/0029-upatch-diff-fix-memory-leak.patch b/0029-upatch-diff-fix-memory-leak.patch new file mode 100644 index 0000000000000000000000000000000000000000..fcb86f7af117b789cc4abce4ec720128958aa6cb --- /dev/null +++ b/0029-upatch-diff-fix-memory-leak.patch @@ -0,0 +1,611 @@ +From 70ba20b8a6b5e7fdb05b79aeada4882a6fd2ca1e Mon Sep 17 00:00:00 2001 +From: liuxiaobo +Date: Thu, 27 Jun 2024 14:22:53 +0800 +Subject: [PATCH] upatch-diff: fix memory leak + +Signed-off-by: liuxiaobo +--- + upatch-diff/create-diff-object.c | 34 +++++--- + upatch-diff/elf-correlate.c | 10 +-- + upatch-diff/elf-create.c | 83 ++++++++++++-------- + upatch-diff/elf-debug.c | 7 +- + upatch-diff/running-elf.c | 2 +- + upatch-diff/running-elf.h | 2 +- + upatch-diff/upatch-elf.c | 128 ++++++++++++++++++++++--------- + upatch-diff/upatch-elf.h | 14 +++- + 8 files changed, 191 insertions(+), 89 deletions(-) + +diff --git a/upatch-diff/create-diff-object.c b/upatch-diff/create-diff-object.c +index 5ec6f31..8830956 100644 +--- a/upatch-diff/create-diff-object.c ++++ b/upatch-diff/create-diff-object.c +@@ -836,8 +836,10 @@ static void include_debug_sections(struct upatch_elf *uelf) + + list_for_each_entry_safe(rela, saferela, &sec->relas, list) + // The shndex of symbol is SHN_COMMON, there is no related section +- if (rela->sym && !rela->sym->include) ++ if (rela->sym && !rela->sym->include) { + list_del(&rela->list); ++ free(rela); ++ } + } + + if (eh_sec) +@@ -993,15 +995,20 @@ int main(int argc, char*argv[]) + mark_ignored_functions_same(); + mark_ignored_sections_same(); + +- upatch_elf_teardown(&uelf_source); +- upatch_elf_free(&uelf_source); +- + include_standard_elements(&uelf_patched); + + num_changed = include_changed_functions(&uelf_patched); + new_globals_exist = include_new_globals(&uelf_patched); + if (!num_changed && !new_globals_exist) { + log_normal("No functional changes\n"); ++ upatch_elf_destroy(&uelf_source); ++ upatch_elf_destroy(&uelf_patched); ++ ++ upatch_elf_close(&uelf_source); ++ upatch_elf_close(&uelf_patched); ++ ++ relf_close(&relf); ++ + return 0; + } + +@@ -1019,9 +1026,6 @@ int main(int argc, char*argv[]) + + migrate_included_elements(&uelf_patched, &uelf_out); + +- /* since out elf still point to it, we only destroy it, not free it */ +- upatch_elf_teardown(&uelf_patched); +- + upatch_create_strings_elements(&uelf_out); + + upatch_create_patches_sections(&uelf_out, &relf); +@@ -1060,11 +1064,19 @@ int main(int argc, char*argv[]) + + upatch_write_output_elf(&uelf_out, uelf_patched.elf, arguments.output_obj, 0664); + +- relf_destroy(&relf); +- upatch_elf_free(&uelf_patched); +- upatch_elf_teardown(&uelf_out); +- upatch_elf_free(&uelf_out); ++ upatch_elf_destroy(&uelf_source); ++ upatch_elf_destroy(&uelf_patched); ++ upatch_elf_destroy(&uelf_out); ++ ++ upatch_elf_close(&uelf_source); ++ upatch_elf_close(&uelf_patched); ++ upatch_elf_close(&uelf_out); ++ ++ relf_close(&relf); + + log_normal("Done\n"); ++ fflush(stdout); ++ fflush(stderr); ++ + return 0; + } +diff --git a/upatch-diff/elf-correlate.c b/upatch-diff/elf-correlate.c +index 3e3a536..cc3b925 100644 +--- a/upatch-diff/elf-correlate.c ++++ b/upatch-diff/elf-correlate.c +@@ -36,9 +36,8 @@ static void correlate_symbol(struct symbol *sym_orig, struct symbol *sym_patched + sym_orig->status = sym_patched->status = SAME; + if (strcmp(sym_orig->name, sym_patched->name)) { + log_debug("renaming symbol %s to %s \n", sym_patched->name, sym_orig->name); +- sym_patched->name = strdup(sym_orig->name); +- if (!sym_patched->name) +- ERROR("strdup"); ++ sym_patched->name = sym_orig->name; ++ sym_patched->name_source = DATA_SOURCE_REF; + } + if (sym_orig->relf_sym && !sym_patched->relf_sym) + sym_patched->relf_sym = sym_orig->relf_sym; +@@ -98,9 +97,8 @@ static void __correlate_section(struct section *sec_orig, struct section *sec_pa + /* Make sure these two sections have the same name */ + if (strcmp(sec_orig->name, sec_patched->name)) { + log_debug("renaming section %s to %s \n", sec_patched->name, sec_orig->name); +- sec_patched->name = strdup(sec_orig->name); +- if (!sec_patched->name) +- ERROR("strdup"); ++ sec_patched->name = sec_orig->name; ++ sec_patched->name_source = DATA_SOURCE_REF; + } + } + +diff --git a/upatch-diff/elf-create.c b/upatch-diff/elf-create.c +index 8ac212a..bd7edf0 100644 +--- a/upatch-diff/elf-create.c ++++ b/upatch-diff/elf-create.c +@@ -41,10 +41,12 @@ static struct section *create_section_pair(struct upatch_elf *uelf, char *name, + { + char *relaname; + struct section *sec, *relasec; ++ size_t size = strlen(name) + strlen(".rela") + 1; + +- relaname = malloc(strlen(name) + strlen(".rela") + 1); +- if (!relaname) ++ relaname = calloc(1, size); ++ if (!relaname) { + ERROR("relaname malloc failed."); ++ } + + strcpy(relaname, ".rela"); + strcat(relaname, name); +@@ -52,13 +54,17 @@ static struct section *create_section_pair(struct upatch_elf *uelf, char *name, + /* allocate text section resourcce */ + ALLOC_LINK(sec, &uelf->sections); + sec->name = name; +- sec->data = malloc(sizeof(*sec->data)); +- if (!sec->data) ++ sec->data = calloc(1, sizeof(Elf_Data)); ++ if (!sec->data) { + ERROR("section data malloc failed."); ++ } ++ sec->data_source = DATA_SOURCE_ALLOC; + + sec->data->d_buf = calloc(nr, entsize); +- if (!sec->data->d_buf) ++ if (!sec->data->d_buf) { + ERROR("d_buf of section data malloc failed."); ++ } ++ sec->dbuf_source = DATA_SOURCE_ALLOC; + + sec->data->d_size = entsize * nr; + sec->data->d_type = ELF_T_BYTE; +@@ -73,12 +79,15 @@ static struct section *create_section_pair(struct upatch_elf *uelf, char *name, + /* set relocation section */ + ALLOC_LINK(relasec, &uelf->sections); + relasec->name = relaname; ++ relasec->name_source = DATA_SOURCE_ALLOC; + INIT_LIST_HEAD(&relasec->relas); + + /* buffers will be generated by upatch_rebuild_rela_section_data */ +- relasec->data = malloc(sizeof(*relasec->data)); +- if (!relasec->data) ++ relasec->data = calloc(1, sizeof(Elf_Data)); ++ if (!relasec->data) { + ERROR("relasec data malloc failed."); ++ } ++ relasec->data_source = DATA_SOURCE_ALLOC; + + relasec->data->d_type = ELF_T_RELA; + +@@ -103,9 +112,12 @@ void upatch_create_strings_elements(struct upatch_elf *uelf) + ALLOC_LINK(sec, &uelf->sections); + sec->name = ".upatch.strings"; + +- sec->data = malloc(sizeof(*sec->data)); +- if (!sec->data) ++ sec->data = calloc(1, sizeof(Elf_Data)); ++ if (!sec->data) { + ERROR("section data malloc failed"); ++ } ++ sec->data_source = DATA_SOURCE_ALLOC; ++ + sec->data->d_type = ELF_T_BYTE; + + /* set section header */ +@@ -310,12 +322,14 @@ void upatch_build_strings_section_data(struct upatch_elf *uelf) + size += strlen(string->name) + 1; + + /* allocate section resources */ +- strtab = malloc(size); +- if (!strtab) ++ strtab = calloc(1, size); ++ if (!strtab) { + ERROR("strtab malloc failed."); ++ } + + sec->data->d_buf = strtab; + sec->data->d_size = size; ++ sec->dbuf_source = DATA_SOURCE_ALLOC; + + /* populate strings section data */ + list_for_each_entry(string, &uelf->strings, list) { +@@ -407,13 +421,15 @@ static void rebuild_rela_section_data(struct section *sec) + nr++; + + size = nr * sizeof(*relas); +- relas = malloc(size); +- if (!relas) ++ relas = calloc(1, size); ++ if (!relas) { + ERROR("relas malloc failed."); ++ } + + sec->data->d_buf = relas; + sec->data->d_size = size; + sec->sh.sh_size = size; ++ sec->dbuf_source = DATA_SOURCE_ALLOC; + + list_for_each_entry(rela, &sec->relas, list) { + relas[index].r_offset = rela->offset; +@@ -469,18 +485,19 @@ void upatch_create_shstrtab(struct upatch_elf *uelf) + char *buf; + + shstrtab = find_section_by_name(&uelf->sections, ".shstrtab"); +- if (!shstrtab) ++ if (!shstrtab) { + ERROR("find_section_by_name failed."); ++ } + + /* determine size of string table */ + size = 1; + list_for_each_entry(sec, &uelf->sections, list) + size += strlen(sec->name) + 1; + +- buf = malloc(size); +- if (!buf) ++ buf = calloc(1, size); ++ if (!buf) { + ERROR("malloc shstrtab failed."); +- memset(buf, 0, size); ++ } + + offset = 1; + list_for_each_entry(sec, &uelf->sections, list) { +@@ -490,11 +507,14 @@ void upatch_create_shstrtab(struct upatch_elf *uelf) + offset += len; + } + +- if (offset != size) ++ if (offset != size) { ++ free(buf); + ERROR("shstrtab size mismatch."); ++ } + + shstrtab->data->d_buf = buf; + shstrtab->data->d_size = size; ++ shstrtab->dbuf_source = DATA_SOURCE_ALLOC; + + log_debug("shstrtab: "); + print_strtab(buf, size); +@@ -506,25 +526,24 @@ void upatch_create_shstrtab(struct upatch_elf *uelf) + + void upatch_create_strtab(struct upatch_elf *uelf) + { +- struct section *strtab; +- struct symbol *sym; + size_t size = 0, offset = 0, len = 0; +- char *buf; + +- strtab = find_section_by_name(&uelf->sections, ".strtab"); +- if (!strtab) ++ struct section *strtab = find_section_by_name(&uelf->sections, ".strtab"); ++ if (!strtab) { + ERROR("find section failed in create strtab."); ++ } + ++ struct symbol *sym = NULL; + list_for_each_entry(sym, &uelf->symbols, list) { + if (sym->type == STT_SECTION) + continue; + size += strlen(sym->name) + 1; + } + +- buf = malloc(size); +- if (!buf) ++ char *buf = calloc(1, size); ++ if (!buf) { + ERROR("malloc buf failed in create strtab"); +- memset(buf, 0, size); ++ } + + list_for_each_entry(sym, &uelf->symbols, list) { + if (sym->type == STT_SECTION) { +@@ -537,11 +556,14 @@ void upatch_create_strtab(struct upatch_elf *uelf) + offset += len; + } + +- if (offset != size) ++ if (offset != size) { ++ free(buf); + ERROR("shstrtab size mismatch."); ++ } + + strtab->data->d_buf = buf; + strtab->data->d_size = size; ++ strtab->dbuf_source = DATA_SOURCE_ALLOC; + + log_debug("strtab: "); + print_strtab(buf, size); +@@ -569,10 +591,10 @@ void upatch_create_symtab(struct upatch_elf *uelf) + nr++; + + size = nr * symtab->sh.sh_entsize; +- buf = malloc(size); +- if (!buf) ++ buf = calloc(1, size); ++ if (!buf) { + ERROR("malloc buf failed in create symtab."); +- memset(buf, 0, size); ++ } + + offset = 0; + list_for_each_entry(sym, &uelf->symbols, list) { +@@ -585,6 +607,7 @@ void upatch_create_symtab(struct upatch_elf *uelf) + + symtab->data->d_buf = buf; + symtab->data->d_size = size; ++ symtab->dbuf_source = DATA_SOURCE_ALLOC; + + /* update symtab section header */ + strtab = find_section_by_name(&uelf->sections, ".strtab"); +diff --git a/upatch-diff/elf-debug.c b/upatch-diff/elf-debug.c +index eaabfa1..0490f86 100644 +--- a/upatch-diff/elf-debug.c ++++ b/upatch-diff/elf-debug.c +@@ -129,9 +129,10 @@ void upatch_rebuild_eh_frame(struct section *sec) + + /* in this time, some relcation entries may have been deleted */ + frame_size = 0; +- eh_frame = malloc(sec->data->d_size); +- if (!eh_frame) ++ eh_frame = calloc(1, sec->data->d_size); ++ if (!eh_frame) { + ERROR("malloc eh_frame failed \n"); ++ } + + /* 8 is the offset of PC begin */ + current_offset = 8; +@@ -191,5 +192,7 @@ void upatch_rebuild_eh_frame(struct section *sec) + + sec->data->d_buf = eh_frame; + sec->data->d_size = frame_size; ++ sec->dbuf_source = DATA_SOURCE_ALLOC; ++ + sec->sh.sh_size = frame_size; + } +diff --git a/upatch-diff/running-elf.c b/upatch-diff/running-elf.c +index 18ff095..c99b395 100644 +--- a/upatch-diff/running-elf.c ++++ b/upatch-diff/running-elf.c +@@ -101,7 +101,7 @@ void relf_init(char *elf_name, struct running_elf *relf) + } + } + +-int relf_destroy(struct running_elf *relf) ++int relf_close(struct running_elf *relf) + { + free(relf->obj_syms); + elf_end(relf->elf); +diff --git a/upatch-diff/running-elf.h b/upatch-diff/running-elf.h +index 0646780..b02c8e2 100644 +--- a/upatch-diff/running-elf.h ++++ b/upatch-diff/running-elf.h +@@ -58,7 +58,7 @@ struct running_elf { + + void relf_init(char *, struct running_elf *); + +-int relf_destroy(struct running_elf *); ++int relf_close(struct running_elf *); + + bool lookup_relf(struct running_elf *, struct symbol *, struct lookup_result *); + +diff --git a/upatch-diff/upatch-elf.c b/upatch-diff/upatch-elf.c +index ee38efc..171e88e 100644 +--- a/upatch-diff/upatch-elf.c ++++ b/upatch-diff/upatch-elf.c +@@ -67,11 +67,14 @@ static void create_section_list(struct upatch_elf *uelf) + sec->name = elf_strptr(uelf->elf, shstrndx, sec->sh.sh_name); + if (!sec->name) + ERROR("elf_strptr with error %s", elf_errmsg(0)); +- + sec->data = elf_getdata(scn, NULL); + if (!sec->data) + ERROR("elf_getdata with error %s", elf_errmsg(0)); + ++ sec->name_source = DATA_SOURCE_ELF; ++ sec->data_source = DATA_SOURCE_ELF; ++ sec->dbuf_source = DATA_SOURCE_ELF; ++ + sec->index = (unsigned int)elf_ndxscn(scn); + /* found extended section header */ + if (sec->sh.sh_type == SHT_SYMTAB_SHNDX) +@@ -157,6 +160,8 @@ static void create_rela_list(struct upatch_elf *uelf, struct section *relasec) + struct rela *rela; + int index = 0, skip = 0; + ++ INIT_LIST_HEAD(&relasec->relas); ++ + /* for relocation sections, sh_info is the index which these informations apply */ + relasec->base = find_section_by_index(&uelf->sections, relasec->sh.sh_info); + if (!relasec->base) +@@ -215,10 +220,86 @@ static void create_rela_list(struct upatch_elf *uelf, struct section *relasec) + } + } + ++static void destroy_rela_list(struct section *relasec) ++{ ++ struct rela *rela = NULL, *saferela = NULL; ++ ++ list_for_each_entry_safe(rela, saferela, &relasec->relas, list) { ++ list_del(&rela->list); ++ free(rela); ++ } ++ ++ INIT_LIST_HEAD(&relasec->relas); ++} ++ ++static void destroy_section_list(struct upatch_elf *uelf) ++{ ++ struct section *sec = NULL, *safesec = NULL; ++ ++ list_for_each_entry_safe(sec, safesec, &uelf->sections, list) { ++ if (sec->twin) { ++ sec->twin->twin = NULL; ++ } ++ ++ if ((sec->name != NULL) && (sec->name_source == DATA_SOURCE_ALLOC)) { ++ free(sec->name); ++ sec->name = NULL; ++ } ++ ++ if (sec->data != NULL) { ++ if (sec->dbuf_source == DATA_SOURCE_ALLOC) { ++ free(sec->data->d_buf); ++ sec->data->d_buf = NULL; ++ } ++ if (sec->data_source == DATA_SOURCE_ALLOC) { ++ free(sec->data); ++ sec->data = NULL; ++ } ++ } ++ ++ if (is_rela_section(sec)) { ++ destroy_rela_list(sec); ++ } ++ ++ list_del(&sec->list); ++ free(sec); ++ } ++ ++ INIT_LIST_HEAD(&uelf->sections); ++} ++ ++static void destroy_symbol_list(struct upatch_elf *uelf) ++{ ++ struct symbol *sym = NULL, *safesym = NULL; ++ ++ list_for_each_entry_safe(sym, safesym, &uelf->symbols, list) { ++ if (sym->twin) { ++ sym->twin->twin = NULL; ++ } ++ ++ list_del(&sym->list); ++ free(sym); ++ } ++ ++ INIT_LIST_HEAD(&uelf->symbols); ++} ++ ++static void destroy_string_list(struct upatch_elf *uelf) ++{ ++ struct string *str = NULL, *safestr = NULL; ++ ++ list_for_each_entry_safe(str, safestr, &uelf->strings, list) { ++ list_del(&str->list); ++ free(str); ++ } ++ ++ INIT_LIST_HEAD(&uelf->strings); ++} ++ + void upatch_elf_open(struct upatch_elf *uelf, const char *name) + { + GElf_Ehdr ehdr; +- struct section *relasec; ++ struct section *sec; + Elf *elf = NULL; + int fd = 1; + +@@ -264,46 +345,21 @@ void upatch_elf_open(struct upatch_elf *uelf, const char *name) + create_section_list(uelf); + create_symbol_list(uelf); + +- list_for_each_entry(relasec, &uelf->sections, list) { +- if (!is_rela_section(relasec)) +- continue; +- INIT_LIST_HEAD(&relasec->relas); +- +- create_rela_list(uelf, relasec); +- } +-} +- +-void upatch_elf_teardown(struct upatch_elf *uelf) +-{ +- struct section *sec, *safesec; +- struct symbol *sym, *safesym; +- struct rela *rela, *saferela; +- +- list_for_each_entry_safe(sec, safesec, &uelf->sections, list) { +- if (sec->twin) +- sec->twin->twin = NULL; ++ list_for_each_entry(sec, &uelf->sections, list) { + if (is_rela_section(sec)) { +- list_for_each_entry_safe(rela, saferela, &sec->relas, list) { +- memset(rela, 0, sizeof(*rela)); +- free(rela); +- } ++ create_rela_list(uelf, sec); + } +- memset(sec, 0, sizeof(*sec)); +- free(sec); +- } +- +- list_for_each_entry_safe(sym, safesym, &uelf->symbols, list) { +- if (sym->twin) +- sym->twin->twin = NULL; +- memset(sym, 0, sizeof(*sym)); +- free(sym); + } ++} + +- INIT_LIST_HEAD(&uelf->sections); +- INIT_LIST_HEAD(&uelf->symbols); ++void upatch_elf_destroy(struct upatch_elf *uelf) ++{ ++ destroy_section_list(uelf); ++ destroy_symbol_list(uelf); ++ destroy_string_list(uelf); + } + +-void upatch_elf_free(struct upatch_elf *uelf) ++void upatch_elf_close(struct upatch_elf *uelf) + { + elf_end(uelf->elf); + close(uelf->fd); +diff --git a/upatch-diff/upatch-elf.h b/upatch-diff/upatch-elf.h +index 3cbb59b..6c62c93 100644 +--- a/upatch-diff/upatch-elf.h ++++ b/upatch-diff/upatch-elf.h +@@ -39,6 +39,12 @@ struct section; + struct rela; + struct symbol; + ++enum data_source { ++ DATA_SOURCE_ELF, ++ DATA_SOURCE_REF, ++ DATA_SOURCE_ALLOC, ++}; ++ + enum status { + NEW, + CHANGED, +@@ -61,6 +67,9 @@ struct section { + struct section *twin; + char *name; + Elf_Data *data; ++ enum data_source name_source; ++ enum data_source data_source; ++ enum data_source dbuf_source; + GElf_Shdr sh; + int ignore; + int include; +@@ -102,6 +111,7 @@ struct symbol { + struct section *sec; + GElf_Sym sym; + char *name; ++ enum data_source name_source; + struct debug_symbol *relf_sym; + unsigned int index; + unsigned char bind; +@@ -132,8 +142,8 @@ struct upatch_elf { + void upatch_elf_open(struct upatch_elf *, const char *); + + // Destory upatch_elf struct +-void upatch_elf_teardown(struct upatch_elf *); ++void upatch_elf_destroy(struct upatch_elf *); + +-void upatch_elf_free(struct upatch_elf *); ++void upatch_elf_close(struct upatch_elf *); + + #endif +-- +2.34.1 + diff --git a/0030-upatch-hijacker-fix-memory-leak.patch b/0030-upatch-hijacker-fix-memory-leak.patch new file mode 100644 index 0000000000000000000000000000000000000000..dfbaa0b2318eb2c8d0f6d508f6c7d301b3374f18 --- /dev/null +++ b/0030-upatch-hijacker-fix-memory-leak.patch @@ -0,0 +1,43 @@ +From 41322f2b7a234f91ca6e8e29cfdee2f77356dd8c Mon Sep 17 00:00:00 2001 +From: liuxiaobo +Date: Thu, 27 Jun 2024 16:22:26 +0800 +Subject: [PATCH] upatch-hijacker: fix memory leak + +Signed-off-by: liuxiaobo +--- + upatch-hijacker/hijacker/gnu-as-hijacker.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/upatch-hijacker/hijacker/gnu-as-hijacker.c b/upatch-hijacker/hijacker/gnu-as-hijacker.c +index 860a84f..886420e 100644 +--- a/upatch-hijacker/hijacker/gnu-as-hijacker.c ++++ b/upatch-hijacker/hijacker/gnu-as-hijacker.c +@@ -48,6 +48,7 @@ int main(int argc, char *argv[], char *envp[]) + { + // Try to get executable path + const char *filename = get_current_exec(); ++ + if (filename == NULL) { + return -ENOENT; + } +@@ -111,9 +112,15 @@ int main(int argc, char *argv[], char *envp[]) + (void)unlink(output_file); + } + ++ int ret = 0; + if (symlink(new_output_file, output_file) != 0) { +- return execve(filename, argv, envp); ++ ret = execve(filename, argv, envp); ++ goto out; + } + +- return execve(filename, (char* const*)new_argv, envp); ++ ret = execve(filename, (char* const*)new_argv, envp); ++out: ++ free(new_argv); ++ ++ return ret; + } +-- +2.34.1 + diff --git a/0031-upatch-manage-fix-memory-leak.patch b/0031-upatch-manage-fix-memory-leak.patch new file mode 100644 index 0000000000000000000000000000000000000000..93faf31a8f5a836f64c166fb3ff18049b89b45a3 --- /dev/null +++ b/0031-upatch-manage-fix-memory-leak.patch @@ -0,0 +1,113 @@ +From 22e9b146b485735389b71e9b71a3f31ea151477c Mon Sep 17 00:00:00 2001 +From: liuxiaobo +Date: Thu, 27 Jun 2024 16:22:02 +0800 +Subject: [PATCH] upatch-manage: fix memory leak + +Signed-off-by: liuxiaobo +--- + upatch-manage/arch/x86_64/ptrace.c | 7 ++-- + upatch-manage/upatch-process.c | 61 ++++++++++++++++++------------ + 2 files changed, 39 insertions(+), 29 deletions(-) + +diff --git a/upatch-manage/arch/x86_64/ptrace.c b/upatch-manage/arch/x86_64/ptrace.c +index 3d6dd72..95e2710 100644 +--- a/upatch-manage/arch/x86_64/ptrace.c ++++ b/upatch-manage/arch/x86_64/ptrace.c +@@ -173,9 +173,8 @@ size_t get_upatch_addr_len() + return UPATCH_ADDR_LEN; + } + +- + unsigned long get_new_insn(void) + { +- char jmp_insn[] = { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00}; +- return *(unsigned long *)jmp_insn; +-} +\ No newline at end of file ++ // ASM: jmp word ptr [di] (FF25 0000 0000 0000) ++ return 0x25FF; ++} +diff --git a/upatch-manage/upatch-process.c b/upatch-manage/upatch-process.c +index 3b8db3b..84ec030 100644 +--- a/upatch-manage/upatch-process.c ++++ b/upatch-manage/upatch-process.c +@@ -385,6 +385,40 @@ process_new_object(struct upatch_process *proc, dev_t dev, ino_t inode, + return o; + } + ++static int add_upatch_object(struct upatch_process *proc, ++ struct object_file *o, unsigned long src, unsigned char *header_buf) ++{ ++ struct object_patch *opatch; ++ ++ opatch = malloc(sizeof(struct object_patch)); ++ if (opatch == NULL) { ++ log_error("malloc opatch failed\n"); ++ return -1; ++ } ++ ++ opatch->uinfo = malloc(sizeof(struct upatch_info)); ++ if (opatch->uinfo == NULL) { ++ log_error("malloc opatch->uinfo failed\n"); ++ free(opatch); ++ return -1; ++ } ++ ++ memcpy(opatch->uinfo, header_buf, sizeof(struct upatch_info)); ++ opatch->funcs = malloc(opatch->uinfo->changed_func_num * ++ sizeof(struct upatch_info_func)); ++ if (upatch_process_mem_read(proc, src, opatch->funcs, ++ opatch->uinfo->changed_func_num * sizeof(struct upatch_info_func))) { ++ log_error("can't read patch funcs at 0x%lx\n", src); ++ free(opatch->uinfo); ++ free(opatch); ++ return -1; ++ } ++ list_add(&opatch->list, &o->applied_patch); ++ o->num_applied_patch++; ++ o->is_patch = 1; ++ ++ return 0; ++} + /** + * Returns: 0 if everything is ok, -1 on error. + */ +@@ -420,33 +454,10 @@ static int process_add_object_vma(struct upatch_process *proc, dev_t dev, + } + + if (object_type == OBJECT_UPATCH) { +- struct object_patch *opatch; +- +- opatch = malloc(sizeof(struct object_patch)); +- if (opatch == NULL) { +- return -1; +- } +- +- opatch->uinfo = malloc(sizeof(struct upatch_info)); +- if (opatch->uinfo == NULL) { +- return -1; +- } +- +- memcpy(opatch->uinfo, header_buf, sizeof(struct upatch_info)); +- opatch->funcs = malloc(opatch->uinfo->changed_func_num * +- sizeof(struct upatch_info_func)); +- if (upatch_process_mem_read( +- proc, vma->start + sizeof(struct upatch_info), +- opatch->funcs, +- opatch->uinfo->changed_func_num * +- sizeof(struct upatch_info_func))) { +- log_error("can't read patch funcs at 0x%lx\n", +- vma->start + sizeof(struct upatch_info)); ++ unsigned long src = vma->start + sizeof(struct upatch_info); ++ if (add_upatch_object(proc, o, src, header_buf) != 0) { + return -1; + } +- list_add(&opatch->list, &o->applied_patch); +- o->num_applied_patch++; +- o->is_patch = 1; + } + if (object_type == OBJECT_ELF) { + o->is_elf = 1; +-- +2.34.1 + diff --git a/0032-security-sanitize-sensitive-code.patch b/0032-security-sanitize-sensitive-code.patch new file mode 100644 index 0000000000000000000000000000000000000000..aadbfeff82325ae3eff534818169828b682b8b6c --- /dev/null +++ b/0032-security-sanitize-sensitive-code.patch @@ -0,0 +1,1989 @@ +From 6d40a02a4a4350dfce9da9418c42d5d232a12394 Mon Sep 17 00:00:00 2001 +From: liuxiaobo +Date: Fri, 7 Jun 2024 16:25:53 +0800 +Subject: [PATCH] security: sanitize sensitive code + +1. rename 'upatch_hijacker' to 'upatch_helper' +2. sanitize all 'hijacker' in source code + +Signed-off-by: liuxiaobo +--- + CMakeLists.txt | 2 +- + upatch-build/src/{hijacker.rs => helper.rs} | 31 ++++--- + upatch-build/src/main.rs | 11 +-- + upatch-build/src/project.rs | 2 +- + upatch-build/src/rpc/proxy.rs | 4 +- + .../CMakeLists.txt | 2 +- + upatch-helper/helper/CMakeLists.txt | 35 ++++++++ + .../helper/gnu-as-helper.c | 18 ++-- + .../helper/gnu-compiler-helper.c | 16 ++-- + .../helper/helper.h | 12 +-- + upatch-helper/ko/CMakeLists.txt | 32 +++++++ + {upatch-hijacker => upatch-helper}/ko/LICENSE | 0 + .../ko/Makefile | 2 +- + {upatch-hijacker => upatch-helper}/ko/cache.c | 4 +- + {upatch-hijacker => upatch-helper}/ko/cache.h | 8 +- + .../ko/context.c | 60 ++++++------- + .../ko/context.h | 16 ++-- + {upatch-hijacker => upatch-helper}/ko/ioctl.c | 82 ++++++++--------- + {upatch-hijacker => upatch-helper}/ko/ioctl.h | 22 ++--- + {upatch-hijacker => upatch-helper}/ko/log.h | 8 +- + {upatch-hijacker => upatch-helper}/ko/main.c | 12 +-- + {upatch-hijacker => upatch-helper}/ko/map.c | 2 +- + {upatch-hijacker => upatch-helper}/ko/map.h | 8 +- + .../ko/records.c | 12 +-- + .../ko/records.h | 16 ++-- + .../ko/uprobe.c | 16 ++-- + .../ko/uprobe.h | 8 +- + {upatch-hijacker => upatch-helper}/ko/utils.h | 8 +- + upatch-hijacker/hijacker/CMakeLists.txt | 35 -------- + upatch-hijacker/ko/CMakeLists.txt | 32 ------- + upatch-manage/upatch-patch.c | 4 +- + upatchd/src/config.rs | 4 +- + upatchd/src/{hijacker => helper}/config.rs | 24 ++--- + .../src/{hijacker => helper}/elf_resolver.rs | 0 + upatchd/src/{hijacker => helper}/ioctl.rs | 28 +++--- + upatchd/src/{hijacker => helper}/kmod.rs | 8 +- + upatchd/src/{hijacker => helper}/mod.rs | 87 ++++++++++--------- + upatchd/src/main.rs | 4 +- + upatchd/src/rpc/skeleton.rs | 8 +- + upatchd/src/rpc/skeleton_impl.rs | 30 +++---- + 40 files changed, 359 insertions(+), 354 deletions(-) + rename upatch-build/src/{hijacker.rs => helper.rs} (69%) + rename {upatch-hijacker => upatch-helper}/CMakeLists.txt (81%) + create mode 100644 upatch-helper/helper/CMakeLists.txt + rename upatch-hijacker/hijacker/gnu-as-hijacker.c => upatch-helper/helper/gnu-as-helper.c (89%) + rename upatch-hijacker/hijacker/gnu-compiler-hijacker.c => upatch-helper/helper/gnu-compiler-helper.c (85%) + rename upatch-hijacker/hijacker/hijacker.h => upatch-helper/helper/helper.h (83%) + create mode 100644 upatch-helper/ko/CMakeLists.txt + rename {upatch-hijacker => upatch-helper}/ko/LICENSE (100%) + rename {upatch-hijacker => upatch-helper}/ko/Makefile (94%) + rename {upatch-hijacker => upatch-helper}/ko/cache.c (94%) + rename {upatch-hijacker => upatch-helper}/ko/cache.h (86%) + rename {upatch-hijacker => upatch-helper}/ko/context.c (70%) + rename {upatch-hijacker => upatch-helper}/ko/context.h (73%) + rename {upatch-hijacker => upatch-helper}/ko/ioctl.c (64%) + rename {upatch-hijacker => upatch-helper}/ko/ioctl.h (69%) + rename {upatch-hijacker => upatch-helper}/ko/log.h (87%) + rename {upatch-hijacker => upatch-helper}/ko/main.c (86%) + rename {upatch-hijacker => upatch-helper}/ko/map.c (99%) + rename {upatch-hijacker => upatch-helper}/ko/map.h (90%) + rename {upatch-hijacker => upatch-helper}/ko/records.c (90%) + rename {upatch-hijacker => upatch-helper}/ko/records.h (80%) + rename {upatch-hijacker => upatch-helper}/ko/uprobe.c (89%) + rename {upatch-hijacker => upatch-helper}/ko/uprobe.h (86%) + rename {upatch-hijacker => upatch-helper}/ko/utils.h (90%) + delete mode 100644 upatch-hijacker/hijacker/CMakeLists.txt + delete mode 100644 upatch-hijacker/ko/CMakeLists.txt + rename upatchd/src/{hijacker => helper}/config.rs (70%) + rename upatchd/src/{hijacker => helper}/elf_resolver.rs (100%) + rename upatchd/src/{hijacker => helper}/ioctl.rs (80%) + rename upatchd/src/{hijacker => helper}/kmod.rs (95%) + rename upatchd/src/{hijacker => helper}/mod.rs (52%) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 4858ba5..659222f 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -66,7 +66,7 @@ set(CMAKE_EXE_LINKER_FLAGS "${LINK_FLAGS}") + # Subdirectories + add_subdirectory(upatch-diff) + add_subdirectory(upatch-manage) +-add_subdirectory(upatch-hijacker) ++add_subdirectory(upatch-helper) + add_subdirectory(misc) + + # Build rust executables +diff --git a/upatch-build/src/hijacker.rs b/upatch-build/src/helper.rs +similarity index 69% +rename from upatch-build/src/hijacker.rs +rename to upatch-build/src/helper.rs +index 3060495..7ce3323 100644 +--- a/upatch-build/src/hijacker.rs ++++ b/upatch-build/src/helper.rs +@@ -9,13 +9,13 @@ use crate::rpc::{RpcRemote, UpatchProxy}; + + const UPATCHD_SOCKET_NAME: &str = "upatchd.sock"; + +-pub struct Hijacker<'a> { ++pub struct UpatchHelper<'a> { + proxy: UpatchProxy, + programs: IndexSet<&'a Path>, + finished: Vec<&'a Path>, + } + +-impl<'a> Hijacker<'a> { ++impl<'a> UpatchHelper<'a> { + pub fn new(compilers: I, work_dir: P) -> Result + where + I: IntoIterator, +@@ -36,20 +36,20 @@ impl<'a> Hijacker<'a> { + programs, + finished: vec![], + }; +- instance.hijack()?; ++ instance.enable()?; + + Ok(instance) + } + } + +-impl Hijacker<'_> { +- fn hijack(&mut self) -> Result<()> { +- info!("Hijacking compiler(s)"); ++impl UpatchHelper<'_> { ++ fn enable(&mut self) -> Result<()> { ++ info!("Hooking compiler(s)"); + for exec_path in &self.programs { + info!("- {}", exec_path.display()); + self.proxy +- .enable_hijack(exec_path) +- .with_context(|| format!("Failed to hijack {}", exec_path.display()))?; ++ .hook_compiler(exec_path) ++ .with_context(|| format!("Failed to hook compiler {}", exec_path.display()))?; + + self.finished.push(exec_path); + } +@@ -57,14 +57,13 @@ impl Hijacker<'_> { + Ok(()) + } + +- fn unhack(&mut self) { +- info!("Releasing compiler(s)"); ++ fn disable(&mut self) { ++ info!("Unhooking compiler(s)"); + while let Some(exec_path) = self.finished.pop() { + info!("- {}", exec_path.display()); +- let result = self +- .proxy +- .disable_hijack(exec_path) +- .with_context(|| format!("Failed to release {}", exec_path.display())); ++ let result = self.proxy.unhook_compiler(exec_path).with_context(|| { ++ format!("Failed to unhook compiler helper {}", exec_path.display()) ++ }); + + if let Err(e) = result { + error!("{:?}", e); +@@ -73,8 +72,8 @@ impl Hijacker<'_> { + } + } + +-impl Drop for Hijacker<'_> { ++impl Drop for UpatchHelper<'_> { + fn drop(&mut self) { +- self.unhack() ++ self.disable() + } + } +diff --git a/upatch-build/src/main.rs b/upatch-build/src/main.rs +index 473b0a7..769cc6c 100644 +--- a/upatch-build/src/main.rs ++++ b/upatch-build/src/main.rs +@@ -36,7 +36,7 @@ mod compiler; + mod dwarf; + mod elf; + mod file_relation; +-mod hijacker; ++mod helper; + mod pattern_path; + mod project; + mod resolve; +@@ -47,7 +47,7 @@ use build_root::BuildRoot; + use compiler::Compiler; + use dwarf::Dwarf; + use file_relation::FileRelation; +-use hijacker::Hijacker; ++use helper::UpatchHelper; + use project::Project; + + const CLI_NAME: &str = "upatch build"; +@@ -401,7 +401,8 @@ impl UpatchBuild { + } + + let mut files = FileRelation::new(); +- let hijacker = Hijacker::new(&compilers, work_dir).context("Failed to hack compilers")?; ++ let upatch_helper = ++ UpatchHelper::new(&compilers, work_dir).context("Failed to hook compilers")?; + + info!("Preparing {}", project); + project +@@ -435,8 +436,8 @@ impl UpatchBuild { + info!("Collecting file relations"); + files.collect_patched_build(object_dir, patched_dir)?; + +- // Unhack compilers +- drop(hijacker); ++ // Restore compilers ++ drop(upatch_helper); + + let build_info = BuildInfo { + linker, +diff --git a/upatch-build/src/project.rs b/upatch-build/src/project.rs +index b36c26b..8b2a7b6 100644 +--- a/upatch-build/src/project.rs ++++ b/upatch-build/src/project.rs +@@ -28,7 +28,7 @@ use syscare_common::{fs, process::Command}; + use crate::{args::Arguments, build_root::BuildRoot}; + + const PATCH_BIN: &str = "patch"; +-const COMPILER_CMD_ENV: &str = "UPATCH_HIJACKER"; ++const COMPILER_CMD_ENV: &str = "UPATCH_HELPER"; + + const PREPARE_SCRIPT_NAME: &str = "prepare.sh"; + const BUILD_SCRIPT_NAME: &str = "build.sh"; +diff --git a/upatch-build/src/rpc/proxy.rs b/upatch-build/src/rpc/proxy.rs +index e249fa5..f63d681 100644 +--- a/upatch-build/src/rpc/proxy.rs ++++ b/upatch-build/src/rpc/proxy.rs +@@ -30,7 +30,7 @@ impl UpatchProxy { + } + + #[named] +- pub fn enable_hijack>(&self, exec_path: P) -> Result<()> { ++ pub fn hook_compiler>(&self, exec_path: P) -> Result<()> { + self.remote.call_with_args( + function_name!(), + RpcArguments::new().arg(exec_path.as_ref().to_path_buf()), +@@ -38,7 +38,7 @@ impl UpatchProxy { + } + + #[named] +- pub fn disable_hijack>(&self, exec_path: P) -> Result<()> { ++ pub fn unhook_compiler>(&self, exec_path: P) -> Result<()> { + self.remote.call_with_args( + function_name!(), + RpcArguments::new().arg(exec_path.as_ref().to_path_buf()), +diff --git a/upatch-hijacker/CMakeLists.txt b/upatch-helper/CMakeLists.txt +similarity index 81% +rename from upatch-hijacker/CMakeLists.txt +rename to upatch-helper/CMakeLists.txt +index 77d1010..bcd7295 100644 +--- a/upatch-hijacker/CMakeLists.txt ++++ b/upatch-helper/CMakeLists.txt +@@ -3,4 +3,4 @@ include_directories(${CMAKE_CURRENT_LIST_DIR}) + + # Build components + add_subdirectory(ko) +-add_subdirectory(hijacker) ++add_subdirectory(helper) +diff --git a/upatch-helper/helper/CMakeLists.txt b/upatch-helper/helper/CMakeLists.txt +new file mode 100644 +index 0000000..fefcebe +--- /dev/null ++++ b/upatch-helper/helper/CMakeLists.txt +@@ -0,0 +1,35 @@ ++# Build helpers ++add_executable(gnu-as-helper gnu-as-helper.c) ++add_executable(gnu-compiler-helper gnu-compiler-helper.c) ++ ++# Generate helpers ++add_custom_target(generate-upatch-helpers ALL ++ COMMENT "Generating upatch helpers..." ++ COMMAND ln -f gnu-as-helper as-helper ++ COMMAND ln -f gnu-compiler-helper gcc-helper ++ COMMAND ln -f gnu-compiler-helper g++-helper ++ COMMAND ln -f gnu-compiler-helper cc-helper ++ COMMAND ln -f gnu-compiler-helper c++-helper ++ DEPENDS ++ gnu-as-helper ++ gnu-compiler-helper ++ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ++) ++ ++# Install helpers ++install( ++ PROGRAMS ++ ${CMAKE_CURRENT_BINARY_DIR}/gnu-as-helper ++ ${CMAKE_CURRENT_BINARY_DIR}/gnu-compiler-helper ++ ${CMAKE_CURRENT_BINARY_DIR}/as-helper ++ ${CMAKE_CURRENT_BINARY_DIR}/gcc-helper ++ ${CMAKE_CURRENT_BINARY_DIR}/g++-helper ++ ${CMAKE_CURRENT_BINARY_DIR}/cc-helper ++ ${CMAKE_CURRENT_BINARY_DIR}/c++-helper ++ PERMISSIONS ++ OWNER_EXECUTE OWNER_WRITE OWNER_READ ++ GROUP_EXECUTE GROUP_READ ++ WORLD_READ WORLD_EXECUTE ++ DESTINATION ++ ${SYSCARE_LIBEXEC_DIR} ++) +diff --git a/upatch-hijacker/hijacker/gnu-as-hijacker.c b/upatch-helper/helper/gnu-as-helper.c +similarity index 89% +rename from upatch-hijacker/hijacker/gnu-as-hijacker.c +rename to upatch-helper/helper/gnu-as-helper.c +index 886420e..05246c3 100644 +--- a/upatch-hijacker/hijacker/gnu-as-hijacker.c ++++ b/upatch-helper/helper/gnu-as-helper.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: Mulan PSL v2 + /* + * Copyright (c) 2024 Huawei Technologies Co., Ltd. +- * gnu-as-hijacker is licensed under Mulan PSL v2. ++ * gnu-as-helper is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 +@@ -20,7 +20,7 @@ + #include + #include + +-#include "hijacker.h" ++#include "helper.h" + + #ifndef SYS_gettid + #error "SYS_gettid is unavailable on this system" +@@ -39,8 +39,8 @@ static char g_new_output_file[PATH_MAX] = { 0 }; + /* + * The whole part: + * 1. Someone called execve() to run a compiler (inode). +- * 2. If the inode was registered, under layer would rewrite argv[0] to hijacker path. +- * 3. Hijacker would add some arguments and calls execve() again. ++ * 2. If the inode was registered, under layer would rewrite argv[0] to helper path. ++ * 3. Helper would add some arguments and calls execve() again. + * 4. Under layer redirects argv[0] to original path. + * Pid would keep same. + */ +@@ -53,27 +53,27 @@ int main(int argc, char *argv[], char *envp[]) + return -ENOENT; + } + +- // If there is no env, stop hijack +- const char *output_dir = get_hijacker_env(); ++ // If there is no env, stop helper ++ const char *output_dir = get_helper_env(); + if (output_dir == NULL) { + return execve(filename, argv, envp); + } + +- // If output dir is not a directory, stop hijack ++ // If output dir is not a directory, stop helper + struct stat output_dir_stat; + if ((stat(output_dir, &output_dir_stat) != 0) || + (!S_ISDIR(output_dir_stat.st_mode))) { + return execve(filename, argv, envp); + } + +- // If there is no output, stop hijack ++ // If there is no output, stop helper + int output_index = find_output_flag(argc, argv); + if (output_index < 0) { + return execve(filename, argv, envp); + } + output_index += 1; + +- // If the output is null device, stop hijack ++ // If the output is null device, stop helper + const char *output_file = argv[output_index]; + if (strncmp(output_file, NULL_DEV_PATH, strlen(NULL_DEV_PATH)) == 0) { + return execve(filename, argv, envp); +diff --git a/upatch-hijacker/hijacker/gnu-compiler-hijacker.c b/upatch-helper/helper/gnu-compiler-helper.c +similarity index 85% +rename from upatch-hijacker/hijacker/gnu-compiler-hijacker.c +rename to upatch-helper/helper/gnu-compiler-helper.c +index d868467..507d709 100644 +--- a/upatch-hijacker/hijacker/gnu-compiler-hijacker.c ++++ b/upatch-helper/helper/gnu-compiler-helper.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: Mulan PSL v2 + /* + * Copyright (c) 2024 Huawei Technologies Co., Ltd. +- * gnu-compiler-hijacker is licensed under Mulan PSL v2. ++ * gnu-compiler-helper is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 +@@ -14,7 +14,7 @@ + + #include + +-#include "hijacker.h" ++#include "helper.h" + + static char* APPEND_ARGS[] = { + "-gdwarf", /* obatain debug information */ +@@ -27,8 +27,8 @@ static const int APPEND_ARG_LEN = (int)(sizeof(APPEND_ARGS) / sizeof(char *)); + /* + * The whole part: + * 1. Someone called execve() to run a compiler (inode). +- * 2. If the inode was registered, under layer would rewrite argv[0] to hijacker path. +- * 3. Hijacker would add some arguments and calls execve() again. ++ * 2. If the inode was registered, under layer would rewrite argv[0] to helper path. ++ * 3. Helper would add some arguments and calls execve() again. + * 4. Under layer redirects argv[0] to original path. + * Pid would keep same. + */ +@@ -40,13 +40,13 @@ int main(int argc, char *argv[], char *envp[]) + return -ENOENT; + } + +- // If there is no env, stop hijack +- const char *hijacker_env = get_hijacker_env(); +- if (hijacker_env == NULL) { ++ // If there is no env, stop helper ++ const char *helper_env = get_helper_env(); ++ if (helper_env == NULL) { + return execve(filename, argv, envp); + } + +- // If there is no output, stop hijack ++ // If there is no output, stop helper + if (find_output_flag(argc, argv) < 0) { + return execve(filename, argv, envp); + } +diff --git a/upatch-hijacker/hijacker/hijacker.h b/upatch-helper/helper/helper.h +similarity index 83% +rename from upatch-hijacker/hijacker/hijacker.h +rename to upatch-helper/helper/helper.h +index cc820ee..67a895c 100644 +--- a/upatch-hijacker/hijacker/hijacker.h ++++ b/upatch-helper/helper/helper.h +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: Mulan PSL v2 + /* + * Copyright (c) 2024 Huawei Technologies Co., Ltd. +- * gnu-compiler-hijacker is licensed under Mulan PSL v2. ++ * gnu-compiler-helper is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 +@@ -12,8 +12,8 @@ + * See the Mulan PSL v2 for more details. + */ + +-#ifndef __UPATCH_HIJACKER_COMMON_H +-#define __UPATCH_HIJACKER_COMMON_H ++#ifndef __UPATCH_HELPER_COMMON_H ++#define __UPATCH_HELPER_COMMON_H + + #include + #include +@@ -22,7 +22,7 @@ + + #include + +-static const char *UPATCH_ENV_NAME = "UPATCH_HIJACKER"; ++static const char *UPATCH_ENV_NAME = "UPATCH_HELPER"; + static const char *EXEC_SELF_PATH = "/proc/self/exe"; + static const char *OUTPUT_FLAG_NAME = "-o"; + +@@ -39,7 +39,7 @@ static inline char* get_current_exec(void) + return (char *)g_filename; + } + +-static inline const char* get_hijacker_env(void) ++static inline const char* get_helper_env(void) + { + return getenv(UPATCH_ENV_NAME); + } +@@ -58,4 +58,4 @@ static inline int find_output_flag(int argc, char* const argv[]) + return -EINVAL; + } + +-#endif /* __UPATCH_HIJACKER_COMMON_H */ ++#endif /* __UPATCH_HELPER_COMMON_H */ +diff --git a/upatch-helper/ko/CMakeLists.txt b/upatch-helper/ko/CMakeLists.txt +new file mode 100644 +index 0000000..2a5b980 +--- /dev/null ++++ b/upatch-helper/ko/CMakeLists.txt +@@ -0,0 +1,32 @@ ++# Build upatch-helper kernel module ++ ++# Set target ++set(UPATCH_HELPER_KMOD "upatch_helper.ko") ++ ++# Detect kernel source path ++if (DEFINED KERNEL_VERSION) ++ set(KERNEL_SOURCE_PATH "/lib/modules/${KERNEL_VERSION}/build") ++ set(UPATCH_HELPER_KMOD_BUILD_CMD make module_version=${BUILD_VERSION} kernel=${KERNEL_SOURCE_PATH}) ++else() ++ set(UPATCH_HELPER_KMOD_BUILD_CMD make module_version=${BUILD_VERSION}) ++endif() ++ ++# Build kernel module ++add_custom_target(upatch-helper-kmod ALL ++ COMMENT "Building kernel module upatch_helper..." ++ BYPRODUCTS ${UPATCH_HELPER_KMOD} ++ COMMAND ${UPATCH_HELPER_KMOD_BUILD_CMD} ++ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ++) ++ ++# Install kernel module ++install( ++ FILES ++ ${UPATCH_HELPER_KMOD} ++ PERMISSIONS ++ OWNER_WRITE OWNER_READ ++ GROUP_READ ++ WORLD_READ ++ DESTINATION ++ ${SYSCARE_LIBEXEC_DIR} ++) +diff --git a/upatch-hijacker/ko/LICENSE b/upatch-helper/ko/LICENSE +similarity index 100% +rename from upatch-hijacker/ko/LICENSE +rename to upatch-helper/ko/LICENSE +diff --git a/upatch-hijacker/ko/Makefile b/upatch-helper/ko/Makefile +similarity index 94% +rename from upatch-hijacker/ko/Makefile +rename to upatch-helper/ko/Makefile +index ebf6314..6ea3b72 100644 +--- a/upatch-hijacker/ko/Makefile ++++ b/upatch-helper/ko/Makefile +@@ -1,4 +1,4 @@ +-module_name ?= upatch_hijacker ++module_name ?= upatch_helper + module_version ?= "1.0-dev" + kernel ?= /lib/modules/$(shell uname -r)/build + +diff --git a/upatch-hijacker/ko/cache.c b/upatch-helper/ko/cache.c +similarity index 94% +rename from upatch-hijacker/ko/cache.c +rename to upatch-helper/ko/cache.c +index b5af6bf..4a5994f 100644 +--- a/upatch-hijacker/ko/cache.c ++++ b/upatch-helper/ko/cache.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /* +- * upatch-hijacker kernel module ++ * upatch-helper kernel module + * Copyright (C) 2024 Huawei Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify +@@ -24,7 +24,7 @@ + + #include "log.h" + +-static const char *CACHE_SLAB_NAME = "upatch_hijacker"; ++static const char *CACHE_SLAB_NAME = "upatch_helper"; + + static struct kmem_cache *g_path_cache = NULL; + +diff --git a/upatch-hijacker/ko/cache.h b/upatch-helper/ko/cache.h +similarity index 86% +rename from upatch-hijacker/ko/cache.h +rename to upatch-helper/ko/cache.h +index e26a49c..b9bdcc4 100644 +--- a/upatch-hijacker/ko/cache.h ++++ b/upatch-helper/ko/cache.h +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /* +- * upatch-hijacker kernel module ++ * upatch-helper kernel module + * Copyright (C) 2024 Huawei Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify +@@ -18,8 +18,8 @@ + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +-#ifndef _UPATCH_HIJACKER_KO_CACHE_H +-#define _UPATCH_HIJACKER_KO_CACHE_H ++#ifndef _UPATCH_HELPER_KO_CACHE_H ++#define _UPATCH_HELPER_KO_CACHE_H + + int cache_init(void); + void cache_exit(void); +@@ -27,4 +27,4 @@ void cache_exit(void); + char *path_buf_alloc(void); + void path_buf_free(char *buff); + +-#endif /* _UPATCH_HIJACKER_KO_CACHE_H */ ++#endif /* _UPATCH_HELPER_KO_CACHE_H */ +diff --git a/upatch-hijacker/ko/context.c b/upatch-helper/ko/context.c +similarity index 70% +rename from upatch-hijacker/ko/context.c +rename to upatch-helper/ko/context.c +index 2e406f4..3a6c920 100644 +--- a/upatch-hijacker/ko/context.c ++++ b/upatch-helper/ko/context.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /* +- * upatch-hijacker kernel module ++ * upatch-helper kernel module + * Copyright (C) 2024 Huawei Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify +@@ -34,34 +34,34 @@ + struct context { + struct pid_namespace *ns; + struct uprobe_record *uprobe; +- struct map *hijacker_map; ++ struct map *helper_map; + }; + +-static bool find_hijacker_context(const struct context *context, ++static bool find_helper_context(const struct context *context, + const struct pid_namespace *ns); +-static void free_hijacker_context(struct context *context); ++static void free_helper_context(struct context *context); + +-static const struct map_ops HIJACK_MAP_OPS = { +- .find_value = (find_value_fn)find_hijacker_record, +- .free_value = (free_value_fn)free_hijacker_record, ++static const struct map_ops HELPER_MAP_OPS = { ++ .find_value = (find_value_fn)find_helper_record, ++ .free_value = (free_value_fn)free_helper_record, + }; + static const struct map_ops CONTEXT_MAP_OPS = { +- .find_value = (find_value_fn)find_hijacker_context, +- .free_value = (free_value_fn)free_hijacker_context, ++ .find_value = (find_value_fn)find_helper_context, ++ .free_value = (free_value_fn)free_helper_context, + }; + + static const size_t MAX_CONTEXT_NUM = 1024; +-static const size_t HIJACKER_PER_CONTEXT = 16; ++static const size_t HELPER_PER_CONTEXT = 16; + + static struct map *g_context_map = NULL; + + /* Context private interface */ +-static int create_hijacker_context(struct context **context, ++static int create_helper_context(struct context **context, + struct pid_namespace *ns, const char *path, loff_t offset) + { + struct context *new_context = NULL; + struct uprobe_record *uprobe = NULL; +- struct map *hijacker_map = NULL; ++ struct map *helper_map = NULL; + int ret = 0; + + new_context = kzalloc(sizeof(struct context), GFP_KERNEL); +@@ -70,9 +70,9 @@ static int create_hijacker_context(struct context **context, + return -ENOMEM; + } + +- ret = new_map(&hijacker_map, HIJACKER_PER_CONTEXT, &HIJACK_MAP_OPS); ++ ret = new_map(&helper_map, HELPER_PER_CONTEXT, &HELPER_MAP_OPS); + if (ret != 0) { +- pr_err("failed to create hijacker map, ret=%d\n", ret); ++ pr_err("failed to create helper map, ret=%d\n", ret); + kfree(new_context); + return ret; + } +@@ -80,7 +80,7 @@ static int create_hijacker_context(struct context **context, + ret = new_uprobe_record(&uprobe, handle_uprobe, path, offset); + if (ret != 0) { + pr_err("failed to create uprobe record, ret=%d\n", ret); +- free_map(hijacker_map); ++ free_map(helper_map); + kfree(new_context); + return ret; + } +@@ -90,20 +90,20 @@ static int create_hijacker_context(struct context **context, + pr_err("failed to register uprobe, inode=%lu, offset=0x%llx, ret=%d\n", + uprobe->inode->i_ino, uprobe->offset, ret); + free_uprobe_record(uprobe); +- free_map(hijacker_map); ++ free_map(helper_map); + kfree(new_context); + return ret; + } + + new_context->ns = get_pid_ns(ns); + new_context->uprobe = uprobe; +- new_context->hijacker_map = hijacker_map; ++ new_context->helper_map = helper_map; + + *context = new_context; + return 0; + } + +-static void free_hijacker_context(struct context *context) ++static void free_helper_context(struct context *context) + { + if (context == NULL) { + return; +@@ -114,11 +114,11 @@ static void free_hijacker_context(struct context *context) + + put_pid_ns(context->ns); + free_uprobe_record(context->uprobe); +- free_map(context->hijacker_map); ++ free_map(context->helper_map); + kfree(context); + } + +-static bool find_hijacker_context(const struct context *context, ++static bool find_helper_context(const struct context *context, + const struct pid_namespace *ns) + { + return ns_equal(context->ns, ns); +@@ -143,7 +143,7 @@ void context_exit(void) + free_map(g_context_map); + } + +-int build_hijacker_context(const char *path, loff_t offset) ++int build_helper_context(const char *path, loff_t offset) + { + struct pid_namespace *ns = task_active_pid_ns(current); + struct context *context = NULL; +@@ -153,37 +153,37 @@ int build_hijacker_context(const char *path, loff_t offset) + return -EINVAL; + } + +- ret = create_hijacker_context(&context, ns, path, offset); ++ ret = create_helper_context(&context, ns, path, offset); + if (ret != 0) { +- pr_err("failed to create hijacker context, ret=%d\n", ret); ++ pr_err("failed to create helper context, ret=%d\n", ret); + return ret; + } + +- pr_debug("hijacker context, addr=0x%lx\n", (unsigned long)context); ++ pr_debug("helper context, addr=0x%lx\n", (unsigned long)context); + ret = map_insert(g_context_map, context); + if (ret != 0) { +- pr_err("failed to register hijacker context, ret=%d\n", ret); ++ pr_err("failed to register helper context, ret=%d\n", ret); + return ret; + } + + return 0; + } + +-void destroy_hijacker_context(void) ++void destroy_helper_context(void) + { +- pr_debug("destroy hijacker context\n"); ++ pr_debug("destroy helper context\n"); + map_remove(g_context_map, task_active_pid_ns(current)); + } + +-size_t hijacker_context_count(void) ++size_t helper_context_count(void) + { + return map_size(g_context_map); + } + +-struct map *get_hijacker_map(void) ++struct map *get_helper_map(void) + { + struct pid_namespace *ns = task_active_pid_ns(current); + struct context *context = (struct context *)map_get(g_context_map, ns); + +- return (context != NULL) ? context->hijacker_map : NULL; ++ return (context != NULL) ? context->helper_map : NULL; + } +diff --git a/upatch-hijacker/ko/context.h b/upatch-helper/ko/context.h +similarity index 73% +rename from upatch-hijacker/ko/context.h +rename to upatch-helper/ko/context.h +index 6b5a50f..2054b75 100644 +--- a/upatch-hijacker/ko/context.h ++++ b/upatch-helper/ko/context.h +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /* +- * upatch-hijacker kernel module ++ * upatch-helper kernel module + * Copyright (C) 2024 Huawei Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify +@@ -18,8 +18,8 @@ + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +-#ifndef _UPATCH_HIJACKER_KO_CONTEXT_H +-#define _UPATCH_HIJACKER_KO_CONTEXT_H ++#ifndef _UPATCH_HELPER_KO_CONTEXT_H ++#define _UPATCH_HELPER_KO_CONTEXT_H + + #include + +@@ -28,10 +28,10 @@ struct map; + int context_init(void); + void context_exit(void); + +-int build_hijacker_context(const char *path, loff_t offset); +-void destroy_hijacker_context(void); +-size_t hijacker_context_count(void); ++int build_helper_context(const char *path, loff_t offset); ++void destroy_helper_context(void); ++size_t helper_context_count(void); + +-struct map *get_hijacker_map(void); ++struct map *get_helper_map(void); + +-#endif /* _UPATCH_HIJACKER_KO_CONTEXT_H */ ++#endif /* _UPATCH_HELPER_KO_CONTEXT_H */ +diff --git a/upatch-hijacker/ko/ioctl.c b/upatch-helper/ko/ioctl.c +similarity index 64% +rename from upatch-hijacker/ko/ioctl.c +rename to upatch-helper/ko/ioctl.c +index f76b5fb..500e7d4 100644 +--- a/upatch-hijacker/ko/ioctl.c ++++ b/upatch-helper/ko/ioctl.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /* +- * upatch-hijacker kernel module ++ * upatch-helper kernel module + * Copyright (C) 2024 Huawei Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify +@@ -32,19 +32,19 @@ + #include "context.h" + #include "utils.h" + +-static const struct file_operations HIJACKER_DEV_FOPS = { ++static const struct file_operations HELPER_DEV_FOPS = { + .owner = THIS_MODULE, + .unlocked_ioctl = handle_ioctl, + }; + +-static struct miscdevice g_hijacker_dev = { ++static struct miscdevice g_helper_dev = { + .minor = MISC_DYNAMIC_MINOR, +- .mode = UPATCH_HIJACKER_DEV_MODE, +- .name = UPATCH_HIJACKER_DEV_NAME, +- .fops = &HIJACKER_DEV_FOPS, ++ .mode = UPATCH_HELPER_DEV_MODE, ++ .name = UPATCH_HELPER_DEV_NAME, ++ .fops = &HELPER_DEV_FOPS, + }; + +-static inline int handle_enable_hijacker(void __user *arg) ++static inline int handle_enable_helper(void __user *arg) + { + int ret = 0; + upatch_enable_request_t *msg = NULL; +@@ -62,10 +62,10 @@ static inline int handle_enable_hijacker(void __user *arg) + return -EFAULT; + } + +- pr_debug("enable hijacker, path=%s, offset=0x%llx\n", msg->path, msg->offset); +- ret = build_hijacker_context(msg->path, msg->offset); ++ pr_debug("enable helper, path=%s, offset=0x%llx\n", msg->path, msg->offset); ++ ret = build_helper_context(msg->path, msg->offset); + if (ret != 0) { +- pr_err("failed to build hijacker context, ret=%d\n", ret); ++ pr_err("failed to build helper context, ret=%d\n", ret); + kfree(msg); + } + +@@ -73,21 +73,21 @@ static inline int handle_enable_hijacker(void __user *arg) + return 0; + } + +-static inline void handle_disable_hijacker(void) ++static inline void handle_disable_helper(void) + { +- pr_debug("disable hijacker\n"); +- destroy_hijacker_context(); ++ pr_debug("disable helper\n"); ++ destroy_helper_context(); + } + +-static inline int handle_register_hijacker(void __user *arg) ++static inline int handle_register_helper(void __user *arg) + { + upatch_register_request_t *msg = NULL; +- struct map *hijacker_map = get_hijacker_map(); +- struct hijacker_record *record = NULL; ++ struct map *helper_map = get_helper_map(); ++ struct helper_record *record = NULL; + int ret = 0; + +- if (hijacker_map == NULL) { +- pr_err("failed to get hijacker map\n"); ++ if (helper_map == NULL) { ++ pr_err("failed to get helper map\n"); + return -EFAULT; + } + +@@ -104,21 +104,21 @@ static inline int handle_register_hijacker(void __user *arg) + return -EFAULT; + } + +- ret = create_hijacker_record(&record, msg->exec_path, msg->jump_path); ++ ret = create_helper_record(&record, msg->exec_path, msg->jump_path); + if (ret != 0) { +- pr_err("failed to create hijacker record [%s -> %s], ret=%d\n", ++ pr_err("failed to create helper record [%s -> %s], ret=%d\n", + msg->exec_path, msg->jump_path, ret); + kfree(msg); + return ret; + } + +- pr_debug("register hijacker, inode=%lu, addr=0x%lx\n", ++ pr_debug("register helper, inode=%lu, addr=0x%lx\n", + record->exec_inode->i_ino, (unsigned long)record); +- ret = map_insert(get_hijacker_map(), record); ++ ret = map_insert(get_helper_map(), record); + if (ret != 0) { +- pr_err("failed to register hijacker record [%s -> %s], ret=%d\n", ++ pr_err("failed to register helper record [%s -> %s], ret=%d\n", + msg->exec_path, msg->jump_path, ret); +- free_hijacker_record(record); ++ free_helper_record(record); + kfree(msg); + return ret; + } +@@ -127,16 +127,16 @@ static inline int handle_register_hijacker(void __user *arg) + return 0; + } + +-static inline int handle_unregister_hijacker(void __user *arg) ++static inline int handle_unregister_helper(void __user *arg) + { + upatch_register_request_t *msg = NULL; +- struct map *hijacker_map = get_hijacker_map(); ++ struct map *helper_map = get_helper_map(); + struct inode *inode = NULL; + + int ret = 0; + +- if (hijacker_map == NULL) { +- pr_err("failed to get hijacker map\n"); ++ if (helper_map == NULL) { ++ pr_err("failed to get helper map\n"); + return -EFAULT; + } + +@@ -161,8 +161,8 @@ static inline int handle_unregister_hijacker(void __user *arg) + return -ENOENT; + } + +- pr_debug("remove hijacker, inode=%lu\n", inode->i_ino); +- map_remove(hijacker_map, inode); ++ pr_debug("remove helper, inode=%lu\n", inode->i_ino); ++ map_remove(helper_map, inode); + + kfree(msg); + return 0; +@@ -172,7 +172,7 @@ int ioctl_init(void) + { + int ret = 0; + +- ret = misc_register(&g_hijacker_dev); ++ ret = misc_register(&g_helper_dev); + if (ret != 0) { + pr_err("failed to register misc device, ret=%d\n", ret); + } +@@ -182,7 +182,7 @@ int ioctl_init(void) + + void ioctl_exit(void) + { +- misc_deregister(&g_hijacker_dev); ++ misc_deregister(&g_helper_dev); + } + + long handle_ioctl(struct file *file, +@@ -190,23 +190,23 @@ long handle_ioctl(struct file *file, + { + int ret = 0; + +- if (_IOC_TYPE(cmd) != UPATCH_HIJACKER_IOC_MAGIC) { ++ if (_IOC_TYPE(cmd) != UPATCH_HELPER_IOC_MAGIC) { + pr_info("invalid command\n"); + return -EBADMSG; + } + + switch (cmd) { +- case UPATCH_HIJACKER_ENABLE: +- ret = handle_enable_hijacker((void __user *)arg); ++ case UPATCH_HELPER_ENABLE: ++ ret = handle_enable_helper((void __user *)arg); + break; +- case UPATCH_HIJACKER_DISABLE: +- handle_disable_hijacker(); ++ case UPATCH_HELPER_DISABLE: ++ handle_disable_helper(); + break; +- case UPATCH_HIJACKER_REGISTER: +- ret = handle_register_hijacker((void __user *)arg); ++ case UPATCH_HELPER_REGISTER: ++ ret = handle_register_helper((void __user *)arg); + break; +- case UPATCH_HIJACKER_UNREGISTER: +- ret = handle_unregister_hijacker((void __user *)arg); ++ case UPATCH_HELPER_UNREGISTER: ++ ret = handle_unregister_helper((void __user *)arg); + break; + default: + ret = -EBADMSG; +diff --git a/upatch-hijacker/ko/ioctl.h b/upatch-helper/ko/ioctl.h +similarity index 69% +rename from upatch-hijacker/ko/ioctl.h +rename to upatch-helper/ko/ioctl.h +index dbcd12e..fd49961 100644 +--- a/upatch-hijacker/ko/ioctl.h ++++ b/upatch-helper/ko/ioctl.h +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /* +- * upatch-hijacker kernel module ++ * upatch-helper kernel module + * Copyright (C) 2024 Huawei Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify +@@ -18,22 +18,22 @@ + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +-#ifndef _UPATCH_HIJACKER_KO_IOCTL_H +-#define _UPATCH_HIJACKER_KO_IOCTL_H ++#ifndef _UPATCH_HELPER_KO_IOCTL_H ++#define _UPATCH_HELPER_KO_IOCTL_H + + #include + #include + +-#define UPATCH_HIJACKER_DEV_NAME "upatch-hijacker" +-#define UPATCH_HIJACKER_DEV_MODE 0600 ++#define UPATCH_HELPER_DEV_NAME "upatch-helper" ++#define UPATCH_HELPER_DEV_MODE 0600 + +-#define UPATCH_HIJACKER_IOC_MAGIC 0xE5 +-#define UPATCH_HIJACKER_ENABLE _IOW(UPATCH_HIJACKER_IOC_MAGIC, 0x1, \ ++#define UPATCH_HELPER_IOC_MAGIC 0xE5 ++#define UPATCH_HELPER_ENABLE _IOW(UPATCH_HELPER_IOC_MAGIC, 0x1, \ + upatch_enable_request_t) +-#define UPATCH_HIJACKER_DISABLE _IO(UPATCH_HIJACKER_IOC_MAGIC, 0x2) +-#define UPATCH_HIJACKER_REGISTER _IOW(UPATCH_HIJACKER_IOC_MAGIC, 0x3, \ ++#define UPATCH_HELPER_DISABLE _IO(UPATCH_HELPER_IOC_MAGIC, 0x2) ++#define UPATCH_HELPER_REGISTER _IOW(UPATCH_HELPER_IOC_MAGIC, 0x3, \ + upatch_register_request_t) +-#define UPATCH_HIJACKER_UNREGISTER _IOW(UPATCH_HIJACKER_IOC_MAGIC, 0x4, \ ++#define UPATCH_HELPER_UNREGISTER _IOW(UPATCH_HELPER_IOC_MAGIC, 0x4, \ + upatch_register_request_t) + + typedef struct { +@@ -52,4 +52,4 @@ int ioctl_init(void); + void ioctl_exit(void); + long handle_ioctl(struct file *file, unsigned int cmd, unsigned long arg); + +-#endif /* _UPATCH_HIJACKER_KO_IOCTL_H */ ++#endif /* _UPATCH_HELPER_KO_IOCTL_H */ +diff --git a/upatch-hijacker/ko/log.h b/upatch-helper/ko/log.h +similarity index 87% +rename from upatch-hijacker/ko/log.h +rename to upatch-helper/ko/log.h +index 2aede01..5341d10 100644 +--- a/upatch-hijacker/ko/log.h ++++ b/upatch-helper/ko/log.h +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /* +- * upatch-hijacker kernel module ++ * upatch-helper kernel module + * Copyright (C) 2024 Huawei Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify +@@ -18,8 +18,8 @@ + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +-#ifndef _UPATCH_HIJACKER_KO_LOG_H +-#define _UPATCH_HIJACKER_KO_LOG_H ++#ifndef _UPATCH_HELPER_KO_LOG_H ++#define _UPATCH_HELPER_KO_LOG_H + + #include + #include +@@ -30,4 +30,4 @@ + + #define pr_fmt(fmt) "%s: " fmt, THIS_MODULE->name + +-#endif /* _UPATCH_HIJACKER_KO_LOG_H */ ++#endif /* _UPATCH_HELPER_KO_LOG_H */ +diff --git a/upatch-hijacker/ko/main.c b/upatch-helper/ko/main.c +similarity index 86% +rename from upatch-hijacker/ko/main.c +rename to upatch-helper/ko/main.c +index e14796e..52f0b86 100644 +--- a/upatch-hijacker/ko/main.c ++++ b/upatch-helper/ko/main.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /* +- * upatch-hijacker kernel module ++ * upatch-helper kernel module + * Copyright (C) 2024 Huawei Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify +@@ -26,7 +26,7 @@ + #include "context.h" + #include "ioctl.h" + +-static int __init upatch_hijacker_init(void) ++static int __init upatch_helper_init(void) + { + int ret = 0; + +@@ -52,17 +52,17 @@ static int __init upatch_hijacker_init(void) + return 0; + } + +-static void __exit upatch_hijacker_exit(void) ++static void __exit upatch_helper_exit(void) + { + ioctl_exit(); + cache_exit(); + context_exit(); + } + +-module_init(upatch_hijacker_init); +-module_exit(upatch_hijacker_exit); ++module_init(upatch_helper_init); ++module_exit(upatch_helper_exit); + + MODULE_AUTHOR("renoseven (dev@renoseven.net)"); +-MODULE_DESCRIPTION("upatch compiler hijacker"); ++MODULE_DESCRIPTION("upatch compiler helper"); + MODULE_LICENSE("GPL"); + MODULE_VERSION(BUILD_VERSION); +diff --git a/upatch-hijacker/ko/map.c b/upatch-helper/ko/map.c +similarity index 99% +rename from upatch-hijacker/ko/map.c +rename to upatch-helper/ko/map.c +index 3049556..7771e8c 100644 +--- a/upatch-hijacker/ko/map.c ++++ b/upatch-helper/ko/map.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /* +- * upatch-hijacker kernel module ++ * upatch-helper kernel module + * Copyright (C) 2024 Huawei Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify +diff --git a/upatch-hijacker/ko/map.h b/upatch-helper/ko/map.h +similarity index 90% +rename from upatch-hijacker/ko/map.h +rename to upatch-helper/ko/map.h +index 37b522b..0e5a790 100644 +--- a/upatch-hijacker/ko/map.h ++++ b/upatch-helper/ko/map.h +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /* +- * upatch-hijacker kernel module ++ * upatch-helper kernel module + * Copyright (C) 2024 Huawei Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify +@@ -18,8 +18,8 @@ + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +-#ifndef _UPATCH_HIJACKER_KO_MAP_H +-#define _UPATCH_HIJACKER_KO_MAP_H ++#ifndef _UPATCH_HELPER_KO_MAP_H ++#define _UPATCH_HELPER_KO_MAP_H + + #include + +@@ -40,4 +40,4 @@ void map_remove(struct map *map, const void *param); + void *map_get(struct map *map, const void *param); + size_t map_size(const struct map *map); + +-#endif /* _UPATCH_HIJACKER_KO_MAP_H */ ++#endif /* _UPATCH_HELPER_KO_MAP_H */ +diff --git a/upatch-hijacker/ko/records.c b/upatch-helper/ko/records.c +similarity index 90% +rename from upatch-hijacker/ko/records.c +rename to upatch-helper/ko/records.c +index ef1e3fd..079240d 100644 +--- a/upatch-hijacker/ko/records.c ++++ b/upatch-helper/ko/records.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /* +- * upatch-hijacker kernel module ++ * upatch-helper kernel module + * Copyright (C) 2024 Huawei Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify +@@ -76,10 +76,10 @@ void free_uprobe_record(struct uprobe_record *record) + kfree(record); + } + +-int create_hijacker_record(struct hijacker_record **record, ++int create_helper_record(struct helper_record **record, + const char *exec_path, const char *jump_path) + { +- struct hijacker_record *new_record = NULL; ++ struct helper_record *new_record = NULL; + struct inode *exec_inode = NULL; + struct inode *jump_inode = NULL; + +@@ -99,7 +99,7 @@ int create_hijacker_record(struct hijacker_record **record, + return -ENOENT; + } + +- new_record = kzalloc(sizeof(struct hijacker_record), GFP_KERNEL); ++ new_record = kzalloc(sizeof(struct helper_record), GFP_KERNEL); + if (record == NULL) { + return -ENOMEM; + } +@@ -113,7 +113,7 @@ int create_hijacker_record(struct hijacker_record **record, + return 0; + } + +-void free_hijacker_record(struct hijacker_record *record) ++void free_helper_record(struct helper_record *record) + { + if (record == NULL) { + return; +@@ -124,7 +124,7 @@ void free_hijacker_record(struct hijacker_record *record) + kfree(record); + } + +-bool find_hijacker_record(const struct hijacker_record *record, ++bool find_helper_record(const struct helper_record *record, + const struct inode *inode) + { + return (inode_equal(record->exec_inode, inode) || +diff --git a/upatch-hijacker/ko/records.h b/upatch-helper/ko/records.h +similarity index 80% +rename from upatch-hijacker/ko/records.h +rename to upatch-helper/ko/records.h +index 759ed5e..e9c8553 100644 +--- a/upatch-hijacker/ko/records.h ++++ b/upatch-helper/ko/records.h +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /* +- * upatch-hijacker kernel module ++ * upatch-helper kernel module + * Copyright (C) 2024 Huawei Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify +@@ -18,8 +18,8 @@ + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +-#ifndef _UPATCH_HIJACKER_KO_ENTITY_H +-#define _UPATCH_HIJACKER_KO_ENTITY_H ++#ifndef _UPATCH_HELPER_KO_ENTITY_H ++#define _UPATCH_HELPER_KO_ENTITY_H + + #include + #include +@@ -36,7 +36,7 @@ struct uprobe_record { + struct uprobe_consumer *uc; + }; + +-struct hijacker_record { ++struct helper_record { + struct inode *exec_inode; + struct inode *jump_inode; + char exec_path[PATH_MAX]; +@@ -47,10 +47,10 @@ int new_uprobe_record(struct uprobe_record **record, + uprobe_handler handler, const char *path, loff_t offset); + void free_uprobe_record(struct uprobe_record *record); + +-int create_hijacker_record(struct hijacker_record **record, ++int create_helper_record(struct helper_record **record, + const char *exec_path, const char *jump_path); +-void free_hijacker_record(struct hijacker_record *record); +-bool find_hijacker_record(const struct hijacker_record *record, ++void free_helper_record(struct helper_record *record); ++bool find_helper_record(const struct helper_record *record, + const struct inode *inode); + +-#endif /* _UPATCH_HIJACKER_KO_ENTITY_H */ ++#endif /* _UPATCH_HELPER_KO_ENTITY_H */ +diff --git a/upatch-hijacker/ko/uprobe.c b/upatch-helper/ko/uprobe.c +similarity index 89% +rename from upatch-hijacker/ko/uprobe.c +rename to upatch-helper/ko/uprobe.c +index bc3c639..ab3513c 100644 +--- a/upatch-hijacker/ko/uprobe.c ++++ b/upatch-helper/ko/uprobe.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /* +- * upatch-hijacker kernel module ++ * upatch-helper kernel module + * Copyright (C) 2024 Huawei Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify +@@ -74,7 +74,7 @@ static inline const char __user *new_user_str(const char *src, size_t len) + return (const char __user *)addr; + } + +-static inline const char *select_jump_path(const struct hijacker_record *record, ++static inline const char *select_jump_path(const struct helper_record *record, + const struct inode *inode) + { + if (inode_equal(inode, record->exec_inode)) { +@@ -92,8 +92,8 @@ int handle_uprobe(struct uprobe_consumer *self, struct pt_regs *regs) + const char __user *argv0 = (const char __user *)_reg_argv0; + const char __user *new_argv0 = NULL; + +- struct map *hijacker_map = get_hijacker_map(); +- const struct hijacker_record *record = NULL; ++ struct map *helper_map = get_helper_map(); ++ const struct helper_record *record = NULL; + + const char *elf_path = NULL; + const char *jump_path = NULL; +@@ -102,11 +102,11 @@ int handle_uprobe(struct uprobe_consumer *self, struct pt_regs *regs) + char *path_buff = NULL; + size_t path_len = 0; + +- if ((argv0 == NULL) || (hijacker_context_count() == 0)) { ++ if ((argv0 == NULL) || (helper_context_count() == 0)) { + return 0; + } + +- if (map_size(hijacker_map) == 0) { ++ if (map_size(helper_map) == 0) { + return 0; + } + +@@ -129,7 +129,7 @@ int handle_uprobe(struct uprobe_consumer *self, struct pt_regs *regs) + return 0; + } + +- record = (const struct hijacker_record *)map_get(hijacker_map, inode); ++ record = (const struct helper_record *)map_get(helper_map, inode); + if (record == NULL) { + pr_debug("record not found, elf_path=%s\n", elf_path); + path_buf_free(path_buff); +@@ -143,7 +143,7 @@ int handle_uprobe(struct uprobe_consumer *self, struct pt_regs *regs) + return 0; + } + path_len = strnlen(jump_path, PATH_MAX) + 1; +- pr_debug("[hijacked] elf_path=%s, jump_path=%s\n", elf_path, jump_path); ++ pr_debug("[helped] elf_path=%s, jump_path=%s\n", elf_path, jump_path); + + new_argv0 = new_user_str(jump_path, path_len); + if (new_argv0 == NULL) { +diff --git a/upatch-hijacker/ko/uprobe.h b/upatch-helper/ko/uprobe.h +similarity index 86% +rename from upatch-hijacker/ko/uprobe.h +rename to upatch-helper/ko/uprobe.h +index 06564d5..39bc11d 100644 +--- a/upatch-hijacker/ko/uprobe.h ++++ b/upatch-helper/ko/uprobe.h +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /* +- * upatch-hijacker kernel module ++ * upatch-helper kernel module + * Copyright (C) 2024 Huawei Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify +@@ -18,8 +18,8 @@ + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +-#ifndef _UPATCH_HIJACKER_KO_UPROBE_H +-#define _UPATCH_HIJACKER_KO_UPROBE_H ++#ifndef _UPATCH_HELPER_KO_UPROBE_H ++#define _UPATCH_HELPER_KO_UPROBE_H + + #include + +@@ -28,4 +28,4 @@ struct pt_regs; + + int handle_uprobe(struct uprobe_consumer *self, struct pt_regs *regs); + +-#endif /* _UPATCH_HIJACKER_KO_UPROBE_H */ ++#endif /* _UPATCH_HELPER_KO_UPROBE_H */ +diff --git a/upatch-hijacker/ko/utils.h b/upatch-helper/ko/utils.h +similarity index 90% +rename from upatch-hijacker/ko/utils.h +rename to upatch-helper/ko/utils.h +index 5e2f7ed..2add3e6 100644 +--- a/upatch-hijacker/ko/utils.h ++++ b/upatch-helper/ko/utils.h +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 + /* +- * upatch-hijacker kernel module ++ * upatch-helper kernel module + * Copyright (C) 2024 Huawei Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify +@@ -18,8 +18,8 @@ + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +-#ifndef _UPATCH_HIJACKER_KO_UTILS_H +-#define _UPATCH_HIJACKER_KO_UTILS_H ++#ifndef _UPATCH_HELPER_KO_UTILS_H ++#define _UPATCH_HELPER_KO_UTILS_H + + #include + #include +@@ -47,4 +47,4 @@ static inline bool ns_equal(const struct pid_namespace *lhs, + return (lhs->ns.inum == rhs->ns.inum); + } + +-#endif /* _UPATCH_HIJACKER_KO_UTILS_H */ ++#endif /* _UPATCH_HELPER_KO_UTILS_H */ +diff --git a/upatch-hijacker/hijacker/CMakeLists.txt b/upatch-hijacker/hijacker/CMakeLists.txt +deleted file mode 100644 +index e42ffb3..0000000 +--- a/upatch-hijacker/hijacker/CMakeLists.txt ++++ /dev/null +@@ -1,35 +0,0 @@ +-# Build hijackers +-add_executable(gnu-as-hijacker gnu-as-hijacker.c) +-add_executable(gnu-compiler-hijacker gnu-compiler-hijacker.c) +- +-# Generate hijackers +-add_custom_target(generate-upatch-hijackers ALL +- COMMENT "Generating upatch hijackers..." +- COMMAND ln -f gnu-as-hijacker as-hijacker +- COMMAND ln -f gnu-compiler-hijacker gcc-hijacker +- COMMAND ln -f gnu-compiler-hijacker g++-hijacker +- COMMAND ln -f gnu-compiler-hijacker cc-hijacker +- COMMAND ln -f gnu-compiler-hijacker c++-hijacker +- DEPENDS +- gnu-as-hijacker +- gnu-compiler-hijacker +- WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +-) +- +-# Install hijackers +-install( +- PROGRAMS +- ${CMAKE_CURRENT_BINARY_DIR}/gnu-as-hijacker +- ${CMAKE_CURRENT_BINARY_DIR}/gnu-compiler-hijacker +- ${CMAKE_CURRENT_BINARY_DIR}/as-hijacker +- ${CMAKE_CURRENT_BINARY_DIR}/gcc-hijacker +- ${CMAKE_CURRENT_BINARY_DIR}/g++-hijacker +- ${CMAKE_CURRENT_BINARY_DIR}/cc-hijacker +- ${CMAKE_CURRENT_BINARY_DIR}/c++-hijacker +- PERMISSIONS +- OWNER_EXECUTE OWNER_WRITE OWNER_READ +- GROUP_EXECUTE GROUP_READ +- WORLD_READ WORLD_EXECUTE +- DESTINATION +- ${SYSCARE_LIBEXEC_DIR} +-) +diff --git a/upatch-hijacker/ko/CMakeLists.txt b/upatch-hijacker/ko/CMakeLists.txt +deleted file mode 100644 +index 9d3c67c..0000000 +--- a/upatch-hijacker/ko/CMakeLists.txt ++++ /dev/null +@@ -1,32 +0,0 @@ +-# Build upatch-hijacker kernel module +- +-# Set target +-set(UPATCH_HIJACKER_KMOD "upatch_hijacker.ko") +- +-# Detect kernel source path +-if (DEFINED KERNEL_VERSION) +- set(KERNEL_SOURCE_PATH "/lib/modules/${KERNEL_VERSION}/build") +- set(UPATCH_HIJACKER_KMOD_BUILD_CMD make module_version=${BUILD_VERSION} kernel=${KERNEL_SOURCE_PATH}) +-else() +- set(UPATCH_HIJACKER_KMOD_BUILD_CMD make module_version=${BUILD_VERSION}) +-endif() +- +-# Build kernel module +-add_custom_target(upatch-hijacker-kmod ALL +- COMMENT "Building kernel module upatch-hijacker..." +- BYPRODUCTS ${UPATCH_HIJACKER_KMOD} +- COMMAND ${UPATCH_HIJACKER_KMOD_BUILD_CMD} +- WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +-) +- +-# Install kernel module +-install( +- FILES +- ${UPATCH_HIJACKER_KMOD} +- PERMISSIONS +- OWNER_WRITE OWNER_READ +- GROUP_READ +- WORLD_READ +- DESTINATION +- ${SYSCARE_LIBEXEC_DIR} +-) +diff --git a/upatch-manage/upatch-patch.c b/upatch-manage/upatch-patch.c +index cbdbbe1..8a1ad41 100644 +--- a/upatch-manage/upatch-patch.c ++++ b/upatch-manage/upatch-patch.c +@@ -730,7 +730,7 @@ int process_patch(int pid, struct upatch_elf *uelf, struct running_elf *relf, co + goto out_free; + } + +- // use uprobe to hack function. the program has been executed to the entry ++ // use uprobe to interpose function. the program has been executed to the entry + // point + + /* +@@ -850,7 +850,7 @@ int process_unpatch(int pid, const char *uuid) + goto out_free; + } + +- // use uprobe to hack function. the program has been executed to the entry ++ // use uprobe to interpose function. the program has been executed to the entry + // point + + /* +diff --git a/upatchd/src/config.rs b/upatchd/src/config.rs +index 125770d..2ddb011 100644 +--- a/upatchd/src/config.rs ++++ b/upatchd/src/config.rs +@@ -18,7 +18,7 @@ use anyhow::{anyhow, Result}; + use serde::{Deserialize, Serialize}; + use syscare_common::fs; + +-use crate::hijacker::HijackerConfig; ++use crate::helper::UpatchHelperConfig; + + const DEFAULT_SOCKET_UID: u32 = 0; + const DEFAULT_SOCKET_GID: u32 = 0; +@@ -46,7 +46,7 @@ pub struct DaemonConfig { + #[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] + pub struct Config { + pub daemon: DaemonConfig, +- pub hijacker: HijackerConfig, ++ pub helper: UpatchHelperConfig, + } + + impl Config { +diff --git a/upatchd/src/hijacker/config.rs b/upatchd/src/helper/config.rs +similarity index 70% +rename from upatchd/src/hijacker/config.rs +rename to upatchd/src/helper/config.rs +index 5f97fb1..e8eaefc 100644 +--- a/upatchd/src/hijacker/config.rs ++++ b/upatchd/src/helper/config.rs +@@ -23,26 +23,26 @@ const GCC_BINARY: &str = "/usr/bin/gcc"; + const GXX_BINARY: &str = "/usr/bin/g++"; + const AS_BINARY: &str = "/usr/bin/as"; + +-const CC_HIJACKER: &str = "/usr/libexec/syscare/cc-hijacker"; +-const CXX_HIJACKER: &str = "/usr/libexec/syscare/c++-hijacker"; +-const GCC_HIJACKER: &str = "/usr/libexec/syscare/gcc-hijacker"; +-const GXX_HIJACKER: &str = "/usr/libexec/syscare/g++-hijacker"; +-const AS_HIJACKER: &str = "/usr/libexec/syscare/as-hijacker"; ++const CC_HELPER: &str = "/usr/libexec/syscare/cc-helper"; ++const CXX_HELPER: &str = "/usr/libexec/syscare/c++-helper"; ++const GCC_HELPER: &str = "/usr/libexec/syscare/gcc-helper"; ++const GXX_HELPER: &str = "/usr/libexec/syscare/g++-helper"; ++const AS_HELPER: &str = "/usr/libexec/syscare/as-helper"; + + #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +-pub struct HijackerConfig { ++pub struct UpatchHelperConfig { + pub mapping: IndexMap, + } + +-impl Default for HijackerConfig { ++impl Default for UpatchHelperConfig { + fn default() -> Self { + Self { + mapping: indexmap! { +- PathBuf::from(CC_BINARY) => PathBuf::from(CC_HIJACKER), +- PathBuf::from(CXX_BINARY) => PathBuf::from(CXX_HIJACKER), +- PathBuf::from(GCC_BINARY) => PathBuf::from(GCC_HIJACKER), +- PathBuf::from(GXX_BINARY) => PathBuf::from(GXX_HIJACKER), +- PathBuf::from(AS_BINARY) => PathBuf::from(AS_HIJACKER), ++ PathBuf::from(CC_BINARY) => PathBuf::from(CC_HELPER), ++ PathBuf::from(CXX_BINARY) => PathBuf::from(CXX_HELPER), ++ PathBuf::from(GCC_BINARY) => PathBuf::from(GCC_HELPER), ++ PathBuf::from(GXX_BINARY) => PathBuf::from(GXX_HELPER), ++ PathBuf::from(AS_BINARY) => PathBuf::from(AS_HELPER), + }, + } + } +diff --git a/upatchd/src/hijacker/elf_resolver.rs b/upatchd/src/helper/elf_resolver.rs +similarity index 100% +rename from upatchd/src/hijacker/elf_resolver.rs +rename to upatchd/src/helper/elf_resolver.rs +diff --git a/upatchd/src/hijacker/ioctl.rs b/upatchd/src/helper/ioctl.rs +similarity index 80% +rename from upatchd/src/hijacker/ioctl.rs +rename to upatchd/src/helper/ioctl.rs +index b187979..0efbab4 100644 +--- a/upatchd/src/hijacker/ioctl.rs ++++ b/upatchd/src/helper/ioctl.rs +@@ -21,20 +21,20 @@ use syscare_common::{ffi::OsStrExt, fs}; + const KMOD_IOCTL_MAGIC: u16 = 0xE5; + + ioctl_write_ptr!( +- ioctl_enable_hijacker, ++ ioctl_enable_hook, + KMOD_IOCTL_MAGIC, + 0x1, + UpatchEnableRequest + ); +-ioctl_none!(ioctl_disable_hijacker, KMOD_IOCTL_MAGIC, 0x2); ++ioctl_none!(ioctl_disable_hook, KMOD_IOCTL_MAGIC, 0x2); + ioctl_write_ptr!( +- ioctl_register_hijacker, ++ ioctl_register_hooker, + KMOD_IOCTL_MAGIC, + 0x3, + UpatchRegisterRequest + ); + ioctl_write_ptr!( +- ioctl_unregister_hijacker, ++ ioctl_unregister_hooker, + KMOD_IOCTL_MAGIC, + 0x4, + UpatchRegisterRequest +@@ -51,18 +51,18 @@ pub struct UpatchRegisterRequest { + jump_path: [u8; PATH_MAX as usize], + } + +-pub struct HijackerIoctl { ++pub struct UpatchHelperIoctl { + dev: File, + } + +-impl HijackerIoctl { ++impl UpatchHelperIoctl { + pub fn new>(dev_path: P) -> Result { + Ok(Self { + dev: fs::open_file(dev_path)?, + }) + } + +- pub fn enable_hijacker>(&self, lib_path: P, offset: u64) -> Result<()> { ++ pub fn enable_hook>(&self, lib_path: P, offset: u64) -> Result<()> { + let mut msg = UpatchEnableRequest { + path: [0; PATH_MAX as usize], + offset: 0, +@@ -74,23 +74,23 @@ impl HijackerIoctl { + msg.offset = offset; + + unsafe { +- ioctl_enable_hijacker(self.dev.as_raw_fd(), &msg) ++ ioctl_enable_hook(self.dev.as_raw_fd(), &msg) + .map_err(|e| anyhow!("Ioctl error, ret={}", e))? + }; + + Ok(()) + } + +- pub fn disable_hijacker(&self) -> Result<()> { ++ pub fn disable_hook(&self) -> Result<()> { + unsafe { +- ioctl_disable_hijacker(self.dev.as_raw_fd()) ++ ioctl_disable_hook(self.dev.as_raw_fd()) + .map_err(|e| anyhow!("Ioctl error, ret={}", e))? + }; + + Ok(()) + } + +- pub fn register_hijacker(&self, exec_path: P, jump_path: Q) -> Result<()> ++ pub fn register_hooker(&self, exec_path: P, jump_path: Q) -> Result<()> + where + P: AsRef, + Q: AsRef, +@@ -108,14 +108,14 @@ impl HijackerIoctl { + .write_all(jump_path.as_ref().to_cstring()?.to_bytes_with_nul())?; + + unsafe { +- ioctl_register_hijacker(self.dev.as_raw_fd(), &msg) ++ ioctl_register_hooker(self.dev.as_raw_fd(), &msg) + .map_err(|e| anyhow!("Ioctl error, {}", e.desc()))? + }; + + Ok(()) + } + +- pub fn unregister_hijacker(&self, exec_path: P, jump_path: Q) -> Result<()> ++ pub fn unregister_hooker(&self, exec_path: P, jump_path: Q) -> Result<()> + where + P: AsRef, + Q: AsRef, +@@ -133,7 +133,7 @@ impl HijackerIoctl { + .write_all(jump_path.as_ref().to_cstring()?.to_bytes_with_nul())?; + + unsafe { +- ioctl_unregister_hijacker(self.dev.as_raw_fd(), &msg) ++ ioctl_unregister_hooker(self.dev.as_raw_fd(), &msg) + .map_err(|e| anyhow!("Ioctl error, {}", e.desc()))? + }; + +diff --git a/upatchd/src/hijacker/kmod.rs b/upatchd/src/helper/kmod.rs +similarity index 95% +rename from upatchd/src/hijacker/kmod.rs +rename to upatchd/src/helper/kmod.rs +index fc89f5f..59b7ede 100644 +--- a/upatchd/src/hijacker/kmod.rs ++++ b/upatchd/src/helper/kmod.rs +@@ -25,13 +25,13 @@ use syscare_common::{fs, os}; + const KMOD_SYS_PATH: &str = "/sys/module"; + + /// An RAII guard of the kernel module. +-pub struct HijackerKmodGuard { ++pub struct UpatchHelperKmodGuard { + kmod_name: String, + kmod_path: PathBuf, + sys_path: PathBuf, + } + +-impl HijackerKmodGuard { ++impl UpatchHelperKmodGuard { + pub fn new, P: AsRef>(name: S, kmod_path: P) -> Result { + let instance = Self { + kmod_name: name.as_ref().to_string(), +@@ -45,7 +45,7 @@ impl HijackerKmodGuard { + } + } + +-impl HijackerKmodGuard { ++impl UpatchHelperKmodGuard { + fn selinux_relabel_kmod(&self) -> Result<()> { + const KMOD_SECURITY_TYPE: &str = "modules_object_t"; + +@@ -92,7 +92,7 @@ impl HijackerKmodGuard { + } + } + +-impl Drop for HijackerKmodGuard { ++impl Drop for UpatchHelperKmodGuard { + fn drop(&mut self) { + if let Err(e) = self.remove_kmod() { + error!("{:?}", e); +diff --git a/upatchd/src/hijacker/mod.rs b/upatchd/src/helper/mod.rs +similarity index 52% +rename from upatchd/src/hijacker/mod.rs +rename to upatchd/src/helper/mod.rs +index d0f2c4d..85245d0 100644 +--- a/upatchd/src/hijacker/mod.rs ++++ b/upatchd/src/helper/mod.rs +@@ -24,24 +24,24 @@ mod elf_resolver; + mod ioctl; + mod kmod; + +-pub use config::HijackerConfig; ++pub use config::UpatchHelperConfig; + use elf_resolver::ElfResolver; +-use ioctl::HijackerIoctl; +-use kmod::HijackerKmodGuard; ++use ioctl::UpatchHelperIoctl; ++use kmod::UpatchHelperKmodGuard; + +-const KMOD_NAME: &str = "upatch_hijacker"; +-const KMOD_DEV_PATH: &str = "/dev/upatch-hijacker"; +-const KMOD_PATH: &str = "/usr/libexec/syscare/upatch_hijacker.ko"; ++const KMOD_NAME: &str = "upatch_helper"; ++const KMOD_DEV_PATH: &str = "/dev/upatch-helper"; ++const KMOD_PATH: &str = "/usr/libexec/syscare/upatch_helper.ko"; + +-const HIJACK_SYMBOL_NAME: &str = "execve"; ++const TARGET_SYMBOL_NAME: &str = "execve"; + +-pub struct Hijacker { +- config: HijackerConfig, +- ioctl: HijackerIoctl, +- _kmod: HijackerKmodGuard, // need to ensure this drops last ++pub struct UpatchHelper { ++ config: UpatchHelperConfig, ++ ioctl: UpatchHelperIoctl, ++ _kmod: UpatchHelperKmodGuard, // need to ensure this drops last + } + +-impl Hijacker { ++impl UpatchHelper { + fn find_symbol_addr(symbol_name: &str) -> Result<(PathBuf, u64)> { + let exec_file = MappedFile::open(os::process::path())?; + let exec_resolver = ElfResolver::new(exec_file.as_bytes())?; +@@ -59,61 +59,66 @@ impl Hijacker { + } + } + +-impl Hijacker { +- pub fn new(config: HijackerConfig) -> Result { +- debug!("Initializing hijacker kernel module..."); +- let kmod = HijackerKmodGuard::new(KMOD_NAME, KMOD_PATH)?; ++impl UpatchHelper { ++ pub fn new(config: UpatchHelperConfig) -> Result { ++ debug!("Initializing upatch kernel module..."); ++ let kmod = UpatchHelperKmodGuard::new(KMOD_NAME, KMOD_PATH)?; + +- debug!("Initializing hijacker ioctl channel..."); +- let ioctl = HijackerIoctl::new(KMOD_DEV_PATH)?; ++ debug!("Initializing upatch ioctl channel..."); ++ let ioctl = UpatchHelperIoctl::new(KMOD_DEV_PATH)?; + +- debug!("Initializing hijacker hooks..."); +- let (lib_path, offset) = Self::find_symbol_addr(HIJACK_SYMBOL_NAME)?; ++ debug!("Initializing upatch hooks..."); ++ let (lib_path, offset) = Self::find_symbol_addr(TARGET_SYMBOL_NAME)?; + info!( + "Hooking library: {}, offset: {:#x}", + lib_path.display(), + offset + ); +- ioctl.enable_hijacker(lib_path, offset)?; ++ ioctl.enable_hook(lib_path, offset)?; + + Ok(Self { + config, +- _kmod: kmod, + ioctl, ++ _kmod: kmod, + }) + } +-} + +-impl Hijacker { +- fn get_hijacker>(&self, exec_path: P) -> Result<&Path> { +- let hijacker = self +- .config +- .mapping +- .get(exec_path.as_ref()) +- .with_context(|| format!("Cannot find hijacker for {}", exec_path.as_ref().display()))? +- .as_path(); ++ pub fn register_hooker>(&self, elf_path: P) -> Result<()> { ++ let exec_path = elf_path.as_ref(); ++ let jump_path = self.jump_path(exec_path)?; + +- Ok(hijacker) ++ self.ioctl.register_hooker(exec_path, jump_path) + } + +- pub fn register>(&self, elf_path: P) -> Result<()> { ++ pub fn unregister_hooker>(&self, elf_path: P) -> Result<()> { + let exec_path = elf_path.as_ref(); +- let jump_path = self.get_hijacker(exec_path)?; ++ let jump_path = self.jump_path(exec_path)?; + +- self.ioctl.register_hijacker(exec_path, jump_path) ++ self.ioctl.unregister_hooker(exec_path, jump_path) + } ++} + +- pub fn unregister>(&self, elf_path: P) -> Result<()> { +- let exec_path = elf_path.as_ref(); +- let jump_path = self.get_hijacker(exec_path)?; ++impl UpatchHelper { ++ fn jump_path>(&self, exec_path: P) -> Result<&Path> { ++ let jump_path = self ++ .config ++ .mapping ++ .get(exec_path.as_ref()) ++ .with_context(|| { ++ format!( ++ "Cannot find hook program for {}", ++ exec_path.as_ref().display() ++ ) ++ })? ++ .as_path(); + +- self.ioctl.unregister_hijacker(exec_path, jump_path) ++ Ok(jump_path) + } + } + +-impl Drop for Hijacker { ++impl Drop for UpatchHelper { + fn drop(&mut self) { +- if let Err(e) = self.ioctl.disable_hijacker() { ++ if let Err(e) = self.ioctl.disable_hook() { + error!("{:?}", e); + } + } +diff --git a/upatchd/src/main.rs b/upatchd/src/main.rs +index 066e53e..8141679 100644 +--- a/upatchd/src/main.rs ++++ b/upatchd/src/main.rs +@@ -30,7 +30,7 @@ use syscare_common::{fs, os}; + + mod args; + mod config; +-mod hijacker; ++mod helper; + mod rpc; + + use args::Arguments; +@@ -175,7 +175,7 @@ impl Daemon { + } + + fn initialize_skeleton(&self) -> Result { +- let config = self.config.hijacker.clone(); ++ let config = self.config.helper.clone(); + let methods = SkeletonImpl::new(config)?.to_delegate(); + + let mut io_handler = IoHandler::new(); +diff --git a/upatchd/src/rpc/skeleton.rs b/upatchd/src/rpc/skeleton.rs +index 9972fc1..a6891e1 100644 +--- a/upatchd/src/rpc/skeleton.rs ++++ b/upatchd/src/rpc/skeleton.rs +@@ -18,9 +18,9 @@ use super::function::{rpc, RpcResult}; + + #[rpc(server)] + pub trait Skeleton { +- #[rpc(name = "enable_hijack")] +- fn enable_hijack(&self, exec_path: PathBuf) -> RpcResult<()>; ++ #[rpc(name = "hook_compiler")] ++ fn hook_compiler(&self, exec_path: PathBuf) -> RpcResult<()>; + +- #[rpc(name = "disable_hijack")] +- fn disable_hijack(&self, exec_path: PathBuf) -> RpcResult<()>; ++ #[rpc(name = "unhook_compiler")] ++ fn unhook_compiler(&self, exec_path: PathBuf) -> RpcResult<()>; + } +diff --git a/upatchd/src/rpc/skeleton_impl.rs b/upatchd/src/rpc/skeleton_impl.rs +index d725166..c5085ae 100644 +--- a/upatchd/src/rpc/skeleton_impl.rs ++++ b/upatchd/src/rpc/skeleton_impl.rs +@@ -17,7 +17,7 @@ use std::path::PathBuf; + use anyhow::{Context, Result}; + use log::{debug, info}; + +-use crate::hijacker::{Hijacker, HijackerConfig}; ++use crate::helper::{UpatchHelper, UpatchHelperConfig}; + + use super::{ + function::{RpcFunction, RpcResult}, +@@ -25,34 +25,34 @@ use super::{ + }; + + pub struct SkeletonImpl { +- hijacker: Hijacker, ++ helper: UpatchHelper, + } + + impl SkeletonImpl { +- pub fn new(config: HijackerConfig) -> Result { +- debug!("Initializing hijacker..."); ++ pub fn new(config: UpatchHelperConfig) -> Result { ++ debug!("Initializing upatch helper..."); + Ok(Self { +- hijacker: Hijacker::new(config).context("Failed to initialize hijacker")?, ++ helper: UpatchHelper::new(config).context("Failed to initialize upatch helper")?, + }) + } + } + + impl Skeleton for SkeletonImpl { +- fn enable_hijack(&self, elf_path: PathBuf) -> RpcResult<()> { ++ fn hook_compiler(&self, elf_path: PathBuf) -> RpcResult<()> { + RpcFunction::call(|| { +- info!("Enable hijack: {}", elf_path.display()); +- self.hijacker +- .register(&elf_path) +- .with_context(|| format!("Failed to register hijack {}", elf_path.display())) ++ info!("Hook compiler: {}", elf_path.display()); ++ self.helper ++ .register_hooker(&elf_path) ++ .with_context(|| format!("Failed to hook helper {}", elf_path.display())) + }) + } + +- fn disable_hijack(&self, elf_path: PathBuf) -> RpcResult<()> { ++ fn unhook_compiler(&self, elf_path: PathBuf) -> RpcResult<()> { + RpcFunction::call(|| { +- info!("Disable hijack: {}", elf_path.display()); +- self.hijacker +- .unregister(&elf_path) +- .with_context(|| format!("Failed to unregister hijack {}", elf_path.display())) ++ info!("Unhook compiler: {}", elf_path.display()); ++ self.helper ++ .unregister_hooker(&elf_path) ++ .with_context(|| format!("Failed to unhook compiler {}", elf_path.display())) + }) + } + } +-- +2.34.1 + diff --git a/0033-all-implement-asan-gcov-build-type.patch b/0033-all-implement-asan-gcov-build-type.patch new file mode 100644 index 0000000000000000000000000000000000000000..344e3f9bb0b78bb5cae8ab94fbe87c2b3e4240aa --- /dev/null +++ b/0033-all-implement-asan-gcov-build-type.patch @@ -0,0 +1,242 @@ +From eeb3f8b656839a374564572d19f675dc56d65ead Mon Sep 17 00:00:00 2001 +From: liuxiaobo +Date: Mon, 17 Jun 2024 16:22:08 +0800 +Subject: [PATCH] all: implement asan & gcov build type + +Signed-off-by: liuxiaobo +--- + CMakeLists.txt | 127 ++++++++++++++++++++-------- + upatch-diff/CMakeLists.txt | 4 +- + upatch-helper/helper/CMakeLists.txt | 4 +- + upatch-manage/CMakeLists.txt | 5 +- + 4 files changed, 99 insertions(+), 41 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 659222f..04872b1 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -8,7 +8,12 @@ project(syscare) + include(GNUInstallDirs) + find_package(Git QUIET) + +-# Version ++# Build type ++if(NOT CMAKE_BUILD_TYPE) ++ set(CMAKE_BUILD_TYPE RelWithDebInfo) ++endif() ++ ++# Build version + if(NOT DEFINED BUILD_VERSION) + execute_process( + COMMAND sh -c "cat syscare/Cargo.toml | grep -F 'version' | head -n 1 | awk -F '\"' '{print $2}'" +@@ -27,12 +32,55 @@ if(GIT_FOUND) + ERROR_QUIET + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} + ) +- set(BUILD_VERSION "${BUILD_VERSION}-g${GIT_VERSION}") ++ set(PROJECT_BUILD_VERSION "${BUILD_VERSION}-g${GIT_VERSION}") + else() +- set(BUILD_VERSION "${BUILD_VERSION}") ++ set(PROJECT_BUILD_VERSION "${BUILD_VERSION}") ++endif() ++ ++# Build configurations ++if(ENABLE_ASAN) ++ set(PROJECT_BUILD_VERSION "${PROJECT_BUILD_VERSION}-asan") ++ list(APPEND PROJECT_C_BUILD_FLAGS -fsanitize=address -fno-omit-frame-pointer) ++ list(APPEND PROJECT_C_LIBRARIES asan) + endif() + +-# Set install directories ++if(ENABLE_GCOV) ++ set(PROJECT_BUILD_VERSION "${PROJECT_BUILD_VERSION}-gcov") ++ list(APPEND PROJECT_C_BUILD_FLAGS -ftest-coverage -fprofile-arcs) ++ list(APPEND PROJECT_RUST_FLAGS -C instrument-coverage) ++ list(APPEND PROJECT_C_LIBRARIES gcov) ++endif() ++ ++# Build flags ++list(APPEND PROJECT_C_BUILD_FLAGS ++ -std=gnu99 -g -Wall -O2 -Werror -Wextra ++ -DBUILD_VERSION="${PROJECT_BUILD_VERSION}" -D_FORTIFY_SOURCE=2 ++ -Wtrampolines -Wformat=2 -Wstrict-prototypes -Wdate-time ++ -Wstack-usage=8192 -Wfloat-equal -Wswitch-default ++ -Wshadow -Wconversion -Wcast-qual -Wcast-align -Wunused -Wundef ++ -funsigned-char -fstack-protector-all -fpic -fpie -ftrapv ++ -fstack-check -freg-struct-return -fno-canonical-system-headers ++ -pipe -fdebug-prefix-map=old=new ++) ++list(APPEND PROJECT_RUST_FLAGS ++ --cfg unsound_local_offset ++ -C relocation_model=pic ++ -D warnings ++ -C link-arg=-s ++ -C overflow_checks ++ -W rust_2021_incompatible_closure_captures ++) ++ ++# Link flags ++list(APPEND PROJECT_C_LINK_FLAGS ++ -pie ++ -Wl,-z,relro,-z,now ++ -Wl,-z,noexecstack -rdynamic ++ -Wl,-Bsymbolic ++ -Wl,-no-undefined ++) ++ ++# Install directories + set(SYSCARE_BINARY_DIR "${CMAKE_INSTALL_FULL_BINDIR}") + set(SYSCARE_LIBEXEC_DIR "${CMAKE_INSTALL_FULL_LIBEXECDIR}/syscare") + set(SYSCARE_SERVICE_DIR "${CMAKE_INSTALL_PREFIX}/lib/systemd/system") +@@ -46,48 +94,53 @@ message("╚════██║ ╚██╔╝ ╚════██║█ + message("███████║ ██║ ███████║╚██████╗██║ ██║██║ ██║███████╗") + message("╚══════╝ ╚═╝ ╚══════╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝") + message("---------------------------------------------------------") +-message("-- Verion: ${BUILD_VERSION}") ++message("-- Verion: ${PROJECT_BUILD_VERSION}") ++message("-- Rust flags: ${PROJECT_RUST_FLAGS}") ++message("-- Build flags: ${PROJECT_C_BUILD_FLAGS}") ++message("-- Link flags: ${PROJECT_C_LINK_FLAGS}") ++message("-- Link libraries: ${PROJECT_C_LIBRARIES}") + message("-- Binary directory: ${SYSCARE_BINARY_DIR}") + message("-- Libexec directory: ${SYSCARE_LIBEXEC_DIR}") + message("-- Service directory: ${SYSCARE_SERVICE_DIR}") + message("---------------------------------------------------------") + +-# Compile options +-add_compile_options(-DBUILD_VERSION="${BUILD_VERSION}") +-add_compile_options(-std=gnu99 -g -Wall -D_FORTIFY_SOURCE=2 -O2 -Werror -Wextra +- -Wtrampolines -Wformat=2 -Wstrict-prototypes -Wdate-time -Wstack-usage=8192 +- -Wfloat-equal -Wswitch-default -Wshadow -Wconversion -Wcast-qual -Wcast-align +- -Wunused -Wundef -funsigned-char -fstack-protector-all -fpic -fpie -ftrapv +- -fstack-check -freg-struct-return -fno-canonical-system-headers -pipe +- -fdebug-prefix-map=old=new) +-set(LINK_FLAGS "-pie -Wl,-z,relro,-z,now -Wl,-z,noexecstack -rdynamic -Wl,-Bsymbolic -Wl,-no-undefined") +-set(CMAKE_SHARED_LINKER_FLAGS "${LINK_FLAGS}") +-set(CMAKE_EXE_LINKER_FLAGS "${LINK_FLAGS}") +-# Subdirectories +-add_subdirectory(upatch-diff) +-add_subdirectory(upatch-manage) +-add_subdirectory(upatch-helper) +-add_subdirectory(misc) ++# Apply all flags ++add_compile_options(${PROJECT_C_BUILD_FLAGS}) ++add_link_options(${PROJECT_C_LINK_FLAGS}) ++link_libraries(${PROJECT_C_LIBRARIES}) + + # Build rust executables +-add_custom_target(rust-executables ALL ++foreach(FLAG IN LISTS PROJECT_RUST_FLAGS) ++ set(RUSTFLAGS "${RUSTFLAGS} ${FLAG}") ++endforeach() ++ ++add_custom_target(rust-build ALL + COMMENT "Building rust executables..." + COMMAND ${CMAKE_COMMAND} -E env +- "BUILD_VERSION=${BUILD_VERSION}" +- "RUSTFLAGS=--cfg unsound_local_offset -C relocation_model=pic -D warnings -C link-arg=-s -C overflow_checks -W rust_2021_incompatible_closure_captures" +- cargo build --release --target-dir ${CMAKE_CURRENT_BINARY_DIR} ++ "BUILD_VERSION=${PROJECT_BUILD_VERSION}" ++ "RUSTFLAGS=${RUSTFLAGS}" ++ cargo build --release --target-dir "${CMAKE_CURRENT_BINARY_DIR}/rust" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + ) + + # Install rust binaries + install( + PROGRAMS +- ${CMAKE_CURRENT_BINARY_DIR}/release/upatchd +- ${CMAKE_CURRENT_BINARY_DIR}/release/syscared +- ${CMAKE_CURRENT_BINARY_DIR}/release/syscare ++ ${CMAKE_CURRENT_BINARY_DIR}/rust/release/upatchd ++ ${CMAKE_CURRENT_BINARY_DIR}/rust/release/syscared ++ PERMISSIONS ++ OWNER_READ OWNER_WRITE OWNER_EXECUTE ++ GROUP_READ GROUP_EXECUTE ++ DESTINATION ++ ${SYSCARE_BINARY_DIR} ++) ++ ++install( ++ PROGRAMS ++ ${CMAKE_CURRENT_BINARY_DIR}/rust/release/syscare + PERMISSIONS +- OWNER_EXECUTE OWNER_WRITE OWNER_READ +- GROUP_EXECUTE GROUP_READ ++ OWNER_READ OWNER_WRITE OWNER_EXECUTE ++ GROUP_READ GROUP_EXECUTE + WORLD_READ WORLD_EXECUTE + DESTINATION + ${SYSCARE_BINARY_DIR} +@@ -95,12 +148,18 @@ install( + + install( + PROGRAMS +- ${CMAKE_CURRENT_BINARY_DIR}/release/upatch-build +- ${CMAKE_CURRENT_BINARY_DIR}/release/syscare-build ++ ${CMAKE_CURRENT_BINARY_DIR}/rust/release/upatch-build ++ ${CMAKE_CURRENT_BINARY_DIR}/rust/release/syscare-build + PERMISSIONS +- OWNER_EXECUTE OWNER_WRITE OWNER_READ +- GROUP_EXECUTE GROUP_READ ++ OWNER_READ OWNER_WRITE OWNER_EXECUTE ++ GROUP_READ GROUP_EXECUTE + WORLD_READ WORLD_EXECUTE + DESTINATION + ${SYSCARE_LIBEXEC_DIR} + ) ++ ++# Build other components ++add_subdirectory(upatch-diff) ++add_subdirectory(upatch-manage) ++add_subdirectory(upatch-helper) ++add_subdirectory(misc) +diff --git a/upatch-diff/CMakeLists.txt b/upatch-diff/CMakeLists.txt +index 45091fc..a1c8688 100644 +--- a/upatch-diff/CMakeLists.txt ++++ b/upatch-diff/CMakeLists.txt +@@ -18,8 +18,8 @@ install( + TARGETS + upatch-diff + PERMISSIONS +- OWNER_EXECUTE OWNER_WRITE OWNER_READ +- GROUP_EXECUTE GROUP_READ ++ OWNER_READ OWNER_WRITE OWNER_EXECUTE ++ GROUP_READ GROUP_EXECUTE + WORLD_READ WORLD_EXECUTE + DESTINATION + ${SYSCARE_LIBEXEC_DIR} +diff --git a/upatch-helper/helper/CMakeLists.txt b/upatch-helper/helper/CMakeLists.txt +index fefcebe..700722b 100644 +--- a/upatch-helper/helper/CMakeLists.txt ++++ b/upatch-helper/helper/CMakeLists.txt +@@ -27,8 +27,8 @@ install( + ${CMAKE_CURRENT_BINARY_DIR}/cc-helper + ${CMAKE_CURRENT_BINARY_DIR}/c++-helper + PERMISSIONS +- OWNER_EXECUTE OWNER_WRITE OWNER_READ +- GROUP_EXECUTE GROUP_READ ++ OWNER_READ OWNER_WRITE OWNER_EXECUTE ++ GROUP_READ GROUP_EXECUTE + WORLD_READ WORLD_EXECUTE + DESTINATION + ${SYSCARE_LIBEXEC_DIR} +diff --git a/upatch-manage/CMakeLists.txt b/upatch-manage/CMakeLists.txt +index 850a308..e09aa9c 100644 +--- a/upatch-manage/CMakeLists.txt ++++ b/upatch-manage/CMakeLists.txt +@@ -25,9 +25,8 @@ install( + TARGETS + ${UPATCH_MANAGE} + PERMISSIONS +- OWNER_EXECUTE OWNER_WRITE OWNER_READ +- GROUP_EXECUTE GROUP_READ +- WORLD_READ WORLD_EXECUTE ++ OWNER_READ OWNER_WRITE OWNER_EXECUTE ++ GROUP_READ GROUP_EXECUTE + DESTINATION + ${SYSCARE_LIBEXEC_DIR} + ) +-- +2.34.1 + diff --git a/0034-all-clean-code.patch b/0034-all-clean-code.patch new file mode 100644 index 0000000000000000000000000000000000000000..9209a9b253a6372693184ff0d5d32df08a583ff3 --- /dev/null +++ b/0034-all-clean-code.patch @@ -0,0 +1,2484 @@ +From 41cfebf61b476600e76420f1198b70845195f67f Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Thu, 27 Jun 2024 16:00:33 +0800 +Subject: [PATCH] all: clean code + +Signed-off-by: liuxiaobo +--- + syscare-abi/build.rs | 33 ++++---- + syscare-abi/src/patch_info.rs | 23 +++--- + syscare-build/build.rs | 33 ++++---- + syscare-build/src/build_root/mod.rs | 4 +- + syscare-build/src/build_root/package_root.rs | 4 +- + syscare-build/src/build_root/patch_root.rs | 4 +- + syscare-build/src/main.rs | 6 +- + syscare-build/src/package/build_root.rs | 4 +- + syscare-build/src/package/rpm/mod.rs | 7 +- + syscare-build/src/package/rpm/spec_file.rs | 72 ++++++++--------- + syscare-build/src/patch/metadata.rs | 4 +- + syscare-common/build.rs | 33 ++++---- + syscare-common/src/ffi/os_str.rs | 11 +-- + syscare-common/src/fs/flock.rs | 7 +- + syscare-common/src/fs/fs_impl.rs | 83 ++++++++++---------- + syscare-common/src/io/select.rs | 5 +- + syscare-common/src/os/cpu.rs | 4 +- + syscare-common/src/os/process.rs | 2 +- + syscare-common/src/os/user.rs | 67 +++++++++------- + syscare-common/src/os_str/iter.rs | 10 ++- + syscare-common/src/os_str/pattern.rs | 28 ++++--- + syscare-common/src/os_str/utf8.rs | 2 +- + syscare-common/src/process/child.rs | 6 +- + syscare-common/src/process/stdio.rs | 2 +- + syscare/build.rs | 33 ++++---- + syscare/src/executor/patch.rs | 4 +- + syscare/src/main.rs | 14 ++-- + syscare/src/rpc/remote.rs | 19 ++--- + syscared/build.rs | 33 ++++---- + syscared/src/main.rs | 14 ++-- + syscared/src/patch/driver/kpatch/sys.rs | 4 +- + syscared/src/patch/driver/mod.rs | 32 ++++---- + syscared/src/patch/driver/upatch/mod.rs | 4 +- + syscared/src/patch/manager.rs | 19 +++-- + syscared/src/patch/monitor.rs | 6 +- + syscared/src/patch/resolver/kpatch.rs | 16 ++-- + syscared/src/patch/resolver/mod.rs | 10 +-- + syscared/src/patch/resolver/upatch.rs | 12 ++- + syscared/src/rpc/skeleton_impl/patch.rs | 14 ++-- + upatch-build/build.rs | 33 ++++---- + upatch-build/src/args.rs | 14 ++-- + upatch-build/src/build_root.rs | 4 +- + upatch-build/src/compiler.rs | 29 ++++--- + upatch-build/src/dwarf/mod.rs | 21 ++--- + upatch-build/src/dwarf/relocate.rs | 14 ++-- + upatch-build/src/elf/header.rs | 4 - + upatch-build/src/elf/read/elfs.rs | 10 +-- + upatch-build/src/elf/read/section.rs | 19 ++--- + upatch-build/src/elf/read/symbol.rs | 34 ++++---- + upatch-build/src/elf/write/elfs.rs | 10 ++- + upatch-build/src/elf/write/symbol.rs | 40 +++++----- + upatch-build/src/file_relation.rs | 12 +-- + upatch-build/src/main.rs | 16 ++-- + upatch-build/src/pattern_path.rs | 26 +++--- + upatch-build/src/resolve.rs | 79 ++++++++++--------- + upatch-build/src/rpc/remote.rs | 19 ++--- + upatchd/build.rs | 33 ++++---- + upatchd/src/helper/elf_resolver.rs | 4 +- + upatchd/src/helper/ioctl.rs | 1 + + upatchd/src/main.rs | 14 ++-- + 60 files changed, 559 insertions(+), 565 deletions(-) + +diff --git a/syscare-abi/build.rs b/syscare-abi/build.rs +index 8a86f63..ed83c43 100644 +--- a/syscare-abi/build.rs ++++ b/syscare-abi/build.rs +@@ -12,26 +12,25 @@ + * See the Mulan PSL v2 for more details. + */ + +-use std::{env, process::Command}; ++use std::{env, ffi::OsStr, os::unix::ffi::OsStrExt, process::Command}; + + fn rewrite_version() { +- const ENV_VERSION_NAME: &str = "BUILD_VERSION"; +- const PKG_VERSION_NAME: &str = "CARGO_PKG_VERSION"; ++ const PKG_VERSION: &str = env!("CARGO_PKG_VERSION"); ++ const ENV_VERSION: Option<&str> = option_env!("BUILD_VERSION"); + +- let version = env::var(ENV_VERSION_NAME).unwrap_or_else(|_| { +- let pkg_version = env::var(PKG_VERSION_NAME).expect("Failed to fetch package version"); +- let git_output = Command::new("git") +- .args(["rev-parse", "--short", "HEAD"]) +- .output() +- .map(|output| String::from_utf8(output.stdout).expect("Failed to fetch git version")); +- +- match git_output { +- Ok(git_version) => format!("{}-g{}", pkg_version, git_version), +- Err(_) => pkg_version, +- } +- }); +- +- println!("cargo:rustc-env={}={}", PKG_VERSION_NAME, version); ++ println!( ++ "cargo:rustc-env=CARGO_PKG_VERSION={}", ++ ENV_VERSION.map(String::from).unwrap_or_else(|| { ++ Command::new("git") ++ .args(["rev-parse", "--short", "HEAD"]) ++ .output() ++ .map(|output| { ++ let git_version = OsStr::from_bytes(&output.stdout).to_string_lossy(); ++ format!("{}-g{}", PKG_VERSION, git_version) ++ }) ++ .unwrap_or_else(|_| PKG_VERSION.to_string()) ++ }) ++ ); + } + + fn main() { +diff --git a/syscare-abi/src/patch_info.rs b/syscare-abi/src/patch_info.rs +index 55618ae..659755d 100644 +--- a/syscare-abi/src/patch_info.rs ++++ b/syscare-abi/src/patch_info.rs +@@ -94,21 +94,18 @@ impl std::fmt::Display for PatchInfo { + writeln!(f, "patches:")?; + let last_idx = self.patches.len() - 1; + for (patch_idx, patch_file) in self.patches.iter().enumerate() { +- match patch_idx == last_idx { +- false => { +- if patch_idx >= LIST_DISPLAY_LIMIT { +- writeln!(f, "* ......")?; +- break; +- } +- writeln!(f, "* {}", patch_file.name.to_string_lossy())? ++ if patch_idx != last_idx { ++ if patch_idx >= LIST_DISPLAY_LIMIT { ++ writeln!(f, "* ......")?; ++ break; + } +- true => { +- if patch_idx >= LIST_DISPLAY_LIMIT { +- write!(f, "* ......")?; +- break; +- } +- write!(f, "* {}", patch_file.name.to_string_lossy())? ++ writeln!(f, "* {}", patch_file.name.to_string_lossy())? ++ } else { ++ if patch_idx >= LIST_DISPLAY_LIMIT { ++ write!(f, "* ......")?; ++ break; + } ++ write!(f, "* {}", patch_file.name.to_string_lossy())? + } + } + } +diff --git a/syscare-build/build.rs b/syscare-build/build.rs +index b3de093..1ca9609 100644 +--- a/syscare-build/build.rs ++++ b/syscare-build/build.rs +@@ -12,26 +12,25 @@ + * See the Mulan PSL v2 for more details. + */ + +-use std::{env, process::Command}; ++use std::{env, ffi::OsStr, os::unix::ffi::OsStrExt, process::Command}; + + fn rewrite_version() { +- const ENV_VERSION_NAME: &str = "BUILD_VERSION"; +- const PKG_VERSION_NAME: &str = "CARGO_PKG_VERSION"; ++ const PKG_VERSION: &str = env!("CARGO_PKG_VERSION"); ++ const ENV_VERSION: Option<&str> = option_env!("BUILD_VERSION"); + +- let version = env::var(ENV_VERSION_NAME).unwrap_or_else(|_| { +- let pkg_version = env::var(PKG_VERSION_NAME).expect("Failed to fetch package version"); +- let git_output = Command::new("git") +- .args(["rev-parse", "--short", "HEAD"]) +- .output() +- .map(|output| String::from_utf8(output.stdout).expect("Failed to fetch git version")); +- +- match git_output { +- Ok(git_version) => format!("{}-g{}", pkg_version, git_version), +- Err(_) => pkg_version, +- } +- }); +- +- println!("cargo:rustc-env={}={}", PKG_VERSION_NAME, version); ++ println!( ++ "cargo:rustc-env=CARGO_PKG_VERSION={}", ++ ENV_VERSION.map(String::from).unwrap_or_else(|| { ++ Command::new("git") ++ .args(["rev-parse", "--short", "HEAD"]) ++ .output() ++ .map(|output| { ++ let git_version = OsStr::from_bytes(&output.stdout).to_string_lossy(); ++ format!("{}-g{}", PKG_VERSION, git_version) ++ }) ++ .unwrap_or_else(|_| PKG_VERSION.to_string()) ++ }) ++ ); + } + + fn main() { +diff --git a/syscare-build/src/build_root/mod.rs b/syscare-build/src/build_root/mod.rs +index 6a12788..395fead 100644 +--- a/syscare-build/src/build_root/mod.rs ++++ b/syscare-build/src/build_root/mod.rs +@@ -36,8 +36,8 @@ pub struct BuildRoot { + } + + impl BuildRoot { +- pub fn new>(path: P) -> Result { +- let path = path.as_ref().to_path_buf(); ++ pub fn new>(directory: P) -> Result { ++ let path = directory.as_ref().to_path_buf(); + let package = PackageRoot::new(path.join(PACKAGE_ROOT_NAME))?; + let patch = PatchRoot::new(path.join(PATCH_ROOT_NAME))?; + let log_file = path.join(BUILD_LOG_NAME); +diff --git a/syscare-build/src/build_root/package_root.rs b/syscare-build/src/build_root/package_root.rs +index 724a42b..75ff65d 100644 +--- a/syscare-build/src/build_root/package_root.rs ++++ b/syscare-build/src/build_root/package_root.rs +@@ -32,8 +32,8 @@ pub struct PackageRoot { + } + + impl PackageRoot { +- pub fn new>(path: P) -> Result { +- let path = path.as_ref().to_path_buf(); ++ pub fn new>(directory: P) -> Result { ++ let path = directory.as_ref().to_path_buf(); + let source = path.join(SOURCE_DIR_NAME); + let debuginfo = path.join(DEBUGINFO_DIR_NAME); + let build_root = PackageBuildRoot::new(path.join(BUILD_ROOT_DIR_NAME))?; +diff --git a/syscare-build/src/build_root/patch_root.rs b/syscare-build/src/build_root/patch_root.rs +index af8ec6b..d493233 100644 +--- a/syscare-build/src/build_root/patch_root.rs ++++ b/syscare-build/src/build_root/patch_root.rs +@@ -28,8 +28,8 @@ pub struct PatchRoot { + } + + impl PatchRoot { +- pub fn new>(base_dir: P) -> Result { +- let path = base_dir.as_ref().to_path_buf(); ++ pub fn new>(directory: P) -> Result { ++ let path = directory.as_ref().to_path_buf(); + let build = path.join(BUILD_DIR_NAME); + let output = path.join(OUTPUT_DIR_NAME); + +diff --git a/syscare-build/src/main.rs b/syscare-build/src/main.rs +index 1faa803..bfff3b4 100644 +--- a/syscare-build/src/main.rs ++++ b/syscare-build/src/main.rs +@@ -217,10 +217,10 @@ impl SyscareBuild { + .find(|entry| entry.target_pkg.name == KERNEL_PKG_NAME); + + match (pkg_entry, kernel_entry) { +- (Some(entry), Some(kernel_entry)) => Ok(( ++ (Some(p_entry), Some(k_entry)) => Ok(( + PatchType::KernelPatch, +- entry.clone(), +- Some(kernel_entry.clone()), ++ p_entry.clone(), ++ Some(k_entry.clone()), + )), + (None, Some(entry)) => Ok((PatchType::KernelPatch, entry.clone(), None)), + (Some(entry), None) => Ok((PatchType::UserPatch, entry.clone(), None)), +diff --git a/syscare-build/src/package/build_root.rs b/syscare-build/src/package/build_root.rs +index 6124156..d8ee182 100644 +--- a/syscare-build/src/package/build_root.rs ++++ b/syscare-build/src/package/build_root.rs +@@ -36,8 +36,8 @@ pub struct PackageBuildRoot { + } + + impl PackageBuildRoot { +- pub fn new>(path: P) -> Result { +- let path = path.as_ref().to_path_buf(); ++ pub fn new>(directory: P) -> Result { ++ let path = directory.as_ref().to_path_buf(); + let build = path.join(BUILD_DIR_NAME); + let buildroot = path.join(BUILDROOT_DIR_NAME); + let rpms = path.join(RPMS_DIR_NAME); +diff --git a/syscare-build/src/package/rpm/mod.rs b/syscare-build/src/package/rpm/mod.rs +index 0e9f77c..4054f67 100644 +--- a/syscare-build/src/package/rpm/mod.rs ++++ b/syscare-build/src/package/rpm/mod.rs +@@ -74,9 +74,10 @@ impl Package for RpmPackage { + } + + let name = pkg_info[0].to_owned(); +- let kind = match pkg_info[6] == SPEC_TAG_VALUE_NONE { +- true => PackageType::SourcePackage, +- false => PackageType::BinaryPackage, ++ let kind = if pkg_info[6] == SPEC_TAG_VALUE_NONE { ++ PackageType::SourcePackage ++ } else { ++ PackageType::BinaryPackage + }; + let arch = pkg_info[1].to_owned(); + let epoch = pkg_info[2].to_owned(); +diff --git a/syscare-build/src/package/rpm/spec_file.rs b/syscare-build/src/package/rpm/spec_file.rs +index 17dcbe3..bd7b647 100644 +--- a/syscare-build/src/package/rpm/spec_file.rs ++++ b/syscare-build/src/package/rpm/spec_file.rs +@@ -62,33 +62,33 @@ impl RpmSpecFile { + description: String, + ) -> Self { + Self { +- defines: Default::default(), ++ defines: BTreeSet::default(), + name, + version, + release, +- group: Default::default(), ++ group: Option::default(), + license, +- url: Default::default(), ++ url: Option::default(), + summary, +- build_requires: Default::default(), +- requires: Default::default(), +- conflicts: Default::default(), +- suggests: Default::default(), +- recommends: Default::default(), ++ build_requires: HashSet::default(), ++ requires: HashSet::default(), ++ conflicts: HashSet::default(), ++ suggests: HashSet::default(), ++ recommends: HashSet::default(), + description, + prep: SPEC_SCRIPT_VALUE_NONE.to_string(), + build: SPEC_SCRIPT_VALUE_NONE.to_string(), + install: SPEC_SCRIPT_VALUE_NONE.to_string(), +- check: Default::default(), +- pre: Default::default(), +- post: Default::default(), +- preun: Default::default(), +- postun: Default::default(), +- defattr: Default::default(), +- files: Default::default(), +- source: Default::default(), +- patch: Default::default(), +- change_log: Default::default(), ++ check: Option::default(), ++ pre: Option::default(), ++ post: Option::default(), ++ preun: Option::default(), ++ postun: Option::default(), ++ defattr: Option::default(), ++ files: BTreeSet::default(), ++ source: BTreeSet::default(), ++ patch: BTreeSet::default(), ++ change_log: Option::default(), + } + } + } +@@ -204,33 +204,33 @@ impl RpmSpecFile { + impl Default for RpmSpecFile { + fn default() -> Self { + Self { +- defines: Default::default(), ++ defines: BTreeSet::default(), + name: SPEC_TAG_VALUE_NONE.to_string(), + version: SPEC_TAG_VALUE_NONE.to_string(), + release: SPEC_TAG_VALUE_NONE.to_string(), +- group: Default::default(), ++ group: Option::default(), + license: SPEC_TAG_VALUE_NONE.to_string(), +- url: Default::default(), ++ url: Option::default(), + summary: SPEC_TAG_VALUE_NONE.to_string(), +- build_requires: Default::default(), +- requires: Default::default(), +- conflicts: Default::default(), +- suggests: Default::default(), +- recommends: Default::default(), ++ build_requires: HashSet::default(), ++ requires: HashSet::default(), ++ conflicts: HashSet::default(), ++ suggests: HashSet::default(), ++ recommends: HashSet::default(), + description: SPEC_TAG_VALUE_NONE.to_string(), + prep: SPEC_SCRIPT_VALUE_NONE.to_string(), + build: SPEC_SCRIPT_VALUE_NONE.to_string(), + install: SPEC_SCRIPT_VALUE_NONE.to_string(), +- check: Default::default(), +- pre: Default::default(), +- post: Default::default(), +- preun: Default::default(), +- postun: Default::default(), +- defattr: Default::default(), +- files: Default::default(), +- source: Default::default(), +- patch: Default::default(), +- change_log: Default::default(), ++ check: Option::default(), ++ pre: Option::default(), ++ post: Option::default(), ++ preun: Option::default(), ++ postun: Option::default(), ++ defattr: Option::default(), ++ files: BTreeSet::default(), ++ source: BTreeSet::default(), ++ patch: BTreeSet::default(), ++ change_log: Option::default(), + } + } + } +diff --git a/syscare-build/src/patch/metadata.rs b/syscare-build/src/patch/metadata.rs +index 284c096..c32c267 100644 +--- a/syscare-build/src/patch/metadata.rs ++++ b/syscare-build/src/patch/metadata.rs +@@ -33,8 +33,8 @@ pub struct PatchMetadata { + } + + impl PatchMetadata { +- pub fn new>(root_dir: P) -> Self { +- let root_dir = root_dir.as_ref().to_path_buf(); ++ pub fn new>(directory: P) -> Self { ++ let root_dir = directory.as_ref().to_path_buf(); + let metadata_dir = root_dir.join(METADATA_DIR_NAME); + let package_path = root_dir.join(METADATA_PKG_NAME); + let metadata_path = metadata_dir.join(METADATA_FILE_NAME); +diff --git a/syscare-common/build.rs b/syscare-common/build.rs +index 1019998..ca9d78c 100644 +--- a/syscare-common/build.rs ++++ b/syscare-common/build.rs +@@ -12,26 +12,25 @@ + * See the Mulan PSL v2 for more details. + */ + +-use std::{env, process::Command}; ++use std::{env, ffi::OsStr, os::unix::ffi::OsStrExt, process::Command}; + + fn rewrite_version() { +- const ENV_VERSION_NAME: &str = "BUILD_VERSION"; +- const PKG_VERSION_NAME: &str = "CARGO_PKG_VERSION"; ++ const PKG_VERSION: &str = env!("CARGO_PKG_VERSION"); ++ const ENV_VERSION: Option<&str> = option_env!("BUILD_VERSION"); + +- let version = env::var(ENV_VERSION_NAME).unwrap_or_else(|_| { +- let pkg_version = env::var(PKG_VERSION_NAME).expect("Failed to fetch package version"); +- let git_output = Command::new("git") +- .args(["rev-parse", "--short", "HEAD"]) +- .output() +- .map(|output| String::from_utf8(output.stdout).expect("Failed to fetch git version")); +- +- match git_output { +- Ok(git_version) => format!("{}-g{}", pkg_version, git_version), +- Err(_) => pkg_version, +- } +- }); +- +- println!("cargo:rustc-env={}={}", PKG_VERSION_NAME, version); ++ println!( ++ "cargo:rustc-env=CARGO_PKG_VERSION={}", ++ ENV_VERSION.map(String::from).unwrap_or_else(|| { ++ Command::new("git") ++ .args(["rev-parse", "--short", "HEAD"]) ++ .output() ++ .map(|output| { ++ let git_version = OsStr::from_bytes(&output.stdout).to_string_lossy(); ++ format!("{}-g{}", PKG_VERSION, git_version) ++ }) ++ .unwrap_or_else(|_| PKG_VERSION.to_string()) ++ }) ++ ); + } + + fn main() { +diff --git a/syscare-common/src/ffi/os_str.rs b/syscare-common/src/ffi/os_str.rs +index 43a9adc..2db26c8 100644 +--- a/syscare-common/src/ffi/os_str.rs ++++ b/syscare-common/src/ffi/os_str.rs +@@ -37,10 +37,7 @@ pub trait OsStrExt: AsRef { + + let haystack = self.as_ref().as_bytes(); + match haystack.get(index) { +- Some(&b) => { +- // This is bit magic equivalent to: b < 128 || b >= 192 +- b as i8 >= -0x40 +- } ++ Some(&b) => !(128..192).contains(&b), + None => index == haystack.len(), + } + } +@@ -135,14 +132,12 @@ pub trait OsStrExt: AsRef { + } + + fn split_whitespace(&self) -> Filter, FilterFn> { +- self.split(char::is_whitespace as SplitFn) ++ self.split(SplitFn::from(char::is_whitespace)) + .filter(|s| !s.is_empty()) + } + + fn split_at(&self, mid: usize) -> (&OsStr, &OsStr) { +- if !self.is_char_boundary(mid) { +- panic!("Failed to slice osstring"); +- } ++ debug_assert!(self.is_char_boundary(mid), "Split out of char boundary"); + + let (lhs, rhs) = self.as_ref().as_bytes().split_at(mid); + (OsStr::from_bytes(lhs), OsStr::from_bytes(rhs)) +diff --git a/syscare-common/src/fs/flock.rs b/syscare-common/src/fs/flock.rs +index b5639a8..bfd39d7 100644 +--- a/syscare-common/src/fs/flock.rs ++++ b/syscare-common/src/fs/flock.rs +@@ -57,9 +57,10 @@ impl FileLock { + impl FileLock { + pub fn new>(path: P, kind: FileLockType) -> Result { + let file_path = path.as_ref(); +- let inner = match file_path.exists() { +- true => File::open(file_path), +- false => File::create(file_path), ++ let inner = if file_path.exists() { ++ File::open(file_path) ++ } else { ++ File::create(file_path) + } + .with_context(|| format!("Failed to create flock on {}", file_path.display()))?; + +diff --git a/syscare-common/src/fs/fs_impl.rs b/syscare-common/src/fs/fs_impl.rs +index af0f60c..e794c98 100644 +--- a/syscare-common/src/fs/fs_impl.rs ++++ b/syscare-common/src/fs/fs_impl.rs +@@ -201,42 +201,50 @@ where + P: AsRef, + S: AsRef, + { +- let path = path.as_ref().to_cstring()?; +- let name = name.as_ref().to_cstring()?; ++ let file_path = path.as_ref().to_cstring()?; ++ let xattr_name = name.as_ref().to_cstring()?; + + /* + * SAFETY: + * This libc function is marked 'unsafe' as unchecked buffer may cause overflow. + * In our implementation, the buffer is checked properly, so that would be safe. + */ +- let ret = unsafe { nix::libc::getxattr(path.as_ptr(), name.as_ptr(), null_mut(), 0) }; ++ let mut ret = ++ unsafe { nix::libc::getxattr(file_path.as_ptr(), xattr_name.as_ptr(), null_mut(), 0) }; + if ret == -1 { + return Err(std::io::Error::last_os_error()).rewrite_err(format!( + "Cannot get path {} xattr {}", +- path.to_string_lossy(), +- name.to_string_lossy() ++ file_path.to_string_lossy(), ++ xattr_name.to_string_lossy() + )); + } + +- let mut buf = vec![0; ret as usize]; +- let value = buf.as_mut_ptr() as *mut c_void; ++ let mut buf = vec![0; ret.unsigned_abs()]; ++ let value_ptr = buf.as_mut_ptr().cast::(); + + /* + * SAFETY: + * This libc function is marked 'unsafe' as unchecked buffer may cause overflow. + * In our implementation, the buffer is checked properly, so that would be safe. + */ +- let ret = unsafe { nix::libc::getxattr(path.as_ptr(), name.as_ptr(), value, buf.len()) }; ++ ret = unsafe { ++ nix::libc::getxattr( ++ file_path.as_ptr(), ++ xattr_name.as_ptr(), ++ value_ptr, ++ buf.len(), ++ ) ++ }; + if ret == -1 { + return Err(std::io::Error::last_os_error()).rewrite_err(format!( + "Cannot get path {} xattr {}", +- path.to_string_lossy(), +- name.to_string_lossy(), ++ file_path.to_string_lossy(), ++ xattr_name.to_string_lossy(), + )); + } + +- let value = CStr::from_bytes_with_nul(&buf[0..ret as usize]) +- .expect("asdf") ++ let value = CStr::from_bytes_with_nul(&buf[0..ret.unsigned_abs()]) ++ .unwrap_or_default() + .to_os_string(); + + Ok(value) +@@ -248,10 +256,10 @@ where + S: AsRef, + T: AsRef, + { +- let path = path.as_ref().to_cstring()?; +- let name = name.as_ref().to_cstring()?; +- let value = value.as_ref().to_cstring()?; +- let size = value.to_bytes_with_nul().len(); ++ let file_path = path.as_ref().to_cstring()?; ++ let xattr_name = name.as_ref().to_cstring()?; ++ let xattr_value = value.as_ref().to_cstring()?; ++ let size = xattr_value.to_bytes_with_nul().len(); + + /* + * SAFETY: +@@ -260,9 +268,9 @@ where + */ + let ret = unsafe { + nix::libc::setxattr( +- path.as_ptr(), +- name.as_ptr(), +- value.as_ptr() as *const c_void, ++ file_path.as_ptr(), ++ xattr_name.as_ptr(), ++ xattr_value.as_ptr().cast::(), + size, + 0, + ) +@@ -270,8 +278,8 @@ where + if ret == -1 { + return Err(std::io::Error::last_os_error()).rewrite_err(format!( + "Cannot set {} xattr {}", +- path.to_string_lossy(), +- name.to_string_lossy() ++ file_path.to_string_lossy(), ++ xattr_name.to_string_lossy() + )); + } + +@@ -425,13 +433,10 @@ where + return false; + } + if let Some(file_name) = file_path.file_name() { +- match options.fuzz { +- false => { +- return file_name == name.as_ref(); +- } +- true => { +- return file_name.contains(name.as_ref()); +- } ++ if options.fuzz { ++ return file_name.contains(name.as_ref()); ++ } else { ++ return file_name == name.as_ref(); + } + } + false +@@ -459,13 +464,10 @@ where + return false; + } + if let Some(file_name) = file_path.file_name() { +- match options.fuzz { +- false => { +- return file_name == name.as_ref(); +- } +- true => { +- return file_name.contains(name.as_ref()); +- } ++ if options.fuzz { ++ return file_name.contains(name.as_ref()); ++ } else { ++ return file_name == name.as_ref(); + } + } + false +@@ -526,13 +528,10 @@ where + return false; + } + if let Some(file_name) = file_path.file_name() { +- match options.fuzz { +- false => { +- return file_name == name.as_ref(); +- } +- true => { +- return file_name.contains(name.as_ref()); +- } ++ if options.fuzz { ++ return file_name.contains(name.as_ref()); ++ } else { ++ return file_name == name.as_ref(); + } + } + false +diff --git a/syscare-common/src/io/select.rs b/syscare-common/src/io/select.rs +index 59e28ac..5d9400f 100644 +--- a/syscare-common/src/io/select.rs ++++ b/syscare-common/src/io/select.rs +@@ -32,7 +32,7 @@ impl Select { + Self::with_timeout(fds, None) + } + +- pub fn with_timeout(fds: I, timeout: Option) -> Self ++ pub fn with_timeout(fds: I, duration: Option) -> Self + where + I: IntoIterator, + F: AsRawFd, +@@ -44,8 +44,7 @@ impl Select { + let readfds = FdSet::new(); + let writefds = FdSet::new(); + let errorfds = FdSet::new(); +- let timeout = timeout +- .map(|timeout| TimeVal::new(timeout.as_secs() as i64, timeout.subsec_micros() as i64)); ++ let timeout = duration.map(|t| TimeVal::new(t.as_secs() as i64, t.subsec_micros() as i64)); + + Self { + fd_set, +diff --git a/syscare-common/src/os/cpu.rs b/syscare-common/src/os/cpu.rs +index 62baa17..ead7eee 100644 +--- a/syscare-common/src/os/cpu.rs ++++ b/syscare-common/src/os/cpu.rs +@@ -30,10 +30,10 @@ pub fn arch() -> &'static OsStr { + pub fn num() -> usize { + lazy_static! { + static ref CPU_NUM: usize = { +- let cpu_set = sched_getaffinity(getpid()).expect("Failed to get thread CPU affinity"); ++ let cpu_set = sched_getaffinity(getpid()).unwrap_or_default(); + let mut cpu_count = 0; + for i in 0..CpuSet::count() { +- if cpu_set.is_set(i).expect("Failed to check cpu set") { ++ if cpu_set.is_set(i).unwrap_or_default() { + cpu_count += 1; + } + } +diff --git a/syscare-common/src/os/process.rs b/syscare-common/src/os/process.rs +index 2cf4ec9..d992372 100644 +--- a/syscare-common/src/os/process.rs ++++ b/syscare-common/src/os/process.rs +@@ -30,7 +30,7 @@ pub fn id() -> i32 { + pub fn path() -> &'static Path { + lazy_static! { + static ref PROCESS_PATH: PathBuf = +- std::env::current_exe().expect("Read process path failed"); ++ std::env::current_exe().unwrap_or_else(|_| PathBuf::from("/")); + } + PROCESS_PATH.as_path() + } +diff --git a/syscare-common/src/os/user.rs b/syscare-common/src/os/user.rs +index ebf2a14..db2e10e 100644 +--- a/syscare-common/src/os/user.rs ++++ b/syscare-common/src/os/user.rs +@@ -12,71 +12,80 @@ + * See the Mulan PSL v2 for more details. + */ + +-use std::ffi::OsStr; +-use std::path::Path; ++use std::{ ++ ffi::{CString, OsStr}, ++ path::{Path, PathBuf}, ++}; + +-use lazy_static::*; +-use nix::unistd::{getuid, User}; ++use lazy_static::lazy_static; ++use nix::unistd::{getuid, Gid, Uid, User}; + + use crate::ffi::CStrExt; + +-#[inline(always)] + fn info() -> &'static User { + lazy_static! { +- static ref USER: User = User::from_uid(getuid()) +- .expect("Failed to read user info") +- .unwrap(); ++ static ref USER_INFO: User = User::from_uid(getuid()) ++ .unwrap_or_default() ++ .unwrap_or(User { ++ name: String::from("root"), ++ passwd: CString::default(), ++ uid: Uid::from_raw(0), ++ gid: Gid::from_raw(0), ++ gecos: CString::default(), ++ dir: PathBuf::from("/root"), ++ shell: PathBuf::from("/bin/sh"), ++ }); + } +- &USER ++ &USER_INFO + } + + pub fn name() -> &'static str { +- info().name.as_str() ++ self::info().name.as_str() + } + + pub fn passwd() -> &'static OsStr { +- info().passwd.as_os_str() ++ self::info().passwd.as_os_str() + } + + pub fn id() -> u32 { +- info().uid.as_raw() ++ self::info().uid.as_raw() + } + + pub fn gid() -> u32 { +- info().gid.as_raw() ++ self::info().gid.as_raw() + } + + pub fn gecos() -> &'static OsStr { +- info().gecos.as_os_str() ++ self::info().gecos.as_os_str() + } + + pub fn home() -> &'static Path { +- info().dir.as_path() ++ self::info().dir.as_path() + } + + pub fn shell() -> &'static Path { +- info().shell.as_path() ++ self::info().shell.as_path() + } + + #[test] + fn test() { +- println!("name: {}", name()); +- assert!(!name().is_empty()); ++ println!("name: {}", self::name()); ++ assert!(!self::name().is_empty()); + +- println!("passwd: {}", passwd().to_string_lossy()); +- assert!(!passwd().is_empty()); ++ println!("passwd: {}", self::passwd().to_string_lossy()); ++ assert!(!self::passwd().is_empty()); + +- println!("id: {}", id()); +- assert!(id() > 0); ++ println!("id: {}", self::id()); ++ assert!(id() < u32::MAX); + +- println!("gid: {}", gid()); +- assert!(gid() > 0); ++ println!("gid: {}", self::gid()); ++ assert!(gid() < u32::MAX); + +- println!("gecos: {}", gecos().to_string_lossy()); ++ println!("gecos: {}", self::gecos().to_string_lossy()); + +- println!("home: {}", home().display()); +- assert!(home().exists()); ++ println!("home: {}", self::home().display()); ++ assert!(self::home().exists()); + +- println!("shell: {}", shell().display()); +- assert!(shell().exists()); ++ println!("shell: {}", self::shell().display()); ++ assert!(self::home().exists()); + } +diff --git a/syscare-common/src/os_str/iter.rs b/syscare-common/src/os_str/iter.rs +index db48771..2fa5d3b 100644 +--- a/syscare-common/src/os_str/iter.rs ++++ b/syscare-common/src/os_str/iter.rs +@@ -44,7 +44,7 @@ impl Iterator for CharIndices<'_> { + } + None => { + // Unable to parse utf-8 char, fallback to byte +- let result = (self.front_idx, char_bytes[0] as char); ++ let result = (self.front_idx, char::from(char_bytes[0])); + self.front_idx += 1; + + Some(result) +@@ -68,7 +68,13 @@ impl DoubleEndedIterator for CharIndices<'_> { + None => { + // Unable to parse utf-8 char, fallback to byte + self.back_idx -= 1; +- Some((self.back_idx, *char_bytes.last().unwrap() as char)) ++ Some(( ++ self.back_idx, ++ char_bytes ++ .last() ++ .map(|b| char::from(*b)) ++ .unwrap_or_default(), ++ )) + } + } + } +diff --git a/syscare-common/src/os_str/pattern.rs b/syscare-common/src/os_str/pattern.rs +index 6e0c1f0..fe15c18 100644 +--- a/syscare-common/src/os_str/pattern.rs ++++ b/syscare-common/src/os_str/pattern.rs +@@ -108,9 +108,10 @@ impl<'a> Searcher<'a> for CharLiteralSearcher<'a> { + match self.indices.next() { + Some((char_idx, c)) => { + let new_idx = char_idx + c.len_utf8(); +- match self.literals.contains(&c) { +- true => SearchStep::Match(char_idx, new_idx), +- false => SearchStep::Reject(char_idx, new_idx), ++ if self.literals.contains(&c) { ++ SearchStep::Match(char_idx, new_idx) ++ } else { ++ SearchStep::Reject(char_idx, new_idx) + } + } + None => SearchStep::Done, +@@ -123,9 +124,10 @@ impl<'a> ReverseSearcher<'a> for CharLiteralSearcher<'a> { + match self.indices.next_back() { + Some((char_idx, c)) => { + let new_idx = char_idx + c.len_utf8(); +- match self.literals.contains(&c) { +- true => SearchStep::Match(char_idx, new_idx), +- false => SearchStep::Reject(char_idx, new_idx), ++ if self.literals.contains(&c) { ++ SearchStep::Match(char_idx, new_idx) ++ } else { ++ SearchStep::Reject(char_idx, new_idx) + } + } + None => SearchStep::Done, +@@ -161,9 +163,10 @@ impl<'a, P: FnMut(char) -> bool> Searcher<'a> for CharPredicateSearcher<'a, P> { + match self.indices.next() { + Some((char_idx, c)) => { + let new_idx = char_idx + c.len_utf8(); +- match (self.predicate)(c) { +- true => SearchStep::Match(char_idx, new_idx), +- false => SearchStep::Reject(char_idx, new_idx), ++ if (self.predicate)(c) { ++ SearchStep::Match(char_idx, new_idx) ++ } else { ++ SearchStep::Reject(char_idx, new_idx) + } + } + None => SearchStep::Done, +@@ -176,9 +179,10 @@ impl<'a, P: FnMut(char) -> bool> ReverseSearcher<'a> for CharPredicateSearcher<' + match self.indices.next_back() { + Some((char_idx, c)) => { + let new_idx = char_idx + c.len_utf8(); +- match (self.predicate)(c) { +- true => SearchStep::Match(char_idx, new_idx), +- false => SearchStep::Reject(char_idx, new_idx), ++ if (self.predicate)(c) { ++ SearchStep::Match(char_idx, new_idx) ++ } else { ++ SearchStep::Reject(char_idx, new_idx) + } + } + None => SearchStep::Done, +diff --git a/syscare-common/src/os_str/utf8.rs b/syscare-common/src/os_str/utf8.rs +index 9a90bc0..8341df2 100644 +--- a/syscare-common/src/os_str/utf8.rs ++++ b/syscare-common/src/os_str/utf8.rs +@@ -46,7 +46,7 @@ pub fn next_valid_char(bytes: &[u8]) -> Option<(usize, char)> { + } + + let mut code = match char_width { +- 1 => return Some((1, first_byte as char)), ++ 1 => return Some((1, char::from(first_byte))), + 2 => u32::from(first_byte & 0x1F) << 0x6, + 3 => u32::from(first_byte & 0x0F) << 0xC, + 4 => u32::from(first_byte & 0x07) << 0x12, +diff --git a/syscare-common/src/process/child.rs b/syscare-common/src/process/child.rs +index 4ce6664..0e8cf54 100644 +--- a/syscare-common/src/process/child.rs ++++ b/syscare-common/src/process/child.rs +@@ -20,7 +20,7 @@ use std::{ + thread::JoinHandle, + }; + +-use anyhow::{ensure, Context, Result}; ++use anyhow::{anyhow, ensure, Context, Result}; + use log::trace; + + use super::{Stdio, StdioLevel}; +@@ -81,7 +81,9 @@ impl Child { + pub fn wait_with_output(&mut self) -> Result { + let stdio_thread = self.capture_stdio()?; + let status = self.wait()?; +- let (stdout, stderr) = stdio_thread.join().expect("Failed to join stdio thread"); ++ let (stdout, stderr) = stdio_thread ++ .join() ++ .map_err(|_| anyhow!("Failed to join stdio thread"))?; + + Ok(Output { + status, +diff --git a/syscare-common/src/process/stdio.rs b/syscare-common/src/process/stdio.rs +index fca944f..450019a 100644 +--- a/syscare-common/src/process/stdio.rs ++++ b/syscare-common/src/process/stdio.rs +@@ -90,7 +90,7 @@ impl Iterator for StdioReader { + match self.select.select().context("Failed to select stdio") { + Ok(result) => { + let stdio_map = &mut self.stdio_map; +- let outputs = result.into_iter().filter_map(|fd| match fd { ++ let outputs = result.into_iter().filter_map(|income| match income { + SelectResult::Readable(fd) => { + stdio_map.get_mut(&fd).and_then(|stdio| match stdio { + StdioLines::Stdout(lines) => { +diff --git a/syscare/build.rs b/syscare/build.rs +index 45eb14a..826ba22 100644 +--- a/syscare/build.rs ++++ b/syscare/build.rs +@@ -12,26 +12,25 @@ + * See the Mulan PSL v2 for more details. + */ + +-use std::{env, process::Command}; ++use std::{env, ffi::OsStr, os::unix::ffi::OsStrExt, process::Command}; + + fn rewrite_version() { +- const ENV_VERSION_NAME: &str = "BUILD_VERSION"; +- const PKG_VERSION_NAME: &str = "CARGO_PKG_VERSION"; ++ const PKG_VERSION: &str = env!("CARGO_PKG_VERSION"); ++ const ENV_VERSION: Option<&str> = option_env!("BUILD_VERSION"); + +- let version = env::var(ENV_VERSION_NAME).unwrap_or_else(|_| { +- let pkg_version = env::var(PKG_VERSION_NAME).expect("Failed to fetch package version"); +- let git_output = Command::new("git") +- .args(["rev-parse", "--short", "HEAD"]) +- .output() +- .map(|output| String::from_utf8(output.stdout).expect("Failed to fetch git version")); +- +- match git_output { +- Ok(git_version) => format!("{}-g{}", pkg_version, git_version), +- Err(_) => pkg_version, +- } +- }); +- +- println!("cargo:rustc-env={}={}", PKG_VERSION_NAME, version); ++ println!( ++ "cargo:rustc-env=CARGO_PKG_VERSION={}", ++ ENV_VERSION.map(String::from).unwrap_or_else(|| { ++ Command::new("git") ++ .args(["rev-parse", "--short", "HEAD"]) ++ .output() ++ .map(|output| { ++ let git_version = OsStr::from_bytes(&output.stdout).to_string_lossy(); ++ format!("{}-g{}", PKG_VERSION, git_version) ++ }) ++ .unwrap_or_else(|_| PKG_VERSION.to_string()) ++ }) ++ ); + } + + fn main() { +diff --git a/syscare/src/executor/patch.rs b/syscare/src/executor/patch.rs +index 1c4109b..98e719d 100644 +--- a/syscare/src/executor/patch.rs ++++ b/syscare/src/executor/patch.rs +@@ -14,7 +14,7 @@ + + use std::{fmt::Write, path::PathBuf}; + +-use anyhow::{anyhow, Error, Result}; ++use anyhow::{anyhow, Context, Error, Result}; + use log::info; + + use syscare_abi::{PackageInfo, PatchInfo, PatchListRecord, PatchStateRecord}; +@@ -39,7 +39,7 @@ impl PatchCommandExecutor { + fn check_error(mut error_list: Vec) -> Result<()> { + match error_list.len() { + 0 => Ok(()), +- 1 => Err(error_list.pop().unwrap()), ++ 1 => Err(error_list.pop().context("Invalid error")?), + _ => { + let mut err_msg = String::new(); + for (idx, e) in error_list.into_iter().enumerate() { +diff --git a/syscare/src/main.rs b/syscare/src/main.rs +index dea5717..754307f 100644 +--- a/syscare/src/main.rs ++++ b/syscare/src/main.rs +@@ -62,9 +62,10 @@ impl SyscareCLI { + let args = Arguments::new()?; + + // Initialize logger +- let log_level_max = match args.verbose { +- false => LevelFilter::Info, +- true => LevelFilter::Trace, ++ let log_level_max = if args.verbose { ++ LevelFilter::Trace ++ } else { ++ LevelFilter::Info + }; + let log_spec = LogSpecification::builder().default(log_level_max).build(); + let logger = Logger::with(log_spec) +@@ -91,10 +92,9 @@ impl SyscareCLI { + + debug!("Initializing command executors..."); + let patch_lock_file = self.args.work_dir.join(PATCH_OP_LOCK_NAME); +- let executors = vec![ +- Box::new(BuildCommandExecutor) as Box, +- Box::new(PatchCommandExecutor::new(patch_proxy, patch_lock_file)) +- as Box, ++ let executors: Vec> = vec![ ++ Box::new(BuildCommandExecutor), ++ Box::new(PatchCommandExecutor::new(patch_proxy, patch_lock_file)), + ]; + + let command = &self.args.command; +diff --git a/syscare/src/rpc/remote.rs b/syscare/src/rpc/remote.rs +index bd4c598..f2c9244 100644 +--- a/syscare/src/rpc/remote.rs ++++ b/syscare/src/rpc/remote.rs +@@ -61,27 +61,22 @@ impl RpcRemote { + impl RpcRemote { + fn parse_error(&self, error: Error) -> anyhow::Error { + match error { +- Error::Transport(e) => { ++ Error::Transport(err) => { + anyhow!( + "Cannot connect to syscare daemon at unix://{}, {}", + self.socket.display(), +- e.source() ++ err.source() + .map(|e| e.to_string()) + .unwrap_or_else(|| "Connection timeout".to_string()) + ) + } +- Error::Json(e) => { +- debug!("Json parse error: {:?}", e); ++ Error::Json(err) => { ++ debug!("Json parse error: {:?}", err); + anyhow!("Failed to parse response") + } +- Error::Rpc(ref e) => match e.message == "Method not found" { +- true => { +- anyhow!("Method is unimplemented") +- } +- false => { +- anyhow!("{}", e.message) +- } +- }, ++ Error::Rpc(err) => { ++ anyhow!("{}", err.message) ++ } + _ => { + debug!("{:?}", error); + anyhow!("Response is invalid") +diff --git a/syscared/build.rs b/syscared/build.rs +index ea4bee7..3a07aa1 100644 +--- a/syscared/build.rs ++++ b/syscared/build.rs +@@ -12,26 +12,25 @@ + * See the Mulan PSL v2 for more details. + */ + +-use std::{env, process::Command}; ++use std::{env, ffi::OsStr, os::unix::ffi::OsStrExt, process::Command}; + + fn rewrite_version() { +- const ENV_VERSION_NAME: &str = "BUILD_VERSION"; +- const PKG_VERSION_NAME: &str = "CARGO_PKG_VERSION"; ++ const PKG_VERSION: &str = env!("CARGO_PKG_VERSION"); ++ const ENV_VERSION: Option<&str> = option_env!("BUILD_VERSION"); + +- let version = env::var(ENV_VERSION_NAME).unwrap_or_else(|_| { +- let pkg_version = env::var(PKG_VERSION_NAME).expect("Failed to fetch package version"); +- let git_output = Command::new("git") +- .args(["rev-parse", "--short", "HEAD"]) +- .output() +- .map(|output| String::from_utf8(output.stdout).expect("Failed to fetch git version")); +- +- match git_output { +- Ok(git_version) => format!("{}-g{}", pkg_version, git_version), +- Err(_) => pkg_version, +- } +- }); +- +- println!("cargo:rustc-env={}={}", PKG_VERSION_NAME, version); ++ println!( ++ "cargo:rustc-env=CARGO_PKG_VERSION={}", ++ ENV_VERSION.map(String::from).unwrap_or_else(|| { ++ Command::new("git") ++ .args(["rev-parse", "--short", "HEAD"]) ++ .output() ++ .map(|output| { ++ let git_version = OsStr::from_bytes(&output.stdout).to_string_lossy(); ++ format!("{}-g{}", PKG_VERSION, git_version) ++ }) ++ .unwrap_or_else(|_| PKG_VERSION.to_string()) ++ }) ++ ); + } + + fn main() { +diff --git a/syscared/src/main.rs b/syscared/src/main.rs +index f13a9f8..42e9564 100644 +--- a/syscared/src/main.rs ++++ b/syscared/src/main.rs +@@ -129,9 +129,10 @@ impl Daemon { + + // Initialize logger + let max_level = args.log_level; +- let stdout_level = match args.daemon { +- true => LevelFilter::Off, +- false => max_level, ++ let stdout_level = if args.daemon { ++ LevelFilter::Off ++ } else { ++ max_level + }; + let log_spec = LogSpecification::builder().default(max_level).build(); + let file_spec = FileSpec::default() +@@ -210,9 +211,10 @@ impl Daemon { + + fs::set_permissions( + &socket_file, +- match socket_owner.as_raw() == socket_group.as_raw() { +- true => Permissions::from_mode(SOCKET_FILE_PERM_STRICT), +- false => Permissions::from_mode(SOCKET_FILE_PERM), ++ if socket_owner.as_raw() == socket_group.as_raw() { ++ Permissions::from_mode(SOCKET_FILE_PERM_STRICT) ++ } else { ++ Permissions::from_mode(SOCKET_FILE_PERM) + }, + )?; + +diff --git a/syscared/src/patch/driver/kpatch/sys.rs b/syscared/src/patch/driver/kpatch/sys.rs +index ea6b68f..22efa93 100644 +--- a/syscared/src/patch/driver/kpatch/sys.rs ++++ b/syscared/src/patch/driver/kpatch/sys.rs +@@ -92,7 +92,7 @@ pub fn apply_patch(patch: &KernelPatch) -> Result<()> { + CString::new("")?.as_c_str(), + kmod::ModuleInitFlags::MODULE_INIT_IGNORE_VERMAGIC, + ) +- .map_err(|e| anyhow!("Kpatch: {}", std::io::Error::from_raw_os_error(e as i32))) ++ .map_err(|e| anyhow!("Kpatch: {}", std::io::Error::from(e))) + } + + pub fn remove_patch(patch: &KernelPatch) -> Result<()> { +@@ -105,7 +105,7 @@ pub fn remove_patch(patch: &KernelPatch) -> Result<()> { + patch.module_name.to_cstring()?.as_c_str(), + kmod::DeleteModuleFlags::O_NONBLOCK, + ) +- .map_err(|e| anyhow!("Kpatch: {}", std::io::Error::from_raw_os_error(e as i32))) ++ .map_err(|e| anyhow!("Kpatch: {}", std::io::Error::from(e))) + } + + pub fn active_patch(patch: &KernelPatch) -> Result<()> { +diff --git a/syscared/src/patch/driver/mod.rs b/syscared/src/patch/driver/mod.rs +index d64c2d4..7a57579 100644 +--- a/syscared/src/patch/driver/mod.rs ++++ b/syscared/src/patch/driver/mod.rs +@@ -39,15 +39,15 @@ pub struct PatchDriver { + impl PatchDriver { + fn check_conflict_functions(&self, patch: &Patch) -> Result<()> { + match patch { +- Patch::KernelPatch(patch) => self.kpatch.check_conflict_functions(patch), +- Patch::UserPatch(patch) => self.upatch.check_conflict_functions(patch), ++ Patch::KernelPatch(kpatch) => self.kpatch.check_conflict_functions(kpatch), ++ Patch::UserPatch(upatch) => self.upatch.check_conflict_functions(upatch), + } + } + + fn check_override_functions(&self, patch: &Patch) -> Result<()> { + match patch { +- Patch::KernelPatch(patch) => self.kpatch.check_override_functions(patch), +- Patch::UserPatch(patch) => self.upatch.check_override_functions(patch), ++ Patch::KernelPatch(kpatch) => self.kpatch.check_override_functions(kpatch), ++ Patch::UserPatch(upatch) => self.upatch.check_override_functions(upatch), + } + } + } +@@ -71,8 +71,8 @@ impl PatchDriver { + /// Fetch and return the patch status. + pub fn patch_status(&self, patch: &Patch) -> Result { + match patch { +- Patch::KernelPatch(patch) => self.kpatch.status(patch), +- Patch::UserPatch(patch) => self.upatch.status(patch), ++ Patch::KernelPatch(kpatch) => self.kpatch.status(kpatch), ++ Patch::UserPatch(upatch) => self.upatch.status(upatch), + } + .with_context(|| format!("Failed to get patch '{}' status", patch)) + } +@@ -84,8 +84,8 @@ impl PatchDriver { + return Ok(()); + } + match patch { +- Patch::KernelPatch(patch) => self.kpatch.check(patch), +- Patch::UserPatch(patch) => self.upatch.check(patch), ++ Patch::KernelPatch(kpatch) => self.kpatch.check(kpatch), ++ Patch::UserPatch(upatch) => self.upatch.check(upatch), + } + .with_context(|| format!("Patch '{}' is not patchable", patch)) + } +@@ -104,8 +104,8 @@ impl PatchDriver { + /// After this action, the patch status would be changed to 'DEACTIVED'. + pub fn apply_patch(&mut self, patch: &Patch) -> Result<()> { + match patch { +- Patch::KernelPatch(patch) => self.kpatch.apply(patch), +- Patch::UserPatch(patch) => self.upatch.apply(patch), ++ Patch::KernelPatch(kpatch) => self.kpatch.apply(kpatch), ++ Patch::UserPatch(upatch) => self.upatch.apply(upatch), + } + .with_context(|| format!("Failed to apply patch '{}'", patch)) + } +@@ -114,8 +114,8 @@ impl PatchDriver { + /// After this action, the patch status would be changed to 'NOT-APPLIED'. + pub fn remove_patch(&mut self, patch: &Patch) -> Result<()> { + match patch { +- Patch::KernelPatch(patch) => self.kpatch.remove(patch), +- Patch::UserPatch(patch) => self.upatch.remove(patch), ++ Patch::KernelPatch(kpatch) => self.kpatch.remove(kpatch), ++ Patch::UserPatch(upatch) => self.upatch.remove(upatch), + } + .with_context(|| format!("Failed to remove patch '{}'", patch)) + } +@@ -127,8 +127,8 @@ impl PatchDriver { + self.check_conflict_functions(patch)?; + } + match patch { +- Patch::KernelPatch(patch) => self.kpatch.active(patch), +- Patch::UserPatch(patch) => self.upatch.active(patch), ++ Patch::KernelPatch(kpatch) => self.kpatch.active(kpatch), ++ Patch::UserPatch(upatch) => self.upatch.active(upatch), + } + .with_context(|| format!("Failed to active patch '{}'", patch)) + } +@@ -140,8 +140,8 @@ impl PatchDriver { + self.check_override_functions(patch)?; + } + match patch { +- Patch::KernelPatch(patch) => self.kpatch.deactive(patch), +- Patch::UserPatch(patch) => self.upatch.deactive(patch), ++ Patch::KernelPatch(kpatch) => self.kpatch.deactive(kpatch), ++ Patch::UserPatch(upatch) => self.upatch.deactive(upatch), + } + .with_context(|| format!("Failed to deactive patch '{}'", patch)) + } +diff --git a/syscared/src/patch/driver/upatch/mod.rs b/syscared/src/patch/driver/upatch/mod.rs +index 66eecf5..73ef94e 100644 +--- a/syscared/src/patch/driver/upatch/mod.rs ++++ b/syscared/src/patch/driver/upatch/mod.rs +@@ -227,8 +227,8 @@ impl UserPatchDriver { + Err(_) => return, + }; + +- let mut target_map = target_map.write(); +- let patch_target = match target_map.get_mut(target_elf) { ++ let mut patch_target_map = target_map.write(); ++ let patch_target = match patch_target_map.get_mut(target_elf) { + Some(target) => target, + None => return, + }; +diff --git a/syscared/src/patch/manager.rs b/syscared/src/patch/manager.rs +index f633567..d156e4a 100644 +--- a/syscared/src/patch/manager.rs ++++ b/syscared/src/patch/manager.rs +@@ -246,12 +246,11 @@ impl PatchManager { + + debug!("Reading patch status..."); + let status_file = &self.patch_status_file; +- let status_map: HashMap = match status_file.exists() { +- true => serde::deserialize(status_file).context("Failed to read patch status")?, +- false => { +- warn!("Cannot find patch status file"); +- return Ok(()); +- } ++ let status_map: HashMap = if status_file.exists() { ++ serde::deserialize(status_file).context("Failed to read patch status")? ++ } else { ++ warn!("Cannot find patch status file"); ++ return Ok(()); + }; + + /* +@@ -301,7 +300,7 @@ impl PatchManager { + pub fn rescan_patches(&mut self) -> Result<()> { + self.patch_map = Self::scan_patches(&self.patch_install_dir)?; + +- let status_keys = self.status_map.keys().cloned().collect::>(); ++ let status_keys = self.status_map.keys().copied().collect::>(); + for patch_uuid in status_keys { + if !self.patch_map.contains_key(&patch_uuid) { + trace!("Patch '{}' was removed, remove its status", patch_uuid); +@@ -362,9 +361,9 @@ impl PatchManager { + let mut patch_map = IndexMap::new(); + + info!("Scanning patches from {}...", directory.as_ref().display()); +- for patch_root in fs::list_dirs(directory, TRAVERSE_OPTION)? { +- let resolve_result = PatchResolver::resolve_patch(&patch_root) +- .with_context(|| format!("Failed to resolve patch from {}", patch_root.display())); ++ for patch_dir in fs::list_dirs(directory, TRAVERSE_OPTION)? { ++ let resolve_result = PatchResolver::resolve_patch(&patch_dir) ++ .with_context(|| format!("Failed to resolve patch from {}", patch_dir.display())); + match resolve_result { + Ok(patches) => { + for patch in patches { +diff --git a/syscared/src/patch/monitor.rs b/syscared/src/patch/monitor.rs +index 1798781..c793600 100644 +--- a/syscared/src/patch/monitor.rs ++++ b/syscared/src/patch/monitor.rs +@@ -44,13 +44,13 @@ impl PatchMonitor { + patch_root: P, + patch_manager: Arc>, + ) -> Result { +- let patch_root = patch_root.as_ref().join(PATCH_INSTALL_DIR); ++ let patch_install_dir = patch_root.as_ref().join(PATCH_INSTALL_DIR); + + let inotify = Arc::new(Mutex::new(Some({ + let mut inotify = Inotify::init().context("Failed to initialize inotify")?; + inotify + .add_watch( +- &patch_root, ++ &patch_install_dir, + WatchMask::CREATE | WatchMask::DELETE | WatchMask::ONLYDIR, + ) + .context("Failed to monitor patch directory")?; +@@ -59,7 +59,7 @@ impl PatchMonitor { + }))); + + let monitor_thread = MonitorThread { +- patch_root, ++ patch_root: patch_install_dir, + inotify: inotify.clone(), + patch_manager, + } +diff --git a/syscared/src/patch/resolver/kpatch.rs b/syscared/src/patch/resolver/kpatch.rs +index 8738225..18d81b0 100644 +--- a/syscared/src/patch/resolver/kpatch.rs ++++ b/syscared/src/patch/resolver/kpatch.rs +@@ -102,8 +102,6 @@ mod ffi { + } + } + +-use ffi::*; +- + const KPATCH_FUNCS_SECTION: &str = ".kpatch.funcs"; + const KPATCH_STRINGS_SECTION: &str = ".kpatch.strings"; + +@@ -132,9 +130,9 @@ impl KpatchResolverImpl { + + // Resolve patch functions + let patch_functions = &mut patch.functions; +- let kpatch_function_slice = object::slice_from_bytes::( ++ let kpatch_function_slice = object::slice_from_bytes::( + function_data, +- function_data.len() / KPATCH_FUNCTION_SIZE, ++ function_data.len() / ffi::KPATCH_FUNCTION_SIZE, + ) + .map(|(f, _)| f) + .map_err(|_| anyhow!("Invalid data format")) +@@ -152,13 +150,13 @@ impl KpatchResolverImpl { + } + + // Relocate patch functions +- for relocation in KpatchRelocationIterator::new(function_section.relocations()) { ++ for relocation in ffi::KpatchRelocationIterator::new(function_section.relocations()) { + let (name_reloc_offset, name_reloc) = relocation.name; + let (object_reloc_offset, obj_reloc) = relocation.object; + + // Relocate patch function name +- let name_index = +- (name_reloc_offset as usize - KPATCH_FUNCTION_OFFSET) / KPATCH_FUNCTION_SIZE; ++ let name_index = (name_reloc_offset as usize - ffi::KPATCH_FUNCTION_OFFSET) ++ / ffi::KPATCH_FUNCTION_SIZE; + let name_function = patch_functions + .get_mut(name_index) + .context("Failed to find patch function")?; +@@ -170,8 +168,8 @@ impl KpatchResolverImpl { + name_function.name = name_string; + + // Relocate patch function object +- let object_index = +- (object_reloc_offset as usize - KPATCH_OBJECT_OFFSET) / KPATCH_FUNCTION_SIZE; ++ let object_index = (object_reloc_offset as usize - ffi::KPATCH_OBJECT_OFFSET) ++ / ffi::KPATCH_FUNCTION_SIZE; + let object_function = patch_functions + .get_mut(object_index) + .context("Failed to find patch function")?; +diff --git a/syscared/src/patch/resolver/mod.rs b/syscared/src/patch/resolver/mod.rs +index 80e26ea..7c4a504 100644 +--- a/syscared/src/patch/resolver/mod.rs ++++ b/syscared/src/patch/resolver/mod.rs +@@ -38,8 +38,8 @@ pub trait PatchResolverImpl { + pub struct PatchResolver; + + impl PatchResolver { +- pub fn resolve_patch>(patch_root: P) -> Result> { +- let patch_root = patch_root.as_ref(); ++ pub fn resolve_patch>(directory: P) -> Result> { ++ let patch_root = directory.as_ref(); + let patch_info = Arc::new( + serde::deserialize_with_magic::( + patch_root.join(PATCH_INFO_FILE_NAME), +@@ -47,9 +47,9 @@ impl PatchResolver { + ) + .context("Failed to resolve patch metadata")?, + ); +- let resolver = match patch_info.kind { +- PatchType::UserPatch => &UpatchResolverImpl as &dyn PatchResolverImpl, +- PatchType::KernelPatch => &KpatchResolverImpl as &dyn PatchResolverImpl, ++ let resolver: &dyn PatchResolverImpl = match patch_info.kind { ++ PatchType::UserPatch => &UpatchResolverImpl, ++ PatchType::KernelPatch => &KpatchResolverImpl, + }; + + let mut patch_list = Vec::with_capacity(patch_info.entities.len()); +diff --git a/syscared/src/patch/resolver/upatch.rs b/syscared/src/patch/resolver/upatch.rs +index 985b8f1..7f04028 100644 +--- a/syscared/src/patch/resolver/upatch.rs ++++ b/syscared/src/patch/resolver/upatch.rs +@@ -87,8 +87,6 @@ mod ffi { + } + } + +-use ffi::*; +- + const UPATCH_FUNCS_SECTION: &str = ".upatch.funcs"; + const UPATCH_STRINGS_SECTION: &str = ".upatch.strings"; + +@@ -117,9 +115,9 @@ impl UpatchResolverImpl { + + // Resolve patch functions + let patch_functions = &mut patch.functions; +- let upatch_function_slice = object::slice_from_bytes::( ++ let upatch_function_slice = object::slice_from_bytes::( + function_data, +- function_data.len() / UPATCH_FUNCTION_SIZE, ++ function_data.len() / ffi::UPATCH_FUNCTION_SIZE, + ) + .map(|(f, _)| f) + .map_err(|_| anyhow!("Invalid data format")) +@@ -136,11 +134,11 @@ impl UpatchResolverImpl { + } + + // Relocate patch functions +- for relocation in UpatchRelocationIterator::new(function_section.relocations()) { ++ for relocation in ffi::UpatchRelocationIterator::new(function_section.relocations()) { + let (name_reloc_offset, name_reloc) = relocation.name; + +- let name_index = +- (name_reloc_offset as usize - UPATCH_FUNCTION_OFFSET) / UPATCH_FUNCTION_SIZE; ++ let name_index = (name_reloc_offset as usize - ffi::UPATCH_FUNCTION_OFFSET) ++ / ffi::UPATCH_FUNCTION_SIZE; + let name_function = patch_functions + .get_mut(name_index) + .context("Failed to find patch function")?; +diff --git a/syscared/src/rpc/skeleton_impl/patch.rs b/syscared/src/rpc/skeleton_impl/patch.rs +index b009d46..8216428 100644 +--- a/syscared/src/rpc/skeleton_impl/patch.rs ++++ b/syscared/src/rpc/skeleton_impl/patch.rs +@@ -96,9 +96,10 @@ impl PatchSkeleton for PatchSkeletonImpl { + format!("Apply patch '{}'", identifier), + self.patch_manager.clone(), + PatchManager::apply_patch, +- match force { +- false => PatchOpFlag::Normal, +- true => PatchOpFlag::Force, ++ if force { ++ PatchOpFlag::Force ++ } else { ++ PatchOpFlag::Normal + }, + identifier, + ) +@@ -131,9 +132,10 @@ impl PatchSkeleton for PatchSkeletonImpl { + format!("Active patch '{}'", identifier), + self.patch_manager.clone(), + PatchManager::active_patch, +- match force { +- false => PatchOpFlag::Normal, +- true => PatchOpFlag::Force, ++ if force { ++ PatchOpFlag::Force ++ } else { ++ PatchOpFlag::Normal + }, + identifier, + ) +diff --git a/upatch-build/build.rs b/upatch-build/build.rs +index 8cbb156..9ef3a36 100644 +--- a/upatch-build/build.rs ++++ b/upatch-build/build.rs +@@ -12,26 +12,25 @@ + * See the Mulan PSL v2 for more details. + */ + +-use std::{env, process::Command}; ++use std::{env, ffi::OsStr, os::unix::ffi::OsStrExt, process::Command}; + + fn rewrite_version() { +- const ENV_VERSION_NAME: &str = "BUILD_VERSION"; +- const PKG_VERSION_NAME: &str = "CARGO_PKG_VERSION"; ++ const PKG_VERSION: &str = env!("CARGO_PKG_VERSION"); ++ const ENV_VERSION: Option<&str> = option_env!("BUILD_VERSION"); + +- let version = env::var(ENV_VERSION_NAME).unwrap_or_else(|_| { +- let pkg_version = env::var(PKG_VERSION_NAME).expect("Failed to fetch package version"); +- let git_output = Command::new("git") +- .args(["rev-parse", "--short", "HEAD"]) +- .output() +- .map(|output| String::from_utf8(output.stdout).expect("Failed to fetch git version")); +- +- match git_output { +- Ok(git_version) => format!("{}-g{}", pkg_version, git_version), +- Err(_) => pkg_version, +- } +- }); +- +- println!("cargo:rustc-env={}={}", PKG_VERSION_NAME, version); ++ println!( ++ "cargo:rustc-env=CARGO_PKG_VERSION={}", ++ ENV_VERSION.map(String::from).unwrap_or_else(|| { ++ Command::new("git") ++ .args(["rev-parse", "--short", "HEAD"]) ++ .output() ++ .map(|output| { ++ let git_version = OsStr::from_bytes(&output.stdout).to_string_lossy(); ++ format!("{}-g{}", PKG_VERSION, git_version) ++ }) ++ .unwrap_or_else(|_| PKG_VERSION.to_string()) ++ }) ++ ); + } + + fn main() { +diff --git a/upatch-build/src/args.rs b/upatch-build/src/args.rs +index c3b6f48..04790c1 100644 +--- a/upatch-build/src/args.rs ++++ b/upatch-build/src/args.rs +@@ -113,13 +113,15 @@ impl Arguments { + args.name.push("-"); + } + +- args.elf_dir = match args.elf_dir.as_os_str().is_empty() { +- false => fs::normalize(&args.elf_dir)?, +- true => args.source_dir.clone(), ++ args.elf_dir = if args.elf_dir.as_os_str().is_empty() { ++ args.source_dir.clone() ++ } else { ++ fs::normalize(&args.elf_dir)? + }; +- args.object_dir = match args.object_dir.as_os_str().is_empty() { +- false => fs::normalize(&args.object_dir)?, +- true => args.source_dir.clone(), ++ args.object_dir = if args.object_dir.as_os_str().is_empty() { ++ args.source_dir.clone() ++ } else { ++ fs::normalize(&args.object_dir)? + }; + + for elf_path in &mut args.elf { +diff --git a/upatch-build/src/build_root.rs b/upatch-build/src/build_root.rs +index 556231d..5915bbc 100644 +--- a/upatch-build/src/build_root.rs ++++ b/upatch-build/src/build_root.rs +@@ -26,8 +26,8 @@ pub struct BuildRoot { + } + + impl BuildRoot { +- pub fn new>(path: P) -> Result { +- let path = path.as_ref().to_path_buf(); ++ pub fn new>(directory: P) -> Result { ++ let path = directory.as_ref().to_path_buf(); + let original_dir = path.join("original"); + let patched_dir = path.join("patched"); + let temp_dir = path.join("temp"); +diff --git a/upatch-build/src/compiler.rs b/upatch-build/src/compiler.rs +index 7778f0b..b4866bd 100644 +--- a/upatch-build/src/compiler.rs ++++ b/upatch-build/src/compiler.rs +@@ -178,23 +178,28 @@ impl Compiler { + let mut result = Vec::new(); + + for compiler in compilers { +- let compiler = compiler.as_ref(); +- let compiler_name = compiler ++ let compiler_path = compiler.as_ref(); ++ let compiler_name = compiler_path + .file_name() + .context("Failed to parse compiler name")?; + + let output_dir = temp_dir.as_ref().join(compiler_name); + fs::create_dir_all(&output_dir)?; + +- debug!("- Checking {}", compiler.display()); +- let assembler_name = +- Self::get_component_name(compiler, ASSEMBLER_NAME).with_context(|| { +- format!("Failed to get assembler name of {}", compiler.display()) ++ debug!("- Checking {}", compiler_path.display()); ++ let assembler_name = Self::get_component_name(compiler_path, ASSEMBLER_NAME) ++ .with_context(|| { ++ format!( ++ "Failed to get assembler name of {}", ++ compiler_path.display() ++ ) ++ })?; ++ let linker_name = ++ Self::get_component_name(compiler_path, LINKER_NAME).with_context(|| { ++ format!("Failed to get linker name of {}", compiler_path.display()) + })?; +- let linker_name = Self::get_component_name(compiler, LINKER_NAME) +- .with_context(|| format!("Failed to get linker name of {}", compiler.display()))?; + +- let path = compiler.to_path_buf(); ++ let path = compiler_path.to_path_buf(); + let assembler = which(assembler_name.trim()).with_context(|| { + format!("Cannot find assembler {}", assembler_name.to_string_lossy()) + })?; +@@ -202,17 +207,17 @@ impl Compiler { + .with_context(|| format!("Cannot find linker {}", linker_name.to_string_lossy()))?; + let versions = IndexSet::new(); + +- let mut compiler = Self { ++ let mut instance = Self { + path, + assembler, + linker, + versions, + }; +- compiler ++ instance + .fetch_versions(output_dir) + .context("Failed to fetch supported versions")?; + +- result.push(compiler); ++ result.push(instance); + } + + Ok(result) +diff --git a/upatch-build/src/dwarf/mod.rs b/upatch-build/src/dwarf/mod.rs +index 35f359e..6a91f7c 100644 +--- a/upatch-build/src/dwarf/mod.rs ++++ b/upatch-build/src/dwarf/mod.rs +@@ -49,9 +49,9 @@ pub struct CompileUnit { + pub struct Dwarf; + + impl Dwarf { +- pub fn parse>(elf: P) -> Result> { ++ pub fn parse>(file_path: P) -> Result> { + // use mmap here, but depend on some devices +- let elf = elf.as_ref(); ++ let elf = file_path.as_ref(); + let file = std::fs::File::open(elf)?; + let mmap = unsafe { memmap2::Mmap::map(&file)? }; + +@@ -88,6 +88,8 @@ impl Dwarf { + file: &File, + section: &Section, + ) { ++ const INVALID_SECTION_NAME: &str = ".invalid"; ++ + for (offset64, mut relocation) in section.relocations() { + let offset = offset64 as usize; + if offset as u64 != offset64 { +@@ -104,8 +106,7 @@ impl Dwarf { + } + Err(_) => { + trace!("Relocation with invalid symbol for section {} at offset 0x{:08x}", +- section.name().unwrap(), +- offset ++ section.name().unwrap_or(INVALID_SECTION_NAME), offset + ); + } + } +@@ -113,7 +114,7 @@ impl Dwarf { + if relocations.insert(offset, relocation).is_some() { + trace!( + "Multiple relocations for section {} at offset 0x{:08x}", +- section.name().unwrap(), ++ section.name().unwrap_or(INVALID_SECTION_NAME), + offset + ); + } +@@ -121,7 +122,7 @@ impl Dwarf { + _ => { + trace!( + "Unsupported relocation for section {} at offset 0x{:08x}", +- section.name().unwrap(), ++ section.name().unwrap_or(INVALID_SECTION_NAME), + offset + ); + } +@@ -136,12 +137,12 @@ impl Dwarf { + arena_data: &'arena Arena>, + arena_relocations: &'arena Arena>, + ) -> Result>> { +- let mut relocations = IndexMap::new(); ++ let mut relocation_map = IndexMap::new(); + let name = Some(id.name()); +- let data = match name.and_then(|name| file.section_by_name(name)) { ++ let data = match name.and_then(|section_name| file.section_by_name(section_name)) { + Some(ref section) => { + // DWO sections never have relocations, so don't bother. +- Self::add_relocations(&mut relocations, file, section); ++ Self::add_relocations(&mut relocation_map, file, section); + section.uncompressed_data()? + } + // Use a non-zero capacity so that `ReaderOffsetId`s are unique. +@@ -150,7 +151,7 @@ impl Dwarf { + let data_ref = (*arena_data.alloc(data)).borrow(); + let reader = EndianSlice::new(data_ref, endian); + let section = reader; +- let relocations = (*arena_relocations.alloc(relocations)).borrow(); ++ let relocations = (*arena_relocations.alloc(relocation_map)).borrow(); + Ok(Relocate { + relocations, + section, +diff --git a/upatch-build/src/dwarf/relocate.rs b/upatch-build/src/dwarf/relocate.rs +index 2a6e393..e8c7cdf 100644 +--- a/upatch-build/src/dwarf/relocate.rs ++++ b/upatch-build/src/dwarf/relocate.rs +@@ -14,6 +14,7 @@ + + use std::borrow::Cow; + ++use gimli::ReaderOffset; + use indexmap::IndexMap; + use object::Relocation; + +@@ -28,10 +29,11 @@ impl<'a, R: gimli::Reader> Relocate<'a, R> { + pub fn relocate(&self, offset: usize, value: u64) -> u64 { + if let Some(relocation) = self.relocations.get(&offset) { + if relocation.kind() == object::RelocationKind::Absolute { +- return match relocation.has_implicit_addend() { ++ return if relocation.has_implicit_addend() { + // Use the explicit addend too, because it may have the symbol value. +- true => value.wrapping_add(relocation.addend() as u64), +- false => relocation.addend() as u64, ++ value.wrapping_add(relocation.addend() as u64) ++ } else { ++ relocation.addend() as u64 + }; + } + }; +@@ -52,19 +54,19 @@ impl<'a, R: gimli::Reader> gimli::Reader for Relocate<'a, R> { + fn read_length(&mut self, format: gimli::Format) -> gimli::Result { + let offset = self.reader.offset_from(&self.section); + let value = self.reader.read_length(format)?; +- ::from_u64(self.relocate(offset, value as u64)) ++ gimli::ReaderOffset::from_u64(self.relocate(offset, value.into_u64())) + } + + fn read_offset(&mut self, format: gimli::Format) -> gimli::Result { + let offset = self.reader.offset_from(&self.section); + let value = self.reader.read_offset(format)?; +- ::from_u64(self.relocate(offset, value as u64)) ++ gimli::ReaderOffset::from_u64(self.relocate(offset, value.into_u64())) + } + + fn read_sized_offset(&mut self, size: u8) -> gimli::Result { + let offset = self.reader.offset_from(&self.section); + let value = self.reader.read_sized_offset(size)?; +- ::from_u64(self.relocate(offset, value as u64)) ++ gimli::ReaderOffset::from_u64(self.relocate(offset, value.into_u64())) + } + + #[inline] +diff --git a/upatch-build/src/elf/header.rs b/upatch-build/src/elf/header.rs +index ad9f8fd..a4c4ca8 100644 +--- a/upatch-build/src/elf/header.rs ++++ b/upatch-build/src/elf/header.rs +@@ -48,10 +48,6 @@ pub trait HeaderWrite: OperateWrite { + fn set_e_ident(&mut self, e_ident: u128) { + self.set(offset_of!(FileHeader64, e_ident), e_ident) + } +- +- fn set_e_shnum(&mut self, e_shnum: u16) { +- self.set(offset_of!(FileHeader64, e_shnum), e_shnum) +- } + } + + #[repr(C)] +diff --git a/upatch-build/src/elf/read/elfs.rs b/upatch-build/src/elf/read/elfs.rs +index 11d57e3..52c5e6b 100644 +--- a/upatch-build/src/elf/read/elfs.rs ++++ b/upatch-build/src/elf/read/elfs.rs +@@ -19,10 +19,10 @@ use anyhow::bail; + use anyhow::Result; + use memmap2::{Mmap, MmapOptions}; + +-use super::super::*; +-use super::Header; +-use super::SectionHeaderTable; +-use super::SymbolHeaderTable; ++use super::{ ++ super::{check_elf, check_header, Endian, HeaderRead, SectionRead, SymbolHeader64, SHT_SYMTAB}, ++ Header, SectionHeaderTable, SymbolHeaderTable, ++}; + + #[derive(Debug)] + pub struct Elf { +@@ -61,7 +61,7 @@ impl Elf { + + pub fn symbols(&self) -> Result { + let sections = self.sections()?; +- for section in sections { ++ for section in sections.clone() { + if section.get_sh_type().eq(&SHT_SYMTAB) { + let offset = section.get_sh_offset() as usize; + let size_sum = section.get_sh_size() as usize; +diff --git a/upatch-build/src/elf/read/section.rs b/upatch-build/src/elf/read/section.rs +index a12c4f3..8f79c8b 100644 +--- a/upatch-build/src/elf/read/section.rs ++++ b/upatch-build/src/elf/read/section.rs +@@ -44,7 +44,7 @@ impl OperateRead for SectionHeader<'_> { + } + } + +-#[derive(Debug, Clone, Copy)] ++#[derive(Debug, Clone)] + pub struct SectionHeaderTable<'a> { + mmap: &'a Mmap, + endian: Endian, +@@ -86,16 +86,13 @@ impl<'a> Iterator for SectionHeaderTable<'a> { + type Item = SectionHeader<'a>; + + fn next(&mut self) -> Option { +- match self.count < self.num { +- true => { +- let offset = self.count * self.size + self.offset; +- self.count += 1; +- Some(SectionHeader::from(self.mmap, self.endian, offset)) +- } +- false => { +- self.count = 0; +- None +- } ++ if self.count < self.num { ++ let offset = self.count * self.size + self.offset; ++ self.count += 1; ++ Some(SectionHeader::from(self.mmap, self.endian, offset)) ++ } else { ++ self.count = 0; ++ None + } + } + } +diff --git a/upatch-build/src/elf/read/symbol.rs b/upatch-build/src/elf/read/symbol.rs +index 70f03e1..0c05cb6 100644 +--- a/upatch-build/src/elf/read/symbol.rs ++++ b/upatch-build/src/elf/read/symbol.rs +@@ -99,9 +99,10 @@ impl<'a> SymbolHeaderTable<'a> { + } + + pub fn reset(&mut self, n: usize) { +- match n < self.num { +- true => self.count = n, +- false => self.count = 0, ++ if n < self.num { ++ self.count = n; ++ } else { ++ self.count = 0; + } + } + } +@@ -110,21 +111,18 @@ impl<'a> Iterator for SymbolHeaderTable<'a> { + type Item = SymbolHeader<'a>; + + fn next(&mut self) -> Option { +- match self.count < self.num { +- true => { +- let offset = self.count * self.size + self.offset; +- self.count += 1; +- Some(SymbolHeader::from( +- self.mmap, +- self.endian, +- self.strtab, +- offset, +- )) +- } +- false => { +- self.count = 0; +- None +- } ++ if self.count < self.num { ++ let offset = self.count * self.size + self.offset; ++ self.count += 1; ++ Some(SymbolHeader::from( ++ self.mmap, ++ self.endian, ++ self.strtab, ++ offset, ++ )) ++ } else { ++ self.count = 0; ++ None + } + } + } +diff --git a/upatch-build/src/elf/write/elfs.rs b/upatch-build/src/elf/write/elfs.rs +index e41ad0f..9ce2847 100644 +--- a/upatch-build/src/elf/write/elfs.rs ++++ b/upatch-build/src/elf/write/elfs.rs +@@ -15,11 +15,13 @@ + use std::fs::{File, OpenOptions}; + use std::path::Path; + +-use anyhow::{bail, Result}; ++use anyhow::{bail, Context, Result}; + use memmap2::{Mmap, MmapOptions}; + +-use super::super::*; +-use super::{Header, SectionHeader, SymbolHeaderTable}; ++use super::{ ++ super::{check_elf, check_header, Endian, HeaderRead, SectionRead, SymbolHeader64, SHT_SYMTAB}, ++ Header, SectionHeader, SymbolHeaderTable, ++}; + + #[derive(Debug)] + pub struct Elf { +@@ -88,7 +90,7 @@ impl Elf { + return Ok(SymbolHeaderTable::from( + &self.file, + self.endian, +- self.strtab.as_ref().unwrap(), ++ self.strtab.as_ref().context("Invalid strtab")?, + offset, + size, + offset + size_sum, +diff --git a/upatch-build/src/elf/write/symbol.rs b/upatch-build/src/elf/write/symbol.rs +index 5946897..0a2d08a 100644 +--- a/upatch-build/src/elf/write/symbol.rs ++++ b/upatch-build/src/elf/write/symbol.rs +@@ -38,13 +38,12 @@ impl<'a> SymbolHeader<'a> { + } + + pub fn get_st_name(&mut self) -> &OsStr { +- match self.name.is_empty() { +- false => <&std::ffi::OsStr>::clone(&self.name), +- true => { +- let name_offset = self.get_st_name_offset() as usize; +- self.name = self.read_to_os_string(name_offset); +- self.name +- } ++ if !self.name.is_empty() { ++ self.name ++ } else { ++ let name_offset = self.get_st_name_offset() as usize; ++ self.name = self.read_to_os_string(name_offset); ++ self.name + } + } + } +@@ -120,22 +119,19 @@ impl<'a> Iterator for SymbolHeaderTable<'a> { + + fn next(&mut self) -> Option { + let offset = self.count * self.size + self.start; +- match offset < self.end { +- true => { +- self.count += 1; +- let mmap = unsafe { +- MmapOptions::new() +- .offset(offset as u64) +- .len(self.size) +- .map_mut(self.file) +- .unwrap() +- }; +- Some(SymbolHeader::from(mmap, self.endian, self.strtab)) +- } +- false => { +- self.count = 0; +- None ++ if offset < self.end { ++ self.count += 1; ++ unsafe { ++ MmapOptions::new() ++ .offset(offset as u64) ++ .len(self.size) ++ .map_mut(self.file) ++ .ok() ++ .map(|mmap_mut| SymbolHeader::from(mmap_mut, self.endian, self.strtab)) + } ++ } else { ++ self.count = 0; ++ None + } + } + } +diff --git a/upatch-build/src/file_relation.rs b/upatch-build/src/file_relation.rs +index 5a58d04..eedd7d8 100644 +--- a/upatch-build/src/file_relation.rs ++++ b/upatch-build/src/file_relation.rs +@@ -60,14 +60,14 @@ impl FileRelation { + P: AsRef, + Q: AsRef, + { +- let mut binaries = binaries.into_iter(); +- let mut debuginfos = debuginfos.into_iter(); ++ let mut binary_iter = binaries.into_iter(); ++ let mut debuginfo_iter = debuginfos.into_iter(); + +- while let (Some(binary), Some(debuginfo)) = (binaries.next(), debuginfos.next()) { +- let binary = Self::find_binary_file(binary)?; +- let debuginfo = debuginfo.as_ref().to_path_buf(); ++ while let (Some(binary), Some(debuginfo)) = (binary_iter.next(), debuginfo_iter.next()) { ++ let binary_file = Self::find_binary_file(binary)?; ++ let debuginfo_file = debuginfo.as_ref().to_path_buf(); + +- self.debuginfo_map.insert(binary, debuginfo); ++ self.debuginfo_map.insert(binary_file, debuginfo_file); + } + + Ok(()) +diff --git a/upatch-build/src/main.rs b/upatch-build/src/main.rs +index 769cc6c..5aefd73 100644 +--- a/upatch-build/src/main.rs ++++ b/upatch-build/src/main.rs +@@ -333,9 +333,10 @@ impl UpatchBuild { + let binary_name = binary + .file_name() + .with_context(|| format!("Failed to parse binary name of {}", binary.display()))?; +- let patch_name = match name.is_empty() { +- true => binary_name.to_os_string(), +- false => concat_os!(name, "-", binary_name), ++ let patch_name = if name.is_empty() { ++ binary_name.to_os_string() ++ } else { ++ concat_os!(name, "-", binary_name) + }; + let output_file = build_info.output_dir.join(&patch_name); + +@@ -393,11 +394,10 @@ impl UpatchBuild { + .context("Patch test failed")?; + + info!("Checking debuginfo version(s)"); +- match self.args.skip_compiler_check { +- false => { +- Self::check_debuginfo(&compilers, debuginfos).context("Debuginfo check failed")?; +- } +- true => warn!("Warning: Skipped compiler version check!"), ++ if self.args.skip_compiler_check { ++ warn!("Warning: Skipped compiler version check!") ++ } else { ++ Self::check_debuginfo(&compilers, debuginfos).context("Debuginfo check failed")?; + } + + let mut files = FileRelation::new(); +diff --git a/upatch-build/src/pattern_path.rs b/upatch-build/src/pattern_path.rs +index 4ef86e1..f468620 100644 +--- a/upatch-build/src/pattern_path.rs ++++ b/upatch-build/src/pattern_path.rs +@@ -40,22 +40,18 @@ pub fn glob>(path: P) -> std::io::Result> { + let mut path_clone = vec![]; + for p in &mut pathes { + let tmp = p.join(components[i]); +- match tmp.exists() { +- true => path_clone.push(tmp), +- false => { +- let all_pathes = match i == (components.len() - 1) { +- true => { +- fs::list_files(&p, fs::TraverseOptions { recursive: false }) +- } +- false => { +- fs::list_dirs(&p, fs::TraverseOptions { recursive: false }) +- } +- }?; +- for name in find_name(components[i].as_os_str(), all_pathes)? { +- path_clone.push(p.join(name)); +- } ++ if tmp.exists() { ++ path_clone.push(tmp); ++ } else { ++ let all_pathes = if i == (components.len() - 1) { ++ fs::list_files(&p, fs::TraverseOptions { recursive: false }) ++ } else { ++ fs::list_dirs(&p, fs::TraverseOptions { recursive: false }) ++ }?; ++ for name in find_name(components[i].as_os_str(), all_pathes)? { ++ path_clone.push(p.join(name)); + } +- }; ++ } + } + pathes = path_clone; + } +diff --git a/upatch-build/src/resolve.rs b/upatch-build/src/resolve.rs +index 58947c0..d579901 100644 +--- a/upatch-build/src/resolve.rs ++++ b/upatch-build/src/resolve.rs +@@ -17,19 +17,19 @@ use std::path::Path; + use anyhow::Result; + use log::trace; + +-use crate::elf::*; ++use crate::elf::{self, HeaderRead, HeaderWrite, SymbolRead, SymbolWrite}; + + pub fn resolve_upatch(patch: Q, debuginfo: P) -> Result<()> + where + P: AsRef, + Q: AsRef, + { +- let mut patch_elf = write::Elf::parse(patch)?; +- let debuginfo_elf = read::Elf::parse(debuginfo)?; ++ let mut patch_elf = elf::write::Elf::parse(patch)?; ++ let debuginfo_elf = elf::read::Elf::parse(debuginfo)?; + + let debuginfo_e_ident = debuginfo_elf.header()?.get_e_ident(); + let debuginfo_e_type = debuginfo_elf.header()?.get_e_type(); +- let ei_osabi = elf_ei_osabi(debuginfo_e_ident); ++ let ei_osabi = elf::elf_ei_osabi(debuginfo_e_ident); + + patch_elf.header()?.set_e_ident(debuginfo_e_ident); + +@@ -37,28 +37,29 @@ where + + for mut symbol in &mut patch_elf.symbols()? { + /* No need to handle section symbol */ +- let sym_info = symbol.get_st_info(); +- if elf_st_type(sym_info) == STT_SECTION { ++ let sym_st_info = symbol.get_st_info(); ++ if elf::elf_st_type(sym_st_info) == elf::STT_SECTION { + continue; + } + + let sym_other = symbol.get_st_other(); +- if sym_other & SYM_OTHER != 0 { ++ if sym_other & elf::SYM_OTHER != 0 { + // TODO: we can delete these symbol's section here. +- symbol.set_st_other(sym_other & !SYM_OTHER); ++ symbol.set_st_other(sym_other & !elf::SYM_OTHER); + match symbol.get_st_value() { +- 0 => symbol.set_st_shndx(SHN_UNDEF), +- _ => symbol.set_st_shndx(SHN_LIVEPATCH), ++ 0 => symbol.set_st_shndx(elf::SHN_UNDEF), ++ _ => symbol.set_st_shndx(elf::SHN_LIVEPATCH), + }; +- } else if symbol.get_st_shndx() == SHN_UNDEF { +- if elf_st_bind(sym_info) == STB_LOCAL { ++ } else if symbol.get_st_shndx() == elf::SHN_UNDEF { ++ if elf::elf_st_bind(sym_st_info) == elf::STB_LOCAL { + /* only partly resolved undefined symbol could have st_value */ + if symbol.get_st_value() != 0 { +- symbol.set_st_shndx(SHN_LIVEPATCH); ++ symbol.set_st_shndx(elf::SHN_LIVEPATCH); + } + } else { + __partial_resolve_patch(&mut symbol, debuginfo_syms, ei_osabi)?; + } ++ } else { /* do nothing */ + } + + /* +@@ -66,21 +67,20 @@ where + * Such code accesses all constant addresses through a global offset table (GOT). + * TODO: consider check PIE + */ +- let sym_info = symbol.get_st_info(); +- if debuginfo_e_type == ET_DYN +- && elf_st_bind(sym_info) == STB_GLOBAL +- && elf_st_type(sym_info) == STT_OBJECT +- && symbol.get_st_shndx() == SHN_LIVEPATCH ++ if debuginfo_e_type == elf::ET_DYN ++ && elf::elf_st_bind(sym_st_info) == elf::STB_GLOBAL ++ && elf::elf_st_type(sym_st_info) == elf::STT_OBJECT ++ && symbol.get_st_shndx() == elf::SHN_LIVEPATCH + { +- symbol.set_st_shndx(SHN_UNDEF); ++ symbol.set_st_shndx(elf::SHN_UNDEF); + } + } + Ok(()) + } + + fn __partial_resolve_patch( +- symbol: &mut write::SymbolHeader, +- debuginfo_syms: &mut read::SymbolHeaderTable, ++ symbol: &mut elf::write::SymbolHeader, ++ debuginfo_syms: &mut elf::read::SymbolHeaderTable, + ei_osabi: u8, + ) -> Result<()> { + debuginfo_syms.reset(0); +@@ -88,28 +88,29 @@ fn __partial_resolve_patch( + for debuginfo_sym in debuginfo_syms { + /* No need to handle section symbol */ + let sym_info = debuginfo_sym.get_st_info(); +- if elf_st_type(sym_info) == STT_SECTION { ++ if elf::elf_st_type(sym_info) == elf::STT_SECTION { + continue; + } + + let debuginfo_name = debuginfo_sym.get_st_name(); +- if elf_st_bind(sym_info).ne(&elf_st_bind(symbol.get_st_info())) ++ if elf::elf_st_bind(sym_info).ne(&elf::elf_st_bind(symbol.get_st_info())) + || debuginfo_name.ne(symbol.get_st_name()) + { + continue; + } + + /* leave it to be handled in running time */ +- if debuginfo_sym.get_st_shndx() == SHN_UNDEF { ++ if debuginfo_sym.get_st_shndx() == elf::SHN_UNDEF { + continue; + } + + // symbol type is STT_IFUNC, need search st_value in .plt table in upatch. +- let is_ifunc = (ei_osabi.eq(&ELFOSABI_GNU) || ei_osabi.eq(&ELFOSABI_FREEBSD)) +- && elf_st_type(sym_info).eq(&STT_IFUNC); +- symbol.set_st_shndx(match is_ifunc { +- true => SHN_UNDEF, +- false => SHN_LIVEPATCH, ++ let is_ifunc = (ei_osabi.eq(&elf::ELFOSABI_GNU) || ei_osabi.eq(&elf::ELFOSABI_FREEBSD)) ++ && elf::elf_st_type(sym_info).eq(&elf::STT_IFUNC); ++ symbol.set_st_shndx(if is_ifunc { ++ elf::SHN_UNDEF ++ } else { ++ elf::SHN_LIVEPATCH + }); + symbol.set_st_info(sym_info); + symbol.set_st_other(debuginfo_sym.get_st_other()); +@@ -131,17 +132,17 @@ fn __partial_resolve_patch( + * then we can't match these symbols, we change these symbols to GLOBAL here. + */ + pub fn resolve_dynamic>(debuginfo: P) -> Result<()> { +- let mut debuginfo_elf = write::Elf::parse(debuginfo)?; ++ let mut debuginfo_elf = elf::write::Elf::parse(debuginfo)?; + let debuginfo_header = debuginfo_elf.header()?; + +- if debuginfo_header.get_e_type().ne(&ET_DYN) { ++ if debuginfo_header.get_e_type().ne(&elf::ET_DYN) { + return Ok(()); + } + + let mut debuginfo_symbols = debuginfo_elf.symbols()?; + + for mut symbol in &mut debuginfo_symbols { +- if elf_st_type(symbol.get_st_info()).ne(&STT_FILE) { ++ if elf::elf_st_type(symbol.get_st_info()).ne(&elf::STT_FILE) { + continue; + } + +@@ -154,23 +155,23 @@ pub fn resolve_dynamic>(debuginfo: P) -> Result<()> { + Ok(()) + } + +-fn _resolve_dynamic(debuginfo_symbols: &mut write::SymbolHeaderTable) -> Result<()> { ++fn _resolve_dynamic(debuginfo_symbols: &mut elf::write::SymbolHeaderTable) -> Result<()> { + for mut symbol in debuginfo_symbols { +- if elf_st_type(symbol.get_st_info()).eq(&STT_FILE) { ++ if elf::elf_st_type(symbol.get_st_info()).eq(&elf::STT_FILE) { + break; + } + +- let info = symbol.get_st_info(); +- if elf_st_bind(info).ne(&STB_GLOBAL) { ++ let st_info = symbol.get_st_info(); ++ if elf::elf_st_bind(st_info).ne(&elf::STB_GLOBAL) { + let symbol_name = symbol.get_st_name(); + trace!( + "resolve_dynamic: set {} bind {} to 1", + symbol_name.to_string_lossy(), +- elf_st_bind(info) ++ elf::elf_st_bind(st_info) + ); + +- let info = elf_st_type(symbol.get_st_info()) | (STB_GLOBAL << 4); +- symbol.set_st_info(info); ++ let new_st_info = elf::elf_st_type(st_info) | (elf::STB_GLOBAL << 4); ++ symbol.set_st_info(new_st_info); + } + } + Ok(()) +diff --git a/upatch-build/src/rpc/remote.rs b/upatch-build/src/rpc/remote.rs +index 9927ece..52ea6a3 100644 +--- a/upatch-build/src/rpc/remote.rs ++++ b/upatch-build/src/rpc/remote.rs +@@ -54,27 +54,22 @@ impl RpcRemote { + impl RpcRemote { + fn parse_error(&self, error: Error) -> anyhow::Error { + match error { +- Error::Transport(e) => { ++ Error::Transport(err) => { + anyhow!( + "Cannot connect to upatch daemon at unix://{}, {}", + self.socket.display(), +- e.source() ++ err.source() + .map(|e| e.to_string()) + .unwrap_or_else(|| "Connection timeout".to_string()) + ) + } +- Error::Json(e) => { +- debug!("Json parse error: {:?}", e); ++ Error::Json(err) => { ++ debug!("Json parse error: {:?}", err); + anyhow!("Failed to parse response") + } +- Error::Rpc(ref e) => match e.message == "Method not found" { +- true => { +- anyhow!("Method is unimplemented") +- } +- false => { +- anyhow!("{}", e.message) +- } +- }, ++ Error::Rpc(err) => { ++ anyhow!("{}", err.message) ++ } + _ => { + debug!("{:?}", error); + anyhow!("Response is invalid") +diff --git a/upatchd/build.rs b/upatchd/build.rs +index 3809c54..6ddb941 100644 +--- a/upatchd/build.rs ++++ b/upatchd/build.rs +@@ -12,26 +12,25 @@ + * See the Mulan PSL v2 for more details. + */ + +-use std::{env, process::Command}; ++use std::{env, ffi::OsStr, os::unix::ffi::OsStrExt, process::Command}; + + fn rewrite_version() { +- const ENV_VERSION_NAME: &str = "BUILD_VERSION"; +- const PKG_VERSION_NAME: &str = "CARGO_PKG_VERSION"; ++ const PKG_VERSION: &str = env!("CARGO_PKG_VERSION"); ++ const ENV_VERSION: Option<&str> = option_env!("BUILD_VERSION"); + +- let version = env::var(ENV_VERSION_NAME).unwrap_or_else(|_| { +- let pkg_version = env::var(PKG_VERSION_NAME).expect("Failed to fetch package version"); +- let git_output = Command::new("git") +- .args(["rev-parse", "--short", "HEAD"]) +- .output() +- .map(|output| String::from_utf8(output.stdout).expect("Failed to fetch git version")); +- +- match git_output { +- Ok(git_version) => format!("{}-g{}", pkg_version, git_version), +- Err(_) => pkg_version, +- } +- }); +- +- println!("cargo:rustc-env={}={}", PKG_VERSION_NAME, version); ++ println!( ++ "cargo:rustc-env=CARGO_PKG_VERSION={}", ++ ENV_VERSION.map(String::from).unwrap_or_else(|| { ++ Command::new("git") ++ .args(["rev-parse", "--short", "HEAD"]) ++ .output() ++ .map(|output| { ++ let git_version = OsStr::from_bytes(&output.stdout).to_string_lossy(); ++ format!("{}-g{}", PKG_VERSION, git_version) ++ }) ++ .unwrap_or_else(|_| PKG_VERSION.to_string()) ++ }) ++ ); + } + + fn main() { +diff --git a/upatchd/src/helper/elf_resolver.rs b/upatchd/src/helper/elf_resolver.rs +index 9b62b00..c6e5e9f 100644 +--- a/upatchd/src/helper/elf_resolver.rs ++++ b/upatchd/src/helper/elf_resolver.rs +@@ -44,8 +44,8 @@ impl ElfResolver<'_> { + let lines = output.stdout.lines(); + for line in lines { + let words = line.split_whitespace().collect::>(); +- if let Some(path) = words.get(2) { +- if let Ok(path) = fs::canonicalize(path) { ++ if let Some(lib_path) = words.get(2) { ++ if let Ok(path) = fs::canonicalize(lib_path) { + paths.push(path); + } + } +diff --git a/upatchd/src/helper/ioctl.rs b/upatchd/src/helper/ioctl.rs +index 0efbab4..4002c3a 100644 +--- a/upatchd/src/helper/ioctl.rs ++++ b/upatchd/src/helper/ioctl.rs +@@ -46,6 +46,7 @@ pub struct UpatchEnableRequest { + offset: u64, + } + ++#[repr(C)] + pub struct UpatchRegisterRequest { + exec_path: [u8; PATH_MAX as usize], + jump_path: [u8; PATH_MAX as usize], +diff --git a/upatchd/src/main.rs b/upatchd/src/main.rs +index 8141679..f73be0e 100644 +--- a/upatchd/src/main.rs ++++ b/upatchd/src/main.rs +@@ -117,9 +117,10 @@ impl Daemon { + + // Initialize logger + let max_level = args.log_level; +- let stdout_level = match args.daemon { +- true => LevelFilter::Off, +- false => max_level, ++ let stdout_level = if args.daemon { ++ LevelFilter::Off ++ } else { ++ max_level + }; + let log_spec = LogSpecification::builder().default(max_level).build(); + let file_spec = FileSpec::default() +@@ -199,9 +200,10 @@ impl Daemon { + + fs::set_permissions( + &socket_file, +- match socket_owner.as_raw() == socket_group.as_raw() { +- true => Permissions::from_mode(SOCKET_FILE_PERM_STRICT), +- false => Permissions::from_mode(SOCKET_FILE_PERM), ++ if socket_owner.as_raw() == socket_group.as_raw() { ++ Permissions::from_mode(SOCKET_FILE_PERM_STRICT) ++ } else { ++ Permissions::from_mode(SOCKET_FILE_PERM) + }, + )?; + +-- +2.34.1 + diff --git a/0035-syscare-abi-remove-display-limit-of-patch_info.patch b/0035-syscare-abi-remove-display-limit-of-patch_info.patch new file mode 100644 index 0000000000000000000000000000000000000000..fe5c6c9dcb6f69a6fda18b928a7bac10b6a1af17 --- /dev/null +++ b/0035-syscare-abi-remove-display-limit-of-patch_info.patch @@ -0,0 +1,62 @@ +From ee2c289262c2677abb57d41534b927fc755d86e8 Mon Sep 17 00:00:00 2001 +From: Zhao Mengmeng +Date: Mon, 17 Jun 2024 16:18:20 +0800 +Subject: [PATCH] syscare-abi: remove display limit of patch_info + +When executing with `syscare info xxx`, show all the patches +it contains. + +Signed-off-by: Zhao Mengmeng +--- + syscare-abi/src/patch_info.rs | 21 +++------------------ + 1 file changed, 3 insertions(+), 18 deletions(-) + +diff --git a/syscare-abi/src/patch_info.rs b/syscare-abi/src/patch_info.rs +index 659755d..65f7664 100644 +--- a/syscare-abi/src/patch_info.rs ++++ b/syscare-abi/src/patch_info.rs +@@ -69,8 +69,6 @@ impl PatchInfo { + + impl std::fmt::Display for PatchInfo { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +- const LIST_DISPLAY_LIMIT: usize = 9; +- + writeln!(f, "name: {}", self.name)?; + writeln!(f, "version: {}", self.version)?; + writeln!(f, "release: {}", self.release)?; +@@ -82,10 +80,6 @@ impl std::fmt::Display for PatchInfo { + if !self.entities.is_empty() { + writeln!(f, "entities:")?; + for (entity_idx, entity) in self.entities.iter().enumerate() { +- if entity_idx >= LIST_DISPLAY_LIMIT { +- writeln!(f, "* ......")?; +- break; +- } + writeln!(f, "* {}", entity.patch_name.to_string_lossy())?; + } + } +@@ -94,18 +88,9 @@ impl std::fmt::Display for PatchInfo { + writeln!(f, "patches:")?; + let last_idx = self.patches.len() - 1; + for (patch_idx, patch_file) in self.patches.iter().enumerate() { +- if patch_idx != last_idx { +- if patch_idx >= LIST_DISPLAY_LIMIT { +- writeln!(f, "* ......")?; +- break; +- } +- writeln!(f, "* {}", patch_file.name.to_string_lossy())? +- } else { +- if patch_idx >= LIST_DISPLAY_LIMIT { +- write!(f, "* ......")?; +- break; +- } +- write!(f, "* {}", patch_file.name.to_string_lossy())? ++ match patch_idx == last_idx { ++ false => writeln!(f, "* {}", patch_file.name.to_string_lossy())?, ++ true => write!(f, "* {}", patch_file.name.to_string_lossy())?, + } + } + } +-- +2.34.1 + diff --git a/0036-syscare-abi-fix-clippy-warnings.patch b/0036-syscare-abi-fix-clippy-warnings.patch new file mode 100644 index 0000000000000000000000000000000000000000..e2647b1028da360569a7639869901e6d32f7cd93 --- /dev/null +++ b/0036-syscare-abi-fix-clippy-warnings.patch @@ -0,0 +1,49 @@ +From 855794af7d0b932a704b1498a30e7c7f9d009eeb Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Sat, 29 Jun 2024 17:03:30 +0800 +Subject: [PATCH] syscare-abi: fix clippy warnings + +Signed-off-by: renoseven +--- + syscare-abi/src/patch_info.rs | 24 ++++++++++-------------- + 1 file changed, 10 insertions(+), 14 deletions(-) + +diff --git a/syscare-abi/src/patch_info.rs b/syscare-abi/src/patch_info.rs +index 65f7664..9108a89 100644 +--- a/syscare-abi/src/patch_info.rs ++++ b/syscare-abi/src/patch_info.rs +@@ -77,21 +77,17 @@ impl std::fmt::Display for PatchInfo { + writeln!(f, "target: {}", self.target.short_name())?; + writeln!(f, "license: {}", self.target.license)?; + writeln!(f, "description: {}", self.description)?; +- if !self.entities.is_empty() { +- writeln!(f, "entities:")?; +- for (entity_idx, entity) in self.entities.iter().enumerate() { +- writeln!(f, "* {}", entity.patch_name.to_string_lossy())?; +- } ++ writeln!(f, "entities:")?; ++ for entity in &self.entities { ++ writeln!(f, "* {}", entity.patch_name.to_string_lossy())?; + } +- +- if !self.patches.is_empty() { +- writeln!(f, "patches:")?; +- let last_idx = self.patches.len() - 1; +- for (patch_idx, patch_file) in self.patches.iter().enumerate() { +- match patch_idx == last_idx { +- false => writeln!(f, "* {}", patch_file.name.to_string_lossy())?, +- true => write!(f, "* {}", patch_file.name.to_string_lossy())?, +- } ++ writeln!(f, "patches:")?; ++ let last_idx = self.patches.len() - 1; ++ for (idx, patch) in self.patches.iter().enumerate() { ++ if idx == last_idx { ++ write!(f, "* {}", patch.name.to_string_lossy())? ++ } else { ++ writeln!(f, "* {}", patch.name.to_string_lossy())? + } + } + +-- +2.34.1 + diff --git a/generate_package.sh b/generate_package.sh index b9b3c407a8a486c31e502825b1b6969a1a32d64d..07c0d87468c5ab5c98976e9fe90256598fc9b09b 100755 --- a/generate_package.sh +++ b/generate_package.sh @@ -19,7 +19,7 @@ echo "Checking out dest branch..." git checkout "$REPO_BRANCH" echo "Vendoring dependencies..." -cargo vendor --respect-source-config --sync upatch/Cargo.toml +cargo vendor --respect-source-config --sync Cargo.toml mkdir -p .cargo cat << EOF > .cargo/config.toml diff --git a/syscare-1.2.0.tar.gz b/syscare-1.2.1.tar.gz similarity index 70% rename from syscare-1.2.0.tar.gz rename to syscare-1.2.1.tar.gz index d2f5be22dff5b930928823d3b98e6395b0f36670..616f843d63e0d3623da168d9c2a4b2bce16a9901 100644 Binary files a/syscare-1.2.0.tar.gz and b/syscare-1.2.1.tar.gz differ diff --git a/syscare.spec b/syscare.spec index fca58152c47938602458a33e486883514acccfb4..daff8f1b6d64f0887e6cd199d6abe7ef2a9a55f6 100644 --- a/syscare.spec +++ b/syscare.spec @@ -1,29 +1,59 @@ %define build_version %{version}-%{release} %define kernel_devel_rpm %(echo $(rpm -q kernel-devel | head -n 1)) -%define kernel_version %(echo $(rpm -q --qf "\%%{VERSION}" %{kernel_devel_rpm})) %define kernel_name %(echo $(rpm -q --qf "\%%{VERSION}-\%%{RELEASE}.\%%{ARCH}" %{kernel_devel_rpm})) -%define pkg_kmod %{name}-kmod -%define pkg_build %{name}-build -%define pkg_build_kmod %{pkg_build}-kmod -%define pkg_build_ebpf %{pkg_build}-ebpf - ############################################ ############ Package syscare ############### ############################################ Name: syscare -Version: 1.2.0 -Release: 10 +Version: 1.2.1 +Release: 9 Summary: System hot-fix service License: MulanPSL-2.0 and GPL-2.0-only URL: https://gitee.com/openeuler/syscare Source0: %{name}-%{version}.tar.gz -Patch0001: 0001-upatch-fix-memory-leak.patch +Patch0001: 0001-upatch-hijacker-fix-compile-bug.patch +Patch0002: 0002-daemon-fix-cannot-get-file-selinux-xattr-when-selinu.patch +Patch0003: 0003-syscared-fix-syscare-check-command-does-not-check-sy.patch +Patch0004: 0004-syscared-fix-cannot-find-process-of-dynlib-patch-iss.patch +Patch0005: 0005-syscared-optimize-patch-error-logic.patch +Patch0006: 0006-syscared-optimize-transaction-creation-logic.patch +Patch0007: 0007-upatch-manage-optimize-output.patch +Patch0008: 0008-common-impl-CStr-from_bytes_with_next_nul.patch +Patch0009: 0009-syscared-improve-patch-management.patch +Patch0010: 0010-syscared-stop-activating-ignored-process-on-new-proc.patch +Patch0011: 0011-syscared-adapt-upatch-manage-exit-code-change.patch +Patch0012: 0012-upatch-manage-change-exit-code.patch +Patch0013: 0013-upatch-manage-change-the-way-to-calculate-frozen-tim.patch +Patch0014: 0014-upatch-build-fix-file-detection-cause-build-failure-.patch +Patch0015: 0015-upatch-diff-optimize-log-output.patch +Patch0016: 0016-security-change-directory-permission.patch +Patch0017: 0017-security-change-daemon-socket-permission.patch +Patch0018: 0018-upatch-manage-Fixed-the-core-dump-issue-after-applyi.patch +Patch0019: 0019-upatch-diff-fix-lookup_relf-failed-issue.patch +Patch0020: 0020-upatch-diff-only-check-changed-file-symbols.patch +Patch0021: 0021-upatch-diff-remove-rela-check-while-build-rebuilding.patch +Patch0022: 0022-syscared-fix-apply-kernel-module-patch-failure-issue.patch +Patch0023: 0023-all-finding-executable-from-environment-variables.patch +Patch0024: 0024-all-remove-redundant-code.patch +Patch0025: 0025-all-add-c-rust-compilation-options.patch +Patch0026: 0026-common-fix-failed-to-set-selinux-status-issue.patch +Patch0027: 0027-upatch-diff-exit-with-error-when-any-tls-var-include.patch +Patch0028: 0028-upatch-diff-fix-lookup_relf-duplicate-failure.patch +Patch0029: 0029-upatch-diff-fix-memory-leak.patch +Patch0030: 0030-upatch-hijacker-fix-memory-leak.patch +Patch0031: 0031-upatch-manage-fix-memory-leak.patch +Patch0032: 0032-security-sanitize-sensitive-code.patch +Patch0033: 0033-all-implement-asan-gcov-build-type.patch +Patch0034: 0034-all-clean-code.patch +Patch0035: 0035-syscare-abi-remove-display-limit-of-patch_info.patch +Patch0036: 0036-syscare-abi-fix-clippy-warnings.patch BuildRequires: cmake >= 3.14 make BuildRequires: rust >= 1.51 cargo >= 1.51 BuildRequires: gcc gcc-c++ +BuildRequires: kernel-devel Requires: coreutils systemd Requires: kpatch-runtime @@ -54,9 +84,6 @@ make cd build %make_install -mkdir -p %{buildroot}/lib/modules/%{kernel_name}/extra/syscare -mv -f %{buildroot}/usr/libexec/syscare/upatch_hijacker.ko %{buildroot}/lib/modules/%{kernel_name}/extra/syscare - ############### PostInstall ################ %post mkdir -p /usr/lib/syscare/patches @@ -94,12 +121,12 @@ fi ################## Files ################### %files -%defattr(-,root,root,-) +%defattr(-,root,root,0555) %dir /usr/libexec/syscare -%attr(644,root,root) /usr/lib/systemd/system/syscare.service -%attr(755,root,root) /usr/bin/syscared -%attr(755,root,root) /usr/bin/syscare -%attr(755,root,root) /usr/libexec/syscare/upatch-manage +%attr(0555,root,root) /usr/bin/syscare +%attr(0550,root,root) /usr/bin/syscared +%attr(0550,root,root) /usr/lib/systemd/system/syscare.service +%attr(0550,root,root) /usr/libexec/syscare/upatch-manage ############################################ ########## Package syscare-build ########### @@ -107,8 +134,6 @@ fi %package build Summary: Syscare build tools. BuildRequires: elfutils-libelf-devel -Suggests: %{pkg_build_kmod} -Requires: (%{pkg_build_kmod} >= %{build_version} or %{pkg_build_ebpf} >= %{build_version}) Requires: coreutils Requires: patch Requires: kpatch @@ -153,82 +178,75 @@ fi ################## Files ################### %files build -%defattr(-,root,root,-) +%defattr(-,root,root,0555) %dir /usr/libexec/syscare -%attr(644,root,root) /usr/lib/systemd/system/upatch.service -%attr(755,root,root) /usr/bin/upatchd -%attr(755,root,root) /usr/libexec/syscare/syscare-build -%attr(755,root,root) /usr/libexec/syscare/upatch-build -%attr(755,root,root) /usr/libexec/syscare/upatch-diff -%attr(755,root,root) /usr/libexec/syscare/as-hijacker -%attr(755,root,root) /usr/libexec/syscare/cc-hijacker -%attr(755,root,root) /usr/libexec/syscare/c++-hijacker -%attr(755,root,root) /usr/libexec/syscare/gcc-hijacker -%attr(755,root,root) /usr/libexec/syscare/g++-hijacker - -############################################ -######## Package syscare-build-kmod ######## -############################################ -%package build-kmod -Summary: Kernel module for syscare patch build tools. -BuildRequires: make gcc -BuildRequires: kernel-devel -Requires: kernel >= %{kernel_version} - -############### Description ################ -%description build-kmod -Syscare build dependency - kernel module. - -############### PostInstall ################ -%post build-kmod -echo "/lib/modules/%{kernel_name}/extra/syscare/upatch_hijacker.ko" | /sbin/weak-modules --add-module --no-initramfs -depmod > /dev/null 2>&1 - -############### PreUninstall ############### -%preun build-kmod -# Nothing - -############## PostUninstall ############### -%postun build-kmod -echo "/lib/modules/%{kernel_name}/extra/syscare/upatch_hijacker.ko" | /sbin/weak-modules --remove-module --no-initramfs -depmod > /dev/null 2>&1 - -################## Files ################### -%files build-kmod -%dir /lib/modules/%{kernel_name}/extra/syscare -%attr(640,root,root) /lib/modules/%{kernel_name}/extra/syscare/upatch_hijacker.ko - -############################################ -######## Package syscare-build-ebpf ######## -############################################ -%package build-ebpf -Summary: eBPF for syscare patch build tools. -BuildRequires: make llvm clang bpftool -BuildRequires: libbpf libbpf-devel libbpf-static - -############### Description ################ -%description build-ebpf -Syscare build dependency - eBPF. - -############### PostInstall ################ -%post build-ebpf - -############### PreUninstall ############### -%preun build-ebpf -# Nothing - -############## PostUninstall ############### -%postun build-ebpf -# Nothing - -################## Files ################### -%files build-ebpf -%attr(755,root,root) /usr/libexec/syscare/upatch_hijacker +%attr(550,root,root) /usr/bin/upatchd +%attr(555,root,root) /usr/libexec/syscare/syscare-build +%attr(555,root,root) /usr/libexec/syscare/upatch-build +%attr(555,root,root) /usr/libexec/syscare/upatch-diff +%attr(555,root,root) /usr/libexec/syscare/as-helper +%attr(555,root,root) /usr/libexec/syscare/cc-helper +%attr(555,root,root) /usr/libexec/syscare/c++-helper +%attr(555,root,root) /usr/libexec/syscare/gcc-helper +%attr(555,root,root) /usr/libexec/syscare/g++-helper +%attr(555,root,root) /usr/libexec/syscare/gnu-as-helper +%attr(555,root,root) /usr/libexec/syscare/gnu-compiler-helper +%attr(440,root,root) /usr/libexec/syscare/upatch_helper.ko +%attr(550,root,root) /usr/lib/systemd/system/upatch.service ############################################ ################ Change log ################ ############################################ %changelog +* Mon Jul 1 2024 renoseven - 1.2.1-9 +- abi: remove display limit of patch info +- all: clean code +- all: implement asan gcov build type +- security: sanitize sensitive code +- upatch-manage: fix memory leak +- upatch-helper: fix memory leak +- upatch-diff: fix memory leak +- upatch-diff: fix find duplicate symbol issue +- upatch-diff: prevent tls variable modification +- common: fix failed to set selinux status issue +- all: add compile options +- all: remove redundant code +- all: finding executable from environment variables +* Mon May 20 2024 ningyu - 1.2.1-8 +- syscared: fix apply kernel module patch failure issue +* Tue May 14 2024 ningyu - 1.2.1-7 +- upatch-diff: remove rela check while build rebuilding .eh_frame +- upatch-diff: only check changed file symbols +* Sat May 11 2024 renoseven - 1.2.1-6 +- upatch-diff: fix 'lookup_elf failed' issue +- upatch-manage: fixed the core dump issue after applying hot patches to nginx on x86_64 architecture +- security: change daemon socket permission +- security: change directory permission +- upatch-build: fix 'file detection cause build failure' issue +- syscared: stop activating ignored process on new process start +* Mon May 6 2024 Peng Haitao - 1.2.1-5 +- add BuildRequires: kernel-devel +* Fri Apr 19 2024 ningyu - 1.2.1-4 +- syscared: stop activating ignored process on new process start +- syscared: adapt upatch-manage exit code change +- upatch-manage: change exit code +- upatch-manage: change the way to calculate frozen time +* Fri Apr 12 2024 ningyu - 1.2.1-3 +- upatch-hijacker: fix compile bug +- daemon: fix 'cannot get file selinux xattr when selinux is not enforcing' issue +- syscared: fix 'syscare check command does not check symbol confiliction' issue +- syscared: fix 'cannot find process of dynlib patch' issue +- Change uuid type from string to uuid bytes +- syscared: optimize patch error logic +- syscared: optimize transaction creation logic +- upatch-manage: optimize output +- syscared: optimize patch error logic +- syscared: optimize transaction creation logic +- spec: fix "cannot find syscare service after upgrade" bug +* Sun Apr 7 2024 ningyu - 1.2.1-2 +- update to syscare.1.2.1-2 +* Thu Mar 28 2024 ningyu - 1.2.1-1 +- update to 1.2.1 * Tue Dec 26 2023 ningyu - 1.2.0-10 - fix memory leak * Fri Dec 22 2023 ningyu - 1.2.0-9