Skip to content

Commit

Permalink
singlestep support added
Browse files Browse the repository at this point in the history
  • Loading branch information
arnabcs17b006 committed Sep 2, 2020
1 parent b2c7e23 commit 14d96ba
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 14 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ hyper-v = ["winapi", "widestring", "ntapi", "vid-sys"]
log = "0.4.8"
env_logger = "0.7.1"
libc = { version = "0.2.58", optional = true }
xenctrl = { git = "https://github.com/arnabcs17b006/xenctrl", branch = "write_register", optional = true }
xenctrl = { git = "https://github.com/arnabcs17b006/xenctrl", branch = "singlestep", optional = true }
xenstore = { git = "https://github.com/Wenzel/xenstore", optional = true }
xenforeignmemory = { git = "https://github.com/Wenzel/xenforeignmemory", optional = true }
kvmi = { version = "0.2.1", optional = true }
Expand Down
8 changes: 4 additions & 4 deletions examples/msr-events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,17 +109,17 @@ fn main() {
let event = drv.listen(1000).expect("Failed to listen for events");
match event {
Some(ev) => {
let (msr_type, new, old) = match ev.kind {
EventType::Msr { msr_type, new, old } => (msr_type, new, old),
let (msr_type, value) = match ev.kind {
EventType::Msr { msr_type, value } => (msr_type, value),
_ => panic!("not msr event"),
};
let msr_color = "blue";
let ev_nb_output = format!("{}", i).cyan();
let vcpu_output = format!("VCPU {}", ev.vcpu).yellow();
let msr_output = format!("0x{:x}", msr_type).color(msr_color);
println!(
"[{}] {} - {}: old value: 0x{:x} new value: 0x{:x}",
ev_nb_output, vcpu_output, msr_output, old, new
"[{}] {} - {}: new value: 0x{:x}",
ev_nb_output, vcpu_output, msr_output, value,
);
drv.reply_event(ev, EventReplyType::Continue)
.expect("Failed to send event reply");
Expand Down
96 changes: 96 additions & 0 deletions examples/singlestep-events.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::time::Instant;

use clap::{App, Arg, ArgMatches};
use colored::*;
use env_logger;

use microvmi::api::*;

fn parse_args() -> ArgMatches<'static> {
App::new(file!())
.version("0.1")
.about("Watches singlestep VMI events")
.arg(Arg::with_name("vm_name").index(1).required(true))
.get_matches()
}

fn toggle_singlestep_interception(drv: &mut Box<dyn Introspectable>, enabled: bool) {
drv.pause().expect("Failed to pause VM");

let intercept = InterceptType::Singlestep;
let status_str = if enabled { "Enabling" } else { "Disabling" };
println!("{} singlestep events", status_str);
for vcpu in 0..1 {
drv.toggle_intercept(vcpu, intercept, enabled)
.expect(&format!("Failed to enable singlestep"));
}

drv.resume().expect("Failed to resume VM");
}

fn main() {
env_logger::init();

let matches = parse_args();

let domain_name = matches.value_of("vm_name").unwrap();

let init_option = matches
.value_of("kvmi_socket")
.map(|socket| DriverInitParam::KVMiSocket(socket.into()));
// set CTRL-C handler
let running = Arc::new(AtomicBool::new(true));
let r = running.clone();
ctrlc::set_handler(move || {
r.store(false, Ordering::SeqCst);
})
.expect("Error setting Ctrl-C handler");

println!("Initialize Libmicrovmi");
let mut drv: Box<dyn Introspectable> = microvmi::init(domain_name, None, init_option);

//Enable singlestep interception
toggle_singlestep_interception(&mut drv, true);

println!("Listen for singlestep events...");
// record elapsed time
let start = Instant::now();
// listen
let mut i: u64 = 0;
while running.load(Ordering::SeqCst) {
let event = drv.listen(1000).expect("Failed to listen for events");
match event {
Some(ev) => {
let gpa = match ev.kind {
EventType::Singlestep { gpa } => (gpa),
_ => panic!("Not singlestep event"),
};
let ev_nb_output = format!("{}", i).cyan();
let vcpu_output = format!("VCPU {}", ev.vcpu).yellow();
let singlestep_output = format!("singlestep occurred!").color("blue");
println!(
"[{}] {} - {}: gpa = 0x{:x} ",
ev_nb_output, vcpu_output, singlestep_output, gpa
);
//drv.reply_event(ev, EventReplyType::Continue)
// .expect("Failed to send event reply");
i = i + 1;
}
None => println!("No events yet..."),
}
}
let duration = start.elapsed();

//disable singlestep interception
toggle_singlestep_interception(&mut drv, false);

let ev_per_sec = i as f64 / duration.as_secs_f64();
println!(
"Caught {} events in {:.2} seconds ({:.2} events/sec)",
i,
duration.as_secs_f64(),
ev_per_sec
);
}
7 changes: 7 additions & 0 deletions src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ pub enum InterceptType {
/// Intercept when guest requests an access to a page for which the requested type of access is not granted. For example , guest tries to write on a read only page.
Breakpoint,
Pagefault,
Singlestep,
}

/// Various types of events along with their relevant attributes being handled by this driver
Expand Down Expand Up @@ -342,6 +343,7 @@ pub enum EventType {
/// instruction length. Generally it should be one. Anything other than one implies malicious guest.
insn_len: u8,
},
///Pagefault interception
Pagefault {
/// Virtual memory address of the guest
gva: u64,
Expand All @@ -350,6 +352,11 @@ pub enum EventType {
/// Acsess responsible for thr pagefault
access: Access,
},
///Singlestep event
Singlestep {
///Physical memory address of the guest
gpa: u64,
},
}

///Types of x86 control registers are listed here
Expand Down
1 change: 1 addition & 0 deletions src/driver/kvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ impl<T: KVMIntrospectable> Introspectable for Kvm<T> {
.kvmi
.control_events(vcpu, KVMiInterceptType::Pagefault, enabled)?)
}
_ => unimplemented!(),
}
}

Expand Down
17 changes: 8 additions & 9 deletions src/driver/xen.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
use libc::{PROT_READ, PROT_WRITE};
use std::error::Error;
use std::mem;
use crate::api::{
CrType, Event, EventType, InterceptType, Introspectable, Registers, SegmentReg, X86Registers, DriverInitParam, SystemTableReg,
Access, CrType, Event, EventType, InterceptType, Introspectable, Registers, SegmentReg,
X86Registers,
Access, CrType, DriverInitParam, Event, EventType, InterceptType, Introspectable, Registers,
SegmentReg, SystemTableReg, X86Registers,
};
use std::convert::{From, TryFrom};
use std::error::Error;
use std::mem;
use libc::{PROT_READ, PROT_WRITE};
use nix::poll::PollFlags;
use nix::poll::{poll, PollFd};
use std::convert::TryInto;
use std::convert::{From, TryFrom};
use std::error::Error;
use std::mem;
use xenctrl::consts::{PAGE_SHIFT, PAGE_SIZE};
use xenctrl::RING_HAS_UNCONSUMED_REQUESTS;
use xenctrl::{XenControl, XenCr, XenEventType, XenPageAccess};
Expand Down Expand Up @@ -303,6 +300,7 @@ impl Introspectable for Xen {
gpa,
access: access.into(),
},
XenEventType::Singlestep { gpa } => EventType::Singlestep { gpa },
};
vcpu = req.vcpu_id.try_into().unwrap();
let mut rsp =
Expand Down Expand Up @@ -361,6 +359,7 @@ impl Introspectable for Xen {
Ok(self.xc.monitor_software_breakpoint(self.domid, enabled)?)
}
InterceptType::Pagefault => Ok(()),
InterceptType::Singlestep => Ok(self.xc.monitor_singlestep(self.domid, enabled)?),
}
}

Expand Down

0 comments on commit 14d96ba

Please sign in to comment.