1use log::{debug, info};
2
3use memflow::connector::MappedPhysicalMemory;
4use memflow::derive::connector;
5use memflow::error::*;
6use memflow::mem::MemoryMap;
7use memflow::plugins::ConnectorArgs;
8use memflow::types::{umem, Address};
9use memflow_kvm_ioctl::{AutoMunmap, VMHandle};
10use std::sync::Arc;
11
12pub type KVMConnector<'a> = MappedPhysicalMemory<&'a mut [u8], KVMMapData<&'a mut [u8]>>;
13
14pub struct KVMMapData<T> {
15 handle: Arc<AutoMunmap>,
16 mappings: MemoryMap<T>,
17 addr_mappings: MemoryMap<(Address, umem)>,
18}
19
20impl<'a> Clone for KVMMapData<&'a mut [u8]> {
21 fn clone(&self) -> Self {
22 unsafe { Self::from_addrmap_mut(self.handle.clone(), self.addr_mappings.clone()) }
23 }
24}
25
26impl<T> AsRef<MemoryMap<T>> for KVMMapData<T> {
27 fn as_ref(&self) -> &MemoryMap<T> {
28 &self.mappings
29 }
30}
31
32impl<'a> KVMMapData<&'a mut [u8]> {
33 unsafe fn from_addrmap_mut(handle: Arc<AutoMunmap>, map: MemoryMap<(Address, umem)>) -> Self {
34 Self {
35 handle,
36 mappings: map.clone().into_bufmap_mut(),
37 addr_mappings: map,
38 }
39 }
40}
41
42#[connector(name = "kvm")]
44pub fn create_connector<'a>(
45 args: &ConnectorArgs,
46) -> Result<MappedPhysicalMemory<&'a mut [u8], KVMMapData<&'a mut [u8]>>> {
47 const ERROR_UNABLE_TO_READ_MEMORY: &str = "Could not access the memflow device at /dev/memflow. Please make sure that you installed the dkms module properly and that it is loaded via `modprobe memflow`. Also ensure that you have read and write access to /dev/memflow. For further information check the readme at https://github.com/memflow/memflow-kvm";
48
49 let pid = match &args.target {
50 Some(pidstr) => Some(
51 pidstr
52 .parse::<i32>()
53 .map_err(|_| Error(ErrorOrigin::Connector, ErrorKind::ArgValidation))?,
54 ),
55 None => None,
56 };
57
58 let vm = VMHandle::try_open(pid).map_err(|_| {
59 Error(ErrorOrigin::Connector, ErrorKind::UnableToReadMemory)
60 .log_error(ERROR_UNABLE_TO_READ_MEMORY)
61 })?;
62 let (pid, memslots) = vm.info(64).map_err(|_| {
63 Error(ErrorOrigin::Connector, ErrorKind::UnableToReadMemory)
64 .log_error(ERROR_UNABLE_TO_READ_MEMORY)
65 })?;
66 debug!("pid={} memslots.len()={}", pid, memslots.len());
67 for slot in memslots.iter() {
68 debug!(
69 "{:x}-{:x} -> {:x}-{:x}",
70 slot.base,
71 slot.base + slot.map_size,
72 slot.host_base,
73 slot.host_base + slot.map_size
74 );
75 }
76 let mapped_memslots = vm.map_vm(64).map_err(|e| {
77 Error(ErrorOrigin::Connector, ErrorKind::UnableToMapFile).log_error(format!(
78 "The mapped memory slots for the vm could not be read: {}",
79 e
80 ))
81 })?;
82
83 let mut mem_map = MemoryMap::new();
84
85 info!("mmapped {} slots", mapped_memslots.len());
86 for slot in mapped_memslots.iter() {
87 debug!(
88 "{:x}-{:x} -> {:x}-{:x}",
89 slot.base,
90 slot.base + slot.map_size,
91 slot.host_base,
92 slot.host_base + slot.map_size
93 );
94 mem_map.push_remap(
95 slot.base.into(),
96 slot.map_size as umem,
97 slot.host_base.into(),
98 );
99 }
100
101 let munmap = Arc::new(unsafe { AutoMunmap::new(mapped_memslots) });
102
103 let map_data = unsafe { KVMMapData::from_addrmap_mut(munmap, mem_map) };
104
105 let mem = MappedPhysicalMemory::with_info(map_data);
106
107 Ok(mem)
108}