@@ -3270,9 +3270,25 @@ network_policies:
32703270 ) ;
32713271 }
32723272
3273+ /// Check if `/proc/<pid>/root/` is accessible for the current process.
3274+ /// In CI containers or restricted environments, this path may not be
3275+ /// readable even for the process's own PID. Tests that depend on
3276+ /// procfs root access should skip gracefully when this returns false.
3277+ #[ cfg( target_os = "linux" ) ]
3278+ fn procfs_root_accessible ( ) -> bool {
3279+ let pid = std:: process:: id ( ) ;
3280+ let probe = format ! ( "/proc/{pid}/root/tmp" ) ;
3281+ std:: fs:: symlink_metadata ( & probe) . is_ok ( )
3282+ }
3283+
32733284 #[ cfg( target_os = "linux" ) ]
32743285 #[ test]
32753286 fn resolve_binary_with_real_symlink ( ) {
3287+ if !procfs_root_accessible ( ) {
3288+ eprintln ! ( "Skipping: /proc/<pid>/root/ not accessible in this environment" ) ;
3289+ return ;
3290+ }
3291+
32763292 // Create a real symlink in a temp directory and verify resolution
32773293 // works through /proc/self/root (which maps to / on the host)
32783294 use std:: os:: unix:: fs:: symlink;
@@ -3304,6 +3320,11 @@ network_policies:
33043320 #[ cfg( target_os = "linux" ) ]
33053321 #[ test]
33063322 fn resolve_binary_non_symlink_returns_none ( ) {
3323+ if !procfs_root_accessible ( ) {
3324+ eprintln ! ( "Skipping: /proc/<pid>/root/ not accessible in this environment" ) ;
3325+ return ;
3326+ }
3327+
33073328 // A regular file should return None (no expansion needed)
33083329 use std:: io:: Write ;
33093330 let mut tmp = tempfile:: NamedTempFile :: new ( ) . unwrap ( ) ;
@@ -3323,6 +3344,11 @@ network_policies:
33233344 #[ cfg( target_os = "linux" ) ]
33243345 #[ test]
33253346 fn resolve_binary_multi_level_symlink ( ) {
3347+ if !procfs_root_accessible ( ) {
3348+ eprintln ! ( "Skipping: /proc/<pid>/root/ not accessible in this environment" ) ;
3349+ return ;
3350+ }
3351+
33263352 // Test multi-level symlink resolution: python3 -> python3.11 -> cpython3.11
33273353 use std:: os:: unix:: fs:: symlink;
33283354 let dir = tempfile:: tempdir ( ) . unwrap ( ) ;
@@ -3349,6 +3375,11 @@ network_policies:
33493375 #[ cfg( target_os = "linux" ) ]
33503376 #[ test]
33513377 fn from_proto_with_pid_expands_symlinks_in_container ( ) {
3378+ if !procfs_root_accessible ( ) {
3379+ eprintln ! ( "Skipping: /proc/<pid>/root/ not accessible in this environment" ) ;
3380+ return ;
3381+ }
3382+
33523383 // End-to-end test: create a symlink, build engine with our PID,
33533384 // verify the resolved path is allowed
33543385 use std:: os:: unix:: fs:: symlink;
@@ -3420,6 +3451,11 @@ network_policies:
34203451 #[ cfg( target_os = "linux" ) ]
34213452 #[ test]
34223453 fn reload_from_proto_with_pid_resolves_symlinks ( ) {
3454+ if !procfs_root_accessible ( ) {
3455+ eprintln ! ( "Skipping: /proc/<pid>/root/ not accessible in this environment" ) ;
3456+ return ;
3457+ }
3458+
34233459 // Test hot-reload path: initial engine at pid=0, then reload with
34243460 // real PID to trigger symlink resolution
34253461 use std:: os:: unix:: fs:: symlink;
0 commit comments