Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 7 additions & 0 deletions architecture/security-policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ For the field-by-field YAML reference, use
Filesystem and process policy are startup-time controls. Network policy is
dynamic and can be hot-reloaded when the new policy validates successfully.

Before applying Landlock, the supervisor enriches baseline filesystem paths that
the runtime needs. Missing baseline paths are skipped so one absent runtime path
does not weaken the whole ruleset. When GPU devices are present, GPU baseline
enrichment adds existing GPU device nodes as read-write paths and promotes
`/proc` to read-write because CUDA workloads write thread metadata under
`/proc/<pid>/task/<tid>/comm`.

## Network Decisions

Ordinary network traffic follows this order:
Expand Down
24 changes: 22 additions & 2 deletions crates/openshell-sandbox/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1556,7 +1556,7 @@ where
}
}
for path in rw {
if fs.read_only.iter().any(|p| p == path) || fs.read_write.iter().any(|p| p == path) {
if fs.read_write.iter().any(|p| p == path) {
continue;
}
if !path_exists(path) {
Expand All @@ -1566,6 +1566,18 @@ where
);
continue;
}
if fs.read_only.iter().any(|p| p == path) {
if path == "/proc" {
info!(
path,
"Promoting /proc from read-only to read-write for GPU runtime compatibility"
);
fs.read_only.retain(|p| p != path);
fs.read_write.push(path.clone());
modified = true;
}
continue;
}
fs.read_write.push(path.clone());
modified = true;
}
Expand Down Expand Up @@ -1769,7 +1781,7 @@ mod baseline_tests {
}

#[test]
fn proto_gpu_enrichment_adds_devices_without_network_policy() {
fn proto_gpu_enrichment_promotes_proc_without_network_policy() {
let mut policy = openshell_policy::restrictive_default_policy();
assert!(
policy.network_policies.is_empty(),
Expand All @@ -1791,6 +1803,14 @@ mod baseline_tests {
filesystem.read_write.contains(&"/dev/nvidia0".to_string()),
"GPU enrichment should add enumerated device nodes without network policies"
);
assert!(
!filesystem.read_only.contains(&"/proc".to_string()),
"GPU enrichment should remove /proc from read_only"
);
assert!(
filesystem.read_write.contains(&"/proc".to_string()),
"GPU enrichment should promote /proc to read_write"
);
}

#[test]
Expand Down
2 changes: 2 additions & 0 deletions docs/sandboxes/policies.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ Raw streams are connection-scoped and outside L7 live-reload guarantees. This in

When a sandbox runs in proxy mode (the default), OpenShell automatically adds baseline filesystem paths required for the sandbox child process to function: `/usr`, `/lib`, `/etc`, `/var/log` (read-only) and `/sandbox`, `/tmp` (read-write). Paths like `/app` are included in the baseline set but are only added if they exist in the container image.

For GPU sandboxes, OpenShell also adds existing GPU device nodes as read-write paths. CUDA workloads require write access to procfs for thread metadata, so GPU baseline enrichment moves `/proc` from read-only to read-write when GPU devices are present.

This filtering prevents a missing baseline path from degrading Landlock enforcement. Without it, a single missing path could cause the entire Landlock ruleset to fail, leaving the sandbox with no filesystem restrictions at all.

User-specified paths in your policy YAML are not pre-filtered. If you list a path that does not exist:
Expand Down
Loading