From da399861694205b762db46d0235ec6145e27197f Mon Sep 17 00:00:00 2001 From: memN0ps <89628341+memN0ps@users.noreply.github.com> Date: Sun, 18 Feb 2024 16:45:17 +1300 Subject: [PATCH] COM logger removed due to Sync issues and custom panic handler added --- driver/Cargo.toml | 3 +- driver/src/main.rs | 30 +++++++++--- driver/src/virtualize.rs | 1 - hypervisor/Cargo.toml | 6 +-- hypervisor/src/config.rs | 28 +++++++++++ hypervisor/src/lib.rs | 7 +-- hypervisor/src/logger.rs | 101 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 158 insertions(+), 18 deletions(-) create mode 100644 hypervisor/src/config.rs create mode 100644 hypervisor/src/logger.rs diff --git a/driver/Cargo.toml b/driver/Cargo.toml index c64ded4..489b1d4 100644 --- a/driver/Cargo.toml +++ b/driver/Cargo.toml @@ -7,9 +7,8 @@ edition = "2021" [dependencies] uefi = {version = "0.26.0", features = ["global_allocator", "alloc"] } # https://crates.io/crates/uefi -uefi-services = { version = "0.23.0", default-features = false, features = ["panic_handler"] } +uefi-services = { version = "0.23.0", default-features = false } # https://crates.io/crates/uefi-services log = { version = "0.4.20", default-features = false } # https://crates.io/crates/log -com_logger = "0.1.1" # https://crates.io/crates/com_logger once_cell = "1.19.0" # https://crates.io/crates/once_cell hypervisor = { path = "../hypervisor" } \ No newline at end of file diff --git a/driver/src/main.rs b/driver/src/main.rs index a287f7b..2b45db0 100644 --- a/driver/src/main.rs +++ b/driver/src/main.rs @@ -1,4 +1,5 @@ #![feature(new_uninit)] +#![feature(panic_info_message)] #![no_main] #![no_std] @@ -18,6 +19,7 @@ use { ept::paging::{AccessType, Ept}, shared_data::SharedData, }, + logger::init_uart_logger, }, log::*, uefi::prelude::*, @@ -26,14 +28,28 @@ use { pub mod processor; pub mod virtualize; +// Change as you like +#[cfg(not(test))] +#[panic_handler] +fn panic_handler(info: &core::panic::PanicInfo) -> ! { + if let Some(location) = info.location() { + error!( + "[-] Panic in {} at ({}, {}):", + location.file(), + location.line(), + location.column() + ); + if let Some(message) = info.message() { + error!("[-] {}", message); + } + } + + loop {} +} + #[entry] fn main(_image_handle: Handle, mut system_table: SystemTable) -> Status { - // Initialize the COM2 port logger with level filter set to Info. - com_logger::builder() - .base(0x2f8) - .filter(LevelFilter::Trace) - .setup(); - + init_uart_logger(); uefi_services::init(&mut system_table).unwrap(); info!("The Matrix is an illusion"); @@ -50,7 +66,7 @@ fn main(_image_handle: Handle, mut system_table: SystemTable) -> Status { info!("Total processors: {}", processor_count.total); info!("Enabled processors: {}", processor_count.enabled); - // Setup the EPT + // Setup EPT let shared_data = match setup_ept() { Ok(shared_data) => shared_data, Err(e) => panic!("Failed to setup EPT: {:?}", e), diff --git a/driver/src/virtualize.rs b/driver/src/virtualize.rs index 869e640..1d61e24 100644 --- a/driver/src/virtualize.rs +++ b/driver/src/virtualize.rs @@ -14,7 +14,6 @@ use { }, }; -#[derive(Default)] pub struct Virtualize { guest_registers: GuestRegisters, shared_data: Box, diff --git a/hypervisor/Cargo.toml b/hypervisor/Cargo.toml index eaba003..22a7ffc 100644 --- a/hypervisor/Cargo.toml +++ b/hypervisor/Cargo.toml @@ -22,7 +22,7 @@ lazy_static = { version = "1.4.0", features = ["spin_no_std"] } # https://crates obfstr = "0.4.3" # https://crates.io/crates/obfstr/ static_assertions = "1.1.0" # https://crates.io/crates/static_assertions log = "0.4.20" # https://crates.io/crates/log -com_logger = "0.1.1" # https://crates.io/crates/com_logger iced-x86 = { version = "1.20.0", default-features = false, features = ["no_std", "decoder", "block_encoder", "instr_info", "no_d3now", "no_evex", "no_vex", "no_xop"] } # https://crates.io/crates/iced-x86 -bstr = { version = "1.9.0", default-features = false} -derivative = { version = "2.2.0", features = ["use_core"]} # https://crates.io/crates/derivative \ No newline at end of file +bstr = { version = "1.9.0", default-features = false} # https://crates.io/crates/bstr +derivative = { version = "2.2.0", features = ["use_core"]} # https://crates.io/crates/derivative +spin = "0.9" # https://crates.io/crates/spin \ No newline at end of file diff --git a/hypervisor/src/config.rs b/hypervisor/src/config.rs new file mode 100644 index 0000000..71c383f --- /dev/null +++ b/hypervisor/src/config.rs @@ -0,0 +1,28 @@ +//! The module containing various constants that may be modified by developers. + +#![allow(dead_code)] + +use crate::logger::{UartComPort, UartLogger}; + +/// The logging level. +pub const LOGGING_LEVEL: log::LevelFilter = log::LevelFilter::Trace; + +/// Once in how many iterations stats should be sent to the serial output. +/// Ignored when [`LOGGING_LEVEL`] is `Trace`. +pub const SERIAL_OUTPUT_INTERVAL: u64 = 500; + +/// Once in how many iterations stats should be displayed on the console. +/// Ignored when `stdout_stats_report` is disabled. +pub const CONSOLE_OUTPUT_INTERVAL: u64 = 1000; + +/// How long a single fuzzing iteration can spend within the guest-mode, in TSC. +/// If the more than this is spent, a timer fires and aborts the VM. +pub const GUEST_EXEC_TIMEOUT_IN_TSC: u64 = 200_000_000; + +/// The number of fuzzing iterations to be done for single input. The lower, the +/// more frequently new files are selected, and it is slightly costly. Ignored +/// when `random_byte_modification` is disabled. +pub const MAX_ITERATION_COUNT_PER_FILE: u64 = 10_000; + +/// The COM port to be used for UART logging. +pub static UART_LOGGER: UartLogger = UartLogger::new(UartComPort::Com2); diff --git a/hypervisor/src/lib.rs b/hypervisor/src/lib.rs index dbe987b..8b6d1b3 100644 --- a/hypervisor/src/lib.rs +++ b/hypervisor/src/lib.rs @@ -13,11 +13,8 @@ extern crate alloc; extern crate static_assertions; +pub mod config; pub mod error; pub mod intel; -//pub mod vcpu; -//pub mod vmcs; -//pub mod vmerror; -//pub mod vmexit; -//pub mod vmlaunch; +pub mod logger; pub mod vmm; diff --git a/hypervisor/src/logger.rs b/hypervisor/src/logger.rs new file mode 100644 index 0000000..8a0d5d5 --- /dev/null +++ b/hypervisor/src/logger.rs @@ -0,0 +1,101 @@ +//! The module containing the UART (serial port) logger implementation. +// Inspired by Ian Kronquist's work: https://github.com/iankronquist/rustyvisor/blob/83b53ac104d85073858ba83326a28a6e08d1af12/pcuart/src/lib.rs +// Credits: https://github.com/tandasat/Hypervisor-101-in-Rust/blob/main/hypervisor/src/logger.rs + +#![allow(dead_code)] + +use { + crate::{ + config::{LOGGING_LEVEL, UART_LOGGER}, + intel::support::{inb, outb}, + }, + core::{fmt, fmt::Write}, + spin::Mutex, +}; + +/// Initializes the logger instance. +pub fn init_uart_logger() { + log::set_logger(&UART_LOGGER) + .map(|()| log::set_max_level(LOGGING_LEVEL)) + .unwrap(); +} + +#[derive(Clone, Copy)] +#[repr(u16)] +pub(crate) enum UartComPort { + Com1 = 0x3f8, + Com2 = 0x2f8, +} + +#[derive(Default)] +struct Uart { + io_port_base: u16, +} + +impl Uart { + const fn new(port: UartComPort) -> Self { + Self { + io_port_base: port as u16, + } + } +} + +const UART_OFFSET_TRANSMITTER_HOLDING_BUFFER: u16 = 0; +const UART_OFFSET_LINE_STATUS: u16 = 5; + +impl Write for Uart { + // Writes bytes `string` to the serial port. + fn write_str(&mut self, string: &str) -> Result<(), fmt::Error> { + for byte in string.bytes() { + while (inb(self.io_port_base + UART_OFFSET_LINE_STATUS) & 0x20) == 0 {} + outb( + self.io_port_base + UART_OFFSET_TRANSMITTER_HOLDING_BUFFER, + byte, + ); + } + Ok(()) + } +} + +pub struct UartLogger { + port: Mutex, +} + +impl UartLogger { + pub(crate) const fn new(port: UartComPort) -> Self { + Self { + port: Mutex::new(Uart::new(port)), + } + } + + fn lock(&self) -> spin::MutexGuard<'_, Uart> { + self.port.lock() + } +} + +impl log::Log for UartLogger { + fn enabled(&self, metadata: &log::Metadata<'_>) -> bool { + metadata.level() <= log::Level::Trace + } + + fn log(&self, record: &log::Record<'_>) { + if self.enabled(record.metadata()) { + let _ = writeln!( + self.lock(), + "#{}:{}: {}", + apic_id(), + record.level(), + record.args() + ); + } + } + + fn flush(&self) {} +} + +/// Gets an APIC ID. +fn apic_id() -> u32 { + // See: (AMD) CPUID Fn0000_0001_EBX LocalApicId, LogicalProcessorCount, CLFlush + // See: (Intel) Table 3-8. Information Returned by CPUID Instruction + x86::cpuid::cpuid!(0x1).ebx >> 24 +}