### sandboxer example Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt Demonstrates a complete command-line sandbox using Landlock, configurable via environment variables for filesystem, TCP, and scope restrictions. ```APIDOC ## `sandboxer` example — full command sandbox The included `examples/sandboxer.rs` demonstrates a complete Landlock sandbox that wraps an arbitrary command. It reads configuration from environment variables and applies filesystem, TCP, and scope restrictions. ### Usage ```bash # Build the example cargo build --example sandboxer # Run bash in a restricted environment: # - Read-only: PATH dirs, /lib, /usr, /proc, /etc, /dev/urandom # - Read-write: /dev/null, /dev/full, /dev/zero, /dev/pts, /tmp # - TCP: bind port 9418, connect to ports 80 and 443 # - Scoped: block abstract UNIX sockets and signal delivery outside sandbox LL_FS_RO="${PATH}:/lib:/usr:/proc:/etc:/dev/urandom" \ LL_FS_RW="/dev/null:/dev/full:/dev/zero:/dev/pts:/tmp" \ LL_TCP_BIND="9418" \ LL_TCP_CONNECT="80:443" \ LL_SCOPED="a:s" \ ./target/debug/examples/sandboxer bash -i ``` ``` -------------------------------- ### Full Command Sandbox Example with Environment Variables Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt Demonstrates a complete Landlock sandbox wrapping an arbitrary command using environment variables for configuration. It applies filesystem, TCP, and scope restrictions. ```bash # Build the example cargo build --example sandboxer # Run bash in a restricted environment: # - Read-only: PATH dirs, /lib, /usr, /proc, /etc, /dev/urandom # - Read-write: /dev/null, /dev/full, /dev/zero, /dev/pts, /tmp # - TCP: bind port 9418, connect to ports 80 and 443 # - Scoped: block abstract UNIX sockets and signal delivery outside sandbox LL_FS_RO="${PATH}:/lib:/usr:/proc:/etc:/dev/urandom" \ LL_FS_RW="/dev/null:/dev/full:/dev/zero:/dev/pts:/tmp" \ LL_TCP_BIND="9418" \ LL_TCP_CONNECT="80:443" \ LL_SCOPED="a:s" \ ./target/debug/examples/sandboxer bash -i ``` -------------------------------- ### Minimal Read-Only Filesystem Sandbox Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt This example demonstrates a basic sandbox configuration that restricts filesystem access to read-only for all paths, with no network restrictions. It's useful for running commands that only need to read files. ```bash LL_FS_RO="/" LL_FS_RW="" ./target/debug/examples/sandboxer ls /tmp ``` -------------------------------- ### Define TCP Network Rules with AccessNet and NetPort in Rust Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt Use `AccessNet` for TCP bind and connect rights, and `NetPort` to associate a port number with an `AccessNet` right. This requires Linux 6.7+ (ABI::V4). The example shows how to allow binding to port 443 and connecting to ports 80 and 443, as well as binding to ephemeral ports. ```rust use landlock::{ Access, AccessFs, AccessNet, NetPort, Ruleset, RulesetAttr, RulesetCreatedAttr, RulesetError, ABI, }; fn sandbox_web_server() -> Result<(), RulesetError> { let abi = ABI::V4; let status = Ruleset::default() .handle_access(AccessFs::from_all(abi))? // Declare both TCP rights as handled (= denied by default) .handle_access(AccessNet::BindTcp | AccessNet::ConnectTcp)? .create()? // Allow the process to bind only port 443 .add_rule(NetPort::new(443, AccessNet::BindTcp))? // Allow connecting to ports 80 and 443 .add_rule(NetPort::new(80, AccessNet::ConnectTcp))? .add_rule(NetPort::new(443, AccessNet::ConnectTcp))? // Port 0 = ephemeral port range from /proc/sys/net/ipv4/ip_local_port_range .add_rule(NetPort::new(0, AccessNet::BindTcp))? .restrict_self()?; println!("Network sandbox status: {:?}", status.ruleset); Ok(()) } ``` -------------------------------- ### Create a Read-Only Filesystem Sandbox Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt Demonstrates the three-phase builder pattern to create a read-only sandbox for specified paths. Declares filesystem access rights and adds path-specific rules. ```rust use landlock::{ Access, AccessFs, Ruleset, RulesetError, PathBeneath, PathFd, ABI, }; fn sandbox_read_only(paths: &[&str]) -> Result<(), RulesetError> { let abi = ABI::V1; // Declare ALL access rights that will be handled (denied by default) // then whitelist specific paths with rules. let status = Ruleset::default() .handle_access(AccessFs::from_all(abi))? .create()? // Transition to RulesetCreated .add_rules( paths.iter().map(|p| -> Result, RuleslockError> { Ok(PathBeneath::new(PathFd::new(p)?, AccessFs::from_read(abi))) }), )? .restrict_self()?; // Enforce the ruleset println!("Sandbox status: {:?}", status.ruleset); // => FullyEnforced | PartiallyEnforced | NotEnforced Ok(()) } sandbox_read_only(&["/usr", "/etc", "/lib"]).expect("sandbox failed"); ``` -------------------------------- ### Ruleset / RulesetAttr - ruleset builder Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt `Ruleset` is the entry point for building a Landlock ruleset. It allows probing the kernel, declaring handled accesses, and creating a ruleset that can then be populated with rules. ```APIDOC ## `Ruleset` / `RulesetAttr` — ruleset builder `Ruleset` is the entry point. Call `Ruleset::default()` to probe the running kernel, declare handled accesses with `.handle_access()`, and transition to `RulesetCreated` via `.create()`. ```rust use landlock::{ Access, AccessFs, AccessNet, Ruleset, RulesetAttr, RulesetCreatedAttr, RulesetError, PathBeneath, PathFd, ABI, }; fn sandbox_read_only(paths: &[&str]) -> Result<(), RulesetError> { let abi = ABI::V1; // Declare ALL access rights that will be handled (denied by default) // then whitelist specific paths with rules. let status = Ruleset::default() .handle_access(AccessFs::from_all(abi))? .create()? // Transition to RulesetCreated .add_rules( paths.iter().map(|p| -> Result, RulesetError> { Ok(PathBeneath::new(PathFd::new(p)?, AccessFs::from_read(abi))) }), )? .restrict_self()?; // Enforce the ruleset println!("Sandbox status: {:?}", status.ruleset); // => FullyEnforced | PartiallyEnforced | NotEnforced Ok(()) } sandbox_read_only(&["/usr", "/etc", "/lib"]).expect("sandbox failed"); ``` ``` -------------------------------- ### Declare Handled Filesystem/Network Accesses with RulesetAttr::handle_access() Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt Registers access rights that the ruleset will restrict. Consecutive calls are OR-ed together. Must be called at least once before `.create()`. ```rust use landlock::{Access, AccessFs, AccessNet, CompatLevel, Compatible, Ruleset, RulesetAttr, ABI}; // Mix filesystem and network access handling let ruleset = Ruleset::default() // Hard-require V1 filesystem rights .set_compatibility(CompatLevel::HardRequirement) .handle_access(AccessFs::from_all(ABI::V1)) .expect("V1 filesystem rights required") // Opportunistically add V2+ rights .set_compatibility(CompatLevel::BestEffort) .handle_access(AccessFs::from_all(ABI::V6)) .expect("best-effort upgrade failed") // Opportunistically restrict TCP (requires ABI::V4 / Linux 6.7) .handle_access(AccessNet::BindTcp | AccessNet::ConnectTcp) .expect("net handle failed"); let _ruleset_created = ruleset.create().expect("create failed"); ``` -------------------------------- ### Bulk Filesystem Rule Helper with path_beneath_rules in Rust Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt The `path_beneath_rules` function simplifies creating multiple `PathBeneath` rules from a list of paths. It silently skips paths that cannot be opened and automatically adjusts directory-only access rights for plain files. ```rust use landlock::{ ABI, Access, AccessFs, RulesetStatus, RulesetError, Ruleset, RulesetAttr, RulesetCreatedAttr, path_beneath_rules, }; fn restrict_thread() -> Result<(), RulesetError> { let abi = ABI::V1; let status = Ruleset::default() .handle_access(AccessFs::from_all(abi))? .create()? // Read-only access to system directories .add_rules(path_beneath_rules( &["/usr", "/etc", "/dev", "/proc"], AccessFs::from_read(abi), ))? // Read-write access to transient directories .add_rules(path_beneath_rules( &["/home", "/tmp", "/var/tmp"], AccessFs::from_all(abi), ))? // Non-existent paths are silently skipped — no error .add_rules(path_beneath_rules( &["/does-not-exist"], AccessFs::from_all(abi), ))? .restrict_self()?; match status.ruleset { RulesetStatus::FullyEnforced => println!("Fully sandboxed."), RulesetStatus::PartiallyEnforced => println!("Partially sandboxed."), RulesetStatus::NotEnforced => eprintln!("Not sandboxed! Please update your kernel."), } Ok(()) } ``` -------------------------------- ### path_beneath_rules() - Bulk Filesystem Rule Helper Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt Convenience function that creates an iterator of `PathBeneath` rules from a list of paths. Silently skips paths that cannot be opened. Automatically downgrades directory-only access rights when the path refers to a plain file. ```APIDOC ## `path_beneath_rules()` — bulk filesystem rule helper Convenience function that creates an iterator of `PathBeneath` rules from a list of paths. Silently skips paths that cannot be opened. Automatically downgrades directory-only access rights when the path refers to a plain file. ```rust use landlock::{ ABI, Access, AccessFs, RulesetStatus, RulesetError, Ruleset, RulesetAttr, RulesetCreatedAttr, path_beneath_rules, }; fn restrict_thread() -> Result<(), RulesetError> { let abi = ABI::V1; let status = Ruleset::default() .handle_access(AccessFs::from_all(abi))? .create()? // Read-only access to system directories .add_rules(path_beneath_rules( &["/usr", "/etc", "/dev", "/proc"], AccessFs::from_read(abi), ))? // Read-write access to transient directories .add_rules(path_beneath_rules( &["/home", "/tmp", "/var/tmp"], AccessFs::from_all(abi), ))? // Non-existent paths are silently skipped — no error .add_rules(path_beneath_rules( &["/does-not-exist"], AccessFs::from_all(abi), ))? .restrict_self()?; match status.ruleset { RulesetStatus::FullyEnforced => println!("Fully sandboxed."), RulesetStatus::PartiallyEnforced => println!("Partially sandboxed."), RulesetStatus::NotEnforced => eprintln!("Not sandboxed! Please update your kernel."), } Ok(()) } ``` ``` -------------------------------- ### Runtime Landlock Availability Check Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt Shows how to check Landlock availability at runtime and convert LandlockStatus to an ABI. This status should inform users but not change sandbox behavior. ```rust use landlock::{ABI, LandlockStatus}; // Check current kernel support at runtime. // (LandlockStatus::current() is internal; status is exposed via RestrictionStatus) // Use this pattern after restrict_self() to inform users: // // match status.landlock { // LandlockStatus::NotImplemented => eprintln!("Kernel not built with Landlock."), // LandlockStatus::NotEnabled => eprintln!("Landlock is disabled at boot."), // LandlockStatus::Available { effective_abi, kernel_abi: None } => { // println!("Landlock ABI {effective_abi} active."); // } // LandlockStatus::Available { effective_abi, kernel_abi: Some(raw) } => { // // Kernel supports a newer ABI than this crate knows about. // eprintln!("Crate uses ABI {effective_abi}; kernel supports ABI {raw}. Update the crate."); // } // } // Conversion: LandlockStatus -> ABI (returns Unsupported when not available) let abi_from_status: ABI = LandlockStatus::NotImplemented.into(); // => ABI::Unsupported println!("{}", abi_from_status); ``` -------------------------------- ### O_PATH File Descriptor Helper with PathFd Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt Opens a file or directory with `O_PATH | O_CLOEXEC` flags for use as a Landlock rule anchor. Preferred over `std::fs::File` for Landlock use to avoid spurious permission errors. ```rust use landlock::{AccessFs, PathBeneath, PathFd, PathFdError}; fn build_home_rule() -> Result, PathFdError> { // Opens /home with O_PATH — no read/write access implied let fd = PathFd::new("/home")?; Ok(PathBeneath::new(fd, AccessFs::ReadDir | AccessFs::ReadFile)) } // PathFd works with any type implementing AsRef let fd_bytes = PathFd::new("/etc/passwd")?; let fd_str = PathFd::new("/usr")?; # Ok::<(), PathFdError>(()) ``` -------------------------------- ### Landlock ABI Version Enum Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt Demonstrates how to use ABI versions to define filesystem, network, and scope access rights. Always derive access right sets through a pinned ABI version. ```rust use landlock::{ABI, Access, AccessFs, AccessNet, Scope}; // V1 — Linux 5.13: filesystem access rights let fs_v1 = AccessFs::from_all(ABI::V1); // V2 — Linux 5.19: adds AccessFs::Refer (cross-directory rename/link) let fs_v2 = AccessFs::from_all(ABI::V2); assert_eq!(fs_v2, fs_v1 | AccessFs::Refer); // V3 — Linux 6.2: adds AccessFs::Truncate // V4 — Linux 6.7: adds AccessNet (TCP bind/connect) let net_v4 = AccessNet::from_all(ABI::V4); // V5 — Linux 6.10: adds AccessFs::IoctlDev // V6 — Linux 6.12: adds Scope (abstract UNIX sockets, signals) let scope_v6 = Scope::from_all(ABI::V6); // ABI can also be created from an integer (primarily for testing) let abi: ABI = ABI::from(3); // => ABI::V3 println!("{}", abi); // prints "3" let unsupported: ABI = ABI::from(-1); // => ABI::Unsupported println!("{}", unsupported); // prints "unsupported" ``` -------------------------------- ### AccessFs Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt Bitflag enum covering all Landlock filesystem access rights across all ABI versions. Use `from_all()`, `from_read()`, `from_write()`, and `from_file()` helpers rather than constructing `BitFlags` manually. ```APIDOC ## `AccessFs` — filesystem access rights Bitflag enum covering all Landlock filesystem access rights across all ABI versions. Use `from_all()`, `from_read()`, `from_write()`, and `from_file()` helpers rather than constructing `BitFlags` manually. ```rust use landlock::{ABI, Access, AccessFs, make_bitflags}; // All read-only rights for V1 let read_only = AccessFs::from_read(ABI::V1); // => Execute | ReadFile | ReadDir // All write rights for V1 let write_only = AccessFs::from_write(ABI::V1); // => WriteFile | RemoveDir | RemoveFile | MakeChar | MakeDir | MakeReg | MakeSock | MakeFifo | MakeBlock | MakeSym // Rights valid for non-directory files only (auto-used by path_beneath_rules) let file_rights = AccessFs::from_file(ABI::V5); // => ReadFile | WriteFile | Execute | Truncate | IoctlDev // Manual bitflag composition let custom = make_bitflags!(AccessFs::{Execute | ReadFile | WriteFile}); // Subtracting a right let without_exec = AccessFs::from_all(ABI::V1) & !AccessFs::Execute; // Check ABI progression assert_eq!(AccessFs::from_all(ABI::V1) | AccessFs::Refer, AccessFs::from_all(ABI::V2)); assert_eq!(AccessFs::from_all(ABI::V2) | AccessFs::Truncate, AccessFs::from_all(ABI::V3)); ``` ``` -------------------------------- ### Configure and Create Landlock Ruleset in Rust Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt This Rust code configures a Landlock ruleset with specific filesystem and network access controls. It demonstrates how to handle access permissions, define scopes, and create the ruleset. Use this pattern when setting up granular restrictions for a process. ```rust use landlock::{ path_beneath_rules, Access, AccessFs, AccessNet, NetPort, Ruleset, RulesetAttr, RulesetCreatedAttr, RulesetStatus, Scope, ABI, }; let abi = ABI::V6; let status = Ruleset::default() .handle_access(AccessFs::from_all(abi)).unwrap() .handle_access(AccessNet::BindTcp | AccessNet::ConnectTcp).unwrap() .scope(Scope::AbstractUnixSocket | Scope::Signal).unwrap() .create().unwrap() .add_rules(path_beneath_rules(&["/usr", "/etc", "/proc"], AccessFs::from_read(abi))).unwrap() .add_rules(path_beneath_rules(&["/tmp", "/dev/null"], AccessFs::from_all(abi))).unwrap() .add_rule(NetPort::new(9418, AccessNet::BindTcp)).unwrap() .add_rule(NetPort::new(443, AccessNet::ConnectTcp)).unwrap() .restrict_self().unwrap(); assert_ne!(status.ruleset, RulesetStatus::NotEnforced); ``` -------------------------------- ### Filesystem Access Rights with AccessFs Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt Bitflag enum covering all Landlock filesystem access rights across all ABI versions. Use helper methods like `from_all()`, `from_read()`, `from_write()`, and `from_file()` for clarity. ```rust use landlock::{ABI, Access, AccessFs, make_bitflags}; // All read-only rights for V1 let read_only = AccessFs::from_read(ABI::V1); // => Execute | ReadFile | ReadDir // All write rights for V1 let write_only = AccessFs::from_write(ABI::V1); // => WriteFile | RemoveDir | RemoveFile | MakeChar | MakeDir | MakeReg | MakeSock | MakeFifo | MakeBlock | MakeSym // Rights valid for non-directory files only (auto-used by path_beneath_rules) let file_rights = AccessFs::from_file(ABI::V5); // => ReadFile | WriteFile | Execute | Truncate | IoctlDev // Manual bitflag composition let custom = make_bitflags!(AccessFs::{Execute | ReadFile | WriteFile}); // Subtracting a right let without_exec = AccessFs::from_all(ABI::V1) & !AccessFs::Execute; // Check ABI progression assert_eq!(AccessFs::from_all(ABI::V1) | AccessFs::Refer, AccessFs::from_all(ABI::V2)); assert_eq!(AccessFs::from_all(ABI::V2) | AccessFs::Truncate, AccessFs::from_all(ABI::V3)); ``` -------------------------------- ### PathFd Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt O_PATH file descriptor helper. Opens a file or directory with `O_PATH | O_CLOEXEC` flags for use as a Landlock rule anchor. Preferred over `std::fs::File` for Landlock use to avoid spurious permission errors. ```APIDOC ## `PathFd` — O_PATH file descriptor helper Opens a file or directory with `O_PATH | O_CLOEXEC` flags for use as a Landlock rule anchor. Preferred over `std::fs::File` for Landlock use to avoid spurious permission errors. ```rust use landlock::{AccessFs, PathBeneath, PathFd, PathFdError}; fn build_home_rule() -> Result, PathFdError> { // Opens /home with O_PATH — no read/write access implied let fd = PathFd::new("/home")?; Ok(PathBeneath::new(fd, AccessFs::ReadDir | AccessFs::ReadFile)) } // PathFd works with any type implementing AsRef let fd_bytes = PathFd::new("/etc/passwd")?; let fd_str = PathFd::new("/usr")?; # Ok::<(), PathFdError>(()) ``` ``` -------------------------------- ### Landlock Compatibility Levels in Rust Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt Demonstrates three compatibility levels for handling unsupported Landlock features: BestEffort (default, ignores), SoftRequirement (skips sandbox), and HardRequirement (returns error). Use SoftRequirement when correctness depends on a feature, and HardRequirement for security-critical applications. ```rust use landlock::{ Access, AccessFs, CompatLevel, Compatible, Ruleset, RulesetAttr, RulesetCreatedAttr, RulesetCreated, RulesetError, ABI, }; // Pattern 1 — BestEffort (default): silently ignore unsupported features. // Safe for most applications. fn best_effort_sandbox() -> Result { Ok(Ruleset::default() .handle_access(AccessFs::from_all(ABI::V6))? // must succeed .create()?) } // Pattern 2 — SoftRequirement: if Refer is unsupported, skip the whole sandbox. // Use when correctness requires a specific feature. fn sandbox_requiring_rename() -> Result { Ok(Ruleset::default() .set_compatibility(CompatLevel::SoftRequirement) .handle_access(AccessFs::Refer)? .set_compatibility(CompatLevel::BestEffort) .handle_access(AccessFs::from_all(ABI::V6))? // opportunistic .create()?) } // Pattern 3 — HardRequirement: return an error if any required feature is absent. // Use for security-critical launchers. fn mandatory_sandbox() -> Result { Ok(Ruleset::default() .set_compatibility(CompatLevel::HardRequirement) .handle_access(AccessFs::from_all(ABI::V1))? // must succeed .set_compatibility(CompatLevel::BestEffort) .handle_access(AccessFs::from_all(ABI::V6))? // opportunistic .create()?) } ``` -------------------------------- ### AccessNet / NetPort - TCP Network Rules Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt `AccessNet` defines TCP bind and connect rights. `NetPort` associates a port number with an `AccessNet` right to create a network allowlist rule. Requires Linux 6.7+ (ABI::V4). ```APIDOC ## `AccessNet` / `NetPort` — TCP network rules (ABI::V4+) `AccessNet` defines TCP bind and connect rights. `NetPort` associates a port number with an `AccessNet` right to create a network allowlist rule. Requires Linux 6.7+ (ABI::V4). ```rust use landlock::{ Access, AccessFs, AccessNet, NetPort, Ruleset, RulesetAttr, RulesetCreatedAttr, RulesetError, ABI, }; fn sandbox_web_server() -> Result<(), RulesetError> { let abi = ABI::V4; let status = Ruleset::default() .handle_access(AccessFs::from_all(abi))? // Declare both TCP rights as handled (= denied by default) .handle_access(AccessNet::BindTcp | AccessNet::ConnectTcp)? .create()? // Allow the process to bind only port 443 .add_rule(NetPort::new(443, AccessNet::BindTcp))? // Allow connecting to ports 80 and 443 .add_rule(NetPort::new(80, AccessNet::ConnectTcp))? .add_rule(NetPort::new(443, AccessNet::ConnectTcp))? // Port 0 = ephemeral port range from /proc/sys/net/ipv4/ip_local_port_range .add_rule(NetPort::new(0, AccessNet::BindTcp))? .restrict_self()?; println!("Network sandbox status: {:?}", status.ruleset); Ok(()) } ``` ``` -------------------------------- ### RulesetAttr::handle_access() Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt Registers access rights that the ruleset will restrict. Consecutive calls are OR-ed together. Must be called at least once before `.create()`. ```APIDOC ## `RulesetAttr::handle_access()` — declare handled filesystem/network accesses Registers access rights that the ruleset will restrict. Consecutive calls are OR-ed together. Must be called at least once before `.create()`. ```rust use landlock::{Access, AccessFs, AccessNet, CompatLevel, Compatible, Ruleset, RulesetAttr, ABI}; // Mix filesystem and network access handling let ruleset = Ruleset::default() // Hard-require V1 filesystem rights .set_compatibility(CompatLevel::HardRequirement) .handle_access(AccessFs::from_all(ABI::V1)) .expect("V1 filesystem rights required") // Opportunistically add V2+ rights .set_compatibility(CompatLevel::BestEffort) .handle_access(AccessFs::from_all(ABI::V6)) .expect("best-effort upgrade failed") // Opportunistically restrict TCP (requires ABI::V4 / Linux 6.7) .handle_access(AccessNet::BindTcp | AccessNet::ConnectTcp) .expect("net handle failed"); let _ruleset_created = ruleset.create().expect("create failed"); ``` ``` -------------------------------- ### PathBeneath - Filesystem Hierarchy Rule Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt Defines an allowed access pattern for a file hierarchy rooted at an open file descriptor. When added to a ruleset, it whitelists the specified access rights for all paths under that root. ```APIDOC ## `PathBeneath` — filesystem hierarchy rule Defines an allowed access pattern for a file hierarchy rooted at an open file descriptor. When added to a ruleset, it whitelists the specified access rights for all paths under that root. ```rust use landlock::{ Access, AccessFs, CompatLevel, Compatible, PathBeneath, PathFd, PathFdError, Ruleset, RulesetAttr, RulesetCreatedAttr, RulesetError, ABI, }; fn sandbox_with_rules() -> Result<(), RulesetError> { let abi = ABI::V3; // Truncate support let status = Ruleset::default() .handle_access(AccessFs::from_all(abi))? .create()? // Allow full access to /tmp .add_rule(PathBeneath::new( PathFd::new("/tmp").expect("open /tmp"), AccessFs::from_all(abi), ))? // Allow read-only access to /usr — note: directory-only rights // (ReadDir) are automatically dropped for plain files .add_rule( PathBeneath::new( PathFd::new("/usr").expect("open /usr"), AccessFs::from_read(abi), ) // Optionally tighten compatibility for this specific rule .set_compatibility(CompatLevel::HardRequirement), )? .restrict_self()?; assert!(status.no_new_privs); Ok(()) } ``` ``` -------------------------------- ### Compatible Trait and CompatLevel Enum Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt Manages how missing kernel features are handled in Landlock rulesets. Callers can choose between graceful degradation (BestEffort), skipping the sandbox if a feature is unsupported (SoftRequirement), or hard failure (HardRequirement). ```APIDOC ## `Compatible` / `CompatLevel` — compatibility management The `Compatible` trait, implemented by `Ruleset`, `RulesetCreated`, `PathBeneath`, and `NetPort`, controls how missing kernel features are handled. The three levels let callers choose between graceful degradation and hard failure. ### BestEffort (default) Silently ignore unsupported features. Safe for most applications. ### SoftRequirement If a required feature is unsupported, skip the whole sandbox. Use when correctness requires a specific feature. ### HardRequirement Return an error if any required feature is absent. Use for security-critical launchers. ``` -------------------------------- ### ABI - Landlock ABI version enum Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt Represents specific versions of the Landlock kernel ABI. Use constants like `ABI::V1`–`ABI::V6` to obtain stable sets of access rights. Avoid using `BitFlags::ALL` directly; derive access right sets through a pinned `ABI` version. ```APIDOC ## `ABI` — Landlock ABI version enum Represents a specific version of the Landlock kernel ABI. Use `ABI::V1`–`ABI::V6` constants to obtain stable, tested sets of access rights. Never use `BitFlags::ALL` directly; always derive access right sets through a pinned `ABI` version to avoid surprising behavior when the crate is updated. ```rust use landlock::{ABI, Access, AccessFs, AccessNet, Scope}; // V1 — Linux 5.13: filesystem access rights let fs_v1 = AccessFs::from_all(ABI::V1); // V2 — Linux 5.19: adds AccessFs::Refer (cross-directory rename/link) let fs_v2 = AccessFs::from_all(ABI::V2); assert_eq!(fs_v2, fs_v1 | AccessFs::Refer); // V3 — Linux 6.2: adds AccessFs::Truncate // V4 — Linux 6.7: adds AccessNet (TCP bind/connect) let net_v4 = AccessNet::from_all(ABI::V4); // V5 — Linux 6.10: adds AccessFs::IoctlDev // V6 — Linux 6.12: adds Scope (abstract UNIX sockets, signals) let scope_v6 = Scope::from_all(ABI::V6); // ABI can also be created from an integer (primarily for testing) let abi: ABI = ABI::from(3); // => ABI::V3 println!("{}", abi); // prints "3" let unsupported: ABI = ABI::from(-1); // => ABI::Unsupported println!("{}", unsupported); // prints "unsupported" ``` ``` -------------------------------- ### LandlockStatus - runtime Landlock availability Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt Reports whether Landlock is available on the running kernel. This is useful for informing users about sandbox status but should not be used to change sandbox behavior; use `Compatible` for that. ```APIDOC ## `LandlockStatus` — runtime Landlock availability Reports whether Landlock is available on the running kernel. Useful for informing users about sandbox status; **must not** be used to change sandbox behavior (use `Compatible` for that). ```rust use landlock::{ABI, LandlockStatus}; // Check current kernel support at runtime. // (LandlockStatus::current() is internal; status is exposed via RestrictionStatus) // Use this pattern after restrict_self() to inform users: // // match status.landlock { // LandlockStatus::NotImplemented => eprintln!("Kernel not built with Landlock."), // LandlockStatus::NotEnabled => eprintln!("Landlock is disabled at boot."), // LandlockStatus::Available { effective_abi, kernel_abi: None } => { // println!("Landlock ABI {effective_abi} active."); // } // LandlockStatus::Available { effective_abi, kernel_abi: Some(raw) } => { // // Kernel supports a newer ABI than this crate knows about. // eprintln!("Crate uses ABI {effective_abi}; kernel supports ABI {raw}. Update the crate."); // } // } // Conversion: LandlockStatus -> ABI (returns Unsupported when not available) let abi_from_status: ABI = LandlockStatus::NotImplemented.into(); // => ABI::Unsupported ``` ``` -------------------------------- ### Define PathBeneath Filesystem Hierarchy Rule in Rust Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt Use `PathBeneath` to define allowed access rights for paths under a specific open file descriptor. This rule whitelists access for all paths beneath the given root. The `set_compatibility` method can be used to enforce specific compatibility levels for a rule. ```rust use landlock::{ Access, AccessFs, CompatLevel, Compatible, PathBeneath, PathFd, PathFdError, Ruleset, RulesetAttr, RulesetCreatedAttr, RulesetError, ABI, }; fn sandbox_with_rules() -> Result<(), RulesetError> { let abi = ABI::V3; // Truncate support let status = Ruleset::default() .handle_access(AccessFs::from_all(abi))? .create()? // Allow full access to /tmp .add_rule(PathBeneath::new( PathFd::new("/tmp").expect("open /tmp"), AccessFs::from_all(abi), ))? // Allow read-only access to /usr — note: directory-only rights // (ReadDir) are automatically dropped for plain files .add_rule( PathBeneath::new( PathFd::new("/usr").expect("open /usr"), AccessFs::from_read(abi), ) // Optionally tighten compatibility for this specific rule .set_compatibility(CompatLevel::HardRequirement), )? .restrict_self()?; assert!(status.no_new_privs); Ok(()) } ``` -------------------------------- ### RulesetCreated::try_clone() Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt Duplicates the file descriptor of an existing Landlock ruleset. Both the original and the cloned ruleset refer to the same underlying rule set, allowing modifications to be shared across threads. ```APIDOC ## `RulesetCreated::try_clone()` — duplicate a ruleset file descriptor Duplicates the underlying Landlock ruleset file descriptor. Both instances share the same rule set; modifications to one affect the other. Useful for applying the same restrictions across multiple threads. ### Usage ```rust use landlock::{ Access, AccessFs, PathFd, PathBeneath, Ruleset, RulesetAttr, RulesetCreatedAttr, RulesetError, ABI, }; fn multi_thread_sandbox() -> Result<(), RulesetError> { let abi = ABI::V1; let ruleset = Ruleset::default() .handle_access(AccessFs::Execute)? .create()? .add_rule(PathBeneath::new(PathFd::new("/usr")?, AccessFs::Execute))?; // Clone before restrict_self so each thread can call it independently. let ruleset2 = ruleset.try_clone().expect("clone failed"); std::thread::spawn(move || { ruleset2.restrict_self().expect("restrict failed in thread"); }).join().unwrap(); ruleset.restrict_self()?; Ok(()) } ``` ### Return Value - `Ok(RulesetCreated)`: A new `RulesetCreated` instance referencing the same ruleset. - Panics if cloning fails. ``` -------------------------------- ### RulesetAttr::scope() Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt Restricts interactions with entities created outside the sandbox: abstract UNIX sockets and/or signal delivery. This feature requires ABI::V6 / Linux 6.12. ```APIDOC ## `RulesetAttr::scope()` — declare IPC scoping (ABI::V6 / Linux 6.12) Restricts interactions with entities created outside the sandbox: abstract UNIX sockets and/or signal delivery. ```rust use landlock::{Access, AccessFs, Ruleset, RulesetAttr, RulesetCreatedAttr, Scope, ABI}; let status = Ruleset::default() .handle_access(AccessFs::from_all(ABI::V6)) .expect("handle_access failed") // Prevent sandbox from connecting to abstract UNIX sockets outside sandbox // and from sending signals to processes outside sandbox .scope(Scope::AbstractUnixSocket | Scope::Signal) .expect("scope failed") .create() .expect("create failed") .restrict_self() .expect("restrict_self failed"); println!("{:?}", status.ruleset); // => FullyEnforced on Linux 6.12+, NotEnforced on older kernels (BestEffort default) ``` ``` -------------------------------- ### Apply Landlock Sandbox to Calling Thread in Rust Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt Finalizes a Landlock sandbox by calling `landlock_restrict_self(2)` and optionally `prctl(PR_SET_NO_NEW_PRIVS, 1)`. Returns a `RestrictionStatus` indicating what was enforced. `no_new_privs` is enabled by default. ```rust use landlock::{ Access, AccessFs, PathFd, PathBeneath, RestrictionStatus, RulesetStatus, Ruleset, RulesetAttr, RulesetCreatedAttr, RulesetError, ABI, }; fn apply_and_check() -> Result { let abi = ABI::V1; let status = Ruleset::default() .handle_access(AccessFs::from_all(abi))? .create()? // create ruleset .add_rule(PathBeneath::new(PathFd::new("/")?, AccessFs::from_read(abi)))? // add rule // no_new_privs is enabled by default; disable explicitly if needed: // .set_no_new_privs(false) .restrict_self()?; // apply sandbox // Recommended: only check for Ok(_); log the details for users. assert!(status.no_new_privs); match status.ruleset { RulesetStatus::FullyEnforced => { /* ideal — test on a supported kernel */ } // ideal RulesetStatus::PartiallyEnforced => { /* acceptable for best-effort */ } // acceptable RulesetStatus::NotEnforced => { /* kernel too old or Landlock disabled */ } // not enforced } Ok(status) } ``` -------------------------------- ### Scope - IPC Domain Scoping Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt `Scope` restricts inter-process communication: `AbstractUnixSocket` prevents connecting to abstract UNIX sockets created outside the sandbox, and `Signal` prevents sending signals to processes outside the sandbox. Requires Linux 6.12+ (ABI::V6). ```APIDOC ## `Scope` — IPC domain scoping (ABI::V6+) `Scope` restricts inter-process communication: `AbstractUnixSocket` prevents connecting to abstract UNIX sockets created outside the sandbox, and `Signal` prevents sending signals to processes outside the sandbox. Requires Linux 6.12+ (ABI::V6). ```rust use landlock::{ Access, AccessFs, Ruleset, RulesetAttr, RulesetCreatedAttr, RulesetError, Scope, ABI, }; fn isolated_sandbox() -> Result<(), RulesetError> { let status = Ruleset::default() .handle_access(AccessFs::from_all(ABI::V6))? // Scope-only ruleset is valid (no filesystem rules required) .scope(Scope::AbstractUnixSocket | Scope::Signal)? .create()? .restrict_self()?; println!("{:?}", status.ruleset); Ok(()) } ``` ``` -------------------------------- ### Declare IPC Scoping with RulesetAttr::scope() (ABI::V6 / Linux 6.12) Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt Restricts interactions with entities created outside the sandbox, such as abstract UNIX sockets and signal delivery. This feature requires Linux kernel 6.12 or later. ```rust use landlock::{Access, AccessFs, Ruleset, RulesetAttr, RulesetCreatedAttr, Scope, ABI}; let status = Ruleset::default() .handle_access(AccessFs::from_all(ABI::V6)) .expect("handle_access failed") // Prevent sandbox from connecting to abstract UNIX sockets outside sandbox // and from sending signals to processes outside sandbox .scope(Scope::AbstractUnixSocket | Scope::Signal) .expect("scope failed") .create() .expect("create failed") .restrict_self() .expect("restrict_self failed"); println!("{:?}", status.ruleset); // => FullyEnforced on Linux 6.12+, NotEnforced on older kernels (BestEffort default) ``` -------------------------------- ### RulesetCreated::restrict_self() Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt Finalizes the sandbox by applying the configured ruleset to the calling thread. It optionally enables the `no_new_privs` security feature and returns a `RestrictionStatus` indicating the enforcement level. ```APIDOC ## `RulesetCreated::restrict_self()` — apply sandbox to calling thread Finalizes the sandbox by calling `landlock_restrict_self(2)` and optionally `prctl(PR_SET_NO_NEW_PRIVS, 1)`. Returns a `RestrictionStatus` describing what was actually enforced. ### Usage ```rust use landlock::{ Access, AccessFs, PathFd, PathBeneath, RestrictionStatus, RulesetStatus, Ruleset, RulesetAttr, RulesetCreatedAttr, RulesetError, ABI, }; fn apply_and_check() -> Result { let abi = ABI::V1; let status = Ruleset::default() .handle_access(AccessFs::from_all(abi))? .create()? .add_rule(PathBeneath::new(PathFd::new("/")?, AccessFs::from_read(abi))) // no_new_privs is enabled by default; disable explicitly if needed: // .set_no_new_privs(false) .restrict_self()?; // Recommended: only check for Ok(_); log the details for users. assert!(status.no_new_privs); match status.ruleset { RulesetStatus::FullyEnforced => { /* ideal — test on a supported kernel */ } RulesetStatus::PartiallyEnforced => { /* acceptable for best-effort */ } RulesetStatus::NotEnforced => { /* kernel too old or Landlock disabled */ } } Ok(status) } ``` ### Return Value - `Ok(RestrictionStatus)`: On success, returns the status of the restriction enforcement. - `Err(RulesetError)`: If an error occurs during restriction. ``` -------------------------------- ### Duplicate Landlock Ruleset File Descriptor in Rust Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt Duplicates the underlying Landlock ruleset file descriptor, allowing the same restrictions to be applied across multiple threads. Clone the ruleset before calling `restrict_self` if each thread needs to apply the sandbox independently. ```rust use landlock::{ Access, AccessFs, PathFd, PathBeneath, Ruleset, RulesetAttr, RulesetCreatedAttr, RulesetError, ABI, }; fn multi_thread_sandbox() -> Result<(), RulesetError> { let abi = ABI::V1; let ruleset = Ruleset::default() .handle_access(AccessFs::Execute)? .create()? // create ruleset .add_rule(PathBeneath::new(PathFd::new("/usr")?, AccessFs::Execute))?; // add rule // Clone before restrict_self so each thread can call it independently. let ruleset2 = ruleset.try_clone().expect("clone failed"); // clone ruleset std::thread::spawn(move || { ruleset2.restrict_self().expect("restrict failed in thread"); // apply sandbox in thread }).join().unwrap(); ruleset.restrict_self()?; // apply sandbox in main thread Ok(()) } ``` -------------------------------- ### Restrict IPC with Scope Rules in Rust Source: https://context7.com/landlock-lsm/rust-landlock/llms.txt The `Scope` enum restricts inter-process communication, such as abstract UNIX sockets and signals. `Scope::AbstractUnixSocket` prevents connections to external abstract UNIX sockets, and `Scope::Signal` prevents sending signals outside the sandbox. This requires Linux 6.12+ (ABI::V6). A ruleset can be scope-only, without requiring filesystem rules. ```rust use landlock::{ Access, AccessFs, Ruleset, RulesetAttr, RulesetCreatedAttr, RulesetError, Scope, ABI, }; fn isolated_sandbox() -> Result<(), RulesetError> { let status = Ruleset::default() .handle_access(AccessFs::from_all(ABI::V6))? // Scope-only ruleset is valid (no filesystem rules required) .scope(Scope::AbstractUnixSocket | Scope::Signal)? .create()? .restrict_self()?; println!("{:?}", status.ruleset); Ok(()) } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.