diff --git a/rasp/librasp/Cargo.toml b/rasp/librasp/Cargo.toml index adeb7b21a..1aefe9b7b 100644 --- a/rasp/librasp/Cargo.toml +++ b/rasp/librasp/Cargo.toml @@ -18,7 +18,7 @@ libc = "0.2.80" nix = "0.24" anyhow = "1.0.38" # elf -goblin = "0.8.0" +goblin = "0.3.4" byteorder = "1.0" # lru cache lru_time_cache = "0.11.8" @@ -31,6 +31,7 @@ coarsetime = "0.1" wait-timeout = "0.2.0" lazy_static = "1.4.0" +cgroups-rs = "0.2.6" # plugins plugins = { path = "../../plugins/lib/rust"} diff --git a/rasp/librasp/src/golang.rs b/rasp/librasp/src/golang.rs index 2342567a0..1979997cd 100644 --- a/rasp/librasp/src/golang.rs +++ b/rasp/librasp/src/golang.rs @@ -139,8 +139,8 @@ pub fn golang_bin_inspect(bin_file: &PathBuf, elf: &Elf) -> Result { let shstrtab = &elf.shdr_strtab; for section in elf.section_headers.iter() { let offset = section.sh_name; - if let Some(name) = shstrtab.get_at(offset) { - if name == ".gopclntab" { + if let Some(name) = shstrtab.get(offset) { + if name.unwrap_or_default() == ".gopclntab" { return Ok(size); } } diff --git a/rasp/librasp/src/manager.rs b/rasp/librasp/src/manager.rs index 2673c2236..9a72c79f1 100644 --- a/rasp/librasp/src/manager.rs +++ b/rasp/librasp/src/manager.rs @@ -210,7 +210,8 @@ impl RASPManager { }) } } - let mut need_write_config = true; + // issue: may case oom + let mut need_write_config = false; for m in messages.iter() { if m.message_type >= 12 && m.message_type <= 14 { need_write_config = false; @@ -331,9 +332,9 @@ impl RASPManager { let runtime_info = &process_info.runtime.clone().unwrap(); let root_dir = format!("/proc/{}/root", process_info.pid); let pid = process_info.pid; - let nspid = process_info.nspid; + // let nspid = process_info.nspid; // delete config - self.delete_config_file(pid, nspid)?; + // self.delete_config_file(pid, nspid)?; let attach_result = match runtime_info.name { "JVM" => match JVMProbeState::inspect_process(process_info)? { ProbeState::Attached => { diff --git a/rasp/librasp/src/nodejs.rs b/rasp/librasp/src/nodejs.rs index 5b4764521..00c5143b0 100644 --- a/rasp/librasp/src/nodejs.rs +++ b/rasp/librasp/src/nodejs.rs @@ -13,6 +13,10 @@ use std::fs::File; use std::io::BufReader; use std::io::BufRead; +use anyhow::Result as Anyhow; +// cgroup +use cgroups_rs::{self, cgroup_builder::CgroupBuilder, CgroupPid, Controller}; + const NODEJS_INSPECT_PORT_MIN:u16 = 19230; const NODEJS_INSPECT_PORT_MAX:u16 = 19235; pub struct NodeJSProbe {} @@ -148,6 +152,22 @@ pub fn get_inspect_port(process_info: &ProcessInfo) -> u16 { 0 } +fn setup_cgroup(pid: u32, cg_name: &str) -> Anyhow<()> { + let hier = cgroups_rs::hierarchies::auto(); + let rasp_child_cg = CgroupBuilder::new(cg_name) + .memory() + .memory_hard_limit(1024 * 1024 * 200) + .done() + .cpu() + .quota(1000 * 10).done() + .build(hier); + let mems: &cgroups_rs::memory::MemController = rasp_child_cg.controller_of().unwrap(); + mems.add_task(&CgroupPid::from(pid as u64))?; + let cpus: &cgroups_rs::cpu::CpuController = rasp_child_cg.controller_of().unwrap(); + cpus.add_task(&CgroupPid::from(pid as u64))?; + Ok(()) +} + pub fn nodejs_run(pid: i32, node_path: &str, smith_module_path: &str, port: Option) -> Result { let pid_string = pid.to_string(); let nsenter = settings::RASP_NS_ENTER_BIN(); @@ -205,6 +225,7 @@ pub fn nodejs_run(pid: i32, node_path: &str, smith_module_path: &str, port: Opti .stdout(Stdio::piped()) .spawn()?; + setup_cgroup(child.id(), "rasp_nodejs_attach_cg")?; let timeout = Duration::from_secs(30); match child.wait_timeout(timeout).unwrap() { @@ -261,34 +282,52 @@ pub fn nodejs_version(pid: i32, nodejs_bin_path: &String) -> Result<(u32, u32, S nodejs_bin_path, "-v", ]; - let output = match Command::new(nsenter).args(&args).output() { - Ok(s) => s, - Err(e) => return Err(anyhow!(e.to_string())), - }; - let output_string = String::from_utf8(output.stdout).unwrap_or(String::new()); - if output_string.is_empty() { - return Err(anyhow!("empty stdout")); - } - // parse nodejs version - let re = Regex::new(r"v((\d+)\.(\d+)\.\d+)").unwrap(); - let (major, minor, version) = match re.captures(&output_string) { - Some(c) => { - let major = c.get(2).map_or("", |m| m.as_str()); - let minor = c.get(3).map_or("", |m| m.as_str()); - let version = c.get(1).map_or("", |m| m.as_str()); - (major, minor, version) + let mut child = Command::new(nsenter) + .args(&args) + .stderr(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn()?; + + setup_cgroup(child.id(), "rasp_nodejs_inspect_cg")?; + + let timeout = Duration::from_secs(30); + + match child.wait_timeout(timeout).unwrap() { + Some(_) => { + let out = child.wait_with_output()?; + + let output_string = String::from_utf8(out.stdout).unwrap_or(String::new()); + if output_string.is_empty() { + return Err(anyhow!("empty stdout")); + } + // parse nodejs version + let re = Regex::new(r"v((\d+)\.(\d+)\.\d+)").unwrap(); + let (major, minor, version) = match re.captures(&output_string) { + Some(c) => { + let major = c.get(2).map_or("", |m| m.as_str()); + let minor = c.get(3).map_or("", |m| m.as_str()); + let version = c.get(1).map_or("", |m| m.as_str()); + (major, minor, version) + } + None => return Err(anyhow!(String::from("can not find version"))), + }; + let major_number = match major.parse::() { + Ok(n) => n, + Err(e) => return Err(anyhow!(e.to_string())), + }; + let minor_number = match minor.parse::() { + Ok(n) => n, + Err(e) => return Err(anyhow!(e.to_string())), + }; + return Ok((major_number, minor_number, String::from(version))); + }, + None => { + // child hasn't exited yet within 30s, kill the child process + child.kill()?; + child.wait()?; + return Err(anyhow!("command execution timeout")); } - None => return Err(anyhow!(String::from("can not find version"))), - }; - let major_number = match major.parse::() { - Ok(n) => n, - Err(e) => return Err(anyhow!(e.to_string())), - }; - let minor_number = match minor.parse::() { - Ok(n) => n, - Err(e) => return Err(anyhow!(e.to_string())), - }; - Ok((major_number, minor_number, String::from(version))) + } } pub fn check_nodejs_version(ver: &String) -> Result<()> { diff --git a/rasp/librasp/src/parse_elf.rs b/rasp/librasp/src/parse_elf.rs index 7d79847f5..4dd716553 100644 --- a/rasp/librasp/src/parse_elf.rs +++ b/rasp/librasp/src/parse_elf.rs @@ -81,8 +81,8 @@ fn read_data_at_address(mut file: &File, elf: &Elf, address: u64, size: usize) - fn find_symbol<'a>(elf: &'a Elf<'a>, symbol_name: &str) -> Option { for sym in &elf.syms { - if let Some(name) = elf.strtab.get_at(sym.st_name) { - if name == symbol_name { + if let Some(name) = elf.strtab.get(sym.st_name) { + if name.unwrap_or_default() == symbol_name { return Some(sym.clone()); } } @@ -148,8 +148,8 @@ pub fn find_by_section(elf: &Elf, file: &File, mmap: &Mmap) -> Result { // find .go.buildinfo if let Some(go_buildinfo_section) = elf.section_headers.iter().find(|section| { - if let Some(sect_name) = elf.shdr_strtab.get_at(section.sh_name) { - sect_name == ".go.buildinfo" + if let Some(sect_name) = elf.shdr_strtab.get(section.sh_name) { + sect_name.unwrap_or_default() == ".go.buildinfo" } else { false }