diff --git a/Cargo.toml b/Cargo.toml index f5124b9..ceb4fdd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,11 +2,17 @@ name = "yoke" version = "0.1.0" authors = [ "atagen" ] -description = "A simple sandboxing tool, similar to bwrap" +description = "CLI sandboxing tool similar to landrun or bwrap" repository = "https://git.atagen.co/atagen/yoke" license = "GPL-3.0-or-later" edition = "2024" +[features] +default = [] +ldd = ["dep:elb-dl"] +which = ["dep:which"] + + [profile.release] strip = true opt-level = "s" @@ -14,7 +20,7 @@ codegen-units = 1 [dependencies] anyhow = "1.0.100" -elb-dl = { version = "0.3.2", features = ["glibc"], default-features = false } -exec = "0.3.1" landlock = "0.4.3" -which = "8.0.0" +exec = "0.3.1" +elb-dl = { version = "0.3.2", features = ["glibc"], default-features = false, optional = true } +which = { version = "8.0.0", optional = true } diff --git a/src/main.rs b/src/main.rs index f003e6c..b37cd4b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,25 +1,28 @@ mod parse; mod types; -use std::{collections::VecDeque, path::PathBuf, str::FromStr}; use anyhow::{Context, Result, anyhow}; -use elb_dl::{DependencyTree, DynamicLoader, glibc}; use landlock::{ ABI, Access, AccessFs, AccessNet, BitFlags, Compatible, NetPort, Ruleset, RulesetAttr, RulesetCreatedAttr, Scope, make_bitflags, path_beneath_rules, }; +#[cfg(feature = "ldd")] +use elb_dl::{DependencyTree, DynamicLoader, glibc}; +#[cfg(feature = "ldd")] +use std::{collections::VecDeque, path::PathBuf, str::FromStr}; + fn main() -> Result<()> { let opts = parse::parse_args()?; if opts.exec.is_empty() { // print help eprintln!( " -yoke -- simple command sandboxer +yoke -- simple sandboxer use: yoke [ruletype] [space separated rules] -- [command] -rule types +rules ------------ filesystem: --fs | -f [access]=/path:/another/path @@ -39,7 +42,8 @@ rule types allow sending signals to other processes: --signals | -k - resolve process dependencies and add to sandbox: + resolve process dependencies and add to sandbox + (with `ldd` feature): --ldd | -l unsandbox: @@ -47,7 +51,7 @@ rule types --no-tcp | -nt -specifiers +access specifiers ------------ fs: r - read @@ -165,7 +169,11 @@ examples } // locate our executable + #[cfg(feature = "which")] let fullpath = which::which(&opts.exec[0]).context("finding executable")?; + #[cfg(not(feature = "which"))] + let fullpath = &opts.exec[0]; + // add executeable as read+execute if !opts.unsandbox.fs { ruleset = ruleset.add_rules(path_beneath_rules( @@ -175,6 +183,7 @@ examples } // if requested, trace dependencies and add as read+execute + #[cfg(feature = "ldd")] if opts.ldd { let loader = DynamicLoader::options() .search_dirs(glibc::get_hard_coded_search_dirs(None)?) diff --git a/src/parse.rs b/src/parse.rs index a369689..0ce3731 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -1,5 +1,5 @@ use crate::types::{Direction, Permissions, Yoke}; -use anyhow::{anyhow, Context, Result}; +use anyhow::{Context, Result, anyhow}; use std::{collections::HashMap, path::PathBuf, str::FromStr}; #[derive(PartialEq)] @@ -145,12 +145,15 @@ pub fn parse_args() -> Result { cur_arg = Unset; yoke.retain_env = true; } + + #[cfg(feature = "ldd")] "--ldd" | "-l" => { collect_args(&mut yoke, &collector, &cur_arg)?; collector.clear(); cur_arg = Unset; yoke.ldd = true; } + "--no-fs" | "-nf" => { collect_args(&mut yoke, &collector, &cur_arg)?; collector.clear();