Description
CLOEXEC
is a per-fd flag that tells the OS to automatically close the fd at an execve
-family call. This prevents fds from being implicitly leaked into child processes, which can otherwise cause surprising and even security-relevant bugs. I am considering changing rustix's stance to set CLOEXEC
on fds it creates in safe APIs, and more broadly, proposing CLOEXEC
to be considered a requirement for safety in Rust in general.
On some OS's, it's not always possible to set CLOEXEC
atomically. As std does, we'd set it as soon as possible, and explain the gap by saying that those OS's behave as if execve
sometimes has the side effect of attaching a debugger which executes some commands outside of Rust's semantics. That's not pretty, but ultimately it's a reflection of the underlying platform, so I think it's an acceptable tradeoff.
Rust's std already sets CLOEXEC
on fds it creates, so this change wouldn't imply that any code in std needs to change. But I will submit a PR documenting this as an I/O safety guarantee in the std documentation (including a mention of the non-atomic situation).
If that PR is accepted, then I'd expect to make the following changes in rustix: openat
and others would implicitly add the O_CLOEXEC
flag, and OFlags::CLOEXEC
would no longer exist. On OS's that need it, rustix would implicitly do additional system calls to set CLOEXEC
in fds that can't have it set atomically. fcntl_setfd
, dup
etc. would become unsafe. fcntl_dupfd_cloexec
would be renamed to fcntl_dupfd
. And execveat
would be made a public function in the process
module (still unsafe, but only because of the char*'s). This will all require a semver bump.
I won't be able to do the actual work for this for a while, but I wanted to file this now in case anyone here has any feedback.