diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-07 04:45:28 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-07 04:45:28 +0000 |
commit | 28202e520ea44fbf2a0932b8139debcb8846833b (patch) | |
tree | 736fef5accd88a211d1028ae6622451dc45331aa | |
parent | f3d51fe8925b7602c1f207d0fbb603d2fa6a147a (diff) | |
parent | 13c9ba703b10052628884ae3f02240c5c51180d1 (diff) | |
download | vsock-aml_art_341110060.tar.gz |
Snap for 10453563 from 13c9ba703b10052628884ae3f02240c5c51180d1 to mainline-art-releaseaml_art_341810020aml_art_341711000aml_art_341615020aml_art_341514450aml_art_341514410aml_art_341411300aml_art_341311100aml_art_341110110aml_art_341110060aml_art_341010050aml_art_340915060android14-mainline-art-releaseaml_art_341810020
Change-Id: I85e8761d0fb9fc7bd0120ab87c7b79d121fa6540
-rw-r--r-- | .cargo_vcs_info.json | 7 | ||||
-rw-r--r-- | Android.bp | 5 | ||||
-rw-r--r-- | Cargo.toml | 13 | ||||
-rw-r--r-- | Cargo.toml.orig | 6 | ||||
-rw-r--r-- | METADATA | 8 | ||||
-rw-r--r-- | TEST_MAPPING | 14 | ||||
-rw-r--r-- | cargo2android.json | 1 | ||||
-rw-r--r-- | src/lib.rs | 287 | ||||
-rw-r--r-- | tests/vsock.rs | 32 |
9 files changed, 127 insertions, 246 deletions
diff --git a/.cargo_vcs_info.json b/.cargo_vcs_info.json index 3d9568d..906003c 100644 --- a/.cargo_vcs_info.json +++ b/.cargo_vcs_info.json @@ -1,5 +1,6 @@ { "git": { - "sha1": "9b5e180bf04fd1d02db0c1e79c5ddd838dd42328" - } -} + "sha1": "41d1faa752299f665d3ca429bf7a3d2367e7e774" + }, + "path_in_vcs": "" +}
\ No newline at end of file @@ -23,7 +23,7 @@ rust_library { host_supported: true, crate_name: "vsock", cargo_env_compat: true, - cargo_pkg_version: "0.2.6", + cargo_pkg_version: "0.3.0", srcs: ["src/lib.rs"], edition: "2018", rustlibs: [ @@ -32,6 +32,9 @@ rust_library { ], apex_available: [ "//apex_available:platform", + "com.android.compos", "com.android.virt", ], + product_available: true, + vendor_available: true, } @@ -12,19 +12,24 @@ [package] edition = "2018" name = "vsock" -version = "0.2.6" -authors = ["fsyncd", "rust-vsock"] +version = "0.3.0" +authors = [ + "fsyncd", + "rust-vsock", +] exclude = ["test_fixture"] description = "Virtio socket support for Rust" homepage = "https://github.com/rust-vsock/vsock-rs" readme = "README.md" license = "Apache-2.0" repository = "https://github.com/rust-vsock/vsock-rs" + [dependencies.libc] -version = "0.2.79" +version = "0.2.126" [dependencies.nix] -version = "0.23.0" +version = "0.24.2" + [dev-dependencies.rand] version = "0.8.3" diff --git a/Cargo.toml.orig b/Cargo.toml.orig index 7a6d39a..6b098e9 100644 --- a/Cargo.toml.orig +++ b/Cargo.toml.orig @@ -1,6 +1,6 @@ [package] name = "vsock" -version = "0.2.6" +version = "0.3.0" authors = ["fsyncd", "rust-vsock"] description = "Virtio socket support for Rust" repository = "https://github.com/rust-vsock/vsock-rs" @@ -11,8 +11,8 @@ edition = "2018" exclude = ["test_fixture"] [dependencies] -libc = "0.2.79" -nix = "0.23.0" +libc = "0.2.126" +nix = "0.24.2" [dev-dependencies] rand = "0.8.3" @@ -7,13 +7,13 @@ third_party { } url { type: ARCHIVE - value: "https://static.crates.io/crates/vsock/vsock-0.2.6.crate" + value: "https://static.crates.io/crates/vsock/vsock-0.3.0.crate" } - version: "0.2.6" + version: "0.3.0" license_type: NOTICE last_upgrade_date { year: 2022 - month: 3 - day: 1 + month: 10 + day: 6 } } diff --git a/TEST_MAPPING b/TEST_MAPPING index b7c1df9..23589d9 100644 --- a/TEST_MAPPING +++ b/TEST_MAPPING @@ -1,19 +1,11 @@ // Generated by update_crate_tests.py for tests that depend on this crate. { - "presubmit": [ + "imports": [ { - "name": "microdroid_manager_test" + "path": "packages/modules/Virtualization/microdroid_manager" }, { - "name": "virtualizationservice_device_test" - } - ], - "presubmit-rust": [ - { - "name": "microdroid_manager_test" - }, - { - "name": "virtualizationservice_device_test" + "path": "packages/modules/Virtualization/virtualizationmanager" } ] } diff --git a/cargo2android.json b/cargo2android.json index 42b7833..07302e7 100644 --- a/cargo2android.json +++ b/cargo2android.json @@ -1,6 +1,7 @@ { "apex-available": [ "//apex_available:platform", + "com.android.compos", "com.android.virt" ], "dependencies": true, @@ -17,9 +17,19 @@ //! Virtio socket support for Rust. -use libc::*; -use nix::ioctl_read_bad; -use std::ffi::c_void; +use libc::{ + accept4, ioctl, sa_family_t, sockaddr, sockaddr_vm, socklen_t, suseconds_t, timeval, AF_VSOCK, + FIONBIO, SOCK_CLOEXEC, +}; +use nix::{ + ioctl_read_bad, + sys::socket::{ + self, bind, connect, getpeername, getsockname, listen, recv, send, shutdown, socket, + sockopt::{ReceiveTimeout, SendTimeout, SocketError}, + AddressFamily, GetSockOpt, MsgFlags, SetSockOpt, SockFlag, SockType, + }, + unistd::close, +}; use std::fs::File; use std::io::{Error, ErrorKind, Read, Result, Write}; use std::mem::{self, size_of}; @@ -28,10 +38,15 @@ use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; use std::time::Duration; pub use libc::{VMADDR_CID_ANY, VMADDR_CID_HOST, VMADDR_CID_HYPERVISOR, VMADDR_CID_LOCAL}; -pub use nix::sys::socket::{SockAddr, VsockAddr}; - -fn new_socket() -> libc::c_int { - unsafe { socket(AF_VSOCK, SOCK_STREAM | SOCK_CLOEXEC, 0) } +pub use nix::sys::socket::{SockaddrLike, VsockAddr}; + +fn new_socket() -> Result<RawFd> { + Ok(socket( + AddressFamily::Vsock, + SockType::Stream, + SockFlag::SOCK_CLOEXEC, + None, + )?) } /// An iterator that infinitely accepts connections on a VsockListener. @@ -56,68 +71,32 @@ pub struct VsockListener { impl VsockListener { /// Create a new VsockListener which is bound and listening on the socket address. - pub fn bind(addr: &SockAddr) -> Result<VsockListener> { - let mut vsock_addr = if let SockAddr::Vsock(addr) = addr { - addr.0 - } else { + pub fn bind(addr: &impl SockaddrLike) -> Result<Self> { + if addr.family() != Some(AddressFamily::Vsock) { return Err(Error::new( ErrorKind::Other, "requires a virtio socket address", )); - }; - - let socket = new_socket(); - if socket < 0 { - return Err(Error::last_os_error()); } - let res = unsafe { - bind( - socket, - &mut vsock_addr as *mut _ as *mut sockaddr, - size_of::<sockaddr_vm>() as socklen_t, - ) - }; - if res < 0 { - return Err(Error::last_os_error()); - } + let socket = new_socket()?; + + bind(socket, addr)?; // rust stdlib uses a 128 connection backlog - let res = unsafe { listen(socket, 128) }; - if res < 0 { - return Err(Error::last_os_error()); - } + listen(socket, 128)?; Ok(Self { socket }) } /// Create a new VsockListener with specified cid and port. pub fn bind_with_cid_port(cid: u32, port: u32) -> Result<VsockListener> { - Self::bind(&SockAddr::Vsock(VsockAddr::new(cid, port))) + Self::bind(&VsockAddr::new(cid, port)) } /// The local socket address of the listener. - pub fn local_addr(&self) -> Result<SockAddr> { - let mut vsock_addr = sockaddr_vm { - svm_family: AF_VSOCK as sa_family_t, - svm_reserved1: 0, - svm_port: 0, - svm_cid: 0, - svm_zero: [0u8; 4], - }; - let mut vsock_addr_len = size_of::<sockaddr_vm>() as socklen_t; - if unsafe { - getsockname( - self.socket, - &mut vsock_addr as *mut _ as *mut sockaddr, - &mut vsock_addr_len, - ) - } < 0 - { - Err(Error::last_os_error()) - } else { - Ok(SockAddr::Vsock(VsockAddr(vsock_addr))) - } + pub fn local_addr(&self) -> Result<VsockAddr> { + Ok(getsockname(self.socket)?) } /// Create a new independently owned handle to the underlying socket. @@ -126,7 +105,7 @@ impl VsockListener { } /// Accept a new incoming connection from this listener. - pub fn accept(&self) -> Result<(VsockStream, SockAddr)> { + pub fn accept(&self) -> Result<(VsockStream, VsockAddr)> { let mut vsock_addr = sockaddr_vm { svm_family: AF_VSOCK as sa_family_t, svm_reserved1: 0, @@ -148,7 +127,7 @@ impl VsockListener { } else { Ok(( unsafe { VsockStream::from_raw_fd(socket as RawFd) }, - SockAddr::Vsock(VsockAddr::new(vsock_addr.svm_cid, vsock_addr.svm_port)), + VsockAddr::new(vsock_addr.svm_cid, vsock_addr.svm_port), )) } } @@ -160,26 +139,12 @@ impl VsockListener { /// Retrieve the latest error associated with the underlying socket. pub fn take_error(&self) -> Result<Option<Error>> { - let mut error: i32 = 0; - let mut error_len: socklen_t = 0; - if unsafe { - getsockopt( - self.socket, - SOL_SOCKET, - SO_ERROR, - &mut error as *mut _ as *mut c_void, - &mut error_len, - ) - } < 0 - { - Err(Error::last_os_error()) + let error = SocketError.get(self.socket)?; + Ok(if error == 0 { + None } else { - Ok(if error == 0 { - None - } else { - Some(Error::from_raw_os_error(error)) - }) - } + Some(Error::from_raw_os_error(error)) + }) } /// Move this stream in and out of nonblocking mode. @@ -215,7 +180,7 @@ impl IntoRawFd for VsockListener { impl Drop for VsockListener { fn drop(&mut self) { - unsafe { close(self.socket) }; + let _ = close(self.socket); } } @@ -227,99 +192,42 @@ pub struct VsockStream { impl VsockStream { /// Open a connection to a remote host. - pub fn connect(addr: &SockAddr) -> Result<Self> { - let vsock_addr = if let SockAddr::Vsock(addr) = addr { - addr.0 - } else { + pub fn connect(addr: &impl SockaddrLike) -> Result<Self> { + if addr.family() != Some(AddressFamily::Vsock) { return Err(Error::new( ErrorKind::Other, "requires a virtio socket address", )); - }; - - let sock = new_socket(); - if sock < 0 { - return Err(Error::last_os_error()); - } - if unsafe { - connect( - sock, - &vsock_addr as *const _ as *const sockaddr, - size_of::<sockaddr_vm>() as socklen_t, - ) - } < 0 - { - Err(Error::last_os_error()) - } else { - Ok(unsafe { VsockStream::from_raw_fd(sock) }) } + + let sock = new_socket()?; + connect(sock, addr)?; + Ok(unsafe { Self::from_raw_fd(sock) }) } /// Open a connection to a remote host with specified cid and port. pub fn connect_with_cid_port(cid: u32, port: u32) -> Result<Self> { - Self::connect(&SockAddr::Vsock(VsockAddr::new(cid, port))) + Self::connect(&VsockAddr::new(cid, port)) } /// Virtio socket address of the remote peer associated with this connection. - pub fn peer_addr(&self) -> Result<SockAddr> { - let mut vsock_addr = sockaddr_vm { - svm_family: AF_VSOCK as sa_family_t, - svm_reserved1: 0, - svm_port: 0, - svm_cid: 0, - svm_zero: [0u8; 4], - }; - let mut vsock_addr_len = size_of::<sockaddr_vm>() as socklen_t; - if unsafe { - getpeername( - self.socket, - &mut vsock_addr as *mut _ as *mut sockaddr, - &mut vsock_addr_len, - ) - } < 0 - { - Err(Error::last_os_error()) - } else { - Ok(SockAddr::Vsock(VsockAddr(vsock_addr))) - } + pub fn peer_addr(&self) -> Result<VsockAddr> { + Ok(getpeername(self.socket)?) } /// Virtio socket address of the local address associated with this connection. - pub fn local_addr(&self) -> Result<SockAddr> { - let mut vsock_addr = sockaddr_vm { - svm_family: AF_VSOCK as sa_family_t, - svm_reserved1: 0, - svm_port: 0, - svm_cid: 0, - svm_zero: [0u8; 4], - }; - let mut vsock_addr_len = size_of::<sockaddr_vm>() as socklen_t; - if unsafe { - getsockname( - self.socket, - &mut vsock_addr as *mut _ as *mut sockaddr, - &mut vsock_addr_len, - ) - } < 0 - { - Err(Error::last_os_error()) - } else { - Ok(SockAddr::Vsock(VsockAddr(vsock_addr))) - } + pub fn local_addr(&self) -> Result<VsockAddr> { + Ok(getsockname(self.socket)?) } /// Shutdown the read, write, or both halves of this connection. pub fn shutdown(&self, how: Shutdown) -> Result<()> { let how = match how { - Shutdown::Write => SHUT_WR, - Shutdown::Read => SHUT_RD, - Shutdown::Both => SHUT_RDWR, + Shutdown::Write => socket::Shutdown::Write, + Shutdown::Read => socket::Shutdown::Read, + Shutdown::Both => socket::Shutdown::Both, }; - if unsafe { shutdown(self.socket, how) } < 0 { - Err(Error::last_os_error()) - } else { - Ok(()) - } + Ok(shutdown(self.socket, how)?) } /// Create a new independently owned handle to the underlying socket. @@ -329,64 +237,24 @@ impl VsockStream { /// Set the timeout on read operations. pub fn set_read_timeout(&self, dur: Option<Duration>) -> Result<()> { - let timeout = Self::timeval_from_duration(dur)?; - if unsafe { - setsockopt( - self.socket, - SOL_SOCKET, - SO_SNDTIMEO, - &timeout as *const _ as *const c_void, - size_of::<timeval>() as socklen_t, - ) - } < 0 - { - Err(Error::last_os_error()) - } else { - Ok(()) - } + let timeout = Self::timeval_from_duration(dur)?.into(); + Ok(SendTimeout.set(self.socket, &timeout)?) } /// Set the timeout on write operations. pub fn set_write_timeout(&self, dur: Option<Duration>) -> Result<()> { - let timeout = Self::timeval_from_duration(dur)?; - if unsafe { - setsockopt( - self.socket, - SOL_SOCKET, - SO_RCVTIMEO, - &timeout as *const _ as *const c_void, - size_of::<timeval>() as socklen_t, - ) - } < 0 - { - Err(Error::last_os_error()) - } else { - Ok(()) - } + let timeout = Self::timeval_from_duration(dur)?.into(); + Ok(ReceiveTimeout.set(self.socket, &timeout)?) } /// Retrieve the latest error associated with the underlying socket. pub fn take_error(&self) -> Result<Option<Error>> { - let mut error: i32 = 0; - let mut error_len: socklen_t = 0; - if unsafe { - getsockopt( - self.socket, - SOL_SOCKET, - SO_ERROR, - &mut error as *mut _ as *mut c_void, - &mut error_len, - ) - } < 0 - { - Err(Error::last_os_error()) + let error = SocketError.get(self.socket)?; + Ok(if error == 0 { + None } else { - Ok(if error == 0 { - None - } else { - Some(Error::from_raw_os_error(error)) - }) - } + Some(Error::from_raw_os_error(error)) + }) } /// Move this stream in and out of nonblocking mode. @@ -411,10 +279,10 @@ impl VsockStream { // https://github.com/rust-lang/libc/issues/1848 #[cfg_attr(target_env = "musl", allow(deprecated))] - let secs = if dur.as_secs() > time_t::max_value() as u64 { - time_t::max_value() + let secs = if dur.as_secs() > libc::time_t::max_value() as u64 { + libc::time_t::max_value() } else { - dur.as_secs() as time_t + dur.as_secs() as libc::time_t }; let mut timeout = timeval { tv_sec: secs, @@ -451,30 +319,13 @@ impl Write for VsockStream { impl Read for &VsockStream { fn read(&mut self, buf: &mut [u8]) -> Result<usize> { - let ret = unsafe { recv(self.socket, buf.as_mut_ptr() as *mut c_void, buf.len(), 0) }; - if ret < 0 { - Err(Error::last_os_error()) - } else { - Ok(ret as usize) - } + Ok(recv(self.socket, buf, MsgFlags::empty())?) } } impl Write for &VsockStream { fn write(&mut self, buf: &[u8]) -> Result<usize> { - let ret = unsafe { - send( - self.socket, - buf.as_ptr() as *const c_void, - buf.len(), - MSG_NOSIGNAL, - ) - }; - if ret < 0 { - Err(Error::last_os_error()) - } else { - Ok(ret as usize) - } + Ok(send(self.socket, buf, MsgFlags::MSG_NOSIGNAL)?) } fn flush(&mut self) -> Result<()> { @@ -504,7 +355,7 @@ impl IntoRawFd for VsockStream { impl Drop for VsockStream { fn drop(&mut self) { - unsafe { close(self.socket) }; + let _ = close(self.socket); } } diff --git a/tests/vsock.rs b/tests/vsock.rs index 52d908b..1ac60c9 100644 --- a/tests/vsock.rs +++ b/tests/vsock.rs @@ -17,11 +17,15 @@ use rand::RngCore; use sha2::{Digest, Sha256}; use std::io::{Read, Write}; -use vsock::{get_local_cid, SockAddr, VsockAddr, VsockStream, VMADDR_CID_HOST}; +use vsock::{get_local_cid, VsockAddr, VsockListener, VsockStream, VMADDR_CID_HOST}; const TEST_BLOB_SIZE: usize = 1_000_000; const TEST_BLOCK_SIZE: usize = 5_000; +const SERVER_CID: u32 = 3; +const SERVER_PORT: u32 = 8000; +const LISTEN_PORT: u32 = 9000; + /// A simple test for the vsock implementation. /// Generate a large random blob of binary data, and transfer it in chunks over the VsockStream /// interface. The vm enpoint is running a simple echo server, so for each chunk we will read @@ -40,7 +44,7 @@ fn test_vsock() { rng.fill_bytes(&mut blob); let mut stream = - VsockStream::connect(&SockAddr::Vsock(VsockAddr::new(3, 8000))).expect("connection failed"); + VsockStream::connect(&VsockAddr::new(SERVER_CID, SERVER_PORT)).expect("connection failed"); while tx_pos < TEST_BLOB_SIZE { let written_bytes = stream @@ -72,3 +76,27 @@ fn test_vsock() { fn test_get_local_cid() { assert_eq!(get_local_cid().unwrap(), VMADDR_CID_HOST); } + +#[test] +fn test_listener_local_addr() { + let listener = VsockListener::bind(&VsockAddr::new(VMADDR_CID_HOST, LISTEN_PORT)).unwrap(); + + let local_addr = listener.local_addr().unwrap(); + assert_eq!(local_addr.cid(), VMADDR_CID_HOST); + assert_eq!(local_addr.port(), LISTEN_PORT); +} + +#[test] +fn test_stream_addresses() { + let stream = + VsockStream::connect(&VsockAddr::new(SERVER_CID, SERVER_PORT)).expect("connection failed"); + + let local_addr = stream.local_addr().unwrap(); + // Apparently on some systems a client socket has the host CID, on some it has CID_ANY. Allow + // either. + assert!([libc::VMADDR_CID_ANY, VMADDR_CID_HOST].contains(&local_addr.cid())); + + let peer_addr = stream.peer_addr().unwrap(); + assert_eq!(peer_addr.cid(), SERVER_CID); + assert_eq!(peer_addr.port(), SERVER_PORT); +} |