Skip to content
This repository has been archived by the owner on Sep 1, 2024. It is now read-only.

Commit

Permalink
Merge pull request #33 from memN0ps/dev
Browse files Browse the repository at this point in the history
Isolation and Security
  • Loading branch information
memN0ps committed Jun 30, 2024
2 parents 20d8310 + 9081dba commit a8881fa
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 35 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ The diagram below illustrates the structure and flow of the Windows UEFI Blue Pi

- :x: Neither basic nor advanced techniques to evade hypervisor detection will be implemented in the public version of this hypervisor.

### Isolation and Security

- :white_check_mark: Custom implementations of the Global Descriptor Table (GDT), Interrupt Descriptor Table (IDT), and Page Tables to enhance the security and isolation of the hypervisor.

## Supported Hardware

- :white_check_mark: Intel processors with VT-x and Extended Page Tables (EPT) support.
Expand Down
2 changes: 1 addition & 1 deletion hypervisor/src/global_const.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
///
/// This value is set to 1 for testing purposes but can be adjusted up to 64 or more based on the system.
/// Adjusting this value will increase the total heap size accordingly.
const DEFAULT_LOGICAL_PROCESSORS: usize = 8;
const DEFAULT_LOGICAL_PROCESSORS: usize = 16;

/// The number of pages for the stack per processor/core.
///
Expand Down
73 changes: 46 additions & 27 deletions hypervisor/src/intel/descriptor.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
//! Manages GDT and TSS for VMX virtualization contexts.
//! Manages GDT, IDT, and TSS for VMX virtualization contexts.
//!
//! Facilitates the creation and manipulation of the Global Descriptor Table (GDT) and
//! Task State Segment (TSS) necessary for VMX operations. Supports both host and guest
//! environments, ensuring compatibility and proper setup for virtualization.
//! Facilitates the creation and manipulation of the Global Descriptor Table (GDT),
//! Interrupt Descriptor Table (IDT), and Task State Segment (TSS) necessary for VMX operations.
//! Supports both host and guest environments, ensuring compatibility and proper setup for virtualization.
//! Credits to Satoshi Tanda: https://github.com/tandasat/Hello-VT-rp/blob/main/hypervisor/src/intel_vt/descriptors.rs

use {
crate::intel::support::sgdt,
crate::intel::support::{sgdt, sidt},
alloc::vec::Vec,
x86::{
dtables::DescriptorTablePointer,
Expand All @@ -16,18 +16,22 @@ use {
},
};

/// Manages GDT and TSS for VMX operations.
///
/// Supports creating a new GDT that includes TSS, addressing compatibility issues in UEFI environments
/// and ensuring proper VM and hypervisor states. This struct is essential for setting up the environment
/// for both host and guest VMX operations.
/// Represents the descriptor tables (GDT and IDT) for the host and guest.
/// Contains the GDT, IDT, TSS, and their respective register pointers.
#[repr(C, align(4096))]
pub struct Descriptors {
/// Vector holding the GDT entries.
pub gdt: Vec<u64>,

/// Descriptor table pointer to the GDT.
pub gdtr: DescriptorTablePointer<u64>,

/// Vector holding the IDT entries.
pub idt: Vec<u64>,

/// Descriptor table pointer to the IDT.
pub idtr: DescriptorTablePointer<u64>,

/// Code segment selector.
pub cs: SegmentSelector,

Expand All @@ -46,16 +50,22 @@ impl Descriptors {
///
/// # Returns
/// A `Descriptors` instance with an updated GDT including TSS.
pub fn new_from_current() -> Self {
pub fn initialize_for_guest() -> Self {
log::debug!("Creating a new GDT with TSS for guest");

// Get the current GDT.
let current_gdtr = sgdt();
let current_gdt = unsafe { core::slice::from_raw_parts(current_gdtr.base.cast::<u64>(), usize::from(current_gdtr.limit + 1) / 8) };

// Get the current IDT.
let current_idtr = sidt();
let current_idt = unsafe { core::slice::from_raw_parts(current_idtr.base.cast::<u64>(), usize::from(current_idtr.limit + 1) / 8) };

let mut descriptors = Descriptors {
gdt: current_gdt.to_vec(),
gdtr: DescriptorTablePointer::<u64>::default(),
idt: current_idt.to_vec(),
idtr: DescriptorTablePointer::<u64>::default(),
cs: SegmentSelector::from_raw(0),
tr: SegmentSelector::from_raw(0),
tss: TaskStateSegment::default(),
Expand Down Expand Up @@ -83,12 +93,14 @@ impl Descriptors {
///
/// # Returns
/// A `Descriptors` instance with a newly created GDT for the host.
pub fn new_for_host() -> Self {
pub fn initialize_for_host() -> Self {
log::debug!("Creating a new GDT with TSS for host");

let mut descriptors = Descriptors {
gdt: Vec::new(),
gdtr: DescriptorTablePointer::<u64>::default(),
idt: Vec::new(),
idtr: DescriptorTablePointer::<u64>::default(),
cs: SegmentSelector::from_raw(0),
tr: SegmentSelector::from_raw(0),
tss: TaskStateSegment::default(),
Expand All @@ -103,7 +115,11 @@ impl Descriptors {
descriptors.cs = SegmentSelector::new(1, x86::Ring::Ring0);
descriptors.tr = SegmentSelector::new(2, x86::Ring::Ring0);

log::debug!("New GDT with TSS created for host successfully!");
// Initialize the IDT with empty descriptors for the host
descriptors.idt = Self::copy_current_idt();
descriptors.idtr = DescriptorTablePointer::new_from_slice(&descriptors.idt);

log::debug!("New GDT with TSS and IDT created for host successfully!");

descriptors
}
Expand Down Expand Up @@ -144,24 +160,29 @@ impl Descriptors {
.finish()
}

/// Converts a descriptor table pointer to a slice of GDT entries.
///
/// # Arguments
///
/// - `pointer`: A reference to the `DescriptorTablePointer` for the GDT.
///
/// # Returns
///
/// A slice of the GDT entries represented as `u64` values.
pub fn from_pointer(pointer: &DescriptorTablePointer<u64>) -> &[u64] {
unsafe { core::slice::from_raw_parts(pointer.base.cast::<u64>(), (pointer.limit + 1) as usize / size_of::<u64>()) }
/// Copies the current IDT for the guest.
fn copy_current_idt() -> Vec<u64> {
log::trace!("Copying current IDT");

// Get the current IDTR
let current_idtr = sidt();

// Create a slice from the current IDT entries.
let current_idt = unsafe { core::slice::from_raw_parts(current_idtr.base.cast::<u64>(), usize::from(current_idtr.limit + 1) / 8) };

// Create a new IDT from the slice.
let new_idt = current_idt.to_vec();

log::trace!("Copied current IDT");

new_idt
}
}

/// Represents the Task State Segment (TSS).
///
/// Encapsulates the TSS, which is critical for task-switching and storing state information
/// in protected mode operations. Includes fields for the base address, limit, and access rights.:
/// in protected mode operations. Includes fields for the base address, limit, and access rights.
#[derive(derivative::Derivative)]
#[derivative(Debug)]
pub struct TaskStateSegment {
Expand Down Expand Up @@ -203,7 +224,5 @@ impl Default for TaskStateSegment {
/// Low-level representation of the 64-bit Task State Segment (TSS).
///
/// Encapsulates the raw structure of the TSS as defined in the x86_64 architecture.
/// This structure is used internally to manage the TSS's memory layout directly.
/// See: Figure 8-11. 64-Bit TSS Format
#[allow(dead_code)]
struct TaskStateSegmentRaw([u8; 104]);
14 changes: 7 additions & 7 deletions hypervisor/src/intel/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ pub struct Vm {
/// The VMCS (Virtual Machine Control Structure) for the VM.
pub vmcs_region: Vmcs,

/// Descriptor tables for the host state.
pub host_descriptor: Descriptors,

/// Descriptor tables for the guest state.
pub guest_descriptor: Descriptors,

/// Descriptor tables for the host state.
pub host_descriptor: Descriptors,

/// Paging tables for the host.
pub host_paging: PageTables,

Expand Down Expand Up @@ -95,11 +95,11 @@ impl Vm {
trace!("Initializing VMCS region");
self.vmcs_region.init();

trace!("Initializing Host Descriptor Tables");
self.host_descriptor = Descriptors::new_for_host();

trace!("Initializing Guest Descriptor Tables");
self.guest_descriptor = Descriptors::new_from_current();
self.guest_descriptor = Descriptors::initialize_for_guest();

trace!("Initializing Host Descriptor Tables");
self.host_descriptor = Descriptors::initialize_for_host();

trace!("Initializing Host Paging Tables");
self.host_paging.init();
Expand Down

0 comments on commit a8881fa

Please sign in to comment.