From f7312dafdbe311a34e31da62bc80144087e3fd17 Mon Sep 17 00:00:00 2001 From: viyatb-oai Date: Thu, 9 Apr 2026 18:19:40 -0700 Subject: [PATCH] fix: handle missing proc fd table before sandbox exec Co-authored-by: Codex --- codex-rs/linux-sandbox/src/fd_cleanup.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/codex-rs/linux-sandbox/src/fd_cleanup.rs b/codex-rs/linux-sandbox/src/fd_cleanup.rs index ca916e0b17..375e77884c 100644 --- a/codex-rs/linux-sandbox/src/fd_cleanup.rs +++ b/codex-rs/linux-sandbox/src/fd_cleanup.rs @@ -1,5 +1,7 @@ //! File descriptor hygiene before entering the sandboxed command. +use std::io::ErrorKind; + /// Close helper-inherited descriptors unless they are standard input/output/error /// or already close-on-exec. /// @@ -8,6 +10,10 @@ pub(crate) fn close_inherited_exec_fds() { let fds = match non_stdio_fds_from_proc() { Ok(fds) => fds, + Err(err) if err.kind() == ErrorKind::NotFound => { + mark_inherited_exec_fds_cloexec(); + return; + } Err(err) => panic!("failed to enumerate inherited file descriptors: {err}"), }; for fd in fds { @@ -15,6 +21,21 @@ pub(crate) fn close_inherited_exec_fds() { } } +fn mark_inherited_exec_fds_cloexec() { + let result = unsafe { + libc::syscall( + libc::SYS_close_range, + (libc::STDERR_FILENO + 1) as libc::c_uint, + u32::MAX as libc::c_uint, + libc::CLOSE_RANGE_CLOEXEC, + ) + }; + if result != 0 { + let err = std::io::Error::last_os_error(); + panic!("failed to mark inherited file descriptors close-on-exec: {err}"); + } +} + fn non_stdio_fds_from_proc() -> std::io::Result> { let mut fds = Vec::new(); for entry in std::fs::read_dir("/proc/self/fd")? {