Skip to content

Commit

Permalink
mirrord-layer: Split error LayerError Enum into two (#276)
Browse files Browse the repository at this point in the history
  • Loading branch information
aviramha authored Aug 24, 2022
1 parent ec12fe9 commit 922e145
Show file tree
Hide file tree
Showing 9 changed files with 146 additions and 157 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how

### Changed
- mirrord-layer: Added common `Result` type to to reduce boilerplate, removed dependency of `anyhow` crate.
- mirrord-layer: Split `LayerError` into `LayerError` and `HookError` to distinguish between errors that can be handled by the layer and errors that can be handled by the hook. (no more requiring libc errno for each error!). Closes [#247](https://github.com/metalbear-co/mirrord/issues/247)

## 2.8.1

Expand Down
6 changes: 3 additions & 3 deletions mirrord-layer/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ use mirrord_protocol::{AddrInfoHint, AddrInfoInternal, RemoteResult};
use tokio::sync::oneshot;

use crate::{
error::{LayerError, Result},
error::{HookError, HookResult},
file::HookMessageFile,
tcp::HookMessageTcp,
HOOK_SENDER,
};

pub(crate) fn blocking_send_hook_message(message: HookMessage) -> Result<()> {
pub(crate) fn blocking_send_hook_message(message: HookMessage) -> HookResult<()> {
unsafe {
HOOK_SENDER
.as_ref()
.ok_or(LayerError::EmptyHookSender)
.ok_or(HookError::EmptyHookSender)
.and_then(|hook_sender| hook_sender.blocking_send(message).map_err(Into::into))
}
}
Expand Down
188 changes: 88 additions & 100 deletions mirrord-layer/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,56 @@ use tracing::{error, warn};

use super::HookMessage;

#[derive(Error, Debug)]
pub(crate) enum HookError {
#[error("mirrord-layer: DNS does not resolve!")]
DNSNoName,
#[error("mirrord-layer: Failed to `Lock` resource!")]
LockError,

#[error("mirrord-layer: Socket operation called on port `{0}` that is not handled by us!")]
BypassedPort(u16),

#[error("mirrord-layer: Socket `{0}` is in an invalid state!")]
SocketInvalidState(RawFd),

#[error("mirrord-layer: Null pointer found!")]
NullPointer,

#[error("mirrord-layer: Failed while getting a response!")]
ResponseError(#[from] ResponseError),

#[error("mirrord-layer: Receiver failed with `{0}`!")]
RecvError(#[from] RecvError),

#[error("mirrord-layer: IO failed with `{0}`!")]
IO(#[from] std::io::Error),

#[error("mirrord-layer: Failed to find local fd `{0}`!")]
LocalFDNotFound(RawFd),

#[error("mirrord-layer: HOOK_SENDER is `None`!")]
EmptyHookSender,

#[error("mirrord-layer: Failed converting `sockaddr`!")]
AddressConversion,

#[error("mirrord-layer: Converting int failed with `{0}`!")]
TryFromInt(#[from] std::num::TryFromIntError),

#[error("mirrord-layer: Failed request to create socket with domain `{0}`!")]
UnsupportedDomain(i32),

#[error("mirrord-layer: Creating `CString` failed with `{0}`!")]
Null(#[from] std::ffi::NulError),

#[error("mirrord-layer: Failed converting `to_str` with `{0}`!")]
Utf8(#[from] std::str::Utf8Error),

#[error("mirrord-layer: Sender<HookMessage> failed with `{0}`!")]
SendErrorHookMessage(#[from] SendError<HookMessage>),
}

#[derive(Error, Debug)]
pub(crate) enum LayerError {
#[error("mirrord-layer: Frida failed with `{0}`!")]
Expand All @@ -24,9 +74,6 @@ pub(crate) enum LayerError {
#[error("mirrord-layer: Parsing `bool` value failed with `{0}`!")]
ParseBoolError(#[from] ParseBoolError),

#[error("mirrord-layer: Sender<HookMessage> failed with `{0}`!")]
SendErrorHookMessage(#[from] SendError<HookMessage>),

#[error("mirrord-layer: Sender<Vec<u8>> failed with `{0}`!")]
SendErrorConnection(#[from] SendError<Vec<u8>>),

Expand All @@ -42,42 +89,15 @@ pub(crate) enum LayerError {
#[error("mirrord-layer: Failed to get `Sender` for sending getaddrinfo response!")]
SendErrorGetAddrInfoResponse,

#[error("mirrord-layer: Receiver failed with `{0}`!")]
RecvError(#[from] RecvError),

#[error("mirrord-layer: Creating `CString` failed with `{0}`!")]
Null(#[from] std::ffi::NulError),

#[error("mirrord-layer: Converting int failed with `{0}`!")]
TryFromInt(#[from] std::num::TryFromIntError),

#[error("mirrord-layer: Failed to find local fd `{0}`!")]
LocalFDNotFound(RawFd),

#[error("mirrord-layer: HOOK_SENDER is `None`!")]
EmptyHookSender,

#[error("mirrord-layer: No connection found for id `{0}`!")]
NoConnectionId(u16),

#[error("mirrord-layer: IO failed with `{0}`!")]
IO(#[from] std::io::Error),

#[error("mirrord-layer: Failed to find port `{0}`!")]
PortNotFound(u16),

#[error("mirrord-layer: Failed to find connection_id `{0}`!")]
ConnectionIdNotFound(u16),

#[error("mirrord-layer: Failed inserting listen, already exists!")]
ListenAlreadyExists,

#[error("mirrord-layer: Failed to `Lock` resource!")]
LockError,

#[error("mirrord-layer: Failed while getting a response!")]
ResponseError(#[from] ResponseError),

#[error("mirrord-layer: Unmatched pong!")]
UnmatchedPong,

Expand All @@ -96,94 +116,62 @@ pub(crate) enum LayerError {
#[error("mirrord-layer: JSON convert error")]
JSONConvertError(#[from] serde_json::Error),

#[error("mirrord-layer: DNS does not resolve!")]
DNSNoName,

#[error("mirrord-layer: Failed converting `to_str` with `{0}`!")]
Utf8(#[from] std::str::Utf8Error),

#[error("mirrord-layer: Failed converting `sockaddr`!")]
AddressConversion,

#[error("mirrord-layer: Failed request to create socket with domain `{0}`!")]
UnsupportedDomain(i32),

#[error("mirrord-layer: Socket operation called on port `{0}` that is not handled by us!")]
BypassedPort(u16),

#[error("mirrord-layer: Socket `{0}` is in an invalid state!")]
SocketInvalidState(RawFd),

#[error("mirrord-layer: Null pointer found!")]
NullPointer,

#[error("mirrord-layer: Container `{0}` not found in namespace `{1}` pod `{2}`")]
ContainerNotFound(String, String, String),

#[error("mirrord-layer: IO failed with `{0}`!")]
IO(#[from] std::io::Error),

#[error("mirrord-layer: Failed inserting listen, already exists!")]
ListenAlreadyExists,
// #[error("`{0}`")]
// HookError(#[from] HookError),
}

// Cannot have a generic From<T> implementation for this error, so explicitly implemented here.
impl<'a, T> From<std::sync::PoisonError<std::sync::MutexGuard<'a, T>>> for LayerError {
impl<'a, T> From<std::sync::PoisonError<std::sync::MutexGuard<'a, T>>> for HookError {
fn from(_: std::sync::PoisonError<std::sync::MutexGuard<T>>) -> Self {
LayerError::LockError
HookError::LockError
}
}

pub(crate) type Result<T> = std::result::Result<T, LayerError>;
pub(crate) type HookResult<T> = std::result::Result<T, HookError>;

// mapping based on - https://man7.org/linux/man-pages/man3/errno.3.html

impl From<LayerError> for i64 {
fn from(fail: LayerError) -> Self {
impl From<HookError> for i64 {
fn from(fail: HookError) -> Self {
match fail {
LayerError::SocketInvalidState(_) | LayerError::LocalFDNotFound(_) => {
HookError::SocketInvalidState(_) | HookError::LocalFDNotFound(_) => {
warn!("Recoverable issue >> {:#?}", fail)
}
_ => error!("Error occured in Layer >> {:?}", fail),
};

let libc_error = match fail {
LayerError::Frida(_) => libc::EINVAL,
LayerError::NoExportName(_) => libc::EINVAL,
LayerError::VarError(_) => libc::EINVAL,
LayerError::ParseBoolError(_) => libc::EINVAL,
LayerError::SendErrorHookMessage(_) => libc::EBADMSG,
LayerError::SendErrorConnection(_) => libc::EBADMSG,
LayerError::Join(_) => libc::EBADMSG,
LayerError::SendErrorLayerTcp(_) => libc::EBADMSG,
LayerError::RecvError(_) => libc::EBADMSG,
LayerError::Null(_) => libc::EINVAL,
LayerError::TryFromInt(_) => libc::EINVAL,
LayerError::LocalFDNotFound(..) => libc::EBADF,
LayerError::EmptyHookSender => libc::EINVAL,
LayerError::NoConnectionId(_) => libc::ECONNREFUSED,
LayerError::IO(io_fail) => io_fail.raw_os_error().unwrap_or(libc::EIO),
LayerError::PortNotFound(_) => libc::EADDRNOTAVAIL,
LayerError::ConnectionIdNotFound(_) => libc::EADDRNOTAVAIL,
LayerError::ListenAlreadyExists => libc::EEXIST,
LayerError::SendErrorFileResponse => libc::EINVAL,
LayerError::SendErrorGetAddrInfoResponse => libc::EINVAL,
LayerError::LockError => libc::EINVAL,
LayerError::ResponseError(response_fail) => match response_fail {
HookError::SendErrorHookMessage(_) => libc::EBADMSG,
HookError::RecvError(_) => libc::EBADMSG,
HookError::Null(_) => libc::EINVAL,
HookError::TryFromInt(_) => libc::EINVAL,
HookError::LocalFDNotFound(..) => libc::EBADF,
HookError::EmptyHookSender => libc::EINVAL,
HookError::IO(io_fail) => io_fail.raw_os_error().unwrap_or(libc::EIO),
HookError::LockError => libc::EINVAL,
HookError::ResponseError(response_fail) => match response_fail {
ResponseError::AllocationFailure(_) => libc::ENOMEM,
ResponseError::NotFound(_) => libc::ENOENT,
ResponseError::NotDirectory(_) => libc::ENOTDIR,
ResponseError::NotFile(_) => libc::EISDIR,
ResponseError::RemoteIO(io_fail) => io_fail.raw_os_error.unwrap_or(libc::EIO),
},
LayerError::UnmatchedPong => libc::ETIMEDOUT,
LayerError::KubeConfigError(_) => libc::EINVAL,
LayerError::PodSpecNotFound(_) => libc::EINVAL,
LayerError::KubeError(_) => libc::EINVAL,
LayerError::JSONConvertError(_) => libc::EINVAL,
LayerError::DNSNoName => libc::EFAULT,
LayerError::Utf8(_) => libc::EINVAL,
LayerError::AddressConversion => libc::EINVAL,
LayerError::UnsupportedDomain(_) => libc::EINVAL,
LayerError::BypassedPort(_) => libc::EINVAL,
LayerError::SocketInvalidState(_) => libc::EINVAL,
LayerError::NullPointer => libc::EINVAL,
LayerError::PodNotFound(_) => libc::EINVAL,
LayerError::ContainerNotFound(_, _, _) => libc::EINVAL,
HookError::DNSNoName => libc::EFAULT,
HookError::Utf8(_) => libc::EINVAL,
HookError::AddressConversion => libc::EINVAL,
HookError::UnsupportedDomain(_) => libc::EINVAL,
HookError::BypassedPort(_) => libc::EINVAL,
HookError::SocketInvalidState(_) => libc::EINVAL,
HookError::NullPointer => libc::EINVAL,
};

set_errno(errno::Errno(libc_error));
Expand All @@ -192,28 +180,28 @@ impl From<LayerError> for i64 {
}
}

impl From<LayerError> for isize {
fn from(fail: LayerError) -> Self {
impl From<HookError> for isize {
fn from(fail: HookError) -> Self {
i64::from(fail) as _
}
}

impl From<LayerError> for usize {
fn from(fail: LayerError) -> Self {
impl From<HookError> for usize {
fn from(fail: HookError) -> Self {
let _ = i64::from(fail);

0
}
}

impl From<LayerError> for i32 {
fn from(fail: LayerError) -> Self {
impl From<HookError> for i32 {
fn from(fail: HookError) -> Self {
i64::from(fail) as _
}
}

impl From<LayerError> for *mut FILE {
fn from(fail: LayerError) -> Self {
impl From<HookError> for *mut FILE {
fn from(fail: HookError) -> Self {
let _ = i64::from(fail);

ptr::null_mut()
Expand Down
14 changes: 7 additions & 7 deletions mirrord-layer/src/file/hooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use super::{
OpenOptionsInternalExt, IGNORE_FILES, OPEN_FILES,
};
use crate::{
error::LayerError,
error::HookError,
file::ops::{access, lseek, open, read, write},
replace,
};
Expand All @@ -30,7 +30,7 @@ pub(super) unsafe extern "C" fn open_detour(raw_path: *const c_char, open_flags:
unsafe fn open_logic(raw_path: *const c_char, open_flags: c_int) -> RawFd {
let path = match CStr::from_ptr(raw_path)
.to_str()
.map_err(LayerError::from)
.map_err(HookError::from)
.map(PathBuf::from)
{
Ok(path) => path,
Expand Down Expand Up @@ -61,7 +61,7 @@ pub(super) unsafe extern "C" fn fopen_detour(

let path = match CStr::from_ptr(raw_path)
.to_str()
.map_err(LayerError::from)
.map_err(HookError::from)
.map(PathBuf::from)
{
Ok(path) => path,
Expand All @@ -71,7 +71,7 @@ pub(super) unsafe extern "C" fn fopen_detour(
let mode = match CStr::from_ptr(raw_mode)
.to_str()
.map(String::from)
.map_err(LayerError::from)
.map_err(HookError::from)
{
Ok(mode) => mode,
Err(fail) => return fail.into(),
Expand Down Expand Up @@ -99,7 +99,7 @@ pub(super) unsafe extern "C" fn fdopen_detour(fd: RawFd, raw_mode: *const c_char
let mode = match CStr::from_ptr(raw_mode)
.to_str()
.map(String::from)
.map_err(LayerError::from)
.map_err(HookError::from)
{
Ok(mode) => mode,
Err(fail) => return fail.into(),
Expand Down Expand Up @@ -138,7 +138,7 @@ pub(crate) unsafe extern "C" fn openat_detour(

let path = match CStr::from_ptr(raw_path)
.to_str()
.map_err(LayerError::from)
.map_err(HookError::from)
.map(PathBuf::from)
{
Ok(path) => path,
Expand Down Expand Up @@ -355,7 +355,7 @@ pub(crate) unsafe extern "C" fn access_detour(raw_path: *const c_char, mode: c_i
unsafe fn access_logic(raw_path: *const c_char, mode: c_int) -> c_int {
let path = match CStr::from_ptr(raw_path)
.to_str()
.map_err(LayerError::from)
.map_err(HookError::from)
.map(PathBuf::from)
{
Ok(path) => path,
Expand Down
4 changes: 2 additions & 2 deletions mirrord-layer/src/file/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use tracing::{debug, error, trace};

use crate::{
common::blocking_send_hook_message,
error::{LayerError, Result},
error::{HookError, HookResult as Result},
file::{
Access, Close, HookMessageFile, Open, OpenOptionsInternalExt, OpenRelative, Read, Seek,
Write, OPEN_FILES,
Expand Down Expand Up @@ -165,7 +165,7 @@ pub(crate) fn fopen(path: PathBuf, open_options: OpenOptionsInternal) -> Result<

open_files
.get_key_value(&local_file_fd)
.ok_or(LayerError::LocalFDNotFound(local_file_fd))
.ok_or(HookError::LocalFDNotFound(local_file_fd))
// Convert the fd into a `*FILE`, this is be ok as long as `OPEN_FILES` holds the fd.
.map(|(local_fd, _)| local_fd as *const _ as *mut _)
}
Expand Down
4 changes: 2 additions & 2 deletions mirrord-layer/src/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use libc::{c_int, sockaddr, socklen_t};
use mirrord_protocol::{AddrInfoHint, Port};
use socket2::SockAddr;

use crate::error::{LayerError, Result};
use crate::error::{HookError, HookResult as Result};

pub(super) mod hooks;
mod ops;
Expand Down Expand Up @@ -112,7 +112,7 @@ fn fill_address(
if address.is_null() {
Ok(())
} else if address_len.is_null() {
Err(LayerError::NullPointer)
Err(HookError::NullPointer)
} else {
let os_address = SockAddr::from(new_address);

Expand Down
Loading

0 comments on commit 922e145

Please sign in to comment.