Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c4d071d
core: introduce Protection enum with per-variant ABI floor
dzerik May 25, 2026
047c14f
core: add ProtectionState and ProtectionPolicy with Strict default
dzerik May 25, 2026
f0b8b9e
core: add Sandbox::protection_policy field defaulting to strict-all
dzerik May 25, 2026
1c6067b
core: add ConfinementError::ProtectionUnavailable variant
dzerik May 25, 2026
6d6c38d
core: per-protection availability resolution in confine_inner
dzerik May 25, 2026
014746e
core: mask Degraded fs protections; consolidate net_wildcard computation
dzerik May 25, 2026
85bbc5d
cli: extend 'sandlock check' with per-protection availability report
dzerik May 25, 2026
ce11c8f
core: add Sandbox::active_protections() runtime accessor
dzerik May 25, 2026
93a398a
core: SandboxBuilder::allow_degraded and ::disable polarity-out methods
dzerik May 26, 2026
75b3693
ffi: C ABI for Protection + allow_degraded / disable builders
dzerik May 26, 2026
b9a69a4
python: Sandbox allow_degraded / disable kwargs + Protection IntEnum
dzerik May 26, 2026
5540dd2
cli: --allow-degraded and --disable flags for sandlock run
dzerik May 26, 2026
40ff410
docs: document Protection opt-out (allow_degraded / disable)
dzerik May 26, 2026
28b350d
ffi: validate Protection discriminant at the C ABI boundary
dzerik May 27, 2026
432ce90
protection: rename AbstractUnixScope to AbstractUnixSocketScope
dzerik May 27, 2026
558f354
core: test compute_*_mask security contract; document scope-mask prec…
dzerik May 27, 2026
8389ebe
ci: add ubuntu-22.04 to the Rust matrix and log host Landlock ABI
dzerik May 27, 2026
cd733b5
ffi: regenerate sandlock.h with Protection symbols via cbindgen
dzerik Jun 2, 2026
ac9036b
core: consolidate Resolved into ProtectionStatus (single resolver)
dzerik Jun 2, 2026
d152795
core: serialize protection_policy so checkpoints preserve opt-out
dzerik Jun 2, 2026
f47cea1
cli: canonical protection name, drop never-shipped alias
dzerik Jun 2, 2026
14e7774
docs: move Protection reference to sandbox-reference.md / python/READ…
dzerik Jun 2, 2026
ebc6c79
ci: revert matrix changes (deferred to separate PR)
dzerik Jun 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ Sandlock is implemented in **Rust** for performance and safety:
| Landlock TCP port rules | 6.7 (ABI v4) |
| Landlock IPC scoping | 6.12 (ABI v6) |

Protections can be selectively waived per-policy when needed — see
[`docs/sandbox-reference.md#protection-opt-out`](docs/sandbox-reference.md#protection-opt-out).

## Install

### From source
Expand Down
50 changes: 50 additions & 0 deletions crates/sandlock-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,44 @@ struct RunArgs {
#[arg(long)]
no_supervisor: bool,

/// Allow the named protection to degrade silently if the host kernel ABI lacks support.
/// Repeatable. Accepted values: fs-refer, fs-truncate, net-tcp, fs-ioctl-dev,
/// signal-scope, abstract-unix-socket-scope.
#[arg(long = "allow-degraded", value_name = "PROTECTION")]
allow_degraded: Vec<String>,

/// Disable the named protection entirely (no rule emitted, no error on missing ABI).
/// Repeatable. Accepts the same values as --allow-degraded.
#[arg(long = "disable", value_name = "PROTECTION")]
disable: Vec<String>,

#[arg(last = true)]
cmd: Vec<String>,
}

/// Parse a kebab-case protection name into a `Protection` value.
///
/// The canonical names match the Landlock kernel constants
/// (`LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET` → `abstract-unix-socket-scope`,
/// etc.) and are case-insensitive. Accepted: `fs-refer`, `fs-truncate`,
/// `net-tcp`, `fs-ioctl-dev`, `signal-scope`,
/// `abstract-unix-socket-scope`.
fn parse_protection(s: &str) -> Result<sandlock_core::Protection, String> {
use sandlock_core::Protection;
match s.to_ascii_lowercase().as_str() {
"fs-refer" => Ok(Protection::FsRefer),
"fs-truncate" => Ok(Protection::FsTruncate),
"net-tcp" => Ok(Protection::NetTcp),
"fs-ioctl-dev" => Ok(Protection::FsIoctlDev),
"signal-scope" => Ok(Protection::SignalScope),
"abstract-unix-socket-scope" => Ok(Protection::AbstractUnixSocketScope),
other => Err(format!(
"unknown protection: {} (valid: fs-refer, fs-truncate, net-tcp, fs-ioctl-dev, signal-scope, abstract-unix-socket-scope)",
other,
)),
}
}

#[derive(Subcommand)]
enum ProfileAction {
/// List available profiles
Expand Down Expand Up @@ -221,6 +255,14 @@ async fn main() -> Result<()> {
println!(" Device ioctl: {}", if v >= 5 { "supported (ABI v5+)" } else { "not supported" });
println!(" IPC scoping: {}", if v >= 6 { "supported (ABI v6+)" } else { "not supported" });
println!(" Signal scoping: {}", if v >= 6 { "supported (ABI v6+)" } else { "not supported" });

println!();
println!("Per-protection availability (host Landlock ABI v{}):", v);
for p in sandlock_core::Protection::all() {
let available = v >= p.min_abi();
let marker = if available { "available" } else { "unavailable" };
println!(" {:<22} requires v{} — {}", format!("{:?}", p), p.min_abi(), marker);
}
}
Err(e) => {
println!(" Landlock: unavailable ({})", e);
Expand Down Expand Up @@ -475,6 +517,14 @@ async fn run_command(args: RunArgs) -> Result<i32> {
builder = builder.no_supervisor(true);
}

// CLI overrides — protection policy
for s in &args.allow_degraded {
builder = builder.allow_degraded(parse_protection(s).map_err(|e| anyhow!(e))?);
}
for s in &args.disable {
builder = builder.disable(parse_protection(s).map_err(|e| anyhow!(e))?);
}

let policy = builder.build()?;
let cmd_strs: Vec<&str> = if let Some(ref shell_cmd) = args.exec_shell {
vec!["/bin/sh", "-c", shell_cmd.as_str()]
Expand Down
13 changes: 13 additions & 0 deletions crates/sandlock-core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,19 @@ pub enum ConfinementError {
feature: String,
},

/// A `Protection` in `ProtectionState::Strict` is unavailable
/// because the host kernel's Landlock ABI is below the
/// protection's `min_abi()`. Build (or `confine`) refuses to
/// proceed; the caller can resolve by setting that protection to
/// `Degradable` or `Disabled`, or by running on a kernel that
/// supports it.
#[error("required protection {protection:?} is not available: host Landlock ABI is v{host_abi}, requires v{required_abi}")]
ProtectionUnavailable {
protection: crate::protection::Protection,
required_abi: u32,
host_abi: u32,
},

#[error("landlock error: {0}")]
Landlock(String),

Expand Down
Loading
Loading