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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use crate::{EnhancedChan, VmwError};
pub(crate) const BACKDOOR_MAGIC: u32 = 0x564D5868;
pub(crate) const BACKDOOR_PORT_LB: u32 = 0x5658;
pub(crate) const BACKDOOR_PORT_HB: u32 = 0x5659;
pub(crate) const COMMAND_GET_VERSION: u32 = 0x0A;
pub(crate) const COMMAND_ERPC: u32 = 0x1E;
pub fn access_backdoor_privileged() -> Result<BackdoorGuard, VmwError> {
BackdoorGuard::change_io_access(true)?;
Ok(BackdoorGuard {
release_on_drop: true,
})
}
pub fn access_backdoor() -> Result<BackdoorGuard, VmwError> {
Ok(BackdoorGuard {
release_on_drop: false,
})
}
pub fn probe_backdoor_privileged() -> Result<BackdoorGuard, VmwError> {
BackdoorGuard::change_io_access(true)?;
let mut guard = BackdoorGuard {
release_on_drop: true,
};
guard.probe_vmware_backdoor()?;
Ok(guard)
}
pub fn probe_backdoor() -> Result<BackdoorGuard, VmwError> {
let mut guard = BackdoorGuard {
release_on_drop: false,
};
guard.probe_vmware_backdoor()?;
Ok(guard)
}
#[derive(Debug)]
pub struct BackdoorGuard {
release_on_drop: bool,
}
impl BackdoorGuard {
pub fn probe_vmware_backdoor(&mut self) -> Result<(), VmwError> {
self.get_version().and(Ok(()))
}
pub fn release_access(self) -> Result<(), Self> {
let mut guard = self;
if Self::change_io_access(false).is_err() {
return Err(guard);
}
guard.release_on_drop = false;
drop(guard);
Ok(())
}
pub fn open_enhanced_chan(&mut self) -> Result<EnhancedChan, VmwError> {
EnhancedChan::open(self)
}
pub(crate) fn change_io_access(acquire: bool) -> Result<(), VmwError> {
let level = if acquire { 0b11 } else { 0b00 };
let err = unsafe { libc::iopl(level) };
if err != 0 {
let err_code = errno::errno();
return Err(format!("iopl failed: {} (errno: {})", err_code, err_code.0).into());
};
Ok(())
}
}
impl Drop for BackdoorGuard {
fn drop(&mut self) {
if self.release_on_drop {
if let Err(e) = Self::change_io_access(false) {
log::error!("failed to release backdoor access: {}", e);
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_magic_string() {
assert_eq!(BACKDOOR_MAGIC, u32::from_be_bytes(*b"VMXh"));
}
}