Skip to content

Commit 5745433

Browse files
authored
Merge pull request #196 from Wenzel/driver/memflow
Add Memflow driver
2 parents c878e2c + 7cb60c8 commit 5745433

File tree

15 files changed

+360
-9
lines changed

15 files changed

+360
-9
lines changed

.github/workflows/ci.yml

+25-2
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,29 @@ jobs:
126126
flags: unittests
127127
fail_ci_if_error: true
128128

129+
memflow:
130+
runs-on: ubuntu-20.04
131+
132+
steps:
133+
- name: install stable toolchain with clippy
134+
uses: actions-rs/toolchain@v1
135+
with:
136+
profile: minimal
137+
toolchain: stable
138+
components: clippy
139+
- uses: actions/checkout@v1
140+
- name: build Memflow driver
141+
uses: actions-rs/cargo@v1
142+
with:
143+
command: build
144+
args: --features mflow
145+
- name: annotate commit with clippy warnings
146+
uses: actions-rs/clippy-check@v1
147+
with:
148+
name: clippy memflow
149+
token: ${{ secrets.GITHUB_TOKEN }}
150+
args: --features mflow -- -D warnings
151+
129152
virtualbox:
130153
runs-on: ubuntu-20.04
131154

@@ -248,7 +271,7 @@ jobs:
248271
uses: satackey/[email protected]
249272

250273
- name: Build Wheels with manylinux
251-
run: nox -r -s generate_wheels -- --features xen,kvm,virtualbox --release
274+
run: nox -r -s generate_wheels -- --features xen,kvm,virtualbox,mflow --release
252275
working-directory: python
253276

254277
# upload all generated wheels *.whl
@@ -311,7 +334,7 @@ jobs:
311334
run: cargo install cargo-deb
312335

313336
- name: build debian package
314-
run: cargo deb -- --features xen,kvm,virtualbox
337+
run: cargo deb -- --features xen,kvm,virtualbox,mflow
315338

316339
- name: upload artifact
317340
uses: actions/upload-artifact@v2

Cargo.toml

+4
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ xen = ["xenctrl", "xenstore-rs", "xenforeignmemory", "xenevtchn", "xenvmevent-sy
2020
kvm = ["kvmi"]
2121
# VirtualBox driver
2222
virtualbox = ["fdp"]
23+
# memflow driver
24+
# feature name is "mflow" to avoid conflict with the dependency
25+
mflow = ["memflow"]
2326

2427

2528
[dependencies]
@@ -42,6 +45,7 @@ winapi = { version = "0.3", features = ["tlhelp32", "winnt", "handleapi", "secur
4245
widestring = { version = "0.4", optional = true }
4346
ntapi = { version = "0.3", optional = true }
4447
vid-sys = { version = "=0.3.0", features = ["deprecated-apis"], optional = true }
48+
memflow = { version = "0.1.5", optional = true }
4549

4650
[dev-dependencies]
4751
utilities = { path = "utilities" }

doc/src/reference/drivers.md

+10
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,18 @@ This section documents the drivers available and the requirements to compile the
99
| `xen` | Build the Xen driver |
1010
| `kvm` | Build the KVM driver |
1111
| `virtualbox` | Build the VirtualBox driver |
12+
| `mflow` | Build the memflow driver |
1213

1314
Example
1415
~~~
1516
$ cargo build --features xen,kvm
1617
~~~
1718

19+
## Rust API initialization parameters
20+
21+
To initialize each Driver from the Rust API,
22+
please check [`DriverInitParams`](https://docs.rs/microvmi/api/params/struct.DriverInitParams.html).
23+
1824
## Xen
1925

2026
~~~
@@ -48,3 +54,7 @@ $ g++ -std=c++11 -shared -fPIC FDP.cpp -o libFDP.so
4854
$ sudo mv include/* /usr/local/include/
4955
$ sudo mv libFDP.so /usr/local/lib/
5056
~~~
57+
58+
## Memflow
59+
60+
Please follow the instructions at [memflow](https://github.com/memflow/memflow)

python/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ xen = ["microvmi/xen"]
2323
kvm = ["microvmi/kvm"]
2424
# VirtualBox driver
2525
virtualbox = ["microvmi/virtualbox"]
26+
# memflow driver
27+
mflow = ["microvmi/mflow"]
2628

2729
[dependencies]
2830
log = "0.4"

python/microvmi/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
from microvmi.microvmi import DriverType, Microvmi
22

3-
from .pymicrovmi import CommonInitParamsPy, DriverInitParamsPy, KVMInitParamsPy
3+
from .pymicrovmi import CommonInitParamsPy, DriverInitParamsPy, KVMInitParamsPy, MemflowInitParamsPy

python/microvmi/volatility/vmi_handler.py

+9-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from urllib.parse import parse_qs, urlparse
44
from urllib.request import BaseHandler, Request
55

6-
from microvmi import CommonInitParamsPy, DriverInitParamsPy, DriverType, KVMInitParamsPy, Microvmi
6+
from microvmi import CommonInitParamsPy, DriverInitParamsPy, DriverType, KVMInitParamsPy, MemflowInitParamsPy, Microvmi
77

88
# to be used by volatility, the VMIHandler should inherit from VolatilityHandler
99
# in order to be non cacheable
@@ -101,16 +101,24 @@ def _parse_driver_init_params(query: str) -> Optional[DriverInitParamsPy]:
101101
return None
102102
common = None
103103
kvm = None
104+
memflow = None
104105
for param, list_value in url_params.items():
105106
if param == "vm_name":
106107
common = CommonInitParamsPy()
107108
common.vm_name = list_value[0]
108109
elif param == "kvm_unix_socket":
109110
kvm = KVMInitParamsPy()
110111
kvm.unix_socket = list_value[0]
112+
elif param == "memflow_connector_name":
113+
memflow = MemflowInitParamsPy(list_value[0])
114+
elif param == "memflow_connector_args":
115+
if memflow is None:
116+
raise MicrovmiHandlerError("memflow connector args received but no connector name specified")
117+
memflow.connector_args = list_value
111118
else:
112119
raise MicrovmiHandlerError(f"Unknown driver initialization parameter: {param}")
113120
init_params = DriverInitParamsPy()
114121
init_params.common = common
115122
init_params.kvm = kvm
123+
init_params.memflow = memflow
116124
return init_params

python/noxfile.py

+30
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,36 @@ def test_volatility_kvm(session):
105105
)
106106

107107

108+
@nox.session
109+
def test_volatility_memflow(session):
110+
"""Run the PsList volatility plugin on the memflow connector specified by the URL"""
111+
# example:
112+
# nox -r -s test_volatility_memflow -- vmi:///?memflow_connector_name=qemu_procfs
113+
args = session.posargs
114+
if not args:
115+
raise RuntimeError("URL required. Example: nox -r -s test_volatility_memflow -- vmi:///...")
116+
# we need to compile and install the extension
117+
session.install("-r", "requirements.txt")
118+
# make sure we have volatility
119+
# Note: we need to use the latest unreleased dev code from Github
120+
session.install("git+https://github.com/volatilityfoundation/volatility3@af090bf29e6bb26a5961e0a6c25b5d1ec6e82498")
121+
# can't use pip install
122+
# see: https://github.com/PyO3/maturin/issues/330
123+
session.run(f'{CUR_DIR / "setup.py"}', "develop", "--features", "mflow")
124+
vol_path = Path(__file__).parent / ".nox" / "test_volatility_memflow" / "bin" / "vol"
125+
plugins_dir = Path(__file__).parent / "microvmi" / "volatility"
126+
session.run(
127+
"sudo",
128+
"-E",
129+
str(vol_path),
130+
"--plugin-dirs",
131+
str(plugins_dir),
132+
"--single-location",
133+
*args,
134+
"windows.pslist.PsList",
135+
)
136+
137+
108138
@nox.session
109139
def coverage_html(session):
110140
session.install("coverage==5.3")

python/src/lib.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use errors::PyMicrovmiError;
1111
use microvmi::api as rapi; // rust api
1212
use microvmi::api::params as rparams; // rust params
1313
use microvmi::init;
14-
use params::{CommonInitParamsPy, DriverInitParamsPy, KVMInitParamsPy};
14+
use params::{CommonInitParamsPy, DriverInitParamsPy, KVMInitParamsPy, MemflowInitParamsPy};
1515

1616
/// microvmi Python module declaration
1717
#[pymodule]
@@ -24,6 +24,7 @@ fn pymicrovmi(_py: Python, m: &PyModule) -> PyResult<()> {
2424
m.add_class::<DriverInitParamsPy>()?;
2525
m.add_class::<CommonInitParamsPy>()?;
2626
m.add_class::<KVMInitParamsPy>()?;
27+
m.add_class::<MemflowInitParamsPy>()?;
2728

2829
Ok(())
2930
}
@@ -89,6 +90,12 @@ impl MicrovmiExt {
8990
kvm: v.kvm.map(|k| rparams::KVMInitParams::UnixSocket {
9091
path: k.unix_socket,
9192
}),
93+
memflow: v.memflow.map(|k| rparams::MemflowInitParams {
94+
connector_name: k.connector_name,
95+
connector_args: Some(rparams::MemflowConnectorParams::Default {
96+
args: k.connector_args,
97+
}),
98+
}),
9299
..Default::default()
93100
});
94101

python/src/params.rs

+23
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,27 @@ impl KVMInitParamsPy {
3333
}
3434
}
3535

36+
/// equivalent of `MemflowInitParams` for Python
37+
#[pyclass]
38+
#[derive(Default, Debug, Clone)]
39+
pub struct MemflowInitParamsPy {
40+
#[pyo3(get, set)]
41+
pub connector_name: String,
42+
#[pyo3(get, set)]
43+
pub connector_args: Vec<String>,
44+
}
45+
46+
#[pymethods]
47+
impl MemflowInitParamsPy {
48+
#[new]
49+
fn new(name: &str) -> Self {
50+
Self {
51+
connector_name: String::from(name),
52+
connector_args: Vec::new(),
53+
}
54+
}
55+
}
56+
3657
/// equivalent of `DriverInitParams` for Python
3758
///
3859
/// # Examples
@@ -58,6 +79,8 @@ pub struct DriverInitParamsPy {
5879
pub common: Option<CommonInitParamsPy>,
5980
#[pyo3(get, set)]
6081
pub kvm: Option<KVMInitParamsPy>,
82+
#[pyo3(get, set)]
83+
pub memflow: Option<MemflowInitParamsPy>,
6184
}
6285

6386
#[pymethods]

src/api/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ bitflags! {
2626
#[derive(Debug, Copy, Clone, PartialEq, IntoEnumIterator)]
2727
pub enum DriverType {
2828
KVM,
29+
Memflow,
2930
VirtualBox,
3031
Xen,
3132
}

src/api/params.rs

+79-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
/// This module describes initialization parameters for all libmicrovmi drivers
1+
//! This module describes initialization parameters for all libmicrovmi drivers
2+
//!
3+
//! The [`DriverInitParams`](struct.DriverInitParams.html) is used to pass additional driver initialization parameters.
4+
//! You might want to check it's documentation for examples on how to initialize your driver.
25
36
/// Xen initialization parameters
47
#[derive(Debug, Clone, PartialEq)]
@@ -10,6 +13,46 @@ pub enum KVMInitParams {
1013
UnixSocket { path: String },
1114
}
1215

16+
/// Memflow connector parameters
17+
///
18+
/// This enumeration reflects the possibilities to initialize Memflow
19+
/// - default: will simply forward the string arguments to the connector
20+
// TODO
21+
// - [`qemu_procfs`](https://github.com/memflow/memflow-qemu-procfs)
22+
// - [`kvm`](https://github.com/memflow/memflow-kvm)
23+
// - [`pcileech`](https://github.com/memflow/memflow-pcileech)
24+
// - [`coredump`](https://github.com/memflow/memflow-coredump)
25+
#[derive(Debug, Clone, PartialEq)]
26+
pub enum MemflowConnectorParams {
27+
// allow to pass an abritrary list of Strings as parameters
28+
Default { args: Vec<String> },
29+
// TODO
30+
// // optional vm_name, otherwise will search for the first QEMU process
31+
// QEMUProcFs {
32+
// vm_name: Option<String>,
33+
// },
34+
// KVM {
35+
// pid: u32,
36+
// },
37+
// // default value for device: "FPGA"
38+
// PCILeech {
39+
// device: Option<String>,
40+
// memmap: Option<String>,
41+
// },
42+
// Coredump {
43+
// filepath: String,
44+
// },
45+
}
46+
47+
/// Memflow initialization parameters
48+
#[derive(Debug, Default, Clone, PartialEq)]
49+
pub struct MemflowInitParams {
50+
/// connector name
51+
pub connector_name: String,
52+
/// optional connector initialization parameters
53+
pub connector_args: Option<MemflowConnectorParams>,
54+
}
55+
1356
/// VirtualBox initialization parameters
1457
#[derive(Debug, Clone, PartialEq)]
1558
pub enum VBoxInitParams {}
@@ -25,10 +68,45 @@ pub struct CommonInitParams {
2568
}
2669

2770
/// This struct is used to specify the initialization parameters for all drivers
71+
///
72+
/// # Examples
73+
///
74+
/// ```no_run
75+
/// // Xen
76+
/// // common.vm_name: mandatory
77+
/// use microvmi::api::params::{DriverInitParams, CommonInitParams, KVMInitParams, MemflowInitParams};
78+
/// let init_params = DriverInitParams {
79+
/// common: Some(CommonInitParams { vm_name: String::from("windows10")}),
80+
/// ..Default::default()
81+
/// };
82+
/// // KVM
83+
/// // common.vm_name: mandatory
84+
/// // kvm.unix_socket: mandatory
85+
/// let init_params = DriverInitParams {
86+
/// common: Some(CommonInitParams { vm_name: String::from("windows10")}),
87+
/// kvm: Some(KVMInitParams::UnixSocket { path: String::from("/tmp/introspector")}),
88+
/// ..Default::default()
89+
/// };
90+
/// // VirtualBox
91+
/// // common.vm_name: mandatory
92+
/// let init_params = DriverInitParams {
93+
/// common: Some(CommonInitParams { vm_name: String::from("windows10")}),
94+
/// ..Default::default()
95+
/// };
96+
/// // Memflow
97+
/// // memflow.connector_name: mandatory
98+
/// // memflow.connector_args: optional
99+
/// let init_params = DriverInitParams {
100+
/// memflow: Some(MemflowInitParams { connector_name: String::from("qemu_procfs"), ///
101+
/// ..Default::default()}),
102+
/// ..Default::default()
103+
/// };
104+
/// ```
28105
#[derive(Default, Debug, Clone, PartialEq)]
29106
pub struct DriverInitParams {
30107
pub common: Option<CommonInitParams>,
31108
pub xen: Option<XenInitParams>,
32109
pub kvm: Option<KVMInitParams>,
110+
pub memflow: Option<MemflowInitParams>,
33111
pub virtualbox: Option<VBoxInitParams>,
34112
}

0 commit comments

Comments
 (0)