Skip to content

Have rustix automatically set CLOEXEC? #495

Closed
@sunfishcode

Description

@sunfishcode

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions