From 6244df9de1b1c53c70558fcaed4e660bc063c7ff Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Mon, 28 Nov 2022 11:22:14 +0100 Subject: [PATCH] Fix possible fd leak in new_socket on Apple --- src/sys/unix/net.rs | 50 +++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/src/sys/unix/net.rs b/src/sys/unix/net.rs index 78f1387b..4454c703 100644 --- a/src/sys/unix/net.rs +++ b/src/sys/unix/net.rs @@ -24,39 +24,35 @@ pub(crate) fn new_socket(domain: libc::c_int, socket_type: libc::c_int) -> io::R ))] let socket_type = socket_type | libc::SOCK_NONBLOCK | libc::SOCK_CLOEXEC; - // Gives a warning for platforms without SOCK_NONBLOCK. - #[allow(clippy::let_and_return)] - let socket = syscall!(socket(domain, socket_type, 0)); + let socket = syscall!(socket(domain, socket_type, 0))?; // Mimick `libstd` and set `SO_NOSIGPIPE` on apple systems. #[cfg(target_vendor = "apple")] - let socket = socket.and_then(|socket| { - syscall!(setsockopt( - socket, - libc::SOL_SOCKET, - libc::SO_NOSIGPIPE, - &1 as *const libc::c_int as *const libc::c_void, - size_of::() as libc::socklen_t - )) - .map(|_| socket) - }); + if let Err(err) = syscall!(setsockopt( + socket, + libc::SOL_SOCKET, + libc::SO_NOSIGPIPE, + &1 as *const libc::c_int as *const libc::c_void, + size_of::() as libc::socklen_t + )) { + let _ = syscall!(close(socket)); + return Err(err); + } // Darwin doesn't have SOCK_NONBLOCK or SOCK_CLOEXEC. - #[cfg(any(target_os = "ios", target_os = "macos"))] - let socket = socket.and_then(|socket| { - // For platforms that don't support flags in socket, we need to - // set the flags ourselves. - syscall!(fcntl(socket, libc::F_SETFL, libc::O_NONBLOCK)) - .and_then(|_| syscall!(fcntl(socket, libc::F_SETFD, libc::FD_CLOEXEC)).map(|_| socket)) - .map_err(|e| { - // If either of the `fcntl` calls failed, ensure the socket is - // closed and return the error. - let _ = syscall!(close(socket)); - e - }) - }); + #[cfg(target_vendor = "apple")] + { + if let Err(err) = syscall!(fcntl(socket, libc::F_SETFL, libc::O_NONBLOCK)) { + let _ = syscall!(close(socket)); + return Err(err); + } + if let Err(err) = syscall!(fcntl(socket, libc::F_SETFD, libc::FD_CLOEXEC)) { + let _ = syscall!(close(socket)); + return Err(err); + } + } - socket + Ok(socket) } /// A type with the same memory layout as `libc::sockaddr`. Used in converting Rust level