pub struct Overlay { /* private fields */ }Expand description
An overlay root: an ordered stack of read-only lower layers, and the upper layer every write lands in.
Set on a builder with CageBuilder::overlay. The command sees a merged
view: the lowers stay pristine, while every create, modify, and delete the
sandbox performs lands in the upper. Discarding the upper afterward reverts
the sandbox’s changes — the “run against a base, discard the changes” model,
and the basis for staging a build root of base + increment over a shared,
unmodified base.
§Example
use ferroday_cage::{Cage, Overlay};
let cage = Cage::builder()
.overlay(
Overlay::new()
.lower("/srv/base")
.lower("/srv/patches")
.upper("/srv/scratch/run-1"),
)
.command("/bin/sh")
.build()?;§Where the upper lives
The upper and its work directory are the one part of an overlay root the
library creates on the host, and they should live under a directory the
calling user controls, not a world-writable one such as /var/tmp — the same
requirement CageBuilder::rootfs states for a plain root.
An entry already at either path is adopted only when it is a directory
belonging to the calling user, and is otherwise refused with
ConfigError::OverlayDirUnowned, so a symbolic link another user planted
there is never followed. That check closes the create; it does not make a
shared parent safe, since the mount options name the layers as paths and the
kernel resolves them again at mount time.
§Layer order
Lowers stack base-first, the way image layers do: the first added is the base, and each later one is laid over it, so a later lower shadows an earlier one where both hold the same path. The first lower is also the directory the overlay is mounted over, and the one the sandbox pivots into.
(The kernel’s own lowerdir= option is highest-precedence-first, the reverse
of this order; the mount options are emitted reversed to match.)
Implementations§
Source§impl Overlay
impl Overlay
Sourcepub fn lower(self, path: impl AsRef<Path>) -> Overlay
pub fn lower(self, path: impl AsRef<Path>) -> Overlay
Appends a read-only lower layer, over any already added.
Repeatable and ordered: the first lower is the base the overlay is
mounted over, and each later one is laid over it, shadowing what an
earlier lower holds at the same path. Each must exist and be a directory,
exactly as CageBuilder::rootfs requires.
Sourcepub fn upper(self, path: impl AsRef<Path>) -> Overlay
pub fn upper(self, path: impl AsRef<Path>) -> Overlay
Sets the upper layer, where every write lands.
Created if absent, and persists on the host after the sandbox exits: it
is the caller’s to keep or discard. Its filesystem must record user.*
extended attributes, so an on-disk filesystem (ext4, xfs, btrfs) works on
Linux 5.11 and later, while a tmpfs upper needs Linux 6.6.
It must live under a directory the calling user controls, not a world-writable one — see Where the upper lives. The upper is also not the filesystem root: it needs a parent directory for the work directory beside it.
Sourcepub fn work(self, path: impl AsRef<Path>) -> Overlay
pub fn work(self, path: impl AsRef<Path>) -> Overlay
Overrides the work directory the overlay requires.
By default the library manages a hidden sibling of the upper. A caller naming its own must place it on the same filesystem as the upper, which the overlay requires so it can move files between them; a work directory on another filesystem is refused at build time rather than at the mount. It carries the same parent-directory requirement the upper does — see Where the upper lives.
The work area holds a directory the kernel creates mode 0, so a plain
recursive delete cannot descend into it: discard it with a removal that
restores traversable permissions as it descends.
Sourcepub fn get_lowers(&self) -> &[PathBuf]
pub fn get_lowers(&self) -> &[PathBuf]
The read-only lower layers, base-first.
Trait Implementations§
Source§impl<'de> Deserialize<'de> for Overlay
impl<'de> Deserialize<'de> for Overlay
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for Overlay
impl StructuralPartialEq for Overlay
Auto Trait Implementations§
impl Freeze for Overlay
impl RefUnwindSafe for Overlay
impl Send for Overlay
impl Sync for Overlay
impl Unpin for Overlay
impl UnsafeUnpin for Overlay
impl UnwindSafe for Overlay
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<T> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.Source§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
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
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
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
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.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
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.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
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.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
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.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
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.