From 855bb538626365c58163a78d6c279a9739b69715 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Mon, 28 Aug 2023 23:02:40 +0200 Subject: [PATCH] Allow controlling Landlock ABI versions --- Cargo.toml | 2 +- src/lib.rs | 2 +- src/linux/mod.rs | 54 +++++++++++++++++++++++++++++++++++------------- 3 files changed, 42 insertions(+), 16 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index df1ecc7..98c884f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ edition = "2021" [target.'cfg(target_os = "linux")'.dependencies] seccompiler = "0.2.0" -landlock = "0.2.0" +landlock = { git = "https://github.com/landlock-lsm/rust-landlock" } libc = "0.2.132" [dev-dependencies] diff --git a/src/lib.rs b/src/lib.rs index b47e8ef..e38ddf3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,7 +36,7 @@ use crate::macos::MacSandbox; pub mod error; #[cfg(target_os = "linux")] -mod linux; +pub mod linux; #[cfg(target_os = "macos")] mod macos; diff --git a/src/linux/mod.rs b/src/linux/mod.rs index de87ff5..591f3f9 100644 --- a/src/linux/mod.rs +++ b/src/linux/mod.rs @@ -4,9 +4,10 @@ //! combined with seccomp for anything other than the filesystem. use landlock::{ - make_bitflags, Access, AccessFs, Compatible, PathBeneath, PathFd, Ruleset, RulesetAttr, - RulesetCreated, RulesetCreatedAttr, RulesetStatus, ABI as LANDLOCK_ABI, + make_bitflags, Access, AccessFs, BitFlags, Compatible, PathBeneath, PathFd, Ruleset, + RulesetAttr, RulesetCreated, RulesetCreatedAttr, RulesetStatus, }; +pub use landlock::{CompatLevel, ABI as LANDLOCK_ABI}; use crate::error::{Error, Result}; use crate::linux::seccomp::Filter; @@ -25,17 +26,42 @@ pub struct LinuxSandbox { full_env: bool, } -impl Sandbox for LinuxSandbox { - fn new() -> Result { - // Setup landlock filtering. - let mut landlock = Ruleset::new() - .set_best_effort(false) - .handle_access(AccessFs::from_all(ABI))? - .create()?; - landlock.as_mut().set_no_new_privs(true); +impl LinuxSandbox { + /// Create a customized Linux sandbox. + /// + /// The [`min_landlock_abi`] argument defines the minimum Landlock Kernel + /// ABI version which must be supported. Sandboxing will fail on systems + /// which do not support this. + /// + /// All landlock ABI versions after [`min_landlock_abi`] versions are used + /// on systems that support them, but are ignored otherwise. This means + /// that the sandbox will be created without any error even if these are + /// not supported. + pub fn new_with_version(min_landlock_abi: LANDLOCK_ABI) -> Result { + let mut ruleset = Ruleset::new(); + + // Require at least `min_landlock_abi`. + (&mut ruleset).set_compatibility(CompatLevel::HardRequirement); + (&mut ruleset).handle_access(AccessFs::from_all(min_landlock_abi))?; + + // Add optional checks for everything after `min_landlock_abi`. + // + // NOTE: This will require these access permissions on systems that support + // checking for them, while ignoring them on all other systems. + (&mut ruleset).set_compatibility(CompatLevel::BestEffort); + (&mut ruleset).handle_access(BitFlags::::all())?; + + let mut landlock = ruleset.create()?; + (&mut landlock).set_no_new_privs(true); Ok(Self { landlock, env_exceptions: Vec::new(), allow_networking: false, full_env: false }) } +} + +impl Sandbox for LinuxSandbox { + fn new() -> Result { + Self::new_with_version(ABI) + } fn add_exception(&mut self, exception: Exception) -> Result<&mut Self> { let (path, access) = match exception { @@ -58,7 +84,7 @@ impl Sandbox for LinuxSandbox { let rule = PathBeneath::new(PathFd::new(path)?, access); - self.landlock.as_mut().add_rule(rule)?; + (&mut self.landlock).add_rule(rule)?; Ok(self) } @@ -80,10 +106,10 @@ impl Sandbox for LinuxSandbox { let status = self.landlock.restrict_self()?; // Ensure all restrictions were properly applied. - if status.no_new_privs && status.ruleset == RulesetStatus::FullyEnforced { - Ok(()) - } else { + if status.ruleset == RulesetStatus::NotEnforced || !status.no_new_privs { Err(Error::ActivationFailed("sandbox could not be fully enforced".into())) + } else { + Ok(()) } } }