Comments (6)
An idea to allow each driver to describe what possible initialization parameters it can take:
api.rs
/// Describe a driver initialization parameter
#[derive(Debug)]
pub struct DriverInitParamDesc {
name: String,
description: String,
required: bool,
}
pub trait Introspectable {
/// Retrieve the possible initialization arguments for this Driver
fn get_possible_args() -> Vec<DriverInitParam> where Self: Sized {
// default: no parameters required
Vec::new()
}
}
lib.rs
fn possible_init_args() -> HashMap<DriverType, Vec<DriverInitParamDesc> {
let map = HashMap::new();
for drv_type in DriverType::into_enum_iter() {
match drv_type {
// pseudo code
DriverType::KVM => {
map.insert(drv_type, KVM::get_possible_args())
}
}
}
map
}
On the user side:
example.rs
use microvmi::api::DriverParams;
use microvmi::{init_driver, possible_init_args}
fn main() {
if ("--help") {
// get all possible init args, to display them for --help usage
let poss_args = possible_init_args();
// display them
// for x in poss_args.iter() ....
// x.display()
return;
}
// prepare driver init
let init_params = DriverParams::with_default("windows_10")
// add arg for KVM driver
.insert("kvmi_unix_socket", "/tmp/introspector")
// add arg for memflow driver
.insert("memflow_pid", "45617")
let driver = init_driver(None, &init_params)
}
from libmicrovmi.
The idea looks good to me. I have one small note though: Why use a hash map? Wouldn't it be nicer to use a complex enum where each enum variant wraps an individual struct for those driver init params?
from libmicrovmi.
I like enums because their a give a strong type definition instead of a losely defined string that wouldn't be checked at compile-time.
However, it would be difficilt to express the init parameter combinatory with fully qualified enums:
Lets assume we want to initialize by passing an enum:
pub enum XenInitParams {
// Xen can be initialized with a vm_name
Default { vm_name: String },
}
use microvmi::init_driver;
use microvmi::api::XenInitParams;
let init_params = XenInitParams::Default(String::from("Windows10"));
let driver = init_driver(None, &init_params);
The situation get less intuitive for KVM:
// both of the enum variant will have to take a vm_name mandatory field
// not very clear from an API user point of view, but okay
pub enum KVMInitParams {
UnixSocket {vm_name: String, socket_path: String },
VSock {vm_name: String, port: u32 },
}
But the problem arises with memflow.
Remember that a memflow driver can be initialized like this:
- no connector name, no arguments
- no connector name, arguments
- connector name, no arguments
- connector name, arguments
and each connector has a set of specific arguments:
qemu_procfs
- required: none (will select the first qemu process)
- optional: vm_name
kvm
- required: pid
pcileech
- required: device, default value:
FPGA
- optional: memap, path to a file
- required: device, default value:
- coredump
- required: filepath
We could sketch an enum like this:
pub enum MemflowInitParams {
Default { connector_name: Option<String>, connector_args: Option<HashMap<str, str>>},
}
but it loosely defines what parameters are actually accepted by the memflow driver.
Also, another issue here is that we can only pass one enum at init, and we forbid the possibility of supplying multiple initialization parameters for multiple drivers at the same time.
If I read from a configuration file, and I want to initialize KVM with a given unix socket and memflow with a QEMU pid, depending on each one of them will be detected at runtime, i would need to express that possibility.
from libmicrovmi.
Update: the memflow connector_args could be rewritten with a more expressive enum like this:
pub enum MemflowConnectorParams {
// optional vm_name, otherwise will search for the first QEMU process
QEMUProcFs { vm_name: Option<String>},
KVM { pid: u32 },
// default value for device: "FPGA"
PCILeech { device: Option<String>, memmap: Option<Path> },
Coredump { filepath: Path },
}
pub enum MemflowInitParams {
Default { connector_name: Option<String>, connector_args: Option<MemflowConnectorParams>},
}
from libmicrovmi.
Update, thinking again on your proposal, to reflect the possibility of passing mutiple initialization parameters for multiple drivers:
use std::path::PathBuf;
/// Describes Xen initialization parameters
pub enum XenInitParams {
Default { vm_name: String },
}
/// Describes KVM initialization parameters
pub enum KVMInitParams {
UnixSocket {
vm_name: String,
socket_path: PathBuf,
},
VSock {
vm_name: String,
port: u32,
},
}
/// Describes Memflow connector parameters
pub enum MemflowConnectorParams {
// optional vm_name, otherwise will search for the first QEMU process
QEMUProcFs {
vm_name: Option<String>,
},
KVM {
pid: u32,
},
// default value for device: "FPGA"
PCILeech {
device: Option<String>,
memmap: Option<PathBuf>,
},
Coredump {
filepath: PathBuf,
},
}
/// Describes Memflow initialization parameters
pub enum MemflowInitParams {
Default {
connector_name: Option<String>,
connector_args: Option<MemflowConnectorParams>,
},
}
/// This struct is used to pass all initialization parameters for all drivers
/// when calling init_driver()
#[derive(Default)]
pub struct MicrovmiInitParams {
xen: Option<XenInitParams>,
kvm: Option<KVMInitParams>,
memflow: Option<MemflowInitParams>,
}
fn main() {
let init_params_kvm = KVMInitParams::UnixSocket {
vm_name: String::from("windows10"),
socket_path: PathBuf::from(r"/tmp/introspector"),
};
let init_params_xen = XenInitParams::Default {
vm_name: String::from("windows10"),
};
let init_params = MicrovmiInitParams {
kvm: Some(init_params_kvm),
xen: Some(init_params_xen),
..Default::default()
};
let driver = init_driver(None, init_params);
}
from libmicrovmi.
Update: we can pack the common parameters inside the MicrovmiInitParams
struct:
use std::error::Error;
use std::path::PathBuf;
pub enum DriverType {}
pub fn init_driver(
driver_type: Option<DriverType>,
driver_init_params: Option<MicrovmiInitParams>,
) -> Result<(), Box<dyn Error>> {
unimplemented!();
}
/// Describes Xen initialization parameters
pub enum XenInitParams {}
/// Describes KVM initialization parameters
pub enum KVMInitParams {
UnixSocket { socket_path: PathBuf },
VSock { port: u32 },
}
/// Describes Memflow connector parameters
pub enum MemflowConnectorParams {
// optional vm_name, otherwise will search for the first QEMU process
QEMUProcFs {
vm_name: Option<String>,
},
KVM {
pid: u32,
},
// default value for device: "FPGA"
PCILeech {
device: Option<String>,
memmap: Option<PathBuf>,
},
Coredump {
filepath: PathBuf,
},
}
/// Describes Memflow initialization parameters
pub enum MemflowInitParams {
Default {
connector_name: Option<String>,
connector_args: Option<MemflowConnectorParams>,
},
}
pub struct CommonInitParams {
vm_name: String,
}
/// This struct is used to pass all initialization parameters for all drivers
/// when calling init_driver()
#[derive(Default)]
pub struct MicrovmiInitParams {
common: Option<CommonInitParams>,
xen: Option<XenInitParams>,
kvm: Option<KVMInitParams>,
memflow: Option<MemflowInitParams>,
}
fn main() {
let common_init_params = CommonInitParams {
vm_name: String::from("windows10"),
};
let init_params_kvm = KVMInitParams::UnixSocket {
socket_path: PathBuf::from(r"/tmp/introspector"),
};
let init_params = MicrovmiInitParams {
common: Some(common_init_params),
kvm: Some(init_params_kvm),
..Default::default()
};
let driver = init_driver(None, Some(init_params));
}
You can find the design code on rust playground
from libmicrovmi.
Related Issues (20)
- Build system: opportunistic drivers
- Volatility3 integration HOT 10
- libmicrovmi python bindings HOT 19
- KVM: Handle read size > 4K
- API: remove get_page_access HOT 2
- Design: refactoring read_physical API HOT 2
- Include libmicrovmi.h generated C header into the Debian package HOT 2
- xen libraries linked with libmicrovmi.so
- Add technical documentation HOT 1
- LeechCore integration HOT 34
- RUSTSEC-2020-0077: memmap is unmaintained
- Native VirtualBox driver via builtin debugger interface HOT 3
- Windows release
- RUSTSEC-2021-0119: Out-of-bounds write in nix::unistd::getgrouplist
- Memflow support; current state of the art
- Can't Install on Arch Based Systems HOT 4
- wrong
- Halt introspected VM on volatility execution HOT 2
- Question: Python volatility3 plugin does not work when VM is paused HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from libmicrovmi.