From af95776d9035483ff3f261a9cc3538fcaf7f1709 Mon Sep 17 00:00:00 2001 From: latenighthackathon Date: Sun, 29 Mar 2026 22:42:25 -0500 Subject: [PATCH] fix(sandbox): skip non-existent paths instead of abandoning Landlock ruleset When a single path in the filesystem policy did not exist, PathFd::new() failed and the error propagated via ? to abandon the entire Landlock ruleset. Under the default best_effort compatibility mode, this silently disabled all filesystem restrictions for the sandbox. Replace the ? operator with per-path match statements that warn and skip individual non-existent paths while continuing to build the ruleset from remaining valid paths. This preserves filesystem isolation even when optional paths like /app are missing from the container image. Closes #664 Signed-off-by: latenighthackathon --- .../src/sandbox/linux/landlock.rs | 54 ++++++++++++++----- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/crates/openshell-sandbox/src/sandbox/linux/landlock.rs b/crates/openshell-sandbox/src/sandbox/linux/landlock.rs index e276840d..a5d0e417 100644 --- a/crates/openshell-sandbox/src/sandbox/linux/landlock.rs +++ b/crates/openshell-sandbox/src/sandbox/linux/landlock.rs @@ -51,23 +51,49 @@ pub fn apply(policy: &SandboxPolicy, workdir: Option<&str>) -> Result<()> { let mut ruleset = ruleset.create().into_diagnostic()?; for path in read_only { - debug!(path = %path.display(), "Landlock allow read-only"); - ruleset = ruleset - .add_rule(PathBeneath::new( - PathFd::new(path).into_diagnostic()?, - access_read, - )) - .into_diagnostic()?; + match PathFd::new(&path) { + Ok(path_fd) => { + debug!( + path = %path.display(), + "Landlock allow read-only" + ); + ruleset = ruleset + .add_rule(PathBeneath::new( + path_fd, access_read, + )) + .into_diagnostic()?; + } + Err(err) => { + warn!( + path = %path.display(), + error = %err, + "Skipping non-existent read-only path" + ); + } + } } for path in read_write { - debug!(path = %path.display(), "Landlock allow read-write"); - ruleset = ruleset - .add_rule(PathBeneath::new( - PathFd::new(path).into_diagnostic()?, - access_all, - )) - .into_diagnostic()?; + match PathFd::new(&path) { + Ok(path_fd) => { + debug!( + path = %path.display(), + "Landlock allow read-write" + ); + ruleset = ruleset + .add_rule(PathBeneath::new( + path_fd, access_all, + )) + .into_diagnostic()?; + } + Err(err) => { + warn!( + path = %path.display(), + error = %err, + "Skipping non-existent read-write path" + ); + } + } } ruleset.restrict_self().into_diagnostic()?;