Revert "Don't duplicate FDs if we are reasonably certain that it isn't needed."

This reverts commit 4485c1f034.
This commit is contained in:
Mathieu Trossevin 2023-12-08 08:53:19 +01:00
parent 4485c1f034
commit da5aba2882
Signed by: mtrossevin
GPG key ID: D1DBB7EA828374E9

View file

@ -6,7 +6,7 @@ use std::os::unix::net::{UnixDatagram, UnixListener, UnixStream};
use std::{env, process};
use error::{GetFdsError, ReceiveError, ReceiveNameError};
use rustix::fd::{AsRawFd, BorrowedFd, OwnedFd, FromRawFd};
use rustix::fd::{AsRawFd, BorrowedFd, OwnedFd};
use rustix::fs::FileType;
use rustix::net::SocketType;
@ -18,6 +18,8 @@ const FD_NUMBER_VAR: &str = "LISTEN_FDS";
const FD_NAMES_VAR: &str = "LISTEN_FDNAMES";
/// File Descriptor passed by systemd.
///
/// They are duplicated from the actual passed file descriptor so as to be safe to use from rust code.
#[derive(Debug)]
pub enum FileDescriptor {
/// The file descriptor is a [`File`](std::fs::File).
@ -76,10 +78,7 @@ impl FileDescriptor {
/// Get any file descriptor passed by systemd or anything implementing the `LISTEN_FD` protocol.
///
/// This isn't necessarily limited to File descriptor of listening sockets, IPCs or FIFOs but also anything that is in the file descriptor store.
///
/// If `unset_env` is `true` then the file descriptor are directly taken as if they were owned. This is only safe if this library is the only place taking these file descriptor but avoid unnecessary duplication of file descriptors.
///
/// If `unset_env` is `false` the file descriptores are duplicated using [`fcntl_dupfd_cloexec`](rustix::fs::fcntl_dupfd_cloexec) so they can safely be used from rust and will not be propagated to children process automatically.
/// The file descriptores are duplicated using [`fcntl_dupfd_cloexec`](rustix::fs::fcntl_dupfd_cloexec) so they can safely be used from rust and will not be propagated to children process automatically.
///
/// # Errors
///
@ -114,7 +113,7 @@ impl FileDescriptor {
});
}
match Self::from_fds(fds, unset_env) {
match Self::from_fds(fds) {
Ok(fds) => Ok(fds),
Err(error) => Err(ReceiveError::GetFds(error)),
}
@ -149,28 +148,25 @@ impl FileDescriptor {
.zip(fd_names))
}
fn from_fds(num_fds: usize, unset_env: bool) -> Result<impl IntoIterator<Item = FileDescriptor>, GetFdsError> {
fn from_fds(num_fds: usize) -> Result<impl IntoIterator<Item = FileDescriptor>, GetFdsError> {
if SD_LISTEN_FDS_START.checked_add(num_fds as RawFd).is_none() {
return Err(GetFdsError::TooManyFDs(num_fds));
}
Ok((0..num_fds).map(move |fd_offset| {
Ok((0..num_fds).map(|fd_offset| {
SD_LISTEN_FDS_START
.checked_add(fd_offset as RawFd)
// SAFETY: We are receiving the fd so it should be safe
.map(|fd| FileDescriptor::from_fd(fd, unset_env))
.map(|fd| FileDescriptor::from_fd(fd, 0))
.expect("Already checked against overflow.")
}))
}
fn from_fd(fd: RawFd, unset_env: bool) -> Self {
let fd = if unset_env {
// SAFETY: The environement is removed so there shouldn't be anything new that might take it and close it.
unsafe { OwnedFd::from_raw_fd(fd) }
} else {
fn from_fd(fd: RawFd, min_new: RawFd) -> Self {
let fd = {
// SAFETY: The file descriptor won't be closed by the time we duplicate it.
let fd = unsafe { BorrowedFd::borrow_raw(fd) };
rustix::fs::fcntl_dupfd_cloexec(fd, 0)
rustix::fs::fcntl_dupfd_cloexec(fd, min_new)
.expect("Couldn't duplicate the file descriptor")
};
let stat = rustix::fs::fstat(&fd)