diff --git a/0001-upatch-hijacker-fix-compile-bug.patch b/0001-upatch-hijacker-fix-compile-bug.patch deleted file mode 100644 index 8c3af45c79decb347e3bf5485039de1812aaa497..0000000000000000000000000000000000000000 --- a/0001-upatch-hijacker-fix-compile-bug.patch +++ /dev/null @@ -1,33 +0,0 @@ -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 01/20] 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 deleted file mode 100644 index ff84d01ca69db41d66d592bb1c5ff5c3380dc58e..0000000000000000000000000000000000000000 --- a/0002-daemon-fix-cannot-get-file-selinux-xattr-when-selinu.patch +++ /dev/null @@ -1,219 +0,0 @@ -From a535e14a7db49df3c8aab017e32b92d8e5bb4087 Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Wed, 10 Apr 2024 10:25:21 +0800 -Subject: [PATCH 02/20] 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 deleted file mode 100644 index 754ca307d0daa241c7638f37562e20a250528c71..0000000000000000000000000000000000000000 --- a/0003-syscared-fix-syscare-check-command-does-not-check-sy.patch +++ /dev/null @@ -1,385 +0,0 @@ -From e5294afa8135f54f44196bd92e5a32c2b09b9bda Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Wed, 10 Apr 2024 12:19:51 +0800 -Subject: [PATCH 03/20] 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 deleted file mode 100644 index 317e96c3c4111638762f5775ef1c43f1c602eec0..0000000000000000000000000000000000000000 --- a/0004-syscared-fix-cannot-find-process-of-dynlib-patch-iss.patch +++ /dev/null @@ -1,687 +0,0 @@ -From 32c3d16175b93627504981d05a1a3e3ec603415e Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Wed, 10 Apr 2024 19:30:56 +0800 -Subject: [PATCH 04/20] 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 deleted file mode 100644 index 6449175801a8829f37dd2c2294653a53578e3982..0000000000000000000000000000000000000000 --- a/0005-syscared-optimize-patch-error-logic.patch +++ /dev/null @@ -1,103 +0,0 @@ -From a61958c837b70c0c530d32ee58b616ab9ad01f4b Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Fri, 12 Apr 2024 11:35:57 +0800 -Subject: [PATCH 05/20] 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 deleted file mode 100644 index e665a269289cbec01c2d6ba1538143f711543c8c..0000000000000000000000000000000000000000 --- a/0006-syscared-optimize-transaction-creation-logic.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 211e4549324a9209dc982b7426af8b832410b619 Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Fri, 12 Apr 2024 11:40:25 +0800 -Subject: [PATCH 06/20] 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 deleted file mode 100644 index f472d10be03830e08e2f979b9194a86721057b5b..0000000000000000000000000000000000000000 --- a/0007-upatch-manage-optimize-output.patch +++ /dev/null @@ -1,136 +0,0 @@ -From a32e9f39965579064dbd504246f13c6431ffed33 Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Fri, 12 Apr 2024 11:50:59 +0800 -Subject: [PATCH 07/20] 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 deleted file mode 100644 index a19298859e409fae369088ba046dd943d56b197b..0000000000000000000000000000000000000000 --- a/0008-common-impl-CStr-from_bytes_with_next_nul.patch +++ /dev/null @@ -1,47 +0,0 @@ -From cc090b31139bb9aa0158e50a8a620fc41b23231c Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Tue, 16 Apr 2024 12:44:11 +0800 -Subject: [PATCH 08/20] 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 deleted file mode 100644 index d2656cf10421bc7dd9f2858e6e3d7cef58dedff8..0000000000000000000000000000000000000000 --- a/0009-syscared-improve-patch-management.patch +++ /dev/null @@ -1,2319 +0,0 @@ -From 354e0888188d4cabd9fff9912fa0935e4e1b4b52 Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Tue, 16 Apr 2024 14:20:27 +0800 -Subject: [PATCH 09/20] 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 deleted file mode 100644 index eb956a91b6f85c0d7261e95659279f04ea5139d0..0000000000000000000000000000000000000000 --- a/0010-syscared-stop-activating-ignored-process-on-new-proc.patch +++ /dev/null @@ -1,237 +0,0 @@ -From a83410a74713c4f191aeb31bc9ea87b9e9f4bcc6 Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Wed, 17 Apr 2024 19:14:19 +0800 -Subject: [PATCH 10/20] 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 deleted file mode 100644 index 5eaacbd54facfb1219cefaa0f55ed1fb7eab7698..0000000000000000000000000000000000000000 --- a/0011-syscared-adapt-upatch-manage-exit-code-change.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 4ad0b0369cd039b64635d2c405fa244b6c6afb59 Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Fri, 19 Apr 2024 12:02:23 +0800 -Subject: [PATCH 11/20] 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 deleted file mode 100644 index ea511b323bc6f943bd78e6a4db3f246b4b3ffd7b..0000000000000000000000000000000000000000 --- a/0012-upatch-manage-change-exit-code.patch +++ /dev/null @@ -1,446 +0,0 @@ -From e04ce4a7539a469091fef8c1566a85fe6050f728 Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Fri, 19 Apr 2024 12:01:38 +0800 -Subject: [PATCH 12/20] 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 deleted file mode 100644 index 471cb6ea46adf59f844d8f9ffa387e3bf21e6355..0000000000000000000000000000000000000000 --- a/0013-upatch-manage-change-the-way-to-calculate-frozen-tim.patch +++ /dev/null @@ -1,140 +0,0 @@ -From ff07e664cb475fa74b4f6531d8e709a5dd9b55dd Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Fri, 19 Apr 2024 14:19:27 +0800 -Subject: [PATCH 13/20] 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-abi-change-uuid-string-to-uuid-bytes.patch b/0014-abi-change-uuid-string-to-uuid-bytes.patch deleted file mode 100644 index 44273ddc723e5113ecae82cf0d72eec88224f8ac..0000000000000000000000000000000000000000 --- a/0014-abi-change-uuid-string-to-uuid-bytes.patch +++ /dev/null @@ -1,224 +0,0 @@ -From c2fc4243ed918717bbcaa4a0c1b400051c7eded7 Mon Sep 17 00:00:00 2001 -From: ningyu -Date: Tue, 9 Apr 2024 09:21:35 +0000 -Subject: [PATCH 14/20] abi: change uuid string to uuid bytes - -Signed-off-by: ningyu ---- - Cargo.lock | 1 + - syscare-abi/Cargo.toml | 1 + - syscare-abi/src/patch_info.rs | 6 ++++-- - syscare-build/src/package/rpm/spec_builder.rs | 4 ++-- - syscare-build/src/patch/kernel_patch/kpatch_builder.rs | 6 +++--- - syscare-build/src/patch/metadata.rs | 4 +++- - syscare-build/src/patch/user_patch/upatch_builder.rs | 4 ++-- - syscared/src/patch/resolver/kpatch.rs | 4 +--- - syscared/src/patch/resolver/upatch.rs | 4 +--- - 9 files changed, 18 insertions(+), 16 deletions(-) - -diff --git a/Cargo.lock b/Cargo.lock -index 1d13df6..e6d830b 100644 ---- a/Cargo.lock -+++ b/Cargo.lock -@@ -1129,6 +1129,7 @@ name = "syscare-abi" - version = "1.2.1" - dependencies = [ - "serde", -+ "uuid", - ] - - [[package]] -diff --git a/syscare-abi/Cargo.toml b/syscare-abi/Cargo.toml -index 7b23a8a..f086850 100644 ---- a/syscare-abi/Cargo.toml -+++ b/syscare-abi/Cargo.toml -@@ -10,3 +10,4 @@ build = "build.rs" - - [dependencies] - serde = { version = "1.0", features = ["derive"] } -+uuid = { version = "0.8", features = ["v4"] } -diff --git a/syscare-abi/src/patch_info.rs b/syscare-abi/src/patch_info.rs -index 55618ae..08cc2c7 100644 ---- a/syscare-abi/src/patch_info.rs -+++ b/syscare-abi/src/patch_info.rs -@@ -16,6 +16,8 @@ use std::{ffi::OsString, path::PathBuf}; - - use serde::{Deserialize, Serialize}; - -+use uuid::Uuid; -+ - use super::package_info::PackageInfo; - - pub const PATCH_INFO_MAGIC: &str = "112574B6EDEE4BA4A05F"; -@@ -34,7 +36,7 @@ impl std::fmt::Display for PatchType { - - #[derive(Debug, Serialize, Deserialize, Clone)] - pub struct PatchEntity { -- pub uuid: String, -+ pub uuid: Uuid, - pub patch_name: OsString, - pub patch_target: PathBuf, - pub checksum: String, -@@ -49,7 +51,7 @@ pub struct PatchFile { - - #[derive(Debug, Serialize, Deserialize, Clone)] - pub struct PatchInfo { -- pub uuid: String, -+ pub uuid: Uuid, - pub name: String, - pub version: String, - pub release: u32, -diff --git a/syscare-build/src/package/rpm/spec_builder.rs b/syscare-build/src/package/rpm/spec_builder.rs -index 88f57d8..5570c34 100644 ---- a/syscare-build/src/package/rpm/spec_builder.rs -+++ b/syscare-build/src/package/rpm/spec_builder.rs -@@ -62,7 +62,7 @@ impl RpmSpecBuilder { - fn parse_patch_uuid(patch_info: &PatchInfo) -> String { - let mut result = String::new(); - for entity in &patch_info.entities { -- result.push_str(&entity.uuid); -+ result.push_str(&entity.uuid.to_string()); - result.push(' '); - } - result = result.trim().to_string(); -@@ -113,7 +113,7 @@ impl RpmSpecBuilder { - patch_info.name - ); - let pkg_version = format!("{}-{}", patch_info.version, patch_info.release); -- let pkg_root = Path::new(PKG_INSTALL_DIR).join(&patch_info.uuid); -+ let pkg_root = Path::new(PKG_INSTALL_DIR).join(&patch_info.uuid.to_string()); - - let mut spec = RpmSpecFile::new( - pkg_name, -diff --git a/syscare-build/src/patch/kernel_patch/kpatch_builder.rs b/syscare-build/src/patch/kernel_patch/kpatch_builder.rs -index 1b66510..ba49661 100644 ---- a/syscare-build/src/patch/kernel_patch/kpatch_builder.rs -+++ b/syscare-build/src/patch/kernel_patch/kpatch_builder.rs -@@ -150,7 +150,7 @@ impl KernelPatchBuilder { - match &kbuild_params.oot_source_dir { - // Kernel patch - None => { -- let entity_uuid = Uuid::new_v4().to_string(); -+ let entity_uuid = Uuid::new_v4(); - let entity_target = VMLINUX_FILE_NAME; - let entity_name = format!("{}-{}", entity_target, entity_uuid); - -@@ -182,7 +182,7 @@ impl KernelPatchBuilder { - .to_string_lossy() - .replace(['.', '-'], "_"); - -- let entity_uuid: String = Uuid::new_v4().to_string(); -+ let entity_uuid = Uuid::new_v4(); - let entitiy_name = format!("{}-{}", module_name, entity_uuid); - let entity_target = file_name.to_os_string(); - -@@ -290,7 +290,7 @@ impl KernelPatchBuilder { - ) -> Result> { - // Generate patch info - let patch_info = PatchInfo { -- uuid: Uuid::new_v4().to_string(), -+ uuid: Uuid::new_v4(), - name: kbuild_params.patch_name.to_owned(), - kind: kbuild_params.patch_type, - version: kbuild_params.patch_version.to_owned(), -diff --git a/syscare-build/src/patch/metadata.rs b/syscare-build/src/patch/metadata.rs -index 284c096..918b487 100644 ---- a/syscare-build/src/patch/metadata.rs -+++ b/syscare-build/src/patch/metadata.rs -@@ -16,6 +16,8 @@ use std::path::{Path, PathBuf}; - - use anyhow::{Context, Result}; - -+use uuid::Uuid; -+ - use syscare_abi::{PatchInfo, PATCH_INFO_MAGIC}; - use syscare_common::{fs, util::serde}; - -@@ -61,7 +63,7 @@ impl PatchMetadata { - } - - let patch_info = PatchInfo { -- uuid: String::default(), -+ uuid: Uuid::default(), - name: build_params.patch_name.to_owned(), - version: build_params.patch_version.to_owned(), - release: build_params.patch_release.to_owned(), -diff --git a/syscare-build/src/patch/user_patch/upatch_builder.rs b/syscare-build/src/patch/user_patch/upatch_builder.rs -index ad8710b..1e0e6b6 100644 ---- a/syscare-build/src/patch/user_patch/upatch_builder.rs -+++ b/syscare-build/src/patch/user_patch/upatch_builder.rs -@@ -259,7 +259,7 @@ impl UserPatchBuilder { - } - - if let Some(patch_file) = patch_entity_map.get(&elf_name) { -- let entity_uuid = Uuid::new_v4().to_string(); -+ let entity_uuid = Uuid::new_v4(); - let entity_name = fs::file_name(patch_file); - let entity_target = elf_file.to_owned(); - let entity_checksum = digest::file(patch_file).with_context(|| { -@@ -277,7 +277,7 @@ impl UserPatchBuilder { - } - - let patch_info = PatchInfo { -- uuid: Uuid::new_v4().to_string(), -+ uuid: Uuid::new_v4(), - name: ubuild_params.patch_name.to_owned(), - kind: ubuild_params.patch_type, - version: ubuild_params.patch_version.to_owned(), -diff --git a/syscared/src/patch/resolver/kpatch.rs b/syscared/src/patch/resolver/kpatch.rs -index 8738225..524482e 100644 ---- a/syscared/src/patch/resolver/kpatch.rs -+++ b/syscared/src/patch/resolver/kpatch.rs -@@ -15,13 +15,11 @@ - use std::{ - ffi::{CStr, OsString}, - path::{Path, PathBuf}, -- 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::{ -@@ -201,7 +199,7 @@ impl PatchResolverImpl for KpatchResolverImpl { - .join(KPATCH_SYS_FILE_NAME); - - let mut patch = KernelPatch { -- uuid: Uuid::from_str(&patch_entity.uuid).context("Invalid patch uuid")?, -+ uuid: patch_entity.uuid, - name: concat_os!( - patch_info.target.short_name(), - "/", -diff --git a/syscared/src/patch/resolver/upatch.rs b/syscared/src/patch/resolver/upatch.rs -index 985b8f1..5df11db 100644 ---- a/syscared/src/patch/resolver/upatch.rs -+++ b/syscared/src/patch/resolver/upatch.rs -@@ -15,13 +15,11 @@ - 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, ffi::CStrExt, fs}; -@@ -164,7 +162,7 @@ impl PatchResolverImpl for UpatchResolverImpl { - patch_entity: &PatchEntity, - ) -> Result { - let mut patch = UserPatch { -- uuid: Uuid::from_str(&patch_entity.uuid).context("Invalid patch uuid")?, -+ uuid: patch_entity.uuid, - name: concat_os!( - patch_info.target.short_name(), - "/", --- -2.34.1 - diff --git a/0015-upatch-build-fix-file-detection-cause-build-failure-.patch b/0015-upatch-build-fix-file-detection-cause-build-failure-.patch deleted file mode 100644 index 646d9b73a8bd7d8786efba58538dc199294de1fe..0000000000000000000000000000000000000000 --- a/0015-upatch-build-fix-file-detection-cause-build-failure-.patch +++ /dev/null @@ -1,557 +0,0 @@ -From 8deffbf247f51a8601e81bd65e448d9f228e98a8 Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Thu, 9 May 2024 18:49:29 +0800 -Subject: [PATCH 15/20] 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/0016-upatch-diff-optimize-log-output.patch b/0016-upatch-diff-optimize-log-output.patch deleted file mode 100644 index 2504736d021bc55549d0dce429a0efedd100a447..0000000000000000000000000000000000000000 --- a/0016-upatch-diff-optimize-log-output.patch +++ /dev/null @@ -1,469 +0,0 @@ -From a7140a02d69b50d57403f2c769767e5365a6aa34 Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Sat, 11 May 2024 08:26:33 +0800 -Subject: [PATCH 16/20] 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/0017-security-change-directory-permission.patch b/0017-security-change-directory-permission.patch deleted file mode 100644 index db9e8f01f1767231436aed05304f9e9a3b28b598..0000000000000000000000000000000000000000 --- a/0017-security-change-directory-permission.patch +++ /dev/null @@ -1,99 +0,0 @@ -From b43d59716bb5ae6811c3f4fcab33ca9a6704b175 Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Sat, 11 May 2024 08:28:48 +0800 -Subject: [PATCH 17/20] 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/0018-security-change-daemon-socket-permission.patch b/0018-security-change-daemon-socket-permission.patch deleted file mode 100644 index 2f2051d1b3679a25f2a1997a03f5899b978e0a6b..0000000000000000000000000000000000000000 --- a/0018-security-change-daemon-socket-permission.patch +++ /dev/null @@ -1,826 +0,0 @@ -From bbbcb0c08f4a6a63230288485d88492465e2a593 Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Sat, 11 May 2024 10:21:58 +0800 -Subject: [PATCH 18/20] 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 e6d830b..e3074a6 100644 ---- a/Cargo.lock -+++ b/Cargo.lock -@@ -511,6 +511,7 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" - dependencies = [ - "autocfg", - "hashbrown", -+ "serde", - ] - - [[package]] -@@ -1185,6 +1186,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/0019-upatch-manage-Fixed-the-core-dump-issue-after-applyi.patch b/0019-upatch-manage-Fixed-the-core-dump-issue-after-applyi.patch deleted file mode 100644 index 7d9b1897ed61a658deb8d5121007ca02b8992511..0000000000000000000000000000000000000000 --- a/0019-upatch-manage-Fixed-the-core-dump-issue-after-applyi.patch +++ /dev/null @@ -1,132 +0,0 @@ -From b9ae8a1ea14d46b3f4ba887fb10f9898c6f5cc53 Mon Sep 17 00:00:00 2001 -From: ningyu -Date: Sat, 11 May 2024 08:06:58 +0000 -Subject: [PATCH 19/20] 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..78c7fd7 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/0020-upatch-diff-fix-lookup_relf-failed-issue.patch b/0020-upatch-diff-fix-lookup_relf-failed-issue.patch deleted file mode 100644 index 183c9a2b44060afdff12654c7c21ebf1d3d04632..0000000000000000000000000000000000000000 --- a/0020-upatch-diff-fix-lookup_relf-failed-issue.patch +++ /dev/null @@ -1,144 +0,0 @@ -From fac8aa17d540e54fa0443015089cdc72c5da72e3 Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Sat, 11 May 2024 17:31:46 +0800 -Subject: [PATCH 20/20] 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/0021-upatch-diff-only-check-changed-file-symbols.patch b/0021-upatch-diff-only-check-changed-file-symbols.patch deleted file mode 100644 index b13eeab9f08b3d6ca50d6af02332c7f64ac5ac40..0000000000000000000000000000000000000000 --- a/0021-upatch-diff-only-check-changed-file-symbols.patch +++ /dev/null @@ -1,165 +0,0 @@ -From 2d711186e1c134b069102e72d6d451942c931eb5 Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Mon, 13 May 2024 21:27:13 +0800 -Subject: [PATCH 21/22] 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.41.0 - diff --git a/0022-upatch-diff-remove-rela-check-while-build-rebuilding.patch b/0022-upatch-diff-remove-rela-check-while-build-rebuilding.patch deleted file mode 100644 index ce7275a17c199e7f5d69663107216ea38ceb7257..0000000000000000000000000000000000000000 --- a/0022-upatch-diff-remove-rela-check-while-build-rebuilding.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 06ef9f212e17cdaa93dc5255d2c881c0b52d603f Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Tue, 14 May 2024 14:10:05 +0800 -Subject: [PATCH 22/22] 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.41.0 - diff --git a/0023-syscared-fix-apply-kernel-module-patch-failure-issue.patch b/0023-syscared-fix-apply-kernel-module-patch-failure-issue.patch deleted file mode 100644 index 669efa973d2f765b60ed4e863d9e296ffe190d39..0000000000000000000000000000000000000000 --- a/0023-syscared-fix-apply-kernel-module-patch-failure-issue.patch +++ /dev/null @@ -1,27 +0,0 @@ -From cf5217d55b2a603cfa0a852d876809c536835f18 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.41.0 - diff --git a/0024-syscare-build-fix-build-oot-module-failure-issue.patch b/0024-syscare-build-fix-build-oot-module-failure-issue.patch deleted file mode 100644 index 2cce7ac2e5a7f6014bbf9e9a7f4e1bdc198d2530..0000000000000000000000000000000000000000 --- a/0024-syscare-build-fix-build-oot-module-failure-issue.patch +++ /dev/null @@ -1,40 +0,0 @@ -From bf34a1c52841e9b33a6239405b7e15b42ddfe8b3 Mon Sep 17 00:00:00 2001 -From: renoseven -Date: Thu, 23 May 2024 09:18:08 +0800 -Subject: [PATCH] syscare-build: fix 'build oot module failure' issue - -Signed-off-by: renoseven ---- - syscare-build/src/package/rpm/pkg_builder.rs | 1 + - syscare-build/src/patch/kernel_patch/kpatch_builder.rs | 3 +++ - 2 files changed, 4 insertions(+) - -diff --git a/syscare-build/src/package/rpm/pkg_builder.rs b/syscare-build/src/package/rpm/pkg_builder.rs -index 5d7ae54..37f4444 100644 ---- a/syscare-build/src/package/rpm/pkg_builder.rs -+++ b/syscare-build/src/package/rpm/pkg_builder.rs -@@ -97,6 +97,7 @@ impl PackageBuilder for RpmPackageBuilder<'_> { - .arg("--define") - .arg("__spec_install_post %{__arch_install_post}") - .arg("--nocheck") -+ .arg("--noclean") - .arg("-bb") - .arg(spec_file) - .run()? -diff --git a/syscare-build/src/patch/kernel_patch/kpatch_builder.rs b/syscare-build/src/patch/kernel_patch/kpatch_builder.rs -index ba49661..bcae962 100644 ---- a/syscare-build/src/patch/kernel_patch/kpatch_builder.rs -+++ b/syscare-build/src/patch/kernel_patch/kpatch_builder.rs -@@ -227,6 +227,9 @@ impl KernelPatchBuilder { - - if let Some(oot_module) = &kbuild_entity.module_path { - cmd_args.arg("--oot-module").arg(oot_module); -+ cmd_args -+ .arg("--oot-module-src") -+ .arg(&kbuild_entity.source_dir); - } - cmd_args.args(kbuild_params.patch_files.iter().map(|patch| &patch.path)); - --- -2.41.0 - diff --git a/generate_package.sh b/generate_package.sh index 07c0d87468c5ab5c98976e9fe90256598fc9b09b..038b659846ccfa88e8b374b66a270abc7635ed12 100755 --- a/generate_package.sh +++ b/generate_package.sh @@ -1,24 +1,26 @@ #!/bin/bash -e -readonly REPO_NAME="syscare" -readonly REPO_PROVIDER="openeuler" -readonly REPO_URL="https://gitee.com/$REPO_PROVIDER/$REPO_NAME" -readonly REPO_BRANCH="openEuler-22.03" +readonly CURRENT_DIR="$(pwd)" -echo "Cloning source code..." -repo_version=$(grep "Version" "$REPO_NAME.spec" | head -n 1 | awk -F ' ' '{print $NF}') -repo_dir="$REPO_NAME-$repo_version" +readonly SPEC_FILE="$(find . -name '*.spec' | head -n 1)" +readonly REPO_NAME="$(basename ${SPEC_FILE} | sed 's/.spec//')" +readonly REPO_VERSION="$(grep Version ${SPEC_FILE} | head -n 1 | awk -F ' ' '{print $NF}')" +readonly REPO_BRANCH="$(git branch --show-current | sed 's/-LTS.*//')" +readonly REPO_URL="https://gitee.com/openeuler/${REPO_NAME}" -rm -rf "$REPO_NAME" "$repo_dir" -git clone "$REPO_URL" +readonly PKG_NAME="${REPO_NAME}-${REPO_VERSION}" +readonly PKG_DIR="${CURRENT_DIR}/${PKG_NAME}" -echo "Prepare build requirements..." -pushd "$REPO_NAME" +echo "Preparing..." +rm -rf ${REPO_NAME} ${PKG_NAME} +rm -f ${REPO_NAME}*.tar.gz -echo "Checking out dest branch..." -git checkout "$REPO_BRANCH" +echo "Cloning source code..." +git clone ${REPO_URL} -b ${REPO_BRANCH} ${PKG_NAME} echo "Vendoring dependencies..." +pushd "${PKG_DIR}" > /dev/null + cargo vendor --respect-source-config --sync Cargo.toml mkdir -p .cargo @@ -30,14 +32,12 @@ replace-with = "vendored-sources" directory = "vendor" EOF -popd +popd > /dev/null echo "Compressing package..." -mv "$REPO_NAME" "$repo_dir" -tar -czf "$repo_dir.tar.gz" "$repo_dir" +tar -czf "${PKG_NAME}.tar.gz" "${PKG_NAME}" echo "Cleaning up..." -rm -rf "$repo_dir" +rm -rf "${PKG_DIR}" echo "Done" - diff --git a/generate_patches.sh b/generate_patches.sh new file mode 100755 index 0000000000000000000000000000000000000000..b0f1ee9741ed5142f8a2bacb281582291bf8c821 --- /dev/null +++ b/generate_patches.sh @@ -0,0 +1,55 @@ +#!/bin/bash -e +readonly ROOT_DIR="$(dirname $(readlink -f ${BASH_SOURCE[0]}))" + +readonly SPEC_FILE="$(find . -name '*.spec' | head -n 1)" +readonly REPO_NAME="$(basename ${SPEC_FILE} | sed 's/.spec//')" +readonly REPO_VERSION="$(grep Version ${SPEC_FILE} | head -n 1 | awk -F ' ' '{print $NF}')" +readonly REPO_REMOTE="origin" + +readonly PKG_NAME="${REPO_NAME}-${REPO_VERSION}" +readonly PKG_DIR="${ROOT_DIR}/${PKG_NAME}" +readonly PKG_BRANCH="$(git branch --show-current | sed 's/-LTS.*//')" + +echo "Preparing..." +# clean old files +rm -f ${ROOT_DIR}/*.patch +rm -rf ${PKG_DIR} + +# extract package +tar -xf ${PKG_NAME}.tar.gz + +# fetch baseline +pushd ${PKG_DIR} > /dev/null +readonly PKG_BASELINE=$(git rev-parse --short HEAD) +popd > /dev/null + +echo "------------------------------" +echo "Name: ${PKG_NAME}" +echo "Branch: ${PKG_BRANCH}" +echo "Baseline: ${PKG_BASELINE}" +echo "------------------------------" + +echo "Syncing with remote..." +pushd ${PKG_DIR} > /dev/null +git fetch ${REPO_REMOTE} +popd > /dev/null + +echo "Generating patches..." +# format patches +pushd ${PKG_DIR} > /dev/null +git checkout -q ${REPO_REMOTE}/${PKG_BRANCH} +git format-patch -qN -o ${ROOT_DIR} ${PKG_BASELINE} +popd > /dev/null + +# print patch list +patch_list="$(find ${ROOT_DIR} -maxdepth 1 -name "*.patch" | sort)" +for patch_file in ${patch_list}; do + patch_name="$(basename ${patch_file})" + patch_id="$(echo ${patch_name} | awk -F '-' '{print $1}')" + echo "Patch${patch_id}: ${patch_name}" +done + +echo "Cleaning up..." +rm -rf ${PKG_DIR} + +echo "Done" diff --git a/syscare-1.2.1.tar.gz b/syscare-1.2.2.tar.gz similarity index 74% rename from syscare-1.2.1.tar.gz rename to syscare-1.2.2.tar.gz index 616f843d63e0d3623da168d9c2a4b2bce16a9901..b0cc200604dbf34ca062b2868987c26a5f54a779 100644 Binary files a/syscare-1.2.1.tar.gz and b/syscare-1.2.2.tar.gz differ diff --git a/syscare.spec b/syscare.spec index 3d3f623ffceb96ec0f3479cab4f75e84fcd085e7..4943f67fb7edf082257543c72bb3fd81607ae45e 100644 --- a/syscare.spec +++ b/syscare.spec @@ -1,54 +1,27 @@ %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 - ############################################ ############ Package syscare ############### ############################################ Name: syscare -Version: 1.2.1 -Release: 8 +Version: 1.2.2 +Release: 1 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-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-abi-change-uuid-string-to-uuid-bytes.patch -Patch0015: 0015-upatch-build-fix-file-detection-cause-build-failure-.patch -Patch0016: 0016-upatch-diff-optimize-log-output.patch -Patch0017: 0017-security-change-directory-permission.patch -Patch0018: 0018-security-change-daemon-socket-permission.patch -Patch0019: 0019-upatch-manage-Fixed-the-core-dump-issue-after-applyi.patch -Patch0020: 0020-upatch-diff-fix-lookup_relf-failed-issue.patch -Patch0021: 0021-upatch-diff-only-check-changed-file-symbols.patch -Patch0022: 0022-upatch-diff-remove-rela-check-while-build-rebuilding.patch -Patch0023: 0023-syscared-fix-apply-kernel-module-patch-failure-issue.patch -Patch0024: 0024-syscare-build-fix-build-oot-module-failure-issue.patch - BuildRequires: cmake >= 3.14 make -BuildRequires: rust >= 1.51 cargo >= 1.51 +BuildRequires: rust >= 1.60 cargo >= 1.60 BuildRequires: gcc gcc-c++ BuildRequires: kernel-devel Requires: coreutils systemd Requires: kpatch-runtime +Excludearch: loongarch64 + ############### Description ################ %description SysCare is a system-level hot-fix service that provides security patches and system error hot-fixes for the operating system. @@ -115,12 +88,12 @@ fi ################## Files ################### %files -%defattr(-,root,root,-) +%defattr(-,root,root,0555) %dir /usr/libexec/syscare -%attr(550,root,root) /usr/lib/systemd/system/syscare.service -%attr(550,root,root) /usr/libexec/syscare/upatch-manage -%attr(550,root,root) /usr/bin/syscared -%attr(555,root,root) /usr/bin/syscare +%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 ########### @@ -140,15 +113,9 @@ Syscare patch building toolset. ############### PostInstall ################ %post build -systemctl daemon-reload -systemctl enable upatch -systemctl start upatch ############### PreUninstall ############### %preun build -systemctl daemon-reload -systemctl stop upatch -systemctl disable upatch ############## PostUninstall ############### %postun build @@ -172,163 +139,17 @@ fi ################## Files ################### %files build -%defattr(-,root,root,-) +%defattr(-,root,root,0555) %dir /usr/libexec/syscare -%attr(550,root,root) /usr/lib/systemd/system/upatch.service -%attr(550,root,root) /usr/bin/upatchd -%attr(440,root,root) /usr/libexec/syscare/upatch_hijacker.ko %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-hijacker -%attr(555,root,root) /usr/libexec/syscare/cc-hijacker -%attr(555,root,root) /usr/libexec/syscare/c++-hijacker -%attr(555,root,root) /usr/libexec/syscare/gcc-hijacker -%attr(555,root,root) /usr/libexec/syscare/g++-hijacker -%attr(555,root,root) /usr/libexec/syscare/gnu-as-hijacker -%attr(555,root,root) /usr/libexec/syscare/gnu-compiler-hijacker +%attr(555,root,root) /usr/libexec/syscare/upatch-helper +%attr(555,root,root) /usr/libexec/syscare/upatch-cc +%attr(555,root,root) /usr/libexec/syscare/upatch-c++ ############################################ ################ Change log ################ ############################################ %changelog -* Mon May 20 2024 ningyu - 1.2.1-8 -- syscared: fix apply kernel module patch failure issue -- syscare-build: fix build oot module failure issue -* Tue May 14 2024 ningyu - 1.2.1-7 -- upatch diff only check changed file symbols -- upatch diff remove rela check while build rebuilding -* 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 -- common: impl CStr::from_bytes_with_next_nul() -- syscared: improve patch management -- 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 -- Add Suggests for syscare-build -- Remove log directory -* Tue Dec 12 2023 renoseven - 1.2.0-8 -- Builder: fix 'enabling multiple kpatch may lead soft-lockup' issue -* Wed Nov 29 2023 renoseven - 1.2.0-7 -- Fix aarch64 compile issue -* Tue Nov 28 2023 renoseven - 1.2.0-6 -- Enable debuginfo for rust code -- Sync arguments with old version -* Tue Nov 28 2023 renoseven - 1.2.0-5 -- Upgrade MSRV to 1.60 -- Optimize syscare build check logic -- Optimize external command calling -- Optimize log output -* Fri Nov 24 2023 renoseven - 1.2.0-4 -- Fix 'kpatch driver cannot support old version' issue -* Fri Nov 24 2023 renoseven - 1.2.0-3 -- Fix 'upatch only apply first patch for new process' issue -* Wed Nov 22 2023 renoseven - 1.2.0-2 -- Fix upatch process detection -* Wed Nov 22 2023 renoseven - 1.2.0-1 -- Fix various issue -* Wed Oct 11 2023 renoseven - 1.1.0-6 -- Support build patch for kernel moudules -- Fix various issue -* Fri Sep 22 2023 renoseven - 1.1.0-5 -- Fix various issue -* Thu Sep 21 2023 renoseven - 1.1.0-4 -- Fix 'syscare-build only accept one patch' issue -* Wed Sep 20 2023 renoseven - 1.1.0-3 -- Fix various issue -- Support MSRV 1.51 -* Mon Aug 28 2023 renoseven - 1.1.0-1 -- Support build patch without kernel module -- Add syscare daemon -- Add syscare-build daemon -- Improve syscare cli -* Wed Jun 28 2023 renoseven - 1.0.2-4 -- Fix builder check failure issue -* Sun Jun 25 2023 renoseven - 1.0.2-3 -- Fix various issue -* Mon Jun 19 2023 renoseven - 1.0.2-2 -- Fix various issue -- Update dependencies -* Fri Jun 09 2023 renoseven - 1.0.2-1 -- Fix 'rpmpbuild getcwd failed' issue -- Fix 'upatch ko prints redundant log' issue -* Fri Jun 09 2023 renoseven - 1.0.1-9 -- Fix 'patch file is not checked' issue -- Rename patched source package -- Update dependencies -* Tue Jun 06 2023 renoseven - 1.0.1-8 -- Fix 'kernel patch sys interface collision' issue -- Fix 'patch GOT table jump fails' issue -- Fix 'patch TLS variable relocation fails' issue -* Fri Jun 02 2023 renoseven - 1.0.1-7 -- Various bugfix -- Support multiple compiler -* Wed May 31 2023 renoseven - 1.0.1-6 -- Various bugfix -- Support multiple debuginfo package -* Mon May 15 2023 renoseven - 1.0.1-5 -- Fix aarch64 kmod patch jump instruction error issue -- Add ifunc support -- Add 'syscare accept' command -- Add patch 'ACCEPT' state -* Tue Apr 04 2023 renoseven - 1.0.1-4 -- Enable aarch64 -- Fix syscare-upatch service may start failed issue -* Thu Mar 30 2023 renoseven - 1.0.1-3 -- Fix upatch may not contain all symbols issue -- Add syscare-kmod package -* Wed Mar 29 2023 renoseven - 1.0.1-2 -- Fix rpm install & remove script issue -* Wed Mar 15 2023 renoseven - 1.0.1-1 -- New syscare cli -- Support building patch for C++ code -- Support patch version verification -- Support elf name derivation -- Support fast reboot -* Wed Dec 21 2022 snoweay - 1.0.0-7 -- Fix 42 relocation caused by gcc 11. -* Tue Dec 20 2022 snoweay - 1.0.0-6 -- Fix patch open failure by reading patches at attach instead of load. -- Support epoch in spec. -* Sat Dec 17 2022 snoweay - 1.0.0-5 -- Check version-release of source pkg & debuginfo pkg. -* Fri Dec 16 2022 snoweay - 1.0.0-4 -- Avoid duplicate elfs by not following symlinks at build. -* Thu Dec 15 2022 snoweay - 1.0.0-3 -- Change kernel patches' scontext before apply not at rpm-post. -* Wed Dec 14 2022 snoweay - 1.0.0-2 -- Fix some issues: -- manager: Allow apply to actived kernel patch -- build: only 'NOT-APPLIED' patch package can be removed -- build: fix 'kernel patch cannot be insmod during system start' issue -- kmod: unregister when rmmod upatch -* Tue Dec 13 2022 snoweay - 1.0.0-1 -- Release the first version 1.0.0. +* Mon Jul 1 2024 renoseven - 1.2.2-1 +- Release version 1.2.2-1