syscare/0006-daemon-check-patch-before-patch-restoration.patch
ningyu 5909c8dc30 update to 1.2.0-10
Sync patch
2023-12-28 17:21:44 +08:00

253 lines
8.5 KiB
Diff

From fdb0d2ab35085bd97d5cae420df0a2c9c6f99c0a Mon Sep 17 00:00:00 2001
From: renoseven <dev@renoseven.net>
Date: Fri, 22 Dec 2023 13:40:29 +0800
Subject: [PATCH 06/15] daemon: check patch before patch restoration
Signed-off-by: renoseven <dev@renoseven.net>
---
daemon/src/patch/manager/driver/kpatch/mod.rs | 37 +++++++++---
daemon/src/patch/manager/driver/mod.rs | 2 +-
daemon/src/patch/manager/driver/upatch/mod.rs | 58 +++++++++++++------
daemon/src/patch/manager/mod.rs | 3 +-
daemon/src/patch/transaction.rs | 2 +-
daemon/src/rpc/skeleton_impl/patch.rs | 2 +-
6 files changed, 73 insertions(+), 31 deletions(-)
diff --git a/daemon/src/patch/manager/driver/kpatch/mod.rs b/daemon/src/patch/manager/driver/kpatch/mod.rs
index 57aa127..efe80e5 100644
--- a/daemon/src/patch/manager/driver/kpatch/mod.rs
+++ b/daemon/src/patch/manager/driver/kpatch/mod.rs
@@ -2,7 +2,7 @@ use std::{ffi::OsString, os::unix::prelude::OsStrExt, path::Path};
use anyhow::{anyhow, bail, ensure, Context, Result};
use lazy_static::lazy_static;
-use log::{debug, warn};
+use log::debug;
use syscare_abi::PatchStatus;
use syscare_common::{
@@ -87,15 +87,10 @@ impl KernelPatchDriver {
}
}
-impl PatchDriver for KernelPatchDriver {
- fn check(&self, patch: &Patch, flag: PatchOpFlag) -> Result<()> {
+impl KernelPatchDriver {
+ fn check_compatiblity(&self, patch: &Patch) -> Result<()> {
const KERNEL_NAME_PREFIX: &str = "kernel-";
- if flag == PatchOpFlag::SkipCheck {
- warn!("Skipped patch \"{}\" check", patch);
- return Ok(());
- }
-
let kernel_version = os::kernel::version();
let current_kernel = OsString::from(KERNEL_NAME_PREFIX).concat(kernel_version);
@@ -113,18 +108,42 @@ impl PatchDriver for KernelPatchDriver {
);
}
+ Ok(())
+ }
+
+ fn check_consistency(&self, patch: &Patch) -> Result<()> {
let patch_ext: &KernelPatchExt = (&patch.info_ext).into();
let patch_file = patch_ext.patch_file.as_path();
let real_checksum = digest::file(patch_file)?;
+ debug!("Target checksum: {}", patch.checksum);
+ debug!("Expected checksum: {}", real_checksum);
+
ensure!(
patch.checksum.eq(&real_checksum),
- "Kpatch: Patch file \"{}\" checksum failed",
+ "Kpatch: Patch \"{}\" consistency check failed",
patch_file.display()
);
Ok(())
}
+ fn check_confliction(&self, _patch: &Patch) -> Result<()> {
+ Ok(())
+ }
+}
+
+impl PatchDriver for KernelPatchDriver {
+ fn check(&self, patch: &Patch, flag: PatchOpFlag) -> Result<()> {
+ self.check_compatiblity(patch)?;
+ self.check_consistency(patch)?;
+
+ if flag != PatchOpFlag::Force {
+ self.check_confliction(patch)?;
+ }
+
+ Ok(())
+ }
+
fn status(&self, patch: &Patch, _flag: PatchOpFlag) -> Result<PatchStatus> {
Self::get_patch_status(patch)
}
diff --git a/daemon/src/patch/manager/driver/mod.rs b/daemon/src/patch/manager/driver/mod.rs
index 9beb999..c3a4ca4 100644
--- a/daemon/src/patch/manager/driver/mod.rs
+++ b/daemon/src/patch/manager/driver/mod.rs
@@ -13,7 +13,7 @@ use super::entity::*;
#[derive(PartialEq, Clone, Copy)]
pub enum PatchOpFlag {
Normal,
- SkipCheck,
+ Force,
}
/// Basic abstraction of patch operation
diff --git a/daemon/src/patch/manager/driver/upatch/mod.rs b/daemon/src/patch/manager/driver/upatch/mod.rs
index 993c116..e4a914b 100644
--- a/daemon/src/patch/manager/driver/upatch/mod.rs
+++ b/daemon/src/patch/manager/driver/upatch/mod.rs
@@ -1,6 +1,5 @@
use std::{
- ffi::OsString,
- os::unix::prelude::OsStringExt,
+ ffi::CStr,
path::{Path, PathBuf},
};
@@ -9,7 +8,7 @@ use anyhow::{anyhow, bail, ensure, Result};
use indexmap::IndexMap;
use lazy_static::lazy_static;
use libc::{c_char, EEXIST, EFAULT, ENOENT, EPERM};
-use log::{info, warn};
+use log::{debug, info};
use parking_lot::Mutex;
use syscare_abi::PatchStatus;
use syscare_common::util::digest;
@@ -92,25 +91,33 @@ impl UserPatchDriver {
}
}
-impl PatchDriver for UserPatchDriver {
- fn check(&self, patch: &Patch, flag: PatchOpFlag) -> Result<()> {
- const ERR_MSG_LEN: usize = 512;
-
- if flag == PatchOpFlag::SkipCheck {
- warn!("Skipped patch \"{}\" check", patch);
- return Ok(());
- }
+impl UserPatchDriver {
+ fn check_compatiblity(&self, _patch: &Patch) -> Result<()> {
+ Ok(())
+ }
+ fn check_consistency(&self, patch: &Patch) -> Result<()> {
let patch_ext: &UserPatchExt = (&patch.info_ext).into();
let patch_file = &patch_ext.patch_file;
let real_checksum = digest::file(patch_file).map_err(|e| anyhow!("Upatch: {}", e))?;
+ debug!("Target checksum: {}", patch.checksum);
+ debug!("Expected checksum: {}", real_checksum);
+
ensure!(
patch.checksum.eq(&real_checksum),
- "Upatch: Patch file \"{}\" checksum failed",
+ "Upatch: Patch \"{}\" consistency check failed",
patch_file.display()
);
+ Ok(())
+ }
+
+ fn check_confliction(&self, patch: &Patch) -> Result<()> {
+ const ERR_MSG_LEN: usize = 512;
+
+ let patch_ext: &UserPatchExt = (&patch.info_ext).into();
+
let target_elf = patch_ext.target_elf.to_cstring()?;
let patch_file = patch_ext.patch_file.to_cstring()?;
let mut msg_buf = vec![0; ERR_MSG_LEN];
@@ -123,11 +130,28 @@ impl PatchDriver for UserPatchDriver {
msg_buf.capacity(),
)
};
+ if ret_val != 0 {
+ match CStr::from_bytes_until_nul(&msg_buf) {
+ Ok(err_msg) => bail!(format!("Upatch: {}", err_msg.to_string_lossy())),
+ Err(_) => bail!(format!(
+ "Upatch: {}",
+ std::io::Error::from_raw_os_error(ret_val)
+ )),
+ }
+ }
- ensure!(
- ret_val == 0,
- OsString::from_vec(msg_buf).to_string_lossy().to_string()
- );
+ Ok(())
+ }
+}
+
+impl PatchDriver for UserPatchDriver {
+ fn check(&self, patch: &Patch, flag: PatchOpFlag) -> Result<()> {
+ self.check_compatiblity(patch)?;
+ self.check_consistency(patch)?;
+
+ if flag != PatchOpFlag::Force {
+ self.check_confliction(patch)?;
+ }
Ok(())
}
@@ -151,7 +175,7 @@ impl PatchDriver for UserPatchDriver {
patch_uuid.as_ptr(),
target_elf.as_ptr(),
patch_file.as_ptr(),
- matches!(flag, PatchOpFlag::SkipCheck),
+ matches!(flag, PatchOpFlag::Force),
)
};
diff --git a/daemon/src/patch/manager/mod.rs b/daemon/src/patch/manager/mod.rs
index 3b1aa8c..fdb218d 100644
--- a/daemon/src/patch/manager/mod.rs
+++ b/daemon/src/patch/manager/mod.rs
@@ -267,8 +267,7 @@ impl PatchManager {
"Restore patch \"{}\" status to \"{}\"",
patch, target_status
);
- if let Err(e) = self.do_status_transition(&patch, target_status, PatchOpFlag::SkipCheck)
- {
+ if let Err(e) = self.do_status_transition(&patch, target_status, PatchOpFlag::Force) {
error!("{}", e);
}
}
diff --git a/daemon/src/patch/transaction.rs b/daemon/src/patch/transaction.rs
index 16bab46..079b024 100644
--- a/daemon/src/patch/transaction.rs
+++ b/daemon/src/patch/transaction.rs
@@ -70,7 +70,7 @@ where
fn rollback(&mut self) -> Result<()> {
let mut patch_manager = self.patch_manager.write();
while let Some((patch, status)) = self.finish_list.pop() {
- patch_manager.do_status_transition(&patch, status, PatchOpFlag::SkipCheck)?;
+ patch_manager.do_status_transition(&patch, status, PatchOpFlag::Force)?;
}
Ok(())
}
diff --git a/daemon/src/rpc/skeleton_impl/patch.rs b/daemon/src/rpc/skeleton_impl/patch.rs
index 4517a03..8d4f57b 100644
--- a/daemon/src/rpc/skeleton_impl/patch.rs
+++ b/daemon/src/rpc/skeleton_impl/patch.rs
@@ -82,7 +82,7 @@ impl PatchSkeleton for PatchSkeletonImpl {
PatchManager::apply_patch,
match force {
false => PatchOpFlag::Normal,
- true => PatchOpFlag::SkipCheck,
+ true => PatchOpFlag::Force,
},
identifier,
)?
--
2.33.0