@@ -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