#![allow(clippy::use_self)]
use std::ffi::OsString;
use std::path::PathBuf;
use std::result::Result as StdResult;
use serde::{Deserialize, Serialize};
use thiserror::Error;
#[derive(Error, Debug, Serialize, Deserialize)]
pub enum FFIError {
#[error("Could not chdir to {path:?}: {error}")]
ChdirError { path: PathBuf, error: String },
#[error("Could not chroot to {path:?}: {error}")]
ChrootError { path: PathBuf, error: String },
#[error("Could not clone process: {0}")]
CloneError(String),
#[error("Could not dup file descriptor {name}({fd}): {error}")]
DupFdError {
fd: i32,
name: String,
error: String,
},
#[error("Could not create directory {path:?}: {error}")]
CreateDirError { path: PathBuf, error: String },
#[error("Could not exec {command:?} (arguments: {arguments:?}): {error}")]
ExecError {
command: PathBuf,
arguments: Vec<OsString>,
error: String,
},
#[error("Could not mount path: {path:?}: {error}")]
MountError { path: PathBuf, error: String },
#[error("Could not open file descriptor {name}({fd}): {error}")]
OpenFdError {
fd: i32,
name: String,
error: String,
},
#[error("Could not disable aslr: {0}")]
PersonalityError(String),
#[error("Could not create pipe: {0}")]
Pipe2Error(String),
#[error("Could not pivot_root to {new_root:?} with old root at {old_root:?}: {error}")]
PivotRootError {
new_root: PathBuf,
old_root: PathBuf,
error: String,
},
#[error("Could not set process to die when parent dies: {0}")]
PrSetPDeathSigError(String),
#[error("Could not disable future priveleges on execve: {0}")]
PrSetNoNewPrivsError(String),
#[error("Could not set interval timer alarm: {0}")]
SetITimerError(String),
#[error("Could not set process group id of {pid} to {pgid}: {error}")]
SetpgidError { pid: i32, pgid: i32, error: String },
#[error("Could not set resource `{resource}` limit: {error}")]
SetRLimitError { resource: String, error: String },
#[error("Could not set a signal handler for {signal}: {error}")]
SigActionError { signal: String, error: String },
#[error("Could not umount path: {path:?}: {error}")]
UMountError { path: PathBuf, error: String },
#[error("Could not unshare cgroup namespace: {0}")]
UnshareCgroupsError(String),
#[error("Could not usleep for {time} microseconds: {error}")]
UsleepError { time: u32, error: String },
#[error("Could not write /proc/self/uid_map file: {0}")]
WriteUidError(String),
#[error("Could not write /proc/self/uid_map file: {0}")]
WriteGidError(String),
#[error("Could not wait for process: {0}")]
WaitPidError(String),
#[error("Could not write /proc/self/setgroups file: {0}")]
WriteSetGroupsError(String),
}
#[derive(Error, Debug, Serialize, Deserialize)]
pub enum CgroupsError {
#[error("Cgroups hierarchy missing: {0:?}")]
HierarchyMissing(PathBuf),
#[error("Could not clear instance hierarchy at {hierarchy_path:?}: {error}")]
InstanceClearError {
hierarchy_path: PathBuf,
error: String,
},
#[error(
"Could not create instance hierarchy under {hierarchy_path:?} for {instance_name:?}: {error}",
)]
InstanceHierarchyCreateError {
hierarchy_path: PathBuf,
instance_name: OsString,
error: String,
},
#[error("Could not open {file:?} for hierarchy {hierarchy_path:?}: {error}")]
OpenCgroupsFileError {
hierarchy_path: PathBuf,
file: PathBuf,
error: String,
},
#[error("Could not parse `{buffer}` from {file:?} for hierarchy {hierarchy_path:?}: {error}")]
ParseCgroupsFileError {
hierarchy_path: PathBuf,
file: PathBuf,
buffer: String,
error: String,
},
#[error("Could not read from {file:?} for hierarchy {hierarchy_path:?}: {error}")]
ReadCgroupsFileError {
hierarchy_path: PathBuf,
file: PathBuf,
error: String,
},
#[error("Could not find field `{field}` in file {file:?} inside hierarchy {hierarchy_path:?}")]
MissingFieldError {
hierarchy_path: PathBuf,
file: PathBuf,
field: String,
},
#[error("Could not write to {file:?} for hierarchy {hierarchy_path:?}: {error}")]
WriteCgroupsFileError {
hierarchy_path: PathBuf,
file: PathBuf,
error: String,
},
}
#[derive(Error, Debug, Serialize, Deserialize)]
pub enum ChildError {
#[error("Caps error occurred: {0}")]
CapsError(i32),
#[error("Cgroups error occurred.")]
CgroupsError(#[from] CgroupsError),
#[error("FFI Error occurred.")]
FFIError(#[from] FFIError),
}
impl From<capctl::Error> for ChildError {
fn from(err: capctl::Error) -> Self {
Self::CapsError(err.code())
}
}
#[derive(Error, Debug, Serialize, Deserialize)]
pub enum Error {
#[error("Cgroups error occurred.")]
CgroupsError(#[from] CgroupsError),
#[error("Child process error occurred.")]
ChildError(#[from] ChildError),
#[error("Child process successfully completed even though it used exec")]
ContinuedPastExecError(String),
#[error("Could not deserialize process result: {}", _0)]
DeserializeError(String),
#[error("FFI Error occurred.")]
FFIError(#[from] FFIError),
#[error("Child process stopped/continued unexpected")]
StoppedContinuedError,
#[error("Supervisor process died and could not collect execution information")]
SupervisorProcessDiedError,
}
pub type Result<T> = StdResult<T, Error>;