Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

backdoor: allow avoiding iopl permission errors #8

Merged
merged 1 commit into from
Oct 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "vmw_backdoor"
version = "0.1.4-alpha.0"
version = "0.2.0-alpha.0"
authors = ["Luca BRUNO <[email protected]>"]
edition = "2018"
license = "MIT/Apache-2.0"
Expand Down
2 changes: 1 addition & 1 deletion examples/check-backdoor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ fn main() {
let is_vmw = vmw::is_vmware_cpu();
println!("VMware CPU detected: {}.", is_vmw);

let mut backdoor = vmw::access_backdoor().unwrap();
let mut backdoor = vmw::access_backdoor_privileged().unwrap();
println!("Raised I/O access to reach backdoor port.");

let found = match backdoor.probe_vmware_backdoor() {
Expand Down
2 changes: 1 addition & 1 deletion examples/get-guestinfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ fn main() {
panic!("Hypervisor not present");
}

let mut backdoor = vmw::probe_backdoor().unwrap();
let mut backdoor = vmw::probe_backdoor_privileged().unwrap();
eprintln!("Got backdoor access.");

let mut erpc = backdoor.open_enhanced_chan().unwrap();
Expand Down
2 changes: 1 addition & 1 deletion examples/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ fn main() {
panic!("Hypervisor not present");
}

let mut backdoor = vmw::probe_backdoor().unwrap();
let mut backdoor = vmw::probe_backdoor_privileged().unwrap();
eprintln!("Got backdoor access.");

let mut erpc = backdoor.open_enhanced_chan().unwrap();
Expand Down
2 changes: 1 addition & 1 deletion examples/report-agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ fn main() {
panic!("Hypervisor not present");
}

let mut backdoor = vmw::probe_backdoor().unwrap();
let mut backdoor = vmw::probe_backdoor_privileged().unwrap();
eprintln!("Got backdoor access.");

let mut erpc = backdoor.open_enhanced_chan().unwrap();
Expand Down
39 changes: 33 additions & 6 deletions src/backdoor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,31 @@ pub(crate) const COMMAND_ERPC: u32 = 0x1E;

/// Try to acquire access to the backdoor, but do NOT probe its presence.
///
/// On Linux, this requires running with `CAP_SYS_RAWIO` privileges.
pub fn access_backdoor() -> Result<BackdoorGuard, VmwError> {
/// On Linux, this tries to change I/O access level via `iopl()`. That requires
/// running with `CAP_SYS_RAWIO` capability and it is not compatible with
/// `kernel_lockdown`.
pub fn access_backdoor_privileged() -> Result<BackdoorGuard, VmwError> {
BackdoorGuard::change_io_access(true)?;
Ok(BackdoorGuard {
release_on_drop: true,
})
}

/// Try to acquire access to the backdoor, but do NOT probe its presence.
///
/// Wherever possible, use `access_backdoor_privileged()` instead.
pub fn access_backdoor() -> Result<BackdoorGuard, VmwError> {
Ok(BackdoorGuard {
release_on_drop: false,
})
}

/// Try to acquire access to the backdoor, and probe its presence.
///
/// On Linux, this requires running with `CAP_SYS_RAWIO` privileges.
pub fn probe_backdoor() -> Result<BackdoorGuard, VmwError> {
/// On Linux, this tries to change I/O access level via `iopl()`. That requires
/// running with `CAP_SYS_RAWIO` capability and it is not compatible with
/// `kernel_lockdown`.
pub fn probe_backdoor_privileged() -> Result<BackdoorGuard, VmwError> {
BackdoorGuard::change_io_access(true)?;
let mut guard = BackdoorGuard {
release_on_drop: true,
Expand All @@ -37,6 +50,17 @@ pub fn probe_backdoor() -> Result<BackdoorGuard, VmwError> {
Ok(guard)
}

/// Try to acquire access to the backdoor, and probe its presence.
///
/// Wherever possible, use `probe_backdoor_privileged()` instead.
pub fn probe_backdoor() -> Result<BackdoorGuard, VmwError> {
let mut guard = BackdoorGuard {
release_on_drop: false,
};
guard.probe_vmware_backdoor()?;
Ok(guard)
}

/// Guard for an open backdoor.
///
/// This can be acquired via [`access_backdoor`](fn.access_backdoor.html) or
Expand Down Expand Up @@ -69,6 +93,7 @@ impl BackdoorGuard {
EnhancedChan::open(self)
}

/// Try to change I/O ports access level.
pub(crate) fn change_io_access(acquire: bool) -> Result<(), VmwError> {
// NOTE(lucab): `ioperm()` is not enough here, as the backdoor
// protocol uses a dynamic range of I/O ports.
Expand All @@ -85,8 +110,10 @@ impl BackdoorGuard {

impl Drop for BackdoorGuard {
fn drop(&mut self) {
if self.release_on_drop && Self::change_io_access(false).is_err() {
log::warn!("failed to release backdoor access");
if self.release_on_drop {
if let Err(e) = Self::change_io_access(false) {
log::error!("failed to release backdoor access: {}", e);
}
}
}
}
Expand Down
7 changes: 5 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
//! let is_vmw = vmw_backdoor::is_vmware_cpu();
//! println!("VMware CPU detected: {}.", is_vmw);
//!
//! let mut guard = vmw_backdoor::access_backdoor().unwrap();
//! let mut guard = vmw_backdoor::access_backdoor_privileged().unwrap();
//! println!("Raised I/O access to reach backdoor port.");
//!
//! let found = guard.probe_vmware_backdoor().unwrap_or(false);
Expand Down Expand Up @@ -54,8 +54,11 @@ cfg_if::cfg_if! {
mod erpc;
mod low_bw;

pub use backdoor::{access_backdoor, probe_backdoor, BackdoorGuard};
pub use asm::is_vmware_cpu;
pub use backdoor::{
access_backdoor, access_backdoor_privileged, probe_backdoor, probe_backdoor_privileged,
BackdoorGuard,
};
pub use erpc::EnhancedChan;
}
}