Skip to content

Commit 759df1e

Browse files
committed
intel PT: check for availability in VMX
1 parent 0802674 commit 759df1e

File tree

3 files changed

+36
-3
lines changed

3 files changed

+36
-3
lines changed

crates/libafl_intelpt/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,6 @@
33
This module is a wrapper around the `IntelPT` kernel driver, exposing functionalities specifically crafted for `LibAFL`.
44

55
At the moment only `Linux` hosts are supported.
6+
7+
You can run `sudo -E cargo test intel_pt_check_availability -- --show-output` to check if your host has all the features
8+
used by this crate.

crates/libafl_intelpt/src/lib.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ pub fn availability_in_qemu_kvm() -> Result<(), String> {
8484

8585
#[cfg(target_os = "linux")]
8686
{
87+
if let Err(reason) = availability_in_vmx() {
88+
reasons.push(reason);
89+
}
90+
8791
let kvm_pt_mode_path = "/sys/module/kvm_intel/parameters/pt_mode";
8892
// Ignore the case when the file does not exist since it has been removed.
8993
// KVM default is `System` mode
@@ -123,7 +127,7 @@ mod test {
123127

124128
/// Quick way to check if your machine is compatible with Intel PT's features used by libafl
125129
///
126-
/// Simply run `cargo test intel_pt_check_availability -- --show-output`
130+
/// Simply run `sudo -E cargo test intel_pt_check_availability -- --show-output`
127131
#[test]
128132
fn intel_pt_check_availability() {
129133
print!("Intel PT availability:\t\t\t");

crates/libafl_intelpt/src/linux.rs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use alloc::{
1111
use core::{ffi::CStr, fmt::Debug, ops::RangeInclusive, ptr};
1212
use std::{
1313
fs,
14+
io::{Read, Seek, SeekFrom},
1415
os::{
1516
fd::{AsRawFd, FromRawFd, OwnedFd},
1617
raw::c_void,
@@ -544,7 +545,7 @@ impl Default for IntelPTBuilder {
544545
/// .inherit(false)
545546
/// .perf_buffer_size(128 * PAGE_SIZE + PAGE_SIZE)
546547
/// .unwrap()
547-
/// .perf_aux_buffer_size(2 * 1024 * 1024)
548+
/// .perf_aux_buffer_size(4 * 1024 * 1024)
548549
/// .unwrap()
549550
/// .ip_filters(&[]);
550551
/// assert_eq!(builder, IntelPTBuilder::default());
@@ -557,7 +558,7 @@ impl Default for IntelPTBuilder {
557558
exclude_hv: true,
558559
inherit: false,
559560
perf_buffer_size: 128 * PAGE_SIZE + PAGE_SIZE,
560-
perf_aux_buffer_size: 2 * 1024 * 1024,
561+
perf_aux_buffer_size: 4 * 1024 * 1024,
561562
ip_filters: Vec::new(),
562563
}
563564
}
@@ -833,6 +834,31 @@ pub(crate) fn availability_in_linux() -> Result<(), String> {
833834
}
834835
}
835836

837+
/// Check if the `MSR IA32_VMX_MISC` has bit 14 set, which indicates that Intel PT is
838+
/// available in VMX operations.
839+
pub(crate) fn availability_in_vmx() -> Result<(), String> {
840+
let error_prefix = "Failed to check for PT availability in VM operations: ";
841+
let mut msrs = fs::OpenOptions::new()
842+
.read(true)
843+
.open("/dev/cpu/0/msr")
844+
.map_err(|e| {
845+
format!(
846+
"{error_prefix} Failed to open /dev/cpu/0/msr: {e} \
847+
Make sure you have the `msr` kernel module loaded"
848+
)
849+
})?;
850+
msrs.seek(SeekFrom::Start(0x485))
851+
.map_err(|e| format!("{error_prefix} Failed to seek in /dev/cpu/0/msr: {e}"))?;
852+
let mut buf = [0u8; 8];
853+
msrs.read_exact(&mut buf)
854+
.map_err(|e| format!("{error_prefix} Failed to read MSR 0x485: {e}"))?;
855+
if buf[1] & 0b0100_0000 == 0 {
856+
return Err("Intel PT is not available for VMX operations.".to_owned());
857+
}
858+
859+
Ok(())
860+
}
861+
836862
fn new_perf_event_attr_intel_pt() -> Result<perf_event_attr, Error> {
837863
let type_ = match &*PERF_EVENT_TYPE {
838864
Ok(t) => Ok(*t),

0 commit comments

Comments
 (0)