VMCS auditor

This commit is contained in:
Masato Imai
2025-08-12 12:10:46 +00:00
parent db6c38b6de
commit f08ed4615c
4 changed files with 118 additions and 1 deletions

View File

@ -0,0 +1,113 @@
use x86::{msr, vmx::vmcs};
use crate::vmm::x86_64::{
common::read_msr,
intel::{self, vmread},
};
pub fn check_vmcs_control_fields() -> Result<(), &'static str> {
let msr_ia32_vmx_basic = read_msr(msr::IA32_VMX_BASIC);
let vmx_true_ctrl = msr_ia32_vmx_basic & (1 << 55) != 0;
check_pin_based_exec_ctrl(vmx_true_ctrl)?;
check_primary_proc_based_exec_ctrl(vmx_true_ctrl)?;
if intel::vmcs::controls::PrimaryProcessorBasedVmExecutionControls::read()?
.activate_secondary_controls()
{
check_secondary_proc_based_exec_ctrl(vmx_true_ctrl)?;
}
Ok(())
}
fn check_pin_based_exec_ctrl(vmx_true_ctrl: bool) -> Result<(), &'static str> {
let msr_vmx_pin_based_exec_ctrl = if vmx_true_ctrl {
read_msr(msr::IA32_VMX_TRUE_PINBASED_CTLS)
} else {
read_msr(msr::IA32_VMX_PINBASED_CTLS)
};
let vmcs_pin_based_exec_ctrl = vmread(vmcs::control::PINBASED_EXEC_CONTROLS)?;
let msr_vmx_pin_based_exec_ctrl_low = (msr_vmx_pin_based_exec_ctrl & 0xFFFFFFFF) as u32;
let msr_vmx_pin_based_exec_ctrl_high = (msr_vmx_pin_based_exec_ctrl >> 32) as u32;
if !(vmcs_pin_based_exec_ctrl & 0xFFFFFFFF) as u32 & msr_vmx_pin_based_exec_ctrl_low != 0 {
return Err(
"VMCS Pin-based execution controls field: IA32_VMX_PINBASED_CTRLS low bits not set",
);
}
if (vmcs_pin_based_exec_ctrl >> 32) as u32 & !msr_vmx_pin_based_exec_ctrl_high != 0 {
return Err(
"VMCS Pin-based execution controls field: IA32_VMX_PINBASED_CTRLS high bits not zero",
);
}
Ok(())
}
fn check_primary_proc_based_exec_ctrl(vmx_true_ctrl: bool) -> Result<(), &'static str> {
let msr_vmx_primary_proc_based_exec_ctrl = if vmx_true_ctrl {
read_msr(msr::IA32_VMX_TRUE_PROCBASED_CTLS)
} else {
read_msr(msr::IA32_VMX_PROCBASED_CTLS)
};
let vmcs_primary_proc_based_exec_ctrl = vmread(vmcs::control::PRIMARY_PROCBASED_EXEC_CONTROLS)?;
let msr_vmx_primary_proc_based_exec_ctrl_low =
(msr_vmx_primary_proc_based_exec_ctrl & 0xFFFFFFFF) as u32;
let msr_vmx_primary_proc_based_exec_ctrl_high =
(msr_vmx_primary_proc_based_exec_ctrl >> 32) as u32;
if !(vmcs_primary_proc_based_exec_ctrl & 0xFFFFFFFF) as u32
& msr_vmx_primary_proc_based_exec_ctrl_low
!= 0
{
return Err(
"VMCS Primary processor-based execution controls field: IA32_VMX_PROCBASED_CTRLS low bits not set",
);
}
if (vmcs_primary_proc_based_exec_ctrl >> 32) as u32 & !msr_vmx_primary_proc_based_exec_ctrl_high
!= 0
{
return Err(
"VMCS Primary processor-based execution controls field: IA32_VMX_PROCBASED_CTRLS high bits not zero",
);
}
Ok(())
}
fn check_secondary_proc_based_exec_ctrl(vmx_true_ctrl: bool) -> Result<(), &'static str> {
let msr_vmx_secondary_proc_based_exec_ctrl = if vmx_true_ctrl {
read_msr(msr::IA32_VMX_PROCBASED_CTLS2)
} else {
0
};
let vmcs_secondary_proc_based_exec_ctrl =
vmread(vmcs::control::SECONDARY_PROCBASED_EXEC_CONTROLS)?;
let msr_vmx_secondary_proc_based_exec_ctrl_low =
(msr_vmx_secondary_proc_based_exec_ctrl & 0xFFFFFFFF) as u32;
let msr_vmx_secondary_proc_based_exec_ctrl_high =
(msr_vmx_secondary_proc_based_exec_ctrl >> 32) as u32;
if !(vmcs_secondary_proc_based_exec_ctrl & 0xFFFFFFFF) as u32
& msr_vmx_secondary_proc_based_exec_ctrl_low
!= 0
{
return Err(
"VMCS Secondary processor-based execution controls field: IA32_VMX_PROCBASED_CTRLS2 low bits not set",
);
}
if (vmcs_secondary_proc_based_exec_ctrl >> 32) as u32
& !msr_vmx_secondary_proc_based_exec_ctrl_high
!= 0
{
return Err(
"VMCS Secondary processor-based execution controls field: IA32_VMX_PROCBASED_CTRLS2 high bits not zero",
);
}
Ok(())
}

View File

@ -0,0 +1 @@
pub mod controls;

View File

@ -1,4 +1,5 @@
pub mod asm; pub mod asm;
mod auditor;
mod controls; mod controls;
mod cpuid; mod cpuid;
mod ept; mod ept;

View File

@ -13,7 +13,7 @@ use crate::{
x86_64::{ x86_64::{
common::{self, read_msr}, common::{self, read_msr},
intel::{ intel::{
controls, cpuid, ept, auditor, controls, cpuid, ept,
msr::{self, ShadowMsr}, msr::{self, ShadowMsr},
register::GuestRegisters, register::GuestRegisters,
vmcs::{ vmcs::{
@ -123,6 +123,8 @@ impl IntelVCpu {
fn vmentry(&mut self) -> Result<(), InstructionError> { fn vmentry(&mut self) -> Result<(), InstructionError> {
msr::update_msrs(self).unwrap(); msr::update_msrs(self).unwrap();
auditor::controls::check_vmcs_control_fields().unwrap();
let success = { let success = {
let result: u16; let result: u16;
unsafe { unsafe {