From 44d7a88a83539d03194a682ec3b8cc8609c9e2f1 Mon Sep 17 00:00:00 2001 From: Adel Zaalouk Date: Wed, 8 Jul 2026 15:27:55 +0200 Subject: [PATCH 1/2] fix(sandbox): undo tmpfs overlay when setns fails during SPIFFE mount namespace setup On OpenShift and other container runtimes that do not grant CAP_SYS_ADMIN, setns(CLONE_NEWNS) fails with EPERM after create_supervisor_identity_mount_namespace has already mounted an empty tmpfs over the SPIFFE workload API socket directory. PID 1 remains stuck in the new mount namespace where the tmpfs hides the socket, making it invisible to all processes. Fix: when setns() fails, call umount2(MNT_DETACH) to remove the tmpfs overlay before returning the error, so the SPIFFE socket stays accessible even without namespace isolation. Signed-off-by: Adel Zaalouk --- .../src/process.rs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/crates/openshell-supervisor-process/src/process.rs b/crates/openshell-supervisor-process/src/process.rs index 322dcadd86..97c7e2a4cc 100644 --- a/crates/openshell-supervisor-process/src/process.rs +++ b/crates/openshell-supervisor-process/src/process.rs @@ -381,16 +381,24 @@ fn create_supervisor_identity_mount_namespace(target: &Path) -> Result .map_err(|err| miette::miette!("failed to open sanitized mount namespace: {err}")) })(); - set_mount_namespace(original_ns.as_raw_fd()).map_err(|restore_err| { + if let Err(restore_err) = set_mount_namespace(original_ns.as_raw_fd()) { + // Cannot restore the original mount namespace. Undo the tmpfs + // overlay so the SPIFFE workload API socket stays reachable in the + // namespace PID 1 is stuck in. + #[allow(unsafe_code)] + unsafe { + libc::umount2(target.as_ptr(), libc::MNT_DETACH); + } let result_msg = result.as_ref().err().map_or_else( || "sanitized namespace was created".to_string(), ToString::to_string, ); - miette::miette!( + return Err(miette::miette!( "failed to restore original mount namespace after supervisor identity isolation setup: \ - {restore_err}; setup result: {result_msg}" - ) - })?; + {restore_err}; undid tmpfs overlay so SPIFFE socket remains accessible; \ + setup result: {result_msg}" + )); + } result } From 33947c3502cbeae886e1577027a0a4c1cbed05d0 Mon Sep 17 00:00:00 2001 From: Adel Zaalouk Date: Fri, 14 Aug 2026 13:40:38 +0200 Subject: [PATCH 2/2] fix(sandbox): check umount2 return value in setns error path Log a warning when the cleanup unmount fails so the outcome is diagnosable, consistent with how every other libc call in this function handles non-zero return codes. Signed-off-by: Adel Zaalouk --- crates/openshell-supervisor-process/src/process.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/crates/openshell-supervisor-process/src/process.rs b/crates/openshell-supervisor-process/src/process.rs index 97c7e2a4cc..88204100ed 100644 --- a/crates/openshell-supervisor-process/src/process.rs +++ b/crates/openshell-supervisor-process/src/process.rs @@ -386,8 +386,12 @@ fn create_supervisor_identity_mount_namespace(target: &Path) -> Result // overlay so the SPIFFE workload API socket stays reachable in the // namespace PID 1 is stuck in. #[allow(unsafe_code)] - unsafe { - libc::umount2(target.as_ptr(), libc::MNT_DETACH); + let umount_rc = unsafe { libc::umount2(target.as_ptr(), libc::MNT_DETACH) }; + if umount_rc != 0 { + tracing::warn!( + errno = ?std::io::Error::last_os_error(), + "umount2 cleanup failed after setns error; SPIFFE socket may remain hidden" + ); } let result_msg = result.as_ref().err().map_or_else( || "sanitized namespace was created".to_string(),