Skip to content

Commit

Permalink
pagefault event support added
Browse files Browse the repository at this point in the history
  • Loading branch information
arnabcs17b006 committed Sep 2, 2020
1 parent 4b0ca56 commit 6b60988
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 31 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 = "breakpoint", optional = true }
xenctrl = { git = "https://github.com/arnabcs17b006/xenctrl", branch = "pagefault", 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
19 changes: 8 additions & 11 deletions examples/mem-events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@ use std::sync::Arc;
use std::time::Instant;

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

const PAGE_SIZE: usize = 4096;

fn parse_args() -> ArgMatches<'static> {
App::new(file!())
.version("0.1")
Expand All @@ -25,7 +23,7 @@ fn toggle_pf_intercept(drv: &mut Box<dyn Introspectable>, enabled: bool) {
let intercept = InterceptType::Pagefault;
let status_str = if enabled { "Enabling" } else { "Disabling" };
println!("{} memory events", status_str);
for vcpu in 0..drv.get_vcpu_count().unwrap() {
for vcpu in 0..1 {
drv.toggle_intercept(vcpu, intercept, enabled)
.expect(&format!("Failed to enable page faults"));
}
Expand All @@ -39,7 +37,6 @@ fn main() {
let matches = parse_args();

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

// set CTRL-C handler
let running = Arc::new(AtomicBool::new(true));
let r = running.clone();
Expand All @@ -61,11 +58,11 @@ fn main() {

//Code snippet to get page fault
let max_addr = drv.get_max_physical_addr().unwrap();

for cur_addr in (0..max_addr).step_by(PAGE_SIZE) {
//println!("max_gpfn: {}", max_addr>>PAGE_SHIFT);
for cur_addr in (0..max_addr).step_by(PAGE_SIZE as usize) {
let mut access: Access = drv.get_page_access(cur_addr).unwrap();
access &= !Access::X;
drv.set_page_access(cur_addr, access)
drv.set_page_access(cur_addr, !Access::X)
.expect("failed to set page access");
}

Expand All @@ -87,10 +84,10 @@ fn main() {
let mut page_access = drv.get_page_access(gpa).expect("Failed to get page access");
//setting the access bits in the page due to which page fault occurred
page_access |= pf_access;
drv.set_page_access(gpa, page_access)
drv.set_page_access(gpa, Access::RWX)
.expect("Failed to set page access");
drv.reply_event(ev, EventReplyType::Continue)
.expect("Failed to send event reply");
//drv.reply_event(ev, EventReplyType::Continue)
// .expect("Failed to send event reply");
i = i + 1;
}
None => println!("No events yet..."),
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
2 changes: 1 addition & 1 deletion src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,6 @@ pub enum EventType {
msr_type: u32,
/// new value after msr register has been intercepted by the guest.
value: u64,

},
///int3 interception
Breakpoint {
Expand All @@ -344,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 Down
4 changes: 2 additions & 2 deletions src/driver/kvm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,9 +309,9 @@ impl<T: KVMIntrospectable> Introspectable for Kvm<T> {
new,
old,
},
KVMiEventType::Msr { msr_type, new, old } => EventType::Msr {
KVMiEventType::Msr { msr_type, new, old: _ } => EventType::Msr {
msr_type,
value,
value: new,
},
KVMiEventType::Breakpoint {gpa, insn_len } => EventType::Breakpoint {
gpa,
Expand Down
67 changes: 55 additions & 12 deletions src/driver/xen.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,56 @@
use crate::api::{
DriverInitParam, Introspectable, Registers, SegmentReg, SystemTableReg, X86Registers,
Access, CrType, DriverInitParam, Event, EventType, InterceptType, Introspectable, Registers,
SegmentReg, SystemTableReg, X86Registers,
};
use libc::{PROT_READ, PROT_WRITE};
use std::error::Error;
use std::mem;

use crate::api::{
CrType, Event, EventType, InterceptType, Introspectable, Registers, SegmentReg, X86Registers,
};

use libc::PROT_READ;
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};
use xenctrl::{XenControl, XenCr, XenEventType, XenPageAccess};
use xenevtchn::XenEventChannel;
use xenforeignmemory::XenForeignMem;
use xenstore::{XBTransaction, Xs, XsOpenFlags};
use xenvmevent_sys::{
vm_event_back_ring, vm_event_response_t, VM_EVENT_FLAG_VCPU_PAUSED, VM_EVENT_INTERFACE_VERSION,
};

impl TryFrom<Access> for XenPageAccess {
type Error = &'static str;
fn try_from(access: Access) -> Result<Self, Self::Error> {
match access {
Access::NIL => Ok(XenPageAccess::NIL),
Access::R => Ok(XenPageAccess::R),
Access::W => Ok(XenPageAccess::W),
Access::RW => Ok(XenPageAccess::RW),
Access::X => Ok(XenPageAccess::X),
Access::RX => Ok(XenPageAccess::RX),
Access::WX => Ok(XenPageAccess::WX),
Access::RWX => Ok(XenPageAccess::RWX),
_ => Err("invalid access value"),
}
}
}

impl From<XenPageAccess> for Access {
fn from(access: XenPageAccess) -> Self {
match access {
XenPageAccess::NIL => Access::NIL,
XenPageAccess::R => Access::R,
XenPageAccess::W => Access::W,
XenPageAccess::RW => Access::RW,
XenPageAccess::X => Access::X,
XenPageAccess::RX => Access::RX,
XenPageAccess::WX => Access::WX,
XenPageAccess::RWX => Access::RWX,
}
}
}

#[derive(Debug)]
pub struct Xen {
xc: XenControl,
Expand Down Expand Up @@ -267,7 +295,11 @@ impl Introspectable for Xen {
XenEventType::Breakpoint { gpa, insn_len } => {
EventType::Breakpoint { gpa, insn_len }
}
_ => unimplemented!(),
XenEventType::Pagefault { gva, gpa, access } => EventType::Pagefault {
gva,
gpa,
access: access.into(),
},
};
vcpu = req.vcpu_id.try_into().unwrap();
let mut rsp =
Expand All @@ -289,6 +321,17 @@ impl Introspectable for Xen {
}
}

fn get_page_access(&self, paddr: u64) -> Result<Access, Box<dyn Error>> {
let access = self.xc.get_mem_access(self.domid, paddr >> PAGE_SHIFT)?;
Ok(access.into())
}

fn set_page_access(&self, paddr: u64, access: Access) -> Result<(), Box<dyn Error>> {
Ok(self
.xc
.set_mem_access(self.domid, access.try_into().unwrap(), paddr >> PAGE_SHIFT)?)
}

fn toggle_intercept(
&mut self,
_vcpu: u16,
Expand All @@ -314,7 +357,7 @@ impl Introspectable for Xen {
InterceptType::Breakpoint => {
Ok(self.xc.monitor_software_breakpoint(self.domid, enabled)?)
}
_ => unimplemented!(),
InterceptType::Pagefault => Ok(()),
}
}

Expand Down

0 comments on commit 6b60988

Please sign in to comment.