Compare commits
10 Commits
4ee0e0f02e
...
0e1995805d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0e1995805d | ||
|
|
eea01c1370 | ||
|
|
784ca2dcb6 | ||
|
|
210a7eb342 | ||
|
|
ff5e0a6bf1 | ||
|
|
aaca4c9c5f | ||
|
|
27bb77c699 | ||
|
|
2901ec3d3c | ||
|
|
37c1009563 | ||
|
|
9dd2411f72 |
@ -0,0 +1,26 @@
|
||||
From abefa18605dd7ec20419e8061739357d2a4d67a4 Mon Sep 17 00:00:00 2001
|
||||
From: liqiang <liqiang64@huawei.com>
|
||||
Date: Wed, 28 Aug 2024 02:24:59 +0800
|
||||
Subject: [PATCH] fix kernel patch ACCEPTED change to DEACTIVED after reboot
|
||||
|
||||
Signed-off-by: liqiang <liqiang64@huawei.com>
|
||||
---
|
||||
syscared/src/patch/driver/kpatch/sys.rs | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/syscared/src/patch/driver/kpatch/sys.rs b/syscared/src/patch/driver/kpatch/sys.rs
|
||||
index 22efa93..fd5160c 100644
|
||||
--- a/syscared/src/patch/driver/kpatch/sys.rs
|
||||
+++ b/syscared/src/patch/driver/kpatch/sys.rs
|
||||
@@ -90,7 +90,7 @@ pub fn apply_patch(patch: &KernelPatch) -> Result<()> {
|
||||
kmod::finit_module(
|
||||
&patch_module,
|
||||
CString::new("")?.as_c_str(),
|
||||
- kmod::ModuleInitFlags::MODULE_INIT_IGNORE_VERMAGIC,
|
||||
+ kmod::ModuleInitFlags::empty(),
|
||||
)
|
||||
.map_err(|e| anyhow!("Kpatch: {}", std::io::Error::from(e)))
|
||||
}
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@ -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
|
||||
|
||||
@ -1,219 +0,0 @@
|
||||
From a535e14a7db49df3c8aab017e32b92d8e5bb4087 Mon Sep 17 00:00:00 2001
|
||||
From: renoseven <dev@renoseven.net>
|
||||
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 <dev@renoseven.net>
|
||||
---
|
||||
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<Vec<OsString>> {
|
||||
Ok(module_names)
|
||||
}
|
||||
|
||||
-pub fn set_security_attribute<P: AsRef<Path>>(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<S: AsRef<str>, P: AsRef<Path>>(name: S, path: P) -> Result<Self> {
|
||||
- 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<S: AsRef<str>, P: AsRef<Path>>(name: S, kmod_path: P) -> Result<Self> {
|
||||
+ 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<P: AsRef<Path>>(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<P: AsRef<Path>>(&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
|
||||
|
||||
97
0002-fix-some-clean-code-problem.patch
Normal file
97
0002-fix-some-clean-code-problem.patch
Normal file
@ -0,0 +1,97 @@
|
||||
From 224df412c95bf4ac95200b6af44927ad2ef2abac Mon Sep 17 00:00:00 2001
|
||||
From: liqiang <liqiang64@huawei.com>
|
||||
Date: Thu, 29 Aug 2024 03:56:58 +0800
|
||||
Subject: [PATCH] fix some clean code problem
|
||||
|
||||
Signed-off-by: liqiang <liqiang64@huawei.com>
|
||||
---
|
||||
upatch-diff/insn/asm/inat.h | 8 ++++----
|
||||
upatch-diff/insn/inat.c | 6 +++---
|
||||
upatch-diff/insn/insn.c | 6 +++---
|
||||
3 files changed, 10 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/upatch-diff/insn/asm/inat.h b/upatch-diff/insn/asm/inat.h
|
||||
index f446ad8..4ab84d6 100644
|
||||
--- a/upatch-diff/insn/asm/inat.h
|
||||
+++ b/upatch-diff/insn/asm/inat.h
|
||||
@@ -156,7 +156,7 @@ static inline int inat_is_escape(insn_attr_t attr)
|
||||
return attr & INAT_ESC_MASK;
|
||||
}
|
||||
|
||||
-static inline int inat_escape_id(insn_attr_t attr)
|
||||
+static inline unsigned int inat_escape_id(insn_attr_t attr)
|
||||
{
|
||||
return (attr & INAT_ESC_MASK) >> INAT_ESC_OFFS;
|
||||
}
|
||||
@@ -166,7 +166,7 @@ static inline int inat_is_group(insn_attr_t attr)
|
||||
return attr & INAT_GRP_MASK;
|
||||
}
|
||||
|
||||
-static inline int inat_group_id(insn_attr_t attr)
|
||||
+static inline unsigned int inat_group_id(insn_attr_t attr)
|
||||
{
|
||||
return (attr & INAT_GRP_MASK) >> INAT_GRP_OFFS;
|
||||
}
|
||||
@@ -181,7 +181,7 @@ static inline int inat_has_immediate(insn_attr_t attr)
|
||||
return attr & INAT_IMM_MASK;
|
||||
}
|
||||
|
||||
-static inline int inat_immediate_size(insn_attr_t attr)
|
||||
+static inline unsigned int inat_immediate_size(insn_attr_t attr)
|
||||
{
|
||||
return (attr & INAT_IMM_MASK) >> INAT_IMM_OFFS;
|
||||
}
|
||||
@@ -220,4 +220,4 @@ static inline int inat_must_vex(insn_attr_t attr)
|
||||
{
|
||||
return attr & INAT_VEXONLY;
|
||||
}
|
||||
-#endif
|
||||
\ No newline at end of file
|
||||
+#endif
|
||||
diff --git a/upatch-diff/insn/inat.c b/upatch-diff/insn/inat.c
|
||||
index 193583f..cb5aec6 100644
|
||||
--- a/upatch-diff/insn/inat.c
|
||||
+++ b/upatch-diff/insn/inat.c
|
||||
@@ -43,7 +43,7 @@ insn_attr_t inat_get_escape_attribute(insn_byte_t opcode, int lpfx_id,
|
||||
insn_attr_t esc_attr)
|
||||
{
|
||||
const insn_attr_t *table;
|
||||
- int n;
|
||||
+ unsigned int n;
|
||||
|
||||
n = inat_escape_id(esc_attr);
|
||||
|
||||
@@ -62,7 +62,7 @@ insn_attr_t inat_get_group_attribute(insn_byte_t modrm, int lpfx_id,
|
||||
insn_attr_t grp_attr)
|
||||
{
|
||||
const insn_attr_t *table;
|
||||
- int n;
|
||||
+ unsigned int n;
|
||||
|
||||
n = inat_group_id(grp_attr);
|
||||
|
||||
@@ -95,4 +95,4 @@ insn_attr_t inat_get_avx_attribute(insn_byte_t opcode, insn_byte_t vex_m,
|
||||
return 0;
|
||||
}
|
||||
return table[opcode];
|
||||
-}
|
||||
\ No newline at end of file
|
||||
+}
|
||||
diff --git a/upatch-diff/insn/insn.c b/upatch-diff/insn/insn.c
|
||||
index d9a356b..7880eed 100644
|
||||
--- a/upatch-diff/insn/insn.c
|
||||
+++ b/upatch-diff/insn/insn.c
|
||||
@@ -574,6 +574,6 @@ void insn_get_length(struct insn *insn)
|
||||
return;
|
||||
if (!insn->immediate.got)
|
||||
insn_get_immediate(insn);
|
||||
- insn->length = (unsigned char)((unsigned long)insn->next_byte
|
||||
- - (unsigned long)insn->kaddr);
|
||||
-}
|
||||
\ No newline at end of file
|
||||
+ insn->length = (unsigned char)((unsigned long)insn->next_byte -
|
||||
+ (unsigned long)insn->kaddr);
|
||||
+}
|
||||
--
|
||||
2.34.1
|
||||
|
||||
49
0003-syscared-fix-active-accepted-patch-failure-issue.patch
Normal file
49
0003-syscared-fix-active-accepted-patch-failure-issue.patch
Normal file
@ -0,0 +1,49 @@
|
||||
From 5a65a46bfe8671ea38710d0fbd230fe6a86ea508 Mon Sep 17 00:00:00 2001
|
||||
From: renoseven <dev@renoseven.net>
|
||||
Date: Fri, 18 Oct 2024 03:10:05 +0800
|
||||
Subject: [PATCH] syscared: fix active accepted patch failure issue
|
||||
|
||||
Signed-off-by: renoseven <dev@renoseven.net>
|
||||
---
|
||||
syscared/src/patch/manager.rs | 11 ++++++++---
|
||||
1 file changed, 8 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/syscared/src/patch/manager.rs b/syscared/src/patch/manager.rs
|
||||
index 3a724db..a17703c 100644
|
||||
--- a/syscared/src/patch/manager.rs
|
||||
+++ b/syscared/src/patch/manager.rs
|
||||
@@ -47,6 +47,7 @@ const PATCH_REMOVE: TransitionAction = &PatchManager::driver_remove_patch;
|
||||
const PATCH_ACTIVE: TransitionAction = &PatchManager::driver_active_patch;
|
||||
const PATCH_DEACTIVE: TransitionAction = &PatchManager::driver_deactive_patch;
|
||||
const PATCH_ACCEPT: TransitionAction = &PatchManager::driver_accept_patch;
|
||||
+const PATCH_DECLINE: TransitionAction = &PatchManager::driver_decline_patch;
|
||||
|
||||
lazy_static! {
|
||||
static ref STATUS_TRANSITION_MAP: IndexMap<Transition, Vec<TransitionAction>> = indexmap! {
|
||||
@@ -59,9 +60,9 @@ lazy_static! {
|
||||
(PatchStatus::Actived, PatchStatus::NotApplied) => vec![PATCH_DEACTIVE, PATCH_REMOVE],
|
||||
(PatchStatus::Actived, PatchStatus::Deactived) => vec![PATCH_DEACTIVE],
|
||||
(PatchStatus::Actived, PatchStatus::Accepted) => vec![PATCH_ACCEPT],
|
||||
- (PatchStatus::Accepted, PatchStatus::NotApplied) => vec![PATCH_ACCEPT, PATCH_DEACTIVE, PATCH_REMOVE],
|
||||
- (PatchStatus::Accepted, PatchStatus::Deactived) => vec![PATCH_ACCEPT, PATCH_DEACTIVE],
|
||||
- (PatchStatus::Accepted, PatchStatus::Actived) => vec![PATCH_ACCEPT],
|
||||
+ (PatchStatus::Accepted, PatchStatus::NotApplied) => vec![PATCH_DECLINE, PATCH_DEACTIVE, PATCH_REMOVE],
|
||||
+ (PatchStatus::Accepted, PatchStatus::Deactived) => vec![PATCH_DECLINE, PATCH_DEACTIVE],
|
||||
+ (PatchStatus::Accepted, PatchStatus::Actived) => vec![PATCH_DECLINE],
|
||||
};
|
||||
}
|
||||
|
||||
@@ -471,6 +472,10 @@ impl PatchManager {
|
||||
fn driver_accept_patch(&mut self, patch: &Patch, _flag: PatchOpFlag) -> Result<()> {
|
||||
self.set_patch_status(patch, PatchStatus::Accepted)
|
||||
}
|
||||
+
|
||||
+ fn driver_decline_patch(&mut self, patch: &Patch, _flag: PatchOpFlag) -> Result<()> {
|
||||
+ self.set_patch_status(patch, PatchStatus::Actived)
|
||||
+ }
|
||||
}
|
||||
|
||||
impl Drop for PatchManager {
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@ -1,385 +0,0 @@
|
||||
From e5294afa8135f54f44196bd92e5a32c2b09b9bda Mon Sep 17 00:00:00 2001
|
||||
From: renoseven <dev@renoseven.net>
|
||||
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 <dev@renoseven.net>
|
||||
---
|
||||
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<Self> {
|
||||
info!("Initializing kernel patch driver...");
|
||||
@@ -53,26 +69,40 @@ impl PatchDriver {
|
||||
}
|
||||
|
||||
/// Fetch and return the patch status.
|
||||
- pub fn status(&self, patch: &Patch) -> Result<PatchStatus> {
|
||||
+ pub fn patch_status(&self, patch: &Patch) -> Result<PatchStatus> {
|
||||
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. </br>
|
||||
- /// Should be used befor patch application.
|
||||
- pub fn check(&self, patch: &Patch, flag: PatchOpFlag) -> Result<()> {
|
||||
+ /// Perform patch file intergrity & consistency check. </br>
|
||||
+ /// 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. </br>
|
||||
+ /// 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. </br>
|
||||
/// 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. </br>
|
||||
/// 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. </br>
|
||||
/// 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. </br>
|
||||
/// 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<PatchStatus> {
|
||||
@@ -438,31 +441,31 @@ impl PatchManager {
|
||||
}
|
||||
|
||||
impl PatchManager {
|
||||
- fn driver_get_patch_status(&self, patch: &Patch, _flag: PatchOpFlag) -> Result<PatchStatus> {
|
||||
- self.driver.status(patch)
|
||||
+ fn driver_patch_status(&self, patch: &Patch, _flag: PatchOpFlag) -> Result<PatchStatus> {
|
||||
+ 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
|
||||
|
||||
@ -1,687 +0,0 @@
|
||||
From 32c3d16175b93627504981d05a1a3e3ec603415e Mon Sep 17 00:00:00 2001
|
||||
From: renoseven <dev@renoseven.net>
|
||||
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 <dev@renoseven.net>
|
||||
---
|
||||
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<Mutex<IndexMap<PathBuf, ActivePatch>>>;
|
||||
+type ElfPatchMap = Arc<Mutex<IndexMap<PathBuf, ElfPatchRecord>>>;
|
||||
|
||||
#[derive(Default)]
|
||||
-struct ActivePatch {
|
||||
- patch_list: Vec<(Uuid, PathBuf)>, // Patch applied to target elf (uuid and patch file)
|
||||
- process_list: IndexSet<i32>, // Target elf process list
|
||||
+struct ElfPatchRecord {
|
||||
+ patch_map: IndexMap<Uuid, PathBuf>, // Patch applied to target elf (uuid and patch file)
|
||||
+ processes: IndexSet<i32>, // Target elf process list
|
||||
}
|
||||
|
||||
pub struct UserPatchDriver {
|
||||
patch_target_map: IndexMap<OsString, PatchTarget>,
|
||||
patch_status_map: IndexMap<Uuid, PatchStatus>,
|
||||
- active_patch_map: ActivePatchMap,
|
||||
+ elf_patch_map: ElfPatchMap,
|
||||
patch_monitor: UserPatchMonitor,
|
||||
}
|
||||
|
||||
impl UserPatchDriver {
|
||||
pub fn new() -> Result<Self> {
|
||||
- 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::<Vec<_>>();
|
||||
- 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::<Vec<_>>();
|
||||
|
||||
- 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::<Vec<_>>();
|
||||
+ 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::<Vec<_>>();
|
||||
+ let need_remove = patch_record
|
||||
+ .processes
|
||||
+ .difference(&process_list)
|
||||
+ .copied()
|
||||
+ .collect::<Vec<_>>();
|
||||
+ 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::<Vec<_>>();
|
||||
+ let need_removed = patch_record
|
||||
+ .processes
|
||||
+ .difference(&process_list)
|
||||
+ .copied()
|
||||
+ .collect::<Vec<_>>();
|
||||
+ 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<F>(active_patch_map: ActivePatchMap, callback: F) -> Result<Self>
|
||||
+ pub fn new<F>(elf_patch_map: ElfPatchMap, callback: F) -> Result<Self>
|
||||
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<F> {
|
||||
inotify: Arc<Mutex<Option<Inotify>>>,
|
||||
target_map: Arc<RwLock<IndexMap<WatchDescriptor, PathBuf>>>,
|
||||
- active_patch_map: ActivePatchMap,
|
||||
+ elf_patch_map: ElfPatchMap,
|
||||
callback: F,
|
||||
}
|
||||
|
||||
impl<F> MonitorThread<F>
|
||||
where
|
||||
- F: Fn(ActivePatchMap, &Path) -> Result<()> + Send + 'static,
|
||||
+ F: Fn(ElfPatchMap, &Path) + Send + Sync + 'static,
|
||||
{
|
||||
fn run(self) -> Result<thread::JoinHandle<()>> {
|
||||
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<P: AsRef<Path>>(path: P) -> Option<i32> {
|
||||
- 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<i32> {
|
||||
+ 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<P: AsRef<Path>>(target_elf: P) -> Result<IndexSet<i32>> {
|
||||
- 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<Item = &'a i32>,
|
||||
-{
|
||||
- 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<Item = &'a i32>,
|
||||
-{
|
||||
- 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
|
||||
|
||||
@ -0,0 +1,50 @@
|
||||
From ab6bc4697532862a9cec3483ce1e24e268ea3a8f Mon Sep 17 00:00:00 2001
|
||||
From: renoseven <dev@renoseven.net>
|
||||
Date: Fri, 6 Sep 2024 22:14:11 +0800
|
||||
Subject: [PATCH] upatch-helper: fix object upatch id duplicated issue
|
||||
|
||||
Signed-off-by: renoseven <dev@renoseven.net>
|
||||
---
|
||||
upatch-helper/Cargo.toml | 2 +-
|
||||
upatch-helper/src/main.rs | 6 +++---
|
||||
2 files changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/upatch-helper/Cargo.toml b/upatch-helper/Cargo.toml
|
||||
index 42f3548..b131b66 100644
|
||||
--- a/upatch-helper/Cargo.toml
|
||||
+++ b/upatch-helper/Cargo.toml
|
||||
@@ -9,5 +9,5 @@ rust-version = "1.60"
|
||||
build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
-syscare-common = { package = "syscare-common", path = "../syscare-common" }
|
||||
anyhow = { version = "1.0" }
|
||||
+uuid = { version = "0.8", features = ["v4"] }
|
||||
diff --git a/upatch-helper/src/main.rs b/upatch-helper/src/main.rs
|
||||
index d98b167..303088c 100644
|
||||
--- a/upatch-helper/src/main.rs
|
||||
+++ b/upatch-helper/src/main.rs
|
||||
@@ -15,7 +15,7 @@
|
||||
use std::{os::unix::process::CommandExt, path::Path, process::Command};
|
||||
|
||||
use anyhow::{bail, Context};
|
||||
-use syscare_common::os;
|
||||
+use uuid::Uuid;
|
||||
|
||||
const UPATCH_CC_ENV: &str = "UPATCH_HELPER_CC";
|
||||
const UPATCH_CXX_ENV: &str = "UPATCH_HELPER_CXX";
|
||||
@@ -50,9 +50,9 @@ fn main() -> anyhow::Result<()> {
|
||||
if exec_args.iter().any(|arg| arg == OUTPUT_FLAG) {
|
||||
command.args(APPEND_ARGS);
|
||||
command.arg(format!(
|
||||
- "-Wa,--defsym,{}0x{:04x}=0",
|
||||
+ "-Wa,--defsym,{}{}=0",
|
||||
UPATCH_ID_PREFIX,
|
||||
- os::process::id()
|
||||
+ Uuid::new_v4(),
|
||||
));
|
||||
}
|
||||
|
||||
--
|
||||
2.34.1
|
||||
|
||||
170
0005-syscare-build-update-README.md.patch
Normal file
170
0005-syscare-build-update-README.md.patch
Normal file
@ -0,0 +1,170 @@
|
||||
From 5e878d9fd7c56591a42e851a3821fdcbd72becab Mon Sep 17 00:00:00 2001
|
||||
From: renoseven <dev@renoseven.net>
|
||||
Date: Mon, 23 Sep 2024 15:34:34 +0800
|
||||
Subject: [PATCH] syscare-build: update README.md
|
||||
|
||||
Signed-off-by: renoseven <dev@renoseven.net>
|
||||
---
|
||||
syscare-build/README.md | 80 ++++++++++++++++++++---------------------
|
||||
1 file changed, 40 insertions(+), 40 deletions(-)
|
||||
|
||||
diff --git a/syscare-build/README.md b/syscare-build/README.md
|
||||
index e0cf66e..1f05c74 100644
|
||||
--- a/syscare-build/README.md
|
||||
+++ b/syscare-build/README.md
|
||||
@@ -9,34 +9,29 @@ syscare build为纯CLI工具,提供从RPM包生成热补丁包的功能,补
|
||||
## 命令行参数
|
||||
|
||||
```bash
|
||||
-Usage: syscare build [OPTIONS] --patch-name <PATCH_NAME> --source <SOURCE> --debuginfo <DEBUGINFO> <PATCHES>...
|
||||
-
|
||||
-Arguments:
|
||||
- <PATCHES>... Patch file(s)
|
||||
-
|
||||
-Options:
|
||||
- -n, --patch-name <PATCH_NAME> Patch name
|
||||
- --patch-arch <PATCH_ARCH> Patch architecture [default: x86_64]
|
||||
- --patch-version <PATCH_VERSION> Patch version [default: 1]
|
||||
- --patch-release <PATCH_RELEASE> Patch release [default: 1]
|
||||
- --patch-description <PATCH_DESCRIPTION> Patch description [default: (none)]
|
||||
- -s, --source <SOURCE> Source package
|
||||
- -d, --debuginfo <DEBUGINFO> Debuginfo package
|
||||
- --workdir <WORKDIR> Working directory [default: .]
|
||||
- -o, --output <OUTPUT> Generated patch output directory [default: .]
|
||||
- --jobs <N> Parallel build jobs [default: 96]
|
||||
- --skip-compiler-check Skip compiler version check (not recommended)
|
||||
- --skip-cleanup Skip post-build cleanup
|
||||
- -v, --verbose Provide more detailed info
|
||||
- -h, --help Print help information
|
||||
- -V, --version Print version information
|
||||
+USAGE:
|
||||
+ syscare build [OPTIONS] --patch-name <PATCH_NAME> --source <SOURCE>... --debuginfo <DEBUGINFO>... --patch <PATCH>...
|
||||
+
|
||||
+OPTIONS:
|
||||
+ -n, --patch-name <PATCH_NAME> Patch name
|
||||
+ --patch-arch <PATCH_ARCH> Patch architecture [default: x86_64]
|
||||
+ --patch-version <PATCH_VERSION> Patch version [default: 1]
|
||||
+ --patch-release <PATCH_RELEASE> Patch release [default: 1]
|
||||
+ --patch-description <PATCH_DESCRIPTION> Patch description [default: (none)]
|
||||
+ --patch-requires <PATCH_REQUIRES>... Patch requirements
|
||||
+ -s, --source <SOURCE>... Source package(s)
|
||||
+ -d, --debuginfo <DEBUGINFO>... Debuginfo package(s)
|
||||
+ -p, --patch <PATCH>... Patch file(s)
|
||||
+ --build-root <BUILD_ROOT> Build directory [default: .]
|
||||
+ -o, --output <OUTPUT> Output directory [default: .]
|
||||
+ -j, --jobs <JOBS> Parallel build jobs [default: 20]
|
||||
+ --skip-compiler-check Skip compiler version check (not recommended)
|
||||
+ --skip-cleanup Skip post-build cleanup
|
||||
+ -v, --verbose Provide more detailed info
|
||||
+ -h, --help Print help information
|
||||
+ -V, --version Print version information
|
||||
```
|
||||
|
||||
-### 参数
|
||||
-|名称|描述|类型|备注|
|
||||
-| ---- | ---- | ---- | ---- |
|
||||
-| ```<PATCHES>```... |补丁文件路径|字符串|必选参数,可指定多个,需为合法路径|
|
||||
-
|
||||
### 选项
|
||||
|名称|描述|类型|备注|
|
||||
| ---- | ---- | ---- | ---- |
|
||||
@@ -45,9 +40,11 @@ Options:
|
||||
|--patch-version ```<PATCH_VERSION>```|补丁版本号|字符串|默认值为1,需符合RPM命名规范|
|
||||
|--patch-release ```<PATCH_RELEASE>```|补丁release|数字|默认值为1,需符合RPM命名规范|
|
||||
|--patch-description ```<PATCH_DESCRIPTION>```|补丁描述|字符串|默认为(none)|
|
||||
+|--patch-requires ```<PATCH_REQUIRES>```|补丁依赖|字符串|默认为(none)|
|
||||
|-s, --source ```<SOURCE>```|目标软件src.rpm源码包路径|字符串|必选参数,需为合法路径|
|
||||
|-d, --debuginfo ```<DEBUGINFO>```|目标软件debuginfo包路径|字符串|必选参数,需为合法路径|
|
||||
-|--workdir ```<WORKDIR>```|临时文件夹路径|字符串|默认为当前执行目录,需为合法路径|
|
||||
+|-p, --patch ```<PATCH>```|目标软件debuginfo包路径|字符串|必选参数,需为合法路径|
|
||||
+|--build-root ```<BUILD_ROOT>```|编译临时目录|字符串|默认为当前执行目录|
|
||||
|-o, --output ```<OUTPUT>```|补丁输出文件夹|字符串|默认为当前执行目录,需为合法路径|
|
||||
|-j, --jobs ```<N>```|并行编译线程数|数字|默认为cpu线程数|
|
||||
|--skip-compiler-check|跳过编译器检查|标识|-|
|
||||
@@ -103,17 +100,19 @@ syscare build \
|
||||
| arch | 补丁架构 |
|
||||
| type | 补丁类型 |
|
||||
| target | 目标软件名 |
|
||||
-| target_elf | 目标软件可执行文件名称 |
|
||||
-| digest | 补丁指纹 |
|
||||
| license | 目标软件许可证 |
|
||||
| description | 补丁描述 |
|
||||
-| patch| 补丁文件列表 |
|
||||
+| entities | 补丁实体列表 |
|
||||
+| patch | 补丁文件列表 |
|
||||
|
||||
|
||||
示例:
|
||||
|
||||
```bash
|
||||
-dev@openeuler-dev:[output]$ syscare info redis-6.2.5-1/HP001
|
||||
+dev@dev-x86:[output]$ syscare info redis-6.2.5-1/HP001-1-1
|
||||
+---------------------------------------------------
|
||||
+Patch: redis-6.2.5-1/HP001-1-1
|
||||
+---------------------------------------------------
|
||||
uuid: ec503257-aa75-4abc-9045-c4afdd7ae0f2
|
||||
name: HP001
|
||||
version: 1
|
||||
@@ -121,12 +120,15 @@ release: 1
|
||||
arch: x86_64
|
||||
type: UserPatch
|
||||
target: redis-6.2.5-1
|
||||
-target_elf: redis-cli, redis-server, redis-benchmark
|
||||
-digest: 31fc7544
|
||||
license: BSD and MIT
|
||||
description: CVE-2021-32675 - When parsing an incoming Redis Standard Protocol (RESP) request, Redis allocates memory according to user-specified values which determine the number of elements (in the multi-bulk header) and size of each element (in the bulk header). An attacker delivering specially crafted requests over multiple connections can cause the server to allocate significant amount of memory. Because the same parsing mechanism is used to handle authentication requests, this vulnerability can also be exploited by unauthenticated users.
|
||||
+entities:
|
||||
+* redis-server
|
||||
+* redis-cli
|
||||
+* redis-benchmark
|
||||
patch:
|
||||
-31fc7544 0001-Prevent-unauthenticated-client-from-easily-consuming.patch
|
||||
+* 0001-Prevent-unauthenticated-client-from-easily-consuming.patch
|
||||
+---------------------------------------------------
|
||||
```
|
||||
|
||||
|
||||
@@ -156,7 +158,7 @@ patch:
|
||||
示例:
|
||||
|
||||
```bash
|
||||
- syscare-build \
|
||||
+ syscare build \
|
||||
--patch-name HP001 \
|
||||
--source kernel-5.10.0-60.66.0.91.oe2203.src.rpm \
|
||||
--debuginfo kernel-debuginfo-5.10.0-60.66.0.91.oe2203.x86_64.rpm \
|
||||
@@ -164,12 +166,10 @@ patch:
|
||||
001-kernel-patch-test.patch
|
||||
```
|
||||
|
||||
- 补丁制作过程将会在由`--workdir`参数所指定的目录中(默认为当前目录)创建以```syscare-build```开头的临时文件夹,用于存放临时文件及编译日志。
|
||||
-
|
||||
示例:
|
||||
|
||||
```bash
|
||||
- dev@openeuler-dev:[kernel_patch]$ ls -l syscare-build.111602/
|
||||
+ dev@dev-x86:[kernel_patch]$ ls -l syscare-build.111602/
|
||||
total 100
|
||||
-rw-r--r--. 1 dev dev 92303 Nov 12 00:00 build.log
|
||||
drwxr-xr-x. 6 dev dev 4096 Nov 12 00:00 package
|
||||
@@ -177,7 +177,7 @@ patch:
|
||||
```
|
||||
编译日志将会生成在临时文件夹中,名称为```build.log```
|
||||
```bash
|
||||
- dev@openeuler-dev:[kernel_patch]$ cat syscare-build.111602/build.log | less
|
||||
+ dev@dev-x86:[kernel_patch]$ cat syscare-build.111602/build.log | less
|
||||
...
|
||||
```
|
||||
若补丁制作成功,将不会保留该临时文件夹。
|
||||
@@ -187,7 +187,7 @@ patch:
|
||||
示例:
|
||||
|
||||
```bash
|
||||
- dev@openeuler-dev:[output]$ ll
|
||||
+ dev@dev-x86:[output]$ ll
|
||||
total 372M
|
||||
-rw-r--r--. 1 dev dev 186M Nov 12 00:00 kernel-5.10.0-60.80.0.104.oe2203-HP001-1-1.x86_64.src.rpm
|
||||
-rw-r--r--. 1 dev dev 11K Nov 12 00:00 patch-kernel-5.10.0-60.80.0.104.oe2203-HP001-1-1.x86_64.rpm
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@ -1,103 +0,0 @@
|
||||
From a61958c837b70c0c530d32ee58b616ab9ad01f4b Mon Sep 17 00:00:00 2001
|
||||
From: renoseven <dev@renoseven.net>
|
||||
Date: Fri, 12 Apr 2024 11:35:57 +0800
|
||||
Subject: [PATCH 05/20] syscared: optimize patch error logic
|
||||
|
||||
Signed-off-by: renoseven <dev@renoseven.net>
|
||||
---
|
||||
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<Self> {
|
||||
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
|
||||
|
||||
@ -1,112 +0,0 @@
|
||||
From 211e4549324a9209dc982b7426af8b832410b619 Mon Sep 17 00:00:00 2001
|
||||
From: renoseven <dev@renoseven.net>
|
||||
Date: Fri, 12 Apr 2024 11:40:25 +0800
|
||||
Subject: [PATCH 06/20] syscared: optimize transaction creation logic
|
||||
|
||||
Signed-off-by: renoseven <dev@renoseven.net>
|
||||
---
|
||||
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<Self> {
|
||||
- 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
|
||||
|
||||
162
0006-syscared-support-saving-restoring-patch-status-by-op.patch
Normal file
162
0006-syscared-support-saving-restoring-patch-status-by-op.patch
Normal file
@ -0,0 +1,162 @@
|
||||
From d98892b0452499284fc577388cf8045af0ffa071 Mon Sep 17 00:00:00 2001
|
||||
From: renoseven <dev@renoseven.net>
|
||||
Date: Thu, 17 Oct 2024 22:24:21 +0800
|
||||
Subject: [PATCH] syscared: support saving & restoring patch status by
|
||||
operation order
|
||||
|
||||
Signed-off-by: renoseven <dev@renoseven.net>
|
||||
---
|
||||
syscared/Cargo.toml | 2 +-
|
||||
syscared/src/patch/manager.rs | 84 ++++++++++++-----------------------
|
||||
2 files changed, 30 insertions(+), 56 deletions(-)
|
||||
|
||||
diff --git a/syscared/Cargo.toml b/syscared/Cargo.toml
|
||||
index 1bfd43f..2eecea8 100644
|
||||
--- a/syscared/Cargo.toml
|
||||
+++ b/syscared/Cargo.toml
|
||||
@@ -16,7 +16,7 @@ clap = { version = "3.2", features = ["cargo", "derive"] }
|
||||
daemonize = { version = "0.5" }
|
||||
flexi_logger = { version = "0.24", features = ["compress"] }
|
||||
inotify = { version = "0.9" }
|
||||
-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/syscared/src/patch/manager.rs b/syscared/src/patch/manager.rs
|
||||
index a17703c..48c583a 100644
|
||||
--- a/syscared/src/patch/manager.rs
|
||||
+++ b/syscared/src/patch/manager.rs
|
||||
@@ -13,8 +13,6 @@
|
||||
*/
|
||||
|
||||
use std::{
|
||||
- cmp::Ordering,
|
||||
- collections::HashMap,
|
||||
path::{Path, PathBuf},
|
||||
str::FromStr,
|
||||
sync::Arc,
|
||||
@@ -221,19 +219,16 @@ impl PatchManager {
|
||||
pub fn save_patch_status(&mut self) -> Result<()> {
|
||||
info!("Saving all patch status...");
|
||||
|
||||
- debug!("Updating all patch status...");
|
||||
+ debug!("Updating patch status...");
|
||||
for patch in self.get_patch_list() {
|
||||
- debug!("Update patch '{}' status", patch);
|
||||
self.get_patch_status(&patch)?;
|
||||
}
|
||||
|
||||
- let mut status_map = HashMap::new();
|
||||
+ debug!("Writing patch status...");
|
||||
for (uuid, status) in &self.status_map {
|
||||
- status_map.insert(uuid, status);
|
||||
+ debug!("Patch '{}' status: {}", uuid, status);
|
||||
}
|
||||
-
|
||||
- debug!("Writing patch status file");
|
||||
- serde::serialize(&status_map, &self.patch_status_file)
|
||||
+ serde::serialize(&self.status_map, &self.patch_status_file)
|
||||
.context("Failed to write patch status file")?;
|
||||
|
||||
fs::sync();
|
||||
@@ -244,57 +239,35 @@ impl PatchManager {
|
||||
|
||||
pub fn restore_patch_status(&mut self, accepted_only: bool) -> Result<()> {
|
||||
info!("Restoring all patch status...");
|
||||
+ if !self.patch_status_file.exists() {
|
||||
+ return Ok(());
|
||||
+ }
|
||||
|
||||
debug!("Reading patch status...");
|
||||
- let status_file = &self.patch_status_file;
|
||||
- let status_map: HashMap<Uuid, PatchStatus> = if status_file.exists() {
|
||||
- serde::deserialize(status_file).context("Failed to read patch status")?
|
||||
- } else {
|
||||
- warn!("Cannot find patch status file");
|
||||
- return Ok(());
|
||||
- };
|
||||
+ let status_map: IndexMap<Uuid, PatchStatus> =
|
||||
+ serde::deserialize(&self.patch_status_file).context("Failed to read patch status")?;
|
||||
+ for (uuid, status) in &status_map {
|
||||
+ debug!("Patch '{}' status: {}", uuid, status);
|
||||
+ }
|
||||
|
||||
- /*
|
||||
- * To ensure that we won't load multiple patches for same target at the same time,
|
||||
- * we take a sort operation of the status to make sure do REMOVE operation at first
|
||||
- */
|
||||
- let mut restore_list = status_map
|
||||
+ let restore_list = status_map
|
||||
.into_iter()
|
||||
- .filter_map(|(uuid, status)| match self.find_patch_by_uuid(&uuid) {
|
||||
+ .filter(|(_, status)| !accepted_only || (*status == PatchStatus::Accepted));
|
||||
+ for (uuid, status) in restore_list {
|
||||
+ match self.find_patch_by_uuid(&uuid) {
|
||||
Ok(patch) => {
|
||||
- if accepted_only && (status != PatchStatus::Accepted) {
|
||||
- debug!(
|
||||
- "Skipped patch '{}', status is not '{}'",
|
||||
- patch,
|
||||
- PatchStatus::Accepted
|
||||
- );
|
||||
- return None;
|
||||
+ debug!("Restore patch '{}' status to '{}'", patch, status);
|
||||
+ if let Err(e) = self.do_status_transition(&patch, status, PatchOpFlag::Force) {
|
||||
+ error!("{}", e);
|
||||
}
|
||||
- Some((patch, status))
|
||||
}
|
||||
Err(e) => {
|
||||
- error!("{:?}", e);
|
||||
- None
|
||||
+ error!("{}", e);
|
||||
}
|
||||
- })
|
||||
- .collect::<Vec<_>>();
|
||||
-
|
||||
- restore_list.sort_by(|(lhs_patch, lhs_status), (rhs_patch, rhs_status)| {
|
||||
- match lhs_status.cmp(rhs_status) {
|
||||
- Ordering::Less => Ordering::Less,
|
||||
- Ordering::Equal => lhs_patch.cmp(rhs_patch),
|
||||
- Ordering::Greater => Ordering::Greater,
|
||||
- }
|
||||
- });
|
||||
-
|
||||
- for (patch, target_status) in restore_list {
|
||||
- debug!("Restore patch '{}' status to '{}'", patch, target_status);
|
||||
- if let Err(e) = self.do_status_transition(&patch, target_status, PatchOpFlag::Force) {
|
||||
- error!("{}", e);
|
||||
}
|
||||
}
|
||||
- info!("All patch status were restored");
|
||||
|
||||
+ info!("All patch status were restored");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -426,13 +399,14 @@ impl PatchManager {
|
||||
bail!("Cannot set patch '{}' status to '{}'", patch, value);
|
||||
}
|
||||
|
||||
- let status_map = &mut self.status_map;
|
||||
- match status_map.get_mut(patch.uuid()) {
|
||||
- Some(status) => {
|
||||
- *status = value;
|
||||
- }
|
||||
- None => {
|
||||
- status_map.insert(*patch.uuid(), value);
|
||||
+ let (index, _) = self.status_map.insert_full(*patch.uuid(), value);
|
||||
+ if let Some(last_index) = self
|
||||
+ .status_map
|
||||
+ .last()
|
||||
+ .and_then(|(key, _)| self.status_map.get_index_of(key))
|
||||
+ {
|
||||
+ if index != last_index {
|
||||
+ self.status_map.move_index(index, last_index);
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.34.1
|
||||
|
||||
34
0007-project-update-Cargo.lock.patch
Normal file
34
0007-project-update-Cargo.lock.patch
Normal file
@ -0,0 +1,34 @@
|
||||
From ad418b6d9f30bda58488da27257efe10ca2906e3 Mon Sep 17 00:00:00 2001
|
||||
From: renoseven <dev@renoseven.net>
|
||||
Date: Thu, 17 Oct 2024 23:15:46 +0800
|
||||
Subject: [PATCH] project: update Cargo.lock
|
||||
|
||||
Signed-off-by: renoseven <dev@renoseven.net>
|
||||
---
|
||||
Cargo.lock | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/Cargo.lock b/Cargo.lock
|
||||
index 48ca061..30f2015 100644
|
||||
--- a/Cargo.lock
|
||||
+++ b/Cargo.lock
|
||||
@@ -511,6 +511,7 @@ checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
+ "serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1337,7 +1338,7 @@ name = "upatch-helper"
|
||||
version = "1.2.2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
- "syscare-common",
|
||||
+ "uuid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@ -1,136 +0,0 @@
|
||||
From a32e9f39965579064dbd504246f13c6431ffed33 Mon Sep 17 00:00:00 2001
|
||||
From: renoseven <dev@renoseven.net>
|
||||
Date: Fri, 12 Apr 2024 11:50:59 +0800
|
||||
Subject: [PATCH 07/20] upatch-manage: optimize output
|
||||
|
||||
Signed-off-by: renoseven <dev@renoseven.net>
|
||||
---
|
||||
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
|
||||
|
||||
74
0008-all-remove-signal-handler.patch
Normal file
74
0008-all-remove-signal-handler.patch
Normal file
@ -0,0 +1,74 @@
|
||||
From 5daf18084f8d2865db24b6627d2d28d9234bcf5c Mon Sep 17 00:00:00 2001
|
||||
From: renoseven <dev@renoseven.net>
|
||||
Date: Mon, 10 Feb 2025 10:49:49 +0800
|
||||
Subject: [PATCH] all: remove signal handler
|
||||
|
||||
Signed-off-by: renoseven <dev@renoseven.net>
|
||||
---
|
||||
syscare-build/Cargo.toml | 1 -
|
||||
syscare-build/src/main.rs | 6 ------
|
||||
upatch-build/Cargo.toml | 1 -
|
||||
upatch-build/src/main.rs | 6 ------
|
||||
4 files changed, 14 deletions(-)
|
||||
|
||||
diff --git a/syscare-build/Cargo.toml b/syscare-build/Cargo.toml
|
||||
index 558b2bc..ba4d1c8 100644
|
||||
--- a/syscare-build/Cargo.toml
|
||||
+++ b/syscare-build/Cargo.toml
|
||||
@@ -14,7 +14,6 @@ syscare-common = { package = "syscare-common", path = "../syscare-common" }
|
||||
anyhow = { version = "1.0" }
|
||||
clap = { version = "3.2", features = ["derive"] }
|
||||
chrono = { version = "0.4" }
|
||||
-ctrlc = { version = "3.3" }
|
||||
flexi_logger = { version = "0.24" }
|
||||
lazy_static = { version = "1.0" }
|
||||
log = { version = "0.4" }
|
||||
diff --git a/syscare-build/src/main.rs b/syscare-build/src/main.rs
|
||||
index 2fb714d..64363bf 100644
|
||||
--- a/syscare-build/src/main.rs
|
||||
+++ b/syscare-build/src/main.rs
|
||||
@@ -103,12 +103,6 @@ impl SyscareBuild {
|
||||
.start()
|
||||
.context("Failed to initialize logger")?;
|
||||
|
||||
- // Initialize signal handler
|
||||
- ctrlc::set_handler(|| {
|
||||
- eprintln!("Interrupt");
|
||||
- })
|
||||
- .context("Failed to initialize signal handler")?;
|
||||
-
|
||||
Ok(Self {
|
||||
args,
|
||||
logger,
|
||||
diff --git a/upatch-build/Cargo.toml b/upatch-build/Cargo.toml
|
||||
index 5123149..88d88b3 100644
|
||||
--- a/upatch-build/Cargo.toml
|
||||
+++ b/upatch-build/Cargo.toml
|
||||
@@ -12,7 +12,6 @@ build = "build.rs"
|
||||
syscare-common = { package = "syscare-common", path = "../syscare-common" }
|
||||
anyhow = { version = "1.0" }
|
||||
clap = { version = "3.2", features = ["cargo", "derive"] }
|
||||
-ctrlc = { version = "3.3" }
|
||||
flexi_logger = { version = "0.24" }
|
||||
function_name = { version = "0.3" }
|
||||
gimli = { version = "0.26" }
|
||||
diff --git a/upatch-build/src/main.rs b/upatch-build/src/main.rs
|
||||
index 77b256a..09f907b 100644
|
||||
--- a/upatch-build/src/main.rs
|
||||
+++ b/upatch-build/src/main.rs
|
||||
@@ -98,12 +98,6 @@ impl UpatchBuild {
|
||||
.start()
|
||||
.context("Failed to initialize logger")?;
|
||||
|
||||
- // Initialize signal handler
|
||||
- ctrlc::set_handler(|| {
|
||||
- eprintln!("Interrupt");
|
||||
- })
|
||||
- .context("Failed to initialize signal handler")?;
|
||||
-
|
||||
Ok(Self {
|
||||
args,
|
||||
logger,
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@ -1,47 +0,0 @@
|
||||
From cc090b31139bb9aa0158e50a8a620fc41b23231c Mon Sep 17 00:00:00 2001
|
||||
From: renoseven <dev@renoseven.net>
|
||||
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 <dev@renoseven.net>
|
||||
---
|
||||
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<CStr> {
|
||||
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<T: AsRef<CStr>> 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
|
||||
|
||||
66
0009-project-update-Cargo.lock.patch
Normal file
66
0009-project-update-Cargo.lock.patch
Normal file
@ -0,0 +1,66 @@
|
||||
From bed35b84e7cbeaafd16c9c01650243ae548a9c14 Mon Sep 17 00:00:00 2001
|
||||
From: renoseven <dev@renoseven.net>
|
||||
Date: Mon, 10 Feb 2025 11:49:40 +0800
|
||||
Subject: [PATCH] project: update Cargo.lock
|
||||
|
||||
Signed-off-by: renoseven <dev@renoseven.net>
|
||||
---
|
||||
Cargo.lock | 21 ---------------------
|
||||
1 file changed, 21 deletions(-)
|
||||
|
||||
diff --git a/Cargo.lock b/Cargo.lock
|
||||
index 30f2015..6ae9f36 100644
|
||||
--- a/Cargo.lock
|
||||
+++ b/Cargo.lock
|
||||
@@ -210,16 +210,6 @@ dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
-[[package]]
|
||||
-name = "ctrlc"
|
||||
-version = "3.3.0"
|
||||
-source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
-checksum = "04d778600249295e82b6ab12e291ed9029407efee0cfb7baf67157edc65964df"
|
||||
-dependencies = [
|
||||
- "nix",
|
||||
- "windows-sys",
|
||||
-]
|
||||
-
|
||||
[[package]]
|
||||
name = "daemonize"
|
||||
version = "0.5.0"
|
||||
@@ -1140,7 +1130,6 @@ dependencies = [
|
||||
"anyhow",
|
||||
"chrono",
|
||||
"clap",
|
||||
- "ctrlc",
|
||||
"flexi_logger",
|
||||
"lazy_static",
|
||||
"log",
|
||||
@@ -1317,7 +1306,6 @@ version = "1.2.2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"clap",
|
||||
- "ctrlc",
|
||||
"flexi_logger",
|
||||
"function_name",
|
||||
"gimli",
|
||||
@@ -1474,15 +1462,6 @@ dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
-[[package]]
|
||||
-name = "windows-sys"
|
||||
-version = "0.48.0"
|
||||
-source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
-checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
-dependencies = [
|
||||
- "windows-targets",
|
||||
-]
|
||||
-
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
--
|
||||
2.34.1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
52
0010-syscare-remove-working-directory-check.patch
Normal file
52
0010-syscare-remove-working-directory-check.patch
Normal file
@ -0,0 +1,52 @@
|
||||
From 707475a7361b6f16ca2b9e62f222b1982a57e506 Mon Sep 17 00:00:00 2001
|
||||
From: renoseven <dev@renoseven.net>
|
||||
Date: Mon, 10 Feb 2025 14:21:29 +0800
|
||||
Subject: [PATCH] syscare: remove working directory check
|
||||
|
||||
Signed-off-by: renoseven <dev@renoseven.net>
|
||||
---
|
||||
syscare/src/args.rs | 14 ++------------
|
||||
1 file changed, 2 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/syscare/src/args.rs b/syscare/src/args.rs
|
||||
index 4f034a0..5e7299d 100644
|
||||
--- a/syscare/src/args.rs
|
||||
+++ b/syscare/src/args.rs
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
-use anyhow::{ensure, Result};
|
||||
+use anyhow::Result;
|
||||
use clap::{AppSettings, ColorChoice, Parser, Subcommand};
|
||||
|
||||
use syscare_common::fs;
|
||||
@@ -131,7 +131,7 @@ pub enum SubCommand {
|
||||
|
||||
impl Arguments {
|
||||
pub fn new() -> Result<Self> {
|
||||
- Self::parse().normalize_path().and_then(Self::check)
|
||||
+ Self::parse().normalize_path()
|
||||
}
|
||||
|
||||
fn normalize_path(mut self) -> Result<Self> {
|
||||
@@ -139,16 +139,6 @@ impl Arguments {
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
-
|
||||
- fn check(self) -> Result<Self> {
|
||||
- let work_dir = &self.work_dir;
|
||||
- ensure!(
|
||||
- work_dir.is_dir(),
|
||||
- format!("Cannot find directory {}", work_dir.display())
|
||||
- );
|
||||
-
|
||||
- Ok(self)
|
||||
- }
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Arguments {
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@ -1,237 +0,0 @@
|
||||
From a83410a74713c4f191aeb31bc9ea87b9e9f4bcc6 Mon Sep 17 00:00:00 2001
|
||||
From: renoseven <dev@renoseven.net>
|
||||
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 <dev@renoseven.net>
|
||||
---
|
||||
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
|
||||
|
||||
162
0011-all-fix-cargo-clippy-warnings.patch
Normal file
162
0011-all-fix-cargo-clippy-warnings.patch
Normal file
@ -0,0 +1,162 @@
|
||||
From 2af03514afcc797cac3125c7b04ee0f5eae43aa0 Mon Sep 17 00:00:00 2001
|
||||
From: renoseven <dev@renoseven.net>
|
||||
Date: Mon, 10 Feb 2025 10:29:00 +0800
|
||||
Subject: [PATCH] all: fix cargo clippy warnings
|
||||
|
||||
Signed-off-by: renoseven <dev@renoseven.net>
|
||||
---
|
||||
syscare-common/src/ffi/os_str.rs | 2 +-
|
||||
syscare-common/src/fs/fs_impl.rs | 4 ++--
|
||||
syscare-common/src/os_str/iter.rs | 2 +-
|
||||
syscare-common/src/process/stdio.rs | 4 ++--
|
||||
syscared/src/args.rs | 1 -
|
||||
syscared/src/patch/resolver/kpatch.rs | 2 +-
|
||||
syscared/src/patch/resolver/upatch.rs | 2 +-
|
||||
upatch-build/src/dwarf/mod.rs | 6 +++---
|
||||
upatch-build/src/dwarf/relocate.rs | 4 ++--
|
||||
9 files changed, 13 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/syscare-common/src/ffi/os_str.rs b/syscare-common/src/ffi/os_str.rs
|
||||
index 375ef82..0c414e1 100644
|
||||
--- a/syscare-common/src/ffi/os_str.rs
|
||||
+++ b/syscare-common/src/ffi/os_str.rs
|
||||
@@ -119,7 +119,7 @@ pub trait OsStrExt: AsRef<OsStr> {
|
||||
}
|
||||
}
|
||||
|
||||
- fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<P> {
|
||||
+ fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> {
|
||||
let haystack = self.as_ref().as_bytes();
|
||||
|
||||
Split(SplitImpl {
|
||||
diff --git a/syscare-common/src/fs/fs_impl.rs b/syscare-common/src/fs/fs_impl.rs
|
||||
index 23f8493..30c11b7 100644
|
||||
--- a/syscare-common/src/fs/fs_impl.rs
|
||||
+++ b/syscare-common/src/fs/fs_impl.rs
|
||||
@@ -379,10 +379,10 @@ where
|
||||
if !file_type.is_file() {
|
||||
return false;
|
||||
}
|
||||
- return file_path
|
||||
+ file_path
|
||||
.extension()
|
||||
.map(|s| s == ext.as_ref())
|
||||
- .unwrap_or(false);
|
||||
+ .unwrap_or(false)
|
||||
})
|
||||
}
|
||||
|
||||
diff --git a/syscare-common/src/os_str/iter.rs b/syscare-common/src/os_str/iter.rs
|
||||
index 2868c2e..e472d0c 100644
|
||||
--- a/syscare-common/src/os_str/iter.rs
|
||||
+++ b/syscare-common/src/os_str/iter.rs
|
||||
@@ -165,7 +165,7 @@ impl<'a, P: Pattern<'a>> SplitImpl<'a, P> {
|
||||
}
|
||||
|
||||
self.finished = true;
|
||||
- return Some(OsStr::from_bytes(&haystack[self.position..]));
|
||||
+ Some(OsStr::from_bytes(&haystack[self.position..]))
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/syscare-common/src/process/stdio.rs b/syscare-common/src/process/stdio.rs
|
||||
index 450019a..9a93e56 100644
|
||||
--- a/syscare-common/src/process/stdio.rs
|
||||
+++ b/syscare-common/src/process/stdio.rs
|
||||
@@ -160,10 +160,10 @@ impl Stdio {
|
||||
}
|
||||
}
|
||||
}
|
||||
- if stdout_buf.ends_with(&[b'\n']) {
|
||||
+ if stdout_buf.ends_with(b"\n") {
|
||||
stdout_buf.pop();
|
||||
}
|
||||
- if stderr_buf.ends_with(&[b'\n']) {
|
||||
+ if stderr_buf.ends_with(b"\n") {
|
||||
stderr_buf.pop();
|
||||
}
|
||||
|
||||
diff --git a/syscared/src/args.rs b/syscared/src/args.rs
|
||||
index 4c28dff..f98b54b 100644
|
||||
--- a/syscared/src/args.rs
|
||||
+++ b/syscared/src/args.rs
|
||||
@@ -37,7 +37,6 @@ const DEFAULT_LOG_LEVEL: &str = "info";
|
||||
global_setting(AppSettings::DeriveDisplayOrder),
|
||||
term_width(120),
|
||||
)]
|
||||
-
|
||||
pub struct Arguments {
|
||||
/// Run as a daemon
|
||||
#[clap(short, long)]
|
||||
diff --git a/syscared/src/patch/resolver/kpatch.rs b/syscared/src/patch/resolver/kpatch.rs
|
||||
index 85ec18e..863f65b 100644
|
||||
--- a/syscared/src/patch/resolver/kpatch.rs
|
||||
+++ b/syscared/src/patch/resolver/kpatch.rs
|
||||
@@ -86,7 +86,7 @@ mod ffi {
|
||||
}
|
||||
}
|
||||
|
||||
- impl<'data, 'file, Elf: FileHeader> Iterator for KpatchRelocationIterator<'data, 'file, Elf> {
|
||||
+ impl<Elf: FileHeader> Iterator for KpatchRelocationIterator<'_, '_, Elf> {
|
||||
type Item = KpatchRelocation;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
diff --git a/syscared/src/patch/resolver/upatch.rs b/syscared/src/patch/resolver/upatch.rs
|
||||
index e8c2f2c..e49dff9 100644
|
||||
--- a/syscared/src/patch/resolver/upatch.rs
|
||||
+++ b/syscared/src/patch/resolver/upatch.rs
|
||||
@@ -73,7 +73,7 @@ mod ffi {
|
||||
}
|
||||
}
|
||||
|
||||
- impl<'data, 'file, Elf: FileHeader> Iterator for UpatchRelocationIterator<'data, 'file, Elf> {
|
||||
+ impl<Elf: FileHeader> Iterator for UpatchRelocationIterator<'_, '_, Elf> {
|
||||
type Item = UpatchRelocation;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
diff --git a/upatch-build/src/dwarf/mod.rs b/upatch-build/src/dwarf/mod.rs
|
||||
index 0c172c5..4399b51 100644
|
||||
--- a/upatch-build/src/dwarf/mod.rs
|
||||
+++ b/upatch-build/src/dwarf/mod.rs
|
||||
@@ -233,13 +233,13 @@ impl Dwarf {
|
||||
while let Some(attr) = attrs.next()? {
|
||||
match attr.name() {
|
||||
constants::DW_AT_comp_dir => {
|
||||
- element.compile_dir.push(&Self::attr_value(&attr, dwarf));
|
||||
+ element.compile_dir.push(Self::attr_value(&attr, dwarf));
|
||||
}
|
||||
constants::DW_AT_name => {
|
||||
- element.file_name.push(&Self::attr_value(&attr, dwarf));
|
||||
+ element.file_name.push(Self::attr_value(&attr, dwarf));
|
||||
}
|
||||
constants::DW_AT_producer => {
|
||||
- element.producer.push(&Self::attr_value(&attr, dwarf));
|
||||
+ element.producer.push(Self::attr_value(&attr, dwarf));
|
||||
}
|
||||
_ => continue,
|
||||
}
|
||||
diff --git a/upatch-build/src/dwarf/relocate.rs b/upatch-build/src/dwarf/relocate.rs
|
||||
index e8c7cdf..a6e8fb9 100644
|
||||
--- a/upatch-build/src/dwarf/relocate.rs
|
||||
+++ b/upatch-build/src/dwarf/relocate.rs
|
||||
@@ -25,7 +25,7 @@ pub struct Relocate<'a, R: gimli::Reader<Offset = usize>> {
|
||||
pub reader: R,
|
||||
}
|
||||
|
||||
-impl<'a, R: gimli::Reader<Offset = usize>> Relocate<'a, R> {
|
||||
+impl<R: gimli::Reader<Offset = usize>> Relocate<'_, R> {
|
||||
pub fn relocate(&self, offset: usize, value: u64) -> u64 {
|
||||
if let Some(relocation) = self.relocations.get(&offset) {
|
||||
if relocation.kind() == object::RelocationKind::Absolute {
|
||||
@@ -41,7 +41,7 @@ impl<'a, R: gimli::Reader<Offset = usize>> Relocate<'a, R> {
|
||||
}
|
||||
}
|
||||
|
||||
-impl<'a, R: gimli::Reader<Offset = usize>> gimli::Reader for Relocate<'a, R> {
|
||||
+impl<R: gimli::Reader<Offset = usize>> gimli::Reader for Relocate<'_, R> {
|
||||
type Endian = R::Endian;
|
||||
type Offset = R::Offset;
|
||||
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@ -1,35 +0,0 @@
|
||||
From 4ad0b0369cd039b64635d2c405fa244b6c6afb59 Mon Sep 17 00:00:00 2001
|
||||
From: renoseven <dev@renoseven.net>
|
||||
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 <dev@renoseven.net>
|
||||
---
|
||||
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
|
||||
|
||||
@ -1,446 +0,0 @@
|
||||
From e04ce4a7539a469091fef8c1566a85fe6050f728 Mon Sep 17 00:00:00 2001
|
||||
From: renoseven <dev@renoseven.net>
|
||||
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 <dev@renoseven.net>
|
||||
---
|
||||
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 <errno.h>
|
||||
+#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
--
|
||||
2.34.1
|
||||
|
||||
@ -1,140 +0,0 @@
|
||||
From ff07e664cb475fa74b4f6531d8e709a5dd9b55dd Mon Sep 17 00:00:00 2001
|
||||
From: renoseven <dev@renoseven.net>
|
||||
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 <dev@renoseven.net>
|
||||
---
|
||||
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
|
||||
|
||||
@ -1,224 +0,0 @@
|
||||
From c2fc4243ed918717bbcaa4a0c1b400051c7eded7 Mon Sep 17 00:00:00 2001
|
||||
From: ningyu <ningyu9@huawei.com>
|
||||
Date: Tue, 9 Apr 2024 09:21:35 +0000
|
||||
Subject: [PATCH 14/20] abi: change uuid string to uuid bytes
|
||||
|
||||
Signed-off-by: ningyu <ningyu9@huawei.com>
|
||||
---
|
||||
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<Vec<PatchInfo>> {
|
||||
// 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<Patch> {
|
||||
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
|
||||
|
||||
@ -1,557 +0,0 @@
|
||||
From 8deffbf247f51a8601e81bd65e448d9f228e98a8 Mon Sep 17 00:00:00 2001
|
||||
From: renoseven <dev@renoseven.net>
|
||||
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 <dev@renoseven.net>
|
||||
---
|
||||
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<PathBuf>,
|
||||
|
||||
- /// Specify the directory of searching elf [default: <SOURCE_DIR>]
|
||||
- #[clap(long, default_value = "", hide_default_value = true)]
|
||||
+ /// Specify the directory for searching elf [default: <SOURCE_DIR>]
|
||||
+ #[clap(long, default_value = DEFAULT_ELF_DIR, hide_default_value = true)]
|
||||
pub elf_dir: PathBuf,
|
||||
|
||||
+ /// Specify the directory for searching object [default: <SOURCE_DIR>]
|
||||
+ #[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<PathBuf>,
|
||||
@@ -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<I, P, Q>(compilers: I, build_dir: Q) -> Result<Vec<Compiler>>
|
||||
+ pub fn parse<I, P, Q>(compilers: I, temp_dir: Q) -> Result<Vec<Compiler>>
|
||||
where
|
||||
I: IntoIterator<Item = P>,
|
||||
P: AsRef<Path>,
|
||||
@@ -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<P: AsRef<Path>>(object: P) -> Result<PathBuf> {
|
||||
- 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::<IndexSet<_>>();
|
||||
-
|
||||
- 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<P: AsRef<Path>>(object: P) -> Result<IndexSet<OsString>> {
|
||||
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<PathBuf, PathBuf>, // Binary -> Debuginfo
|
||||
- source_origin_map: IndexMap<PathBuf, PathBuf>, // Source file -> Original object
|
||||
- binary_patched_map: IndexMap<PathBuf, IndexSet<PathBuf>>, // Binary -> Patched objects
|
||||
- patched_original_map: IndexMap<PathBuf, PathBuf>, // Patched object -> Original object
|
||||
+ debuginfo_map: IndexMap<PathBuf, PathBuf>, // Binary -> Debuginfo
|
||||
+ symlink_map: IndexMap<PathBuf, PathBuf>, // Symlink object -> Orignal object
|
||||
+ patch_objects_map: IndexMap<PathBuf, IndexSet<PathBuf>>, // Binary -> Patched objects
|
||||
+ original_object_map: IndexMap<PathBuf, PathBuf>, // 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<I, J, P, Q>(&mut self, binaries: I, debuginfos: J) -> Result<()>
|
||||
+ pub fn collect_debuginfo<I, J, P, Q>(&mut self, binaries: I, debuginfos: J) -> Result<()>
|
||||
where
|
||||
I: IntoIterator<Item = P>,
|
||||
J: IntoIterator<Item = Q>,
|
||||
@@ -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<P: AsRef<Path>>(&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<P, Q>(&mut self, object_dir: P, expected_dir: Q) -> Result<()>
|
||||
+ where
|
||||
+ P: AsRef<Path>,
|
||||
+ Q: AsRef<Path>,
|
||||
+ {
|
||||
+ 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<P: AsRef<Path>>(&mut self, object_dir: P) -> Result<()> {
|
||||
- for (binary, _) in &self.binary_debug_map {
|
||||
+ pub fn collect_patched_build<P, Q>(&mut self, object_dir: P, expected_dir: Q) -> Result<()>
|
||||
+ where
|
||||
+ P: AsRef<Path>,
|
||||
+ Q: AsRef<Path>,
|
||||
+ {
|
||||
+ 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<Item = (&Path, &Path)> {
|
||||
- self.binary_debug_map
|
||||
+ self.debuginfo_map
|
||||
.iter()
|
||||
.map(|(binary, debuginfo)| (binary.as_path(), debuginfo.as_path()))
|
||||
}
|
||||
|
||||
pub fn get_patched_objects<P: AsRef<Path>>(&self, binary: P) -> Option<&IndexSet<PathBuf>> {
|
||||
- self.binary_patched_map.get(binary.as_ref())
|
||||
+ self.patch_objects_map.get(binary.as_ref())
|
||||
}
|
||||
|
||||
pub fn get_original_object<P: AsRef<Path>>(&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<P, S>(object_dir: P, upatch_id: S) -> Result<PathBuf>
|
||||
+ fn get_object_file<P, S>(object_dir: P, upatch_id: S) -> Result<PathBuf>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
S: AsRef<OsStr>,
|
||||
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
|
||||
|
||||
@ -1,469 +0,0 @@
|
||||
From a7140a02d69b50d57403f2c769767e5365a6aa34 Mon Sep 17 00:00:00 2001
|
||||
From: renoseven <dev@renoseven.net>
|
||||
Date: Sat, 11 May 2024 08:26:33 +0800
|
||||
Subject: [PATCH 16/20] upatch-diff: optimize log output
|
||||
|
||||
Signed-off-by: renoseven <dev@renoseven.net>
|
||||
---
|
||||
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 <stdio.h>
|
||||
#include <error.h>
|
||||
|
||||
-/* 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
|
||||
|
||||
@ -1,99 +0,0 @@
|
||||
From b43d59716bb5ae6811c3f4fcab33ca9a6704b175 Mon Sep 17 00:00:00 2001
|
||||
From: renoseven <dev@renoseven.net>
|
||||
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 <dev@renoseven.net>
|
||||
---
|
||||
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 = "<unnamed>";
|
||||
@@ -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
|
||||
|
||||
@ -1,826 +0,0 @@
|
||||
From bbbcb0c08f4a6a63230288485d88492465e2a593 Mon Sep 17 00:00:00 2001
|
||||
From: renoseven <dev@renoseven.net>
|
||||
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 <dev@renoseven.net>
|
||||
---
|
||||
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> {
|
||||
- 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<P: AsRef<Path>>(path: P) -> Result<Self> {
|
||||
+ 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<P: AsRef<Path>>(&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 = "<unnamed>";
|
||||
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<Server> {
|
||||
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<P: AsRef<Path>>(path: P) -> Result<Self> {
|
||||
+ 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<P: AsRef<Path>>(&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<PathBuf, PathBuf>);
|
||||
-
|
||||
-impl HijackerConfig {
|
||||
- pub fn parse_from<P: AsRef<Path>>(path: P) -> Result<Self> {
|
||||
- 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<P: AsRef<Path>>(&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<PathBuf, PathBuf>;
|
||||
-
|
||||
- fn deref(&self) -> &Self::Target {
|
||||
- &self.0
|
||||
- }
|
||||
+#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
+pub struct HijackerConfig {
|
||||
+ pub mapping: IndexMap<PathBuf, PathBuf>,
|
||||
}
|
||||
|
||||
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<P: AsRef<Path>>(config_path: P) -> Result<HijackerConfig> {
|
||||
- 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<P: AsRef<Path>>(config_path: P) -> Result<Self> {
|
||||
- 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<Self> {
|
||||
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<P: AsRef<Path>>(&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 = "<unnamed>";
|
||||
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<IoHandler> {
|
||||
- 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<P: AsRef<Path>>(config_path: P) -> Result<Self> {
|
||||
+ pub fn new(config: HijackerConfig) -> Result<Self> {
|
||||
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
|
||||
|
||||
@ -1,132 +0,0 @@
|
||||
From b9ae8a1ea14d46b3f4ba887fb10f9898c6f5cc53 Mon Sep 17 00:00:00 2001
|
||||
From: ningyu <ningyu9@huawei.com>
|
||||
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
|
||||
|
||||
@ -1,144 +0,0 @@
|
||||
From fac8aa17d540e54fa0443015089cdc72c5da72e3 Mon Sep 17 00:00:00 2001
|
||||
From: renoseven <dev@renoseven.net>
|
||||
Date: Sat, 11 May 2024 17:31:46 +0800
|
||||
Subject: [PATCH 20/20] upatch-diff: fix 'lookup_relf failed' issue
|
||||
|
||||
Signed-off-by: renoseven <dev@renoseven.net>
|
||||
---
|
||||
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
|
||||
|
||||
@ -1,165 +0,0 @@
|
||||
From 2d711186e1c134b069102e72d6d451942c931eb5 Mon Sep 17 00:00:00 2001
|
||||
From: renoseven <dev@renoseven.net>
|
||||
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 <dev@renoseven.net>
|
||||
---
|
||||
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
|
||||
|
||||
@ -1,27 +0,0 @@
|
||||
From 06ef9f212e17cdaa93dc5255d2c881c0b52d603f Mon Sep 17 00:00:00 2001
|
||||
From: renoseven <dev@renoseven.net>
|
||||
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 <dev@renoseven.net>
|
||||
---
|
||||
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
|
||||
|
||||
@ -1,25 +1,31 @@
|
||||
#!/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 SPEC_FILE="$(find . -name '*.spec' | head -n 1)"
|
||||
|
||||
readonly REPO_NAME="$(basename ${SPEC_FILE} | sed 's/.spec//')"
|
||||
readonly REPO_URL="https://gitee.com/openeuler/${REPO_NAME}"
|
||||
readonly REPO_BRANCH="$(git branch --show-current | sed 's/-LTS.*//')"
|
||||
readonly REPO_VERSION="$(grep Version ${SPEC_FILE} | head -n 1 | awk -F ' ' '{print $NF}')"
|
||||
|
||||
readonly PKG_NAME="${REPO_NAME}-${REPO_VERSION}"
|
||||
readonly PKG_DIR="$(realpath ./${PKG_NAME})"
|
||||
|
||||
echo "Preparing..."
|
||||
rm -rf ./${REPO_NAME} ./${PKG_NAME}
|
||||
rm -f ./*.tar.gz
|
||||
|
||||
echo "--------------------------"
|
||||
echo "Name: ${REPO_NAME}"
|
||||
echo "Branch: ${REPO_BRANCH}"
|
||||
echo "--------------------------"
|
||||
|
||||
echo "Cloning source code..."
|
||||
repo_version=$(grep "Version" "$REPO_NAME.spec" | head -n 1 | awk -F ' ' '{print $NF}')
|
||||
repo_dir="$REPO_NAME-$repo_version"
|
||||
|
||||
rm -rf "$REPO_NAME" "$repo_dir"
|
||||
git clone "$REPO_URL"
|
||||
|
||||
echo "Prepare build requirements..."
|
||||
pushd "$REPO_NAME"
|
||||
|
||||
echo "Checking out dest branch..."
|
||||
git checkout "$REPO_BRANCH"
|
||||
git clone ${REPO_URL} -b ${REPO_BRANCH} ${PKG_NAME}
|
||||
|
||||
echo "Vendoring dependencies..."
|
||||
cargo vendor --respect-source-config --sync Cargo.toml
|
||||
pushd ${PKG_DIR} > /dev/null
|
||||
|
||||
cargo vendor --quiet --respect-source-config --sync Cargo.toml
|
||||
|
||||
mkdir -p .cargo
|
||||
cat << EOF > .cargo/config.toml
|
||||
@ -30,14 +36,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"
|
||||
|
||||
|
||||
54
generate_patches.sh
Executable file
54
generate_patches.sh
Executable file
@ -0,0 +1,54 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
readonly SPEC_FILE="$(find . -name '*.spec' | head -n 1)"
|
||||
|
||||
readonly REPO_NAME="$(basename ${SPEC_FILE} | sed 's/.spec//')"
|
||||
readonly REPO_URL="https://gitee.com/openeuler/${REPO_NAME}"
|
||||
readonly REPO_BRANCH="$(git branch --show-current | sed 's/-LTS.*//')"
|
||||
readonly REPO_VERSION="$(grep Version ${SPEC_FILE} | head -n 1 | awk -F ' ' '{print $NF}')"
|
||||
|
||||
readonly PKG_NAME="${REPO_NAME}-${REPO_VERSION}"
|
||||
readonly PKG_DIR="$(realpath ./${PKG_NAME})"
|
||||
|
||||
readonly PATCH_DIR="$(pwd)"
|
||||
|
||||
echo "Preparing..."
|
||||
rm -rf ${PKG_DIR}
|
||||
rm -f ./*.patch
|
||||
|
||||
tar -xf ./${PKG_NAME}.tar.gz
|
||||
|
||||
pushd ${PKG_DIR} > /dev/null
|
||||
readonly REPO_BASELINE="$(git rev-parse --short HEAD)"
|
||||
popd > /dev/null
|
||||
|
||||
echo "------------------------------"
|
||||
echo "Name: ${REPO_NAME}"
|
||||
echo "Branch: ${REPO_BRANCH}"
|
||||
echo "Baseline: ${REPO_BASELINE}"
|
||||
echo "------------------------------"
|
||||
|
||||
echo "Syncing with remote..."
|
||||
pushd ${PKG_DIR} > /dev/null
|
||||
git fetch origin
|
||||
popd > /dev/null
|
||||
|
||||
echo "Generating patches..."
|
||||
# format patches
|
||||
pushd ${PKG_DIR} > /dev/null
|
||||
git checkout -q origin/${REPO_BRANCH}
|
||||
git format-patch -qN -o ${PATCH_DIR} ${REPO_BASELINE}
|
||||
popd > /dev/null
|
||||
|
||||
# print patch list
|
||||
patch_list="$(find . -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"
|
||||
Binary file not shown.
264
syscare.spec
264
syscare.spec
@ -1,52 +1,36 @@
|
||||
%define build_version %{version}-%{release}
|
||||
%define kernel_devel_rpm %(echo $(rpm -q kernel-devel | head -n 1))
|
||||
%define kernel_version %(echo $(rpm -q --qf "\%%{VERSION}" %{kernel_devel_rpm}))
|
||||
%define kernel_name %(echo $(rpm -q --qf "\%%{VERSION}-\%%{RELEASE}.\%%{ARCH}" %{kernel_devel_rpm}))
|
||||
|
||||
%define pkg_kmod %{name}-kmod
|
||||
%define pkg_build %{name}-build
|
||||
%define build_version %{version}-%{release}
|
||||
|
||||
############################################
|
||||
############ Package syscare ###############
|
||||
############################################
|
||||
Name: syscare
|
||||
Version: 1.2.1
|
||||
Release: 7
|
||||
Version: 1.2.2
|
||||
Release: 4
|
||||
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
|
||||
|
||||
BuildRequires: cmake >= 3.14 make
|
||||
BuildRequires: rust >= 1.51 cargo >= 1.51
|
||||
BuildRequires: gcc gcc-c++
|
||||
BuildRequires: kernel-devel
|
||||
Requires: coreutils systemd
|
||||
Requires: kpatch-runtime
|
||||
|
||||
Excludearch: loongarch64
|
||||
|
||||
Patch0001: 0001-fix-kernel-patch-ACCEPTED-change-to-DEACTIVED-after-.patch
|
||||
Patch0002: 0002-fix-some-clean-code-problem.patch
|
||||
Patch0003: 0003-syscared-fix-active-accepted-patch-failure-issue.patch
|
||||
Patch0004: 0004-upatch-helper-fix-object-upatch-id-duplicated-issue.patch
|
||||
Patch0005: 0005-syscare-build-update-README.md.patch
|
||||
Patch0006: 0006-syscared-support-saving-restoring-patch-status-by-op.patch
|
||||
Patch0007: 0007-project-update-Cargo.lock.patch
|
||||
Patch0008: 0008-all-remove-signal-handler.patch
|
||||
Patch0009: 0009-project-update-Cargo.lock.patch
|
||||
Patch0010: 0010-syscare-remove-working-directory-check.patch
|
||||
Patch0011: 0011-all-fix-cargo-clippy-warnings.patch
|
||||
|
||||
############### Description ################
|
||||
%description
|
||||
SysCare is a system-level hot-fix service that provides security patches and system error hot-fixes for the operating system.
|
||||
@ -62,9 +46,10 @@ mkdir -p build
|
||||
cd build
|
||||
|
||||
cmake \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DENABLE_ASAN=0 \
|
||||
-DENABLE_GCOV=0 \
|
||||
-DBUILD_VERSION=%{build_version} \
|
||||
-DKERNEL_VERSION=%{kernel_name} \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
..
|
||||
|
||||
make
|
||||
@ -113,12 +98,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/libexec/syscare/upatch-manage
|
||||
%attr(0550,root,root) /usr/lib/systemd/system/syscare.service
|
||||
|
||||
############################################
|
||||
########## Package syscare-build ###########
|
||||
@ -136,194 +121,33 @@ Requires: rpm rpm-build
|
||||
%description build
|
||||
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
|
||||
if [ "$1" -eq 0 ] || { [ -n "$2" ] && [ "$2" -eq 0 ]; }; then
|
||||
# Remove config directory
|
||||
rm -rf /etc/syscare
|
||||
|
||||
# Remove log directory
|
||||
rm -f /var/log/syscare/upatchd_r*.log
|
||||
rm -f /var/log/syscare/upatchd_r*.log.gz
|
||||
if [ -z "$(ls -A /var/log/syscare)" ]; then
|
||||
rm -rf /var/log/syscare
|
||||
fi
|
||||
|
||||
# Remove run directory
|
||||
rm -f /var/run/syscare/upatchd.*
|
||||
if [ -z "$(ls -A /var/run/syscare)" ]; then
|
||||
rm -rf /var/run/syscare
|
||||
fi
|
||||
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
|
||||
* Tue May 14 2024 ningyu<ningyu9@huawei.com> - 1.2.1-7
|
||||
- upatch diff only check changed file symbols
|
||||
- upatch diff remove rela check while build rebuilding
|
||||
* Sat May 11 2024 renoseven<dev@renoseven.net> - 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 <htpengc@isoftstone.com> - 1.2.1-5
|
||||
- add BuildRequires: kernel-devel
|
||||
* Fri Apr 19 2024 ningyu<ningyu9@huawei.com> - 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<ningyu9@huawei.com> - 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<ningyu9@huawei.com> - 1.2.1-2
|
||||
- update to syscare.1.2.1-2
|
||||
* Thu Mar 28 2024 ningyu<ningyu9@huawei.com> - 1.2.1-1
|
||||
- update to 1.2.1
|
||||
* Tue Dec 26 2023 ningyu<ningyu9@huawei.com> - 1.2.0-10
|
||||
- fix memory leak
|
||||
* Fri Dec 22 2023 ningyu<ningyu9@huawei.com> - 1.2.0-9
|
||||
- Add Suggests for syscare-build
|
||||
- Remove log directory
|
||||
* Tue Dec 12 2023 renoseven<dev@renoseven.net> - 1.2.0-8
|
||||
- Builder: fix 'enabling multiple kpatch may lead soft-lockup' issue
|
||||
* Wed Nov 29 2023 renoseven<dev@renoseven.net> - 1.2.0-7
|
||||
- Fix aarch64 compile issue
|
||||
* Tue Nov 28 2023 renoseven<dev@renoseven.net> - 1.2.0-6
|
||||
- Enable debuginfo for rust code
|
||||
- Sync arguments with old version
|
||||
* Tue Nov 28 2023 renoseven<dev@renoseven.net> - 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<dev@renoseven.net> - 1.2.0-4
|
||||
- Fix 'kpatch driver cannot support old version' issue
|
||||
* Fri Nov 24 2023 renoseven<dev@renoseven.net> - 1.2.0-3
|
||||
- Fix 'upatch only apply first patch for new process' issue
|
||||
* Wed Nov 22 2023 renoseven<dev@renoseven.net> - 1.2.0-2
|
||||
- Fix upatch process detection
|
||||
* Wed Nov 22 2023 renoseven<dev@renoseven.net> - 1.2.0-1
|
||||
- Fix various issue
|
||||
* Wed Oct 11 2023 renoseven<dev@renoseven.net> - 1.1.0-6
|
||||
- Support build patch for kernel moudules
|
||||
- Fix various issue
|
||||
* Fri Sep 22 2023 renoseven<dev@renoseven.net> - 1.1.0-5
|
||||
- Fix various issue
|
||||
* Thu Sep 21 2023 renoseven<dev@renoseven.net> - 1.1.0-4
|
||||
- Fix 'syscare-build only accept one patch' issue
|
||||
* Wed Sep 20 2023 renoseven<dev@renoseven.net> - 1.1.0-3
|
||||
- Fix various issue
|
||||
- Support MSRV 1.51
|
||||
* Mon Aug 28 2023 renoseven<dev@renoseven.net> - 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<dev@renoseven.net> - 1.0.2-4
|
||||
- Fix builder check failure issue
|
||||
* Sun Jun 25 2023 renoseven<dev@renoseven.net> - 1.0.2-3
|
||||
- Fix various issue
|
||||
* Mon Jun 19 2023 renoseven<dev@renoseven.net> - 1.0.2-2
|
||||
- Fix various issue
|
||||
- Update dependencies
|
||||
* Fri Jun 09 2023 renoseven<dev@renoseven.net> - 1.0.2-1
|
||||
- Fix 'rpmpbuild getcwd failed' issue
|
||||
- Fix 'upatch ko prints redundant log' issue
|
||||
* Fri Jun 09 2023 renoseven<dev@renoseven.net> - 1.0.1-9
|
||||
- Fix 'patch file is not checked' issue
|
||||
- Rename patched source package
|
||||
- Update dependencies
|
||||
* Tue Jun 06 2023 renoseven<dev@renoseven.net> - 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<dev@renoseven.net> - 1.0.1-7
|
||||
- Various bugfix
|
||||
- Support multiple compiler
|
||||
* Wed May 31 2023 renoseven<dev@renoseven.net> - 1.0.1-6
|
||||
- Various bugfix
|
||||
- Support multiple debuginfo package
|
||||
* Mon May 15 2023 renoseven<dev@renoseven.net> - 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<dev@renoseven.net> - 1.0.1-4
|
||||
- Enable aarch64
|
||||
- Fix syscare-upatch service may start failed issue
|
||||
* Thu Mar 30 2023 renoseven<dev@renoseven.net> - 1.0.1-3
|
||||
- Fix upatch may not contain all symbols issue
|
||||
- Add syscare-kmod package
|
||||
* Wed Mar 29 2023 renoseven<dev@renoseven.net> - 1.0.1-2
|
||||
- Fix rpm install & remove script issue
|
||||
* Wed Mar 15 2023 renoseven<dev@renoseven.net> - 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<snoweay@163.com> - 1.0.0-7
|
||||
- Fix 42 relocation caused by gcc 11.
|
||||
* Tue Dec 20 2022 snoweay<snoweay@163.com> - 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<snoweay@163.com> - 1.0.0-5
|
||||
- Check version-release of source pkg & debuginfo pkg.
|
||||
* Fri Dec 16 2022 snoweay<snoweay@163.com> - 1.0.0-4
|
||||
- Avoid duplicate elfs by not following symlinks at build.
|
||||
* Thu Dec 15 2022 snoweay<snoweay@163.com> - 1.0.0-3
|
||||
- Change kernel patches' scontext before apply not at rpm-post.
|
||||
* Wed Dec 14 2022 snoweay<snoweay@163.com> - 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<snoweay@163.com> - 1.0.0-1
|
||||
- Release the first version 1.0.0.
|
||||
* Thu Feb 20 2025 renoseven<dev@renoseven.net> - 1.2.2-4
|
||||
- all: fix rust 1.84 compile failure
|
||||
- syscare: fix cannot find working directory
|
||||
- syscare-build: fix set signal handler failure
|
||||
- syscared: fix active accepted patch failure
|
||||
|
||||
* Mon Nov 11 2024 renoseven<dev@renoseven.net> - 1.2.2-3
|
||||
- syscared: support saving & restoring patch status by operation order
|
||||
|
||||
* Wed Sep 18 2024 renoseven<dev@renoseven.net> - 1.2.2-2
|
||||
- syscared: fix kernel patch apply failure issue
|
||||
- upatch-helper: fix object upatch id duplicated issue
|
||||
|
||||
* Fri Aug 16 2024 renoseven<dev@renoseven.net> - 1.2.2-1
|
||||
- Release version 1.2.2-1.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user