From 024f89ef6aeb8d08dd5cbe5f55ca3d52bb838f7e Mon Sep 17 00:00:00 2001 From: Akira Moroo Date: Wed, 17 Apr 2024 13:43:36 +0900 Subject: [PATCH 1/3] Exclude `VMADDR_CID_LOCAL` for non-linux target VMADDR_CID_LOCAL is used for vsock loopback, and is not supported on non-linux OSes. Signed-off-by: Akira Moroo --- src/lib.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 99fcbb9..a8a1f5c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,7 +39,9 @@ use std::{ os::fd::{AsFd, BorrowedFd}, }; -pub use libc::{VMADDR_CID_ANY, VMADDR_CID_HOST, VMADDR_CID_HYPERVISOR, VMADDR_CID_LOCAL}; +#[cfg(any(target_os = "linux", target_os = "android"))] +pub use libc::VMADDR_CID_LOCAL; +pub use libc::{VMADDR_CID_ANY, VMADDR_CID_HOST, VMADDR_CID_HYPERVISOR}; pub use nix::sys::socket::{SockaddrLike, VsockAddr}; fn new_socket() -> Result { From f817535428c1369d204096d7551f6d4341672026 Mon Sep 17 00:00:00 2001 From: Akira Moroo Date: Wed, 17 Apr 2024 13:48:42 +0900 Subject: [PATCH 2/3] Add macOS-specific cfg guards macOS does not have some constants, and it has slightly different sockaddr_vm struct from other OSes. Signed-off-by: Akira Moroo --- src/lib.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a8a1f5c..8a64248 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,12 +45,11 @@ pub use libc::{VMADDR_CID_ANY, VMADDR_CID_HOST, VMADDR_CID_HYPERVISOR}; pub use nix::sys::socket::{SockaddrLike, VsockAddr}; fn new_socket() -> Result { - Ok(socket( - AddressFamily::Vsock, - SockType::Stream, - SockFlag::SOCK_CLOEXEC, - None, - )?) + #[cfg(not(target_os = "macos"))] + let flags = SockFlag::SOCK_CLOEXEC; + #[cfg(target_os = "macos")] + let flags = SockFlag::empty(); + Ok(socket(AddressFamily::Vsock, SockType::Stream, flags, None)?) } /// An iterator that infinitely accepts connections on a VsockListener. @@ -117,7 +116,10 @@ impl VsockListener { svm_reserved1: 0, svm_port: 0, svm_cid: 0, + #[cfg(not(target_os = "macos"))] svm_zero: [0u8; 4], + #[cfg(target_os = "macos")] + svm_len: size_of::() as u8, }; let mut vsock_addr_len = size_of::() as socklen_t; let socket = unsafe { @@ -333,7 +335,11 @@ impl Read for &VsockStream { impl Write for &VsockStream { fn write(&mut self, buf: &[u8]) -> Result { - Ok(send(self.socket.as_raw_fd(), buf, MsgFlags::MSG_NOSIGNAL)?) + #[cfg(not(target_os = "macos"))] + let flags = MsgFlags::MSG_NOSIGNAL; + #[cfg(target_os = "macos")] + let flags = MsgFlags::empty(); + Ok(send(self.socket.as_raw_fd(), buf, flags)?) } fn flush(&mut self) -> Result<()> { From b9890f166e9acb2ffdebba522bd7666fa814da9e Mon Sep 17 00:00:00 2001 From: Akira Moroo Date: Wed, 17 Apr 2024 13:54:48 +0900 Subject: [PATCH 3/3] Replace `accept4` with `accept` and `fcntl` Since macOS does not have `accept4`, this commit replaces it with `accept` and `fcntl` to avoid fd leak to child processes. Signed-off-by: Akira Moroo --- src/lib.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 8a64248..1a91c69 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,8 +18,8 @@ //! Virtio socket support for Rust. use libc::{ - accept4, ioctl, sa_family_t, sockaddr, sockaddr_vm, socklen_t, suseconds_t, timeval, AF_VSOCK, - FIONBIO, SOCK_CLOEXEC, + accept, fcntl, ioctl, sa_family_t, sockaddr, sockaddr_vm, socklen_t, suseconds_t, timeval, + AF_VSOCK, FD_CLOEXEC, FIONBIO, F_SETFD, }; use nix::{ ioctl_read_bad, @@ -28,6 +28,7 @@ use nix::{ sockopt::{ReceiveTimeout, SendTimeout, SocketError}, AddressFamily, Backlog, GetSockOpt, MsgFlags, SetSockOpt, SockFlag, SockType, }, + unistd::close, }; use std::mem::size_of; use std::net::Shutdown; @@ -123,14 +124,17 @@ impl VsockListener { }; let mut vsock_addr_len = size_of::() as socklen_t; let socket = unsafe { - accept4( + accept( self.socket.as_raw_fd(), &mut vsock_addr as *mut _ as *mut sockaddr, &mut vsock_addr_len, - SOCK_CLOEXEC, ) }; if socket < 0 { + return Err(Error::last_os_error()); + } + if unsafe { fcntl(socket, F_SETFD, FD_CLOEXEC) } < 0 { + close(socket)?; Err(Error::last_os_error()) } else { Ok((