use std::array::TryFromSliceError;
use std::cell::{BorrowError, BorrowMutError};
use std::convert::Infallible;
use std::error::Error;
use std::num::TryFromIntError;
use std::str::Utf8Error;
use std::string::FromUtf8Error;
use std::sync::{MutexGuard, PoisonError};
use std::time::SystemTimeError;
#[cfg(target_os = "windows")]
use crossbeam_channel::{RecvError, SendError};
use flatbuffers::InvalidFlatbuffer;
use hyperlight_common::flatbuffer_wrappers::function_types::{ParameterValue, ReturnValue};
use hyperlight_common::flatbuffer_wrappers::guest_error::ErrorCode;
use serde::{Deserialize, Serialize};
use serde_yaml;
use thiserror::Error;
#[cfg(target_os = "windows")]
use crate::hypervisor::wrappers::HandleWrapper;
use crate::mem::memory_region::MemoryRegionFlags;
use crate::mem::ptr::RawPtr;
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
pub(crate) struct HyperlightHostError {
pub(crate) message: String,
pub(crate) source: String,
}
#[derive(Error, Debug)]
pub enum HyperlightError {
#[error("Anyhow Error was returned: {0}")]
AnyhowError(#[from] anyhow::Error),
#[error("Offset: {0} out of bounds, Max is: {1}")]
BoundsCheckFailed(u64, usize),
#[error("Couldnt add offset to base address. Offset: {0}, Base Address: {1}")]
CheckedAddOverflow(u64, u64),
#[error("{0:?}")]
#[cfg(target_os = "windows")]
CrossBeamReceiveError(#[from] RecvError),
#[error("{0:?}")]
#[cfg(target_os = "windows")]
CrossBeamSendError(#[from] SendError<HandleWrapper>),
#[error("Error converting CString {0:?}")]
CStringConversionError(#[from] std::ffi::NulError),
#[error("Seccomp filter trapped on disallowed syscall (check STDERR for offending syscall)")]
#[cfg(all(feature = "seccomp", target_os = "linux"))]
DisallowedSyscall,
#[error("{0}")]
Error(String),
#[error("Exception Data Length is incorrect. Expected: {0}, Actual: {1}")]
ExceptionDataLengthIncorrect(i32, usize),
#[error("Exception Message is too big. Max Size: {0}, Actual: {1}")]
ExceptionMessageTooBig(usize, usize),
#[error("Non-executable address {0:#x} tried to be executed")]
ExecutionAccessViolation(u64),
#[error("Execution was cancelled by the host.")]
ExecutionCanceledByHost(),
#[error("Failed to get a value from flat buffer parameter")]
FailedToGetValueFromParameter(),
#[error("Field Name {0} not found in decoded GuestLogData")]
FieldIsMissingInGuestLogData(String),
#[error("Guest aborted: {0} {1}")]
GuestAborted(u8, String),
#[error("Cannot run from guest binary when guest binary is a buffer")]
GuestBinaryShouldBeAFile(),
#[error("Guest error occurred {0:?}: {1}")]
GuestError(ErrorCode, String),
#[error("Guest execution hung on the execution of a host function call")]
GuestExecutionHungOnHostFunctionCall(),
#[error("Guest call is already in progress")]
GuestFunctionCallAlreadyInProgress(),
#[error("Unsupported type: {0}")]
GuestInterfaceUnsupportedType(String),
#[error("The guest offset {0} is invalid.")]
GuestOffsetIsInvalid(usize),
#[error("HostFunction {0} was not found")]
HostFunctionNotFound(String),
#[error("Communication failure with the Hypervisor Handler thread")]
HypervisorHandlerCommunicationFailure(),
#[error("Hypervisor Handler execution cancel attempt on a finished execution")]
HypervisorHandlerExecutionCancelAttemptOnFinishedExecution(),
#[error("Hypervisor Handler Message Receive Timedout")]
HypervisorHandlerMessageReceiveTimedout(),
#[error("Reading Writing or Seeking data failed {0:?}")]
IOError(#[from] std::io::Error),
#[error("Failed To Convert Size to usize")]
IntConversionFailure(#[from] TryFromIntError),
#[error("The flatbuffer is invalid")]
InvalidFlatBuffer(#[from] InvalidFlatbuffer),
#[error("Conversion of str data to json failed")]
JsonConversionFailure(#[from] serde_json::Error),
#[error("KVM Error {0:?}")]
#[cfg(kvm)]
KVMError(#[source] kvm_ioctls::Error),
#[error("Unable to lock resource")]
LockAttemptFailed(String),
#[error("Memory Access Violation at address {0:#x} of type {1}, but memory is marked as {2}")]
MemoryAccessViolation(u64, MemoryRegionFlags, MemoryRegionFlags),
#[error("Memory Allocation Failed with OS Error {0:?}.")]
MemoryAllocationFailed(Option<i32>),
#[error("Memory Protection Failed with OS Error {0:?}.")]
MemoryProtectionFailed(Option<i32>),
#[error("Memory requested {0} exceeds maximum size allowed {1}")]
MemoryRequestTooBig(usize, usize),
#[error("Metric Not Found {0:?}.")]
MetricNotFound(&'static str),
#[error("mmap failed with os error {0:?}")]
MmapFailed(Option<i32>),
#[error("mprotect failed with os error {0:?}")]
MprotectFailed(Option<i32>),
#[error("mshv Error {0:?}")]
#[cfg(mshv)]
MSHVError(#[from] mshv_ioctls::MshvError),
#[error("No Hypervisor was found for Sandbox")]
NoHypervisorFound(),
#[error("Restore_state called with no valid snapshot")]
NoMemorySnapshot,
#[error("An error occurred handling an outb message {0:?}: {1}")]
OutBHandlingError(String, String),
#[error("Failed To Convert Parameter Value {0:?} to {1:?}")]
ParameterValueConversionFailure(ParameterValue, &'static str),
#[error("Failure processing PE File {0:?}")]
PEFileProcessingFailure(#[from] goblin::error::Error),
#[error("Prometheus Error {0:?}")]
Prometheus(#[from] prometheus::Error),
#[error("Raw pointer ({0:?}) was less than the base address ({1})")]
RawPointerLessThanBaseAddress(RawPtr, u64),
#[error("RefCell borrow failed")]
RefCellBorrowFailed(#[from] BorrowError),
#[error("RefCell mut borrow failed")]
RefCellMutBorrowFailed(#[from] BorrowMutError),
#[error("Failed To Convert Return Value {0:?} to {1:?}")]
ReturnValueConversionFailure(ReturnValue, &'static str),
#[error("Stack overflow detected")]
StackOverflow(),
#[error("Backend Error with Seccomp Filter {0:?}")]
#[cfg(all(feature = "seccomp", target_os = "linux"))]
SeccompFilterBackendError(#[from] seccompiler::BackendError),
#[error("Error with Seccomp Filter {0:?}")]
#[cfg(all(feature = "seccomp", target_os = "linux"))]
SeccompFilterError(#[from] seccompiler::Error),
#[error("SystemTimeError {0:?}")]
SystemTimeError(#[from] SystemTimeError),
#[error("TryFromSliceError {0:?}")]
TryFromSliceError(#[from] TryFromSliceError),
#[error("The number of arguments to the function is wrong: got {0:?} expected {1:?}")]
UnexpectedNoOfArguments(usize, usize),
#[error("The parameter value type is unexpected got {0:?} expected {1:?}")]
UnexpectedParameterValueType(ParameterValue, String),
#[error("The return value type is unexpected got {0:?} expected {1:?}")]
UnexpectedReturnValueType(ReturnValue, String),
#[error("Slice Conversion of UTF8 data to str failed")]
UTF8SliceConversionFailure(#[from] Utf8Error),
#[error("String Conversion of UTF8 data to str failed")]
UTF8StringConversionFailure(#[from] FromUtf8Error),
#[error(
"The capacity of the vector is incorrect. Capacity: {0}, Length: {1}, FlatBuffer Size: {2}"
)]
VectorCapacityIncorrect(usize, usize, i32),
#[error("vmm sys Error {0:?}")]
#[cfg(target_os = "linux")]
VmmSysError(#[from] vmm_sys_util::errno::Error),
#[cfg(target_os = "windows")]
#[error("Windows API Error Result {0:?}")]
WindowsAPIError(#[from] windows_result::Error),
#[error("Conversion of str data to yaml failed")]
YamlConversionFailure(#[from] serde_yaml::Error),
}
impl From<Infallible> for HyperlightError {
fn from(_: Infallible) -> Self {
"Impossible as this is an infallible error".into()
}
}
impl From<&str> for HyperlightError {
fn from(s: &str) -> Self {
HyperlightError::Error(s.to_string())
}
}
impl<T> From<PoisonError<MutexGuard<'_, T>>> for HyperlightError {
fn from(e: PoisonError<MutexGuard<'_, T>>) -> Self {
let source = match e.source() {
Some(s) => s.to_string(),
None => String::from(""),
};
HyperlightError::LockAttemptFailed(source)
}
}
#[macro_export]
macro_rules! new_error {
($msg:literal $(,)?) => {{
let __args = std::format_args!($msg);
let __err_msg = match __args.as_str() {
Some(msg) => String::from(msg),
None => std::format!($msg),
};
$crate::HyperlightError::Error(__err_msg)
}};
($fmtstr:expr, $($arg:tt)*) => {{
let __err_msg = std::format!($fmtstr, $($arg)*);
$crate::error::HyperlightError::Error(__err_msg)
}};
}