Skip to main content

Error

Enum Error 

Source
#[non_exhaustive]
pub enum Error { Config(ConfigError),
#[non_exhaustive]
UsernsUnavailable { blocker: Option<UsernsBlocker>, source: Error, }, NestedUsernsBudgetExhausted,
#[non_exhaustive]
Setup { step: SetupStep, source: Error, detail: Option<String>, },
#[non_exhaustive]
Spawn { source: Error, },
#[non_exhaustive]
Wait { source: Error, }, SupervisorLost,
#[non_exhaustive]
Signal { source: Error, }, IdentityMap(IdMapError),
#[non_exhaustive]
Terminal { source: Error, }, TerminalsExhausted, }
Expand description

An error from the library itself.

Cage::run returns Err only when the library fails: invalid configuration, an unsupported host, a failed setup step, or a failure to spawn or wait. The sandboxed command’s own exit code is data, carried by ExitStatus, and is never an Error.

Variants (Non-exhaustive)§

This enum is marked as non-exhaustive
Non-exhaustive enums could have additional variants added in future. Therefore, when matching against variants of non-exhaustive enums, an extra wildcard arm must be added to account for any future variants.
§

Config(ConfigError)

The sandbox configuration was rejected at build time.

§

#[non_exhaustive]
UsernsUnavailable

The host cannot create unprivileged user namespaces.

Produced when namespace creation is denied by the kernel. When the probe in crate::host identifies the mechanism responsible, it is carried in blocker.

Fields

This variant is marked as non-exhaustive
Non-exhaustive enum variants could have additional fields added in future. Therefore, non-exhaustive enum variants cannot be constructed in external crates and cannot be matched against.
§blocker: Option<UsernsBlocker>

The host configuration identified as blocking user namespaces, when one could be determined.

§source: Error

The error the kernel returned for namespace creation.

§

NestedUsernsBudgetExhausted

The host’s user-namespace budget is exhausted, so the command could not enter the nested user namespace that locks the sandbox’s mount flags.

A user namespace is charged against user.max_user_namespaces at every level up to the initial namespace, and a launch holds two: the sandbox’s own, and the nested one the command enters. A host whose ceiling admits the first and not the second reports this rather than a bare ENOSPC.

Distinct from UsernsUnavailable, which is a host that permits no user namespace at all: here the sandbox was built and only the second namespace was refused.

§

#[non_exhaustive]
Setup

A sandbox setup step failed in the child process.

Fields

This variant is marked as non-exhaustive
Non-exhaustive enum variants could have additional fields added in future. Therefore, non-exhaustive enum variants cannot be constructed in external crates and cannot be matched against.
§step: SetupStep

The step that failed.

§source: Error

The error the step failed with.

§detail: Option<String>

What the step was operating on, when the step has a subject — for a mount step, the mount it was assembling; for Exec, the command path, and for a command resolved by path lookup, the candidates the search tried.

An ENOENT from the exec step means either that the command itself is absent or that its ELF interpreter is: a dynamically linked binary whose loader is missing from the rootfs reports the same errno as a missing binary. The detail names the command, not the interpreter, so a path that plainly exists inside the rootfs points at the second reading.

§

#[non_exhaustive]
Spawn

The sandbox process could not be created.

Fields

This variant is marked as non-exhaustive
Non-exhaustive enum variants could have additional fields added in future. Therefore, non-exhaustive enum variants cannot be constructed in external crates and cannot be matched against.
§source: Error

The error from pipe creation or fork.

§

#[non_exhaustive]
Wait

The sandbox process outcome could not be collected.

Fields

This variant is marked as non-exhaustive
Non-exhaustive enum variants could have additional fields added in future. Therefore, non-exhaustive enum variants cannot be constructed in external crates and cannot be matched against.
§source: Error

The error from collecting the outcome: reading the setup-error, status, or capture pipes, waiting on them, or the wait itself.

§

SupervisorLost

The sandbox supervisor exited without reporting the command’s outcome.

The supervisor always reports the command’s wait status before it exits; its silent disappearance means it was killed from outside or exited abnormally, and the command’s outcome is unknown. A kill requested through the handle is not this error: after Running::kill, the outcome is reported as termination by SIGKILL.

§

#[non_exhaustive]
Signal

The sandbox could not be signaled through the handle.

Fields

This variant is marked as non-exhaustive
Non-exhaustive enum variants could have additional fields added in future. Therefore, non-exhaustive enum variants cannot be constructed in external crates and cannot be matched against.
§source: Error

The error from the signaling machinery.

§

IdentityMap(IdMapError)

The identity-map delegate failed to establish the range map.

The delegate runs caller-side against the gated launch, so its own error is the diagnostic; the gated sandbox is torn down.

§

#[non_exhaustive]
Terminal

A pseudoterminal operation failed: allocating one for the sandbox, or reading or setting its window size.

Fields

This variant is marked as non-exhaustive
Non-exhaustive enum variants could have additional fields added in future. Therefore, non-exhaustive enum variants cannot be constructed in external crates and cannot be matched against.
§source: Error

The error the operation failed with.

§

TerminalsExhausted

The host has no free pseudoterminal to allocate.

Pseudoterminals are a bounded resource — /proc/sys/kernel/pty/max states the ceiling — so a host running many sandboxes at once can exhaust them. Distinct from Terminal because it is the one allocation failure that says nothing is wrong with the request: the same launch succeeds once something releases a terminal.

Implementations§

Source§

impl Error

Source

pub fn shell_code(&self) -> u8

The exit code a launcher reports when a launch fails, following the conventions sh and timeout(1) established.

A caller whose whole purpose is to run one command inside a sandbox is a launcher, and a launcher’s own failures have to be distinguishable from the command’s exit codes. The conventions are:

CodeMeaning
127The command does not exist.
126The command exists but could not be executed.
125The launcher itself failed, for any other reason.

The distinction between 127 and 126 comes from the errno the Exec step failed with. An ENOENT there has two readings — the command is absent, or its ELF interpreter is — and both are reported as 127, since neither produced a runnable process.

This is what the fcage binary returns. A caller with its own convention is free to map Error itself; this is the answer for one that has none, and the one that makes a consumer behave like a shell.

124, timeout(1)’s “the deadline expired”, is not produced here: an expired deadline is not an Error, it is a Running::wait_timeout that returned no status, so only the caller knows it happened.

§Example
use std::process::ExitCode;

use ferroday_cage::Cage;

fn launch(rootfs: &str) -> ExitCode {
    match Cage::builder().command("/bin/true").rootfs(rootfs).build() {
        Ok(_cage) => ExitCode::SUCCESS,
        Err(error) => {
            eprintln!("myapp: {error}");
            ExitCode::from(error.shell_code())
        }
    }
}

Trait Implementations§

Source§

impl Debug for Error

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Display for Error

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Error for Error

Source§

fn source(&self) -> Option<&(dyn Error + 'static)>

The failure underneath, where there is one.

Every OS failure this type carries is an io::Error, so every one of them is returned here. The variants that answer None carry nothing: NestedUsernsBudgetExhausted, SupervisorLost, and TerminalsExhausted are conditions the library recognized rather than syscalls that failed.

1.0.0 · Source§

fn description(&self) -> &str

👎Deprecated since 1.42.0:

use the Display impl or to_string()

1.0.0 · Source§

fn cause(&self) -> Option<&dyn Error>

👎Deprecated since 1.33.0:

replaced by Error::source, which can support downcasting

Source§

fn provide<'a>(&'a self, request: &mut Request<'a>)

🔬This is a nightly-only experimental API. (error_generic_member_access)
Provides type-based access to context intended for error reports. Read more
Source§

impl From<ConfigError> for Error

Source§

fn from(err: ConfigError) -> Self

Converts to this type from the input type.
Source§

impl From<Error> for DebianError

Source§

fn from(err: Error) -> Self

Converts to this type from the input type.
Source§

impl From<Error> for RelayError

Source§

fn from(error: Error) -> RelayError

Converts to this type from the input type.

Auto Trait Implementations§

§

impl !RefUnwindSafe for Error

§

impl !UnwindSafe for Error

§

impl Freeze for Error

§

impl Send for Error

§

impl Sync for Error

§

impl Unpin for Error

§

impl UnsafeUnpin for Error

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> AsErrorSource for T
where T: Error + 'static,

Source§

fn as_error_source(&self) -> &(dyn Error + 'static)

For maximum effectiveness, this needs to be called as a method to benefit from Rust’s automatic dereferencing of method receivers.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> Conv for T

Source§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
Source§

impl<T> FmtForward for T

Source§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
Source§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
Source§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
Source§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
Source§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
Source§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
Source§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
Source§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
Source§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Pipe for T
where T: ?Sized,

Source§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
Source§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
Source§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
Source§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows self, then passes self.as_ref() into the pipe function.
Source§

fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.as_mut() into the pipe function.
Source§

fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
Source§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> Tap for T

Source§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
Source§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
Source§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
Source§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
Source§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
Source§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
Source§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
Source§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
Source§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
Source§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .tap_borrow() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Calls .tap_ref() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T> TryConv for T

Source§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V