diff --git a/0001-upatch-hijacker-fix-compile-bug.patch b/0001-upatch-hijacker-fix-compile-bug.patch new file mode 100644 index 0000000000000000000000000000000000000000..f8c1c951630abb6b8f3dd8d955d1c71f1b92ab19 --- /dev/null +++ b/0001-upatch-hijacker-fix-compile-bug.patch @@ -0,0 +1,33 @@ +From 8c09e8b3d9d59012c1019c01ac2246c770501c75 Mon Sep 17 00:00:00 2001 +From: ningyu <405888464@qq.com> +Date: Sun, 7 Apr 2024 10:50:13 +0800 +Subject: [PATCH 01/10] 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.41.0 + diff --git a/0002-daemon-fix-cannot-get-file-selinux-xattr-when-selinu.patch b/0002-daemon-fix-cannot-get-file-selinux-xattr-when-selinu.patch new file mode 100644 index 0000000000000000000000000000000000000000..c796929b65df62a823733b1a067dd0a9b8b5dd5d --- /dev/null +++ b/0002-daemon-fix-cannot-get-file-selinux-xattr-when-selinu.patch @@ -0,0 +1,219 @@ +From a535e14a7db49df3c8aab017e32b92d8e5bb4087 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Wed, 10 Apr 2024 10:25:21 +0800 +Subject: [PATCH 02/10] 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.41.0 + diff --git a/0003-syscared-fix-syscare-check-command-does-not-check-sy.patch b/0003-syscared-fix-syscare-check-command-does-not-check-sy.patch new file mode 100644 index 0000000000000000000000000000000000000000..7ed3ba9bcac03e205150bd6a2c5c6d4468e597e1 --- /dev/null +++ b/0003-syscared-fix-syscare-check-command-does-not-check-sy.patch @@ -0,0 +1,385 @@ +From e5294afa8135f54f44196bd92e5a32c2b09b9bda Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Wed, 10 Apr 2024 12:19:51 +0800 +Subject: [PATCH 03/10] 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.41.0 + diff --git a/0004-syscared-fix-cannot-find-process-of-dynlib-patch-iss.patch b/0004-syscared-fix-cannot-find-process-of-dynlib-patch-iss.patch new file mode 100644 index 0000000000000000000000000000000000000000..2f51c249a2cfa338954775fcc33a604f5b851095 --- /dev/null +++ b/0004-syscared-fix-cannot-find-process-of-dynlib-patch-iss.patch @@ -0,0 +1,687 @@ +From 32c3d16175b93627504981d05a1a3e3ec603415e Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Wed, 10 Apr 2024 19:30:56 +0800 +Subject: [PATCH 04/10] 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.41.0 + diff --git a/0005-abi-change-uuid-type-from-string-to-uuid-bytes.patch b/0005-abi-change-uuid-type-from-string-to-uuid-bytes.patch new file mode 100644 index 0000000000000000000000000000000000000000..a860450bfee072c7838c10ebce22d1b5a28cede3 --- /dev/null +++ b/0005-abi-change-uuid-type-from-string-to-uuid-bytes.patch @@ -0,0 +1,222 @@ +From c213504c02d73738a86935fb5883f2e59d083da7 Mon Sep 17 00:00:00 2001 +From: ningyu +Date: Tue, 9 Apr 2024 09:21:35 +0000 +Subject: [PATCH 05/10] abi: change uuid type from string to uuid bytes + +--- + 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 | 5 ++--- + 9 files changed, 19 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..a24954f 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 7de81b3..50711eb 100644 +--- a/syscared/src/patch/resolver/kpatch.rs ++++ b/syscared/src/patch/resolver/kpatch.rs +@@ -16,13 +16,11 @@ use std::{ + ffi::OsString, + os::unix::ffi::OsStringExt, + 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::{concat_os, ffi::OsStrExt, fs}; +@@ -194,7 +192,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 507bf8e..15c7363 100644 +--- a/syscared/src/patch/resolver/upatch.rs ++++ b/syscared/src/patch/resolver/upatch.rs +@@ -12,11 +12,10 @@ + * 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::OsString, os::unix::ffi::OsStringExt, path::Path, 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}; +@@ -152,7 +151,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.41.0 + diff --git a/0006-syscared-optimize-patch-error-logic.patch b/0006-syscared-optimize-patch-error-logic.patch new file mode 100644 index 0000000000000000000000000000000000000000..af4f01fd8f0528001dfc04986b22af050de6929c --- /dev/null +++ b/0006-syscared-optimize-patch-error-logic.patch @@ -0,0 +1,103 @@ +From 1fbb81935c66c47a68716580878f2b983272a2bc Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 12 Apr 2024 11:35:57 +0800 +Subject: [PATCH 06/10] 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.41.0 + diff --git a/0007-syscared-optimize-transaction-creation-logic.patch b/0007-syscared-optimize-transaction-creation-logic.patch new file mode 100644 index 0000000000000000000000000000000000000000..a344865dd3fbd3c7e013a3fc289cc17df1697b94 --- /dev/null +++ b/0007-syscared-optimize-transaction-creation-logic.patch @@ -0,0 +1,112 @@ +From bbf3396adbbd53709ab5a78c1035e6b9b010d549 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 12 Apr 2024 11:40:25 +0800 +Subject: [PATCH 07/10] 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.41.0 + diff --git a/0008-upatch-manage-optimize-output.patch b/0008-upatch-manage-optimize-output.patch new file mode 100644 index 0000000000000000000000000000000000000000..8d2632921c2b9bfac10fe18811ed951c488e429b --- /dev/null +++ b/0008-upatch-manage-optimize-output.patch @@ -0,0 +1,136 @@ +From 7c976ffc72330c85bc815bc1983dd7096778bf1b Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 12 Apr 2024 11:50:59 +0800 +Subject: [PATCH 08/10] 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.41.0 + diff --git a/0009-syscared-optimize-patch-error-logic.patch b/0009-syscared-optimize-patch-error-logic.patch new file mode 100644 index 0000000000000000000000000000000000000000..4601bbd61189efdb75ee977609f97551520b032e --- /dev/null +++ b/0009-syscared-optimize-patch-error-logic.patch @@ -0,0 +1,35 @@ +From 1a419fd88160f45a8fdabd8e6427811804735af1 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 12 Apr 2024 11:35:57 +0800 +Subject: [PATCH 09/10] syscared: optimize patch error logic + +Signed-off-by: renoseven +--- + syscared/src/patch/driver/upatch/sys.rs | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +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.41.0 + diff --git a/0010-syscared-optimize-transaction-creation-logic.patch b/0010-syscared-optimize-transaction-creation-logic.patch new file mode 100644 index 0000000000000000000000000000000000000000..0dd89cd39e0926f158d699db06a0d13e93cb9a08 --- /dev/null +++ b/0010-syscared-optimize-transaction-creation-logic.patch @@ -0,0 +1,35 @@ +From 91b63792ed2b13ce8fc706df1ffa7d9fdadc31c7 Mon Sep 17 00:00:00 2001 +From: renoseven +Date: Fri, 12 Apr 2024 11:40:25 +0800 +Subject: [PATCH 10/10] syscared: optimize transaction creation logic + +Signed-off-by: renoseven +--- + syscared/src/patch/driver/upatch/sys.rs | 4 ++-- + 1 file changed, 2 insertions(+), 2 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(); + +-- +2.41.0 + diff --git a/syscare-1.2.1.tar.gz b/syscare-1.2.1.tar.gz index e572afac63399bf31f5234e925e2d45952de1b47..616f843d63e0d3623da168d9c2a4b2bce16a9901 100644 Binary files a/syscare-1.2.1.tar.gz and b/syscare-1.2.1.tar.gz differ diff --git a/syscare.spec b/syscare.spec index 0eefa6d2f879522b670fb02e4576dd627e33eca5..7304b0be78bceeb93a23e95deb3e8a4f89ceb5db 100644 --- a/syscare.spec +++ b/syscare.spec @@ -11,12 +11,23 @@ ############################################ Name: syscare Version: 1.2.1 -Release: 2 +Release: 3 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-abi-change-uuid-type-from-string-to-uuid-bytes.patch +Patch0006: 0006-syscared-optimize-patch-error-logic.patch +Patch0007: 0007-syscared-optimize-transaction-creation-logic.patch +Patch0008: 0008-upatch-manage-optimize-output.patch +Patch0009: 0009-syscared-optimize-patch-error-logic.patch +Patch0010: 0010-syscared-optimize-transaction-creation-logic.patch + BuildRequires: cmake >= 3.14 make BuildRequires: rust >= 1.51 cargo >= 1.51 BuildRequires: gcc gcc-c++ @@ -60,9 +71,11 @@ systemctl start syscare ############### PreUninstall ############### %preun -systemctl daemon-reload -systemctl stop syscare -systemctl disable syscare +if [ "$1" -eq 0 ]; then + systemctl daemon-reload + systemctl stop syscare + systemctl disable syscare +fi ############## PostUninstall ############### %postun @@ -164,6 +177,18 @@ fi ################ Change log ################ ############################################ %changelog +* 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