Skip to content

Commit

Permalink
singlestep support added
Browse files Browse the repository at this point in the history
  • Loading branch information
arnabcs17b006 committed Aug 18, 2020
1 parent 535e45e commit 891b21f
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 15 deletions.
3 changes: 1 addition & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,12 @@ 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/cs17b006/xenctrl", branch = "pagefault", 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 }
xenevtchn = { git = "https://github.com/arnabcs17b006/xenevtchn", branch = "event-notification"}
xenvmevent-sys = { git = "https://github.com/Wenzel/xenvmevent-sys"}
kvmi = { git = "https://github.com/Wenzel/kvmi", optional = true }
>>>>>>> event support for xen
fdp = { git = "https://github.com/Wenzel/fdp", optional = true }
winapi = { version = "0.3.8", features = ["tlhelp32", "winnt", "handleapi", "securitybaseapi"], optional = true }
widestring = { version = "0.4.0", optional = true }
Expand Down
8 changes: 6 additions & 2 deletions examples/mem-events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::sync::Arc;
use std::time::Instant;

use microvmi::api::{
Access, EventReplyType, EventType, InterceptType, Introspectable, PAGE_SHIFT, PAGE_SIZE,
Access, DriverInitParam, EventReplyType, EventType, InterceptType, Introspectable, PAGE_SIZE,
};

fn parse_args() -> ArgMatches<'static> {
Expand Down Expand Up @@ -38,6 +38,10 @@ fn main() {

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();
Expand All @@ -47,7 +51,7 @@ fn main() {
.expect("Error setting Ctrl-C handler");

println!("Initialize Libmicrovmi");
let mut drv: Box<dyn Introspectable> = microvmi::init(domain_name, None);
let mut drv: Box<dyn Introspectable> = microvmi::init(domain_name, None, init_option);
println!("Listen for memory events...");
// record elapsed time
let start = Instant::now();
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
);
}
16 changes: 15 additions & 1 deletion src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use std::ffi::{CStr, IntoStringError};

use crate::capi::DriverInitParamFFI;


bitflags! {
pub struct Access: u32 {
const R=0b00000001;
Expand Down Expand Up @@ -293,6 +292,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 @@ -322,6 +322,20 @@ 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,
/// Physical memory address of the guest
gpa: u64,
/// 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
10 changes: 4 additions & 6 deletions src/driver/xen.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
use crate::api::{
<<<<<<< HEAD
CrType, Event, EventType, InterceptType, Introspectable, Registers, SegmentReg, X86Registers, DriverInitParam,
=======
Access, CrType, Event, EventType, InterceptType, Introspectable, Registers, SegmentReg,
X86Registers,
>>>>>>> pagefault event support added
Access, CrType, DriverInitParam, Event, EventType, InterceptType, Introspectable, Registers,
SegmentReg, X86Registers,
};
use std::convert::{From, TryFrom};
use std::error::Error;
Expand Down Expand Up @@ -266,6 +262,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 @@ -324,6 +321,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 891b21f

Please sign in to comment.