Skip to content

Commit b6e4cf6

Browse files
committed
refactor(sandbox): deduplicate baseline path enrichment logic
Extract shared helpers for the two enrich_*_baseline_paths functions: - baseline_paths() collects all proxy + GPU paths in one place - missing_baseline_paths() filters to existing, not-yet-present paths This removes the duplicated "check exists, skip if missing, push" pattern that was repeated four times in each enrichment function.
1 parent e1fb27d commit b6e4cf6

File tree

1 file changed

+82
-135
lines changed
  • crates/openshell-sandbox/src

1 file changed

+82
-135
lines changed

crates/openshell-sandbox/src/lib.rs

Lines changed: 82 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -968,6 +968,55 @@ fn gpu_baseline_read_write_paths() -> Vec<std::path::PathBuf> {
968968
paths
969969
}
970970

971+
/// Filter baseline paths to those that exist on disk and are not already
972+
/// present in `existing`.
973+
///
974+
/// Baseline paths are system-injected, not user-specified. Skip paths that
975+
/// do not exist in this container image to avoid noisy warnings from Landlock
976+
/// and, more critically, to prevent a single missing baseline path from
977+
/// abandoning the entire Landlock ruleset under best-effort mode (see
978+
/// issue #664).
979+
fn missing_baseline_paths(
980+
candidates: &[std::path::PathBuf],
981+
existing: &[impl AsRef<std::path::Path>],
982+
) -> Vec<std::path::PathBuf> {
983+
candidates
984+
.iter()
985+
.filter(|p| {
986+
if existing.iter().any(|e| e.as_ref() == p.as_path()) {
987+
return false;
988+
}
989+
if !p.exists() {
990+
debug!(path = %p.display(), "Baseline path does not exist, skipping enrichment");
991+
return false;
992+
}
993+
true
994+
})
995+
.cloned()
996+
.collect()
997+
}
998+
999+
/// All baseline paths that should be added for a proxy-mode sandbox,
1000+
/// split into (read_only, read_write). Includes GPU paths when GPU
1001+
/// devices are detected.
1002+
fn baseline_paths() -> (Vec<std::path::PathBuf>, Vec<std::path::PathBuf>) {
1003+
let mut ro: Vec<std::path::PathBuf> = PROXY_BASELINE_READ_ONLY
1004+
.iter()
1005+
.map(|&p| p.into())
1006+
.collect();
1007+
let mut rw: Vec<std::path::PathBuf> = PROXY_BASELINE_READ_WRITE
1008+
.iter()
1009+
.map(|&p| p.into())
1010+
.collect();
1011+
1012+
if has_gpu_devices() {
1013+
ro.extend(gpu_baseline_read_only_paths());
1014+
rw.extend(gpu_baseline_read_write_paths());
1015+
}
1016+
1017+
(ro, rw)
1018+
}
1019+
9711020
/// Ensure a proto `SandboxPolicy` includes the baseline filesystem paths
9721021
/// required for proxy-mode sandboxes. Paths are only added if missing;
9731022
/// user-specified paths are never removed.
@@ -986,84 +1035,30 @@ fn enrich_proto_baseline_paths(proto: &mut openshell_core::proto::SandboxPolicy)
9861035
..Default::default()
9871036
});
9881037

989-
let mut modified = false;
990-
for &path in PROXY_BASELINE_READ_ONLY {
991-
if !fs.read_only.iter().any(|p| p.as_str() == path) {
992-
// Baseline paths are system-injected, not user-specified. Skip
993-
// paths that do not exist in this container image to avoid noisy
994-
// warnings from Landlock and, more critically, to prevent a single
995-
// missing baseline path from abandoning the entire Landlock
996-
// ruleset under best-effort mode (see issue #664).
997-
if !std::path::Path::new(path).exists() {
998-
debug!(
999-
path,
1000-
"Baseline read-only path does not exist, skipping enrichment"
1001-
);
1002-
continue;
1003-
}
1004-
fs.read_only.push(path.to_string());
1005-
modified = true;
1006-
}
1007-
}
1008-
for &path in PROXY_BASELINE_READ_WRITE {
1009-
if !fs.read_write.iter().any(|p| p.as_str() == path) {
1010-
if !std::path::Path::new(path).exists() {
1011-
debug!(
1012-
path,
1013-
"Baseline read-write path does not exist, skipping enrichment"
1014-
);
1015-
continue;
1016-
}
1017-
fs.read_write.push(path.to_string());
1018-
modified = true;
1019-
}
1020-
}
1038+
let (ro, rw) = baseline_paths();
10211039

1022-
if has_gpu_devices() {
1023-
for path in gpu_baseline_read_only_paths() {
1024-
let path_str = path.to_string_lossy();
1025-
if !fs.read_only.iter().any(|p| p.as_str() == path_str.as_ref())
1026-
&& !fs
1027-
.read_write
1028-
.iter()
1029-
.any(|p| p.as_str() == path_str.as_ref())
1030-
{
1031-
if !path.exists() {
1032-
debug!(
1033-
path = %path.display(),
1034-
"GPU baseline read-only path does not exist, skipping enrichment"
1035-
);
1036-
continue;
1037-
}
1038-
fs.read_only.push(path_str.into_owned());
1039-
modified = true;
1040-
}
1041-
}
1042-
for path in gpu_baseline_read_write_paths() {
1043-
let path_str = path.to_string_lossy();
1044-
if !fs
1045-
.read_write
1046-
.iter()
1047-
.any(|p| p.as_str() == path_str.as_ref())
1048-
{
1049-
if !path.exists() {
1050-
debug!(
1051-
path = %path.display(),
1052-
"GPU baseline read-write path does not exist, skipping enrichment"
1053-
);
1054-
continue;
1055-
}
1056-
fs.read_write.push(path_str.into_owned());
1057-
modified = true;
1058-
}
1059-
}
1040+
// For read-only, skip paths already in either list (read_write subsumes read_only).
1041+
let both: Vec<&str> = fs
1042+
.read_only
1043+
.iter()
1044+
.chain(&fs.read_write)
1045+
.map(String::as_str)
1046+
.collect();
1047+
let ro_add = missing_baseline_paths(&ro, &both);
1048+
let rw_add = missing_baseline_paths(&rw, &fs.read_write);
1049+
1050+
let added = ro_add.len() + rw_add.len();
1051+
for p in ro_add {
1052+
fs.read_only.push(p.to_string_lossy().into_owned());
1053+
}
1054+
for p in rw_add {
1055+
fs.read_write.push(p.to_string_lossy().into_owned());
10601056
}
10611057

1062-
if modified {
1058+
if added > 0 {
10631059
info!("Enriched policy with baseline filesystem paths for proxy mode");
10641060
}
1065-
1066-
modified
1061+
added > 0
10671062
}
10681063

10691064
/// Ensure a `SandboxPolicy` (Rust type) includes the baseline filesystem
@@ -1074,70 +1069,22 @@ fn enrich_sandbox_baseline_paths(policy: &mut SandboxPolicy) {
10741069
return;
10751070
}
10761071

1077-
let mut modified = false;
1078-
for &path in PROXY_BASELINE_READ_ONLY {
1079-
let p = std::path::PathBuf::from(path);
1080-
if !policy.filesystem.read_only.contains(&p) {
1081-
// Baseline paths are system-injected — skip non-existent paths to
1082-
// avoid Landlock ruleset abandonment (issue #664).
1083-
if !p.exists() {
1084-
debug!(
1085-
path,
1086-
"Baseline read-only path does not exist, skipping enrichment"
1087-
);
1088-
continue;
1089-
}
1090-
policy.filesystem.read_only.push(p);
1091-
modified = true;
1092-
}
1093-
}
1094-
for &path in PROXY_BASELINE_READ_WRITE {
1095-
let p = std::path::PathBuf::from(path);
1096-
if !policy.filesystem.read_write.contains(&p) {
1097-
if !p.exists() {
1098-
debug!(
1099-
path,
1100-
"Baseline read-write path does not exist, skipping enrichment"
1101-
);
1102-
continue;
1103-
}
1104-
policy.filesystem.read_write.push(p);
1105-
modified = true;
1106-
}
1107-
}
1072+
let (ro, rw) = baseline_paths();
11081073

1109-
if has_gpu_devices() {
1110-
for p in gpu_baseline_read_only_paths() {
1111-
if !policy.filesystem.read_only.contains(&p)
1112-
&& !policy.filesystem.read_write.contains(&p)
1113-
{
1114-
if !p.exists() {
1115-
debug!(
1116-
path = %p.display(),
1117-
"GPU baseline read-only path does not exist, skipping enrichment"
1118-
);
1119-
continue;
1120-
}
1121-
policy.filesystem.read_only.push(p);
1122-
modified = true;
1123-
}
1124-
}
1125-
for p in gpu_baseline_read_write_paths() {
1126-
if !policy.filesystem.read_write.contains(&p) {
1127-
if !p.exists() {
1128-
debug!(
1129-
path = %p.display(),
1130-
"GPU baseline read-write path does not exist, skipping enrichment"
1131-
);
1132-
continue;
1133-
}
1134-
policy.filesystem.read_write.push(p);
1135-
modified = true;
1136-
}
1137-
}
1138-
}
1074+
let both: Vec<&std::path::PathBuf> = policy
1075+
.filesystem
1076+
.read_only
1077+
.iter()
1078+
.chain(&policy.filesystem.read_write)
1079+
.collect();
1080+
let ro_add = missing_baseline_paths(&ro, &both);
1081+
let rw_add = missing_baseline_paths(&rw, &policy.filesystem.read_write);
1082+
1083+
let added = ro_add.len() + rw_add.len();
1084+
policy.filesystem.read_only.extend(ro_add);
1085+
policy.filesystem.read_write.extend(rw_add);
11391086

1140-
if modified {
1087+
if added > 0 {
11411088
info!("Enriched policy with baseline filesystem paths for proxy mode");
11421089
}
11431090
}

0 commit comments

Comments
 (0)