From f98804148860ce4b59fa59bdb59c062f0e14d020 Mon Sep 17 00:00:00 2001 From: l00580197 Date: Mon, 17 Jul 2023 15:42:52 +0800 Subject: [PATCH] add rollback when bash coredump --- bin/coredump_monitor.rs | 157 ++++++++++++++++++++++++++++++++++--- bin/daemon.rs | 4 +- bin/main.rs | 2 +- tests/test_coredump/test.c | 8 ++ 4 files changed, 159 insertions(+), 12 deletions(-) create mode 100644 tests/test_coredump/test.c diff --git a/bin/coredump_monitor.rs b/bin/coredump_monitor.rs index 3b4b713..81a90ce 100644 --- a/bin/coredump_monitor.rs +++ b/bin/coredump_monitor.rs @@ -1,3 +1,17 @@ +// Copyright (c) 2023 Huawei Technologies Co., Ltd. +// sysboost is licensed under the 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. +// Create: 2023-7-13 + +use crate::daemon; + +use log::{self}; use lazy_static::lazy_static; use std::collections::HashMap; use cnproc::PidMonitor; @@ -5,19 +19,20 @@ use cnproc::PidEvent; use std::sync::Mutex; use std::fs; use procfs::Process; +use std::path::Path; + +const BASH_RTO_PATH: &str = "/usr/bin/bash.rto"; +const BASH_PATH: &str = "/usr/bin/bash"; +const BASH_TOML_PATH: &str = "/etc/sysboost.d/bash.toml"; +const BASH_LINK_PATH: &str = "/var/lib/bash"; lazy_static! { static ref MERGE_FILES: Mutex> = Mutex::new(Vec::new()); static ref PID_INFOS: Mutex> = Mutex::new(HashMap::new()); } -// add merged file into vector, provide for testcase -fn add_merge_file(file_path: String) { - MERGE_FILES.lock().unwrap().push(file_path); -} - fn init_merge_file_list() { - MERGE_FILES.lock().unwrap().push(String::from("/usr/bin/bash.rto")); + MERGE_FILES.lock().unwrap().push(BASH_PATH.to_string()); } fn process_exec_event(pid: i32) { @@ -42,8 +57,55 @@ fn process_exec_event(pid: i32) { PID_INFOS.lock().unwrap().insert(pid, String::from(file_path.to_str().unwrap())); } +fn do_bash_rollback() -> i32 { + // unset flag + let ret = daemon::set_app_aot_flag(&BASH_PATH.to_string(), false); + if ret != 0 { + log::error!("Failed to unset flag for bash!"); + return ret; + } + // remove link + daemon::db_remove_link(&BASH_LINK_PATH.to_string()); + // remove bash.rto + let bash_rto = Path::new(BASH_RTO_PATH); + match fs::remove_file(&bash_rto) { + Ok(_) => {} + Err(e) => { + log::error!("remove file failed: {}", e); + return -1; + } + } + // rename bash.toml + let bash_toml = Path::new(BASH_TOML_PATH); + let bash_toml_err = bash_toml.with_extension("toml.err"); + match fs::rename(&bash_toml_err, &bash_toml) { + Ok(_) => {} + Err(e) => { + log::error!("Mv failed: {}", e); + return -1; + } + } + return 0; +} + +fn do_common_rollback(file_path: &String) -> i32 { + let file_exist = Path::new(file_path).exists(); + if !file_exist { + log::error!("{} is not exist!", file_path); + } + match fs::remove_file(&file_path) { + Ok(_) => {} + Err(e) => { + log::error!("remove file failed: {}", e); + return -1; + } + } + return 0; +} + fn process_coredump_event(pid: i32) { // get file path by pid + println!("process_coredump_event called ,pid is {}", pid); if PID_INFOS.lock().unwrap().contains_key(&pid) == false { log::info!("{} is not exist in PID_INFOS!", pid); return; @@ -51,8 +113,21 @@ fn process_coredump_event(pid: i32) { if let Some(file_path) = PID_INFOS.lock().unwrap().get(&pid) { log::info!("{} has create a coredump!", file_path); - if MERGE_FILES.lock().unwrap().contains(&file_path) { - fs::remove_file(&file_path).expect("File delete failed!"); + println!("{} has create a coredump!", file_path); + if MERGE_FILES.lock().unwrap().contains(&file_path) == false { + return; + } + + if file_path == BASH_PATH { + let ret = do_bash_rollback(); + if ret != 0 { + log::error!("rollback bash failed!"); + } + } else { + let ret = do_common_rollback(file_path); + if ret != 0 { + log::error!("rollback {} failed!", file_path); + } } } @@ -65,7 +140,10 @@ fn process_exit_event(pid: i32) { pub fn coredump_monitor_loop() { init_merge_file_list(); - let mut monitor = PidMonitor::new().unwrap(); + let mut monitor = match PidMonitor::new() { + Ok(p) => p, + Err(e) => panic!("create PidMonitor failed: {}", e) + }; loop { match monitor.recv() { None => {} @@ -81,3 +159,64 @@ pub fn coredump_monitor_loop() { } } +#[cfg(test)] +mod tests { + use super::*; + use std::thread; + use std::process::Command; + + const COREDUMP_TEST_PATH: &str = "tests/test_coredump/test.c"; + const EXCUTE_TEST_PATH: &str = "tests/test_coredump/test"; + + fn add_merge_file(file_path: String) { + MERGE_FILES.lock().unwrap().push(file_path); + } + + #[test] + fn test_coredump_monitor() { + // create excute file + let source_file = Path::new(COREDUMP_TEST_PATH); + let source_file = match fs::canonicalize(source_file) { + Ok(p) => p, + Err(e) => { + panic!("Failed to get realpath: {}", e); + } + }; + let source_file_exist = source_file.exists(); + assert!(source_file_exist == true, "coredump source file does not exist!"); + let excute_file = Path::new(EXCUTE_TEST_PATH); + + let output = Command::new("gcc").args(&["-o", &excute_file.to_str().unwrap(), &source_file.to_str().unwrap()]) + .output().expect("Faild to execute command!"); + if !output.status.success() { + panic!("Failed to create excute file!"); + } + let real_excute_file = match fs::canonicalize(excute_file) { + Ok(p) => p, + Err(e) => { + panic!("Failed to get realpath: {}", e); + } + }; + + let excute_file_exist = real_excute_file.exists(); + assert!(excute_file_exist == true, "excute file is not exist!"); + + add_merge_file(real_excute_file.to_str().unwrap().to_string()); + println!("merge file list is {:?}", MERGE_FILES.lock().unwrap()); + // do coredump monitor + let _coredump_monitor = thread::spawn(|| { + coredump_monitor_loop(); + }); + + // excute a coredump action + let excute_command = String::from("./") + excute_file.to_str().unwrap(); + let output = Command::new(&excute_command).output() + .expect("Failed to excute command!"); + + if output.status.success() { + panic!("Coredump has not created!"); + } + let excute_file_exist = excute_file.exists(); + assert!(excute_file_exist == false, "excute file is not deleted!"); + } +} diff --git a/bin/daemon.rs b/bin/daemon.rs index 70eceb0..233d7a0 100644 --- a/bin/daemon.rs +++ b/bin/daemon.rs @@ -83,7 +83,7 @@ fn db_add_link(conf: &RtoConfig) -> i32 { return 0; } -fn db_remove_link(path: &String) { +pub fn db_remove_link(path: &String) { let ret = fs::remove_file(&path); match ret { Ok(_) => return, @@ -202,7 +202,7 @@ fn bolt_optimize_so(conf: &RtoConfig) -> i32 { return ret; } -fn set_app_aot_flag(old_path: &String, is_set: bool) -> i32 { +pub fn set_app_aot_flag(old_path: &String, is_set: bool) -> i32 { let mut args: Vec = Vec::new(); if is_set { args.push("-set".to_string()); diff --git a/bin/main.rs b/bin/main.rs index 2c0024f..dc846ac 100644 --- a/bin/main.rs +++ b/bin/main.rs @@ -57,7 +57,7 @@ fn main() { } } // start up coredump monitor - let coredump_monitor_handle = thread::spawn(||{ + let _coredump_monitor_handle = thread::spawn(||{ coredump_monitor_loop(); }); diff --git a/tests/test_coredump/test.c b/tests/test_coredump/test.c new file mode 100644 index 0000000..49750cb --- /dev/null +++ b/tests/test_coredump/test.c @@ -0,0 +1,8 @@ +#include + +int main() +{ + int* p = NULL; + *p = 0; + return 0; +} -- Gitee