253 lines
8.5 KiB
Diff
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
|
|
|