vmi_utils/bpm/controller/
memory.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
use vmi_core::{
    arch::{Architecture as _, EventMemoryAccess as _, EventReason as _},
    Gfn, MemoryAccess, Pa, View, VmiCore, VmiDriver, VmiError, VmiEvent,
};

use super::TapController;

#[doc = include_str!("memory.md")]
pub struct MemoryController<Driver>
where
    Driver: VmiDriver,
{
    _marker: std::marker::PhantomData<Driver>,
}

impl<Driver> TapController for MemoryController<Driver>
where
    Driver: VmiDriver,
{
    type Driver = Driver;

    fn new() -> Self {
        Self {
            _marker: std::marker::PhantomData,
        }
    }

    fn check_event(&self, event: &VmiEvent<Driver::Architecture>) -> Option<(View, Gfn)> {
        let memory_access = match event.reason().as_memory_access() {
            Some(memory_access) => memory_access,
            _ => return None,
        };

        if !memory_access.access().contains(MemoryAccess::X) {
            return None;
        }

        let view = match event.view() {
            Some(view) => view,
            None => return None,
        };

        let gfn = Driver::Architecture::gfn_from_pa(memory_access.pa());
        Some((view, gfn))
    }

    fn insert_breakpoint(
        &mut self,
        _vmi: &VmiCore<Driver>,
        _pa: Pa,
        _view: View,
    ) -> Result<(), VmiError> {
        Ok(())
    }

    fn remove_breakpoint(
        &mut self,
        _vmi: &VmiCore<Driver>,
        _pa: Pa,
        _view: View,
    ) -> Result<(), VmiError> {
        Ok(())
    }

    fn monitor(&mut self, vmi: &VmiCore<Driver>, gfn: Gfn, view: View) -> Result<(), VmiError> {
        vmi.set_memory_access(gfn, view, MemoryAccess::RW)
    }

    fn unmonitor(&mut self, vmi: &VmiCore<Driver>, gfn: Gfn, view: View) -> Result<(), VmiError> {
        vmi.set_memory_access(gfn, view, MemoryAccess::RWX)
    }
}