From 6c0da4334a6cc81fbd743d9e6de1d9082ff52373 Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Thu, 26 May 2022 12:53:21 -0700 Subject: Update TEST_MAPPING Test: None Bug: 233924440 Change-Id: I3fce18cc8fb491eaa0fc3d86d03fc04e2bef0799 --- TEST_MAPPING | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/TEST_MAPPING b/TEST_MAPPING index b7c1df9..61745b2 100644 --- a/TEST_MAPPING +++ b/TEST_MAPPING @@ -1,5 +1,13 @@ // Generated by update_crate_tests.py for tests that depend on this crate. { + "postsubmit": [ + { + "name": "microdroid_manager_test" + }, + { + "name": "virtualizationservice_device_test" + } + ], "presubmit": [ { "name": "microdroid_manager_test" -- cgit v1.2.3 From 5ebd8e6020cc34dd5b7ca6e602c21ff3e18dedfb Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Tue, 14 Jun 2022 17:32:03 -0700 Subject: Update TEST_MAPPING Test: None Bug: 236006683 Change-Id: I746d8b84e8c7b92870f88f463cce070342aa2296 --- TEST_MAPPING | 8 -------- 1 file changed, 8 deletions(-) diff --git a/TEST_MAPPING b/TEST_MAPPING index 61745b2..b7c1df9 100644 --- a/TEST_MAPPING +++ b/TEST_MAPPING @@ -1,13 +1,5 @@ // Generated by update_crate_tests.py for tests that depend on this crate. { - "postsubmit": [ - { - "name": "microdroid_manager_test" - }, - { - "name": "virtualizationservice_device_test" - } - ], "presubmit": [ { "name": "microdroid_manager_test" -- cgit v1.2.3 From ecf0949f477868f24cf522c2f3900d819bfc11dd Mon Sep 17 00:00:00 2001 From: Andrew Walbran Date: Thu, 6 Oct 2022 16:50:16 +0000 Subject: Update to version 0.3.0. Test: m virtualizationservice Change-Id: I267d06786de9908fe383ea35997408bd945e8919 --- .cargo_vcs_info.json | 7 +- Android.bp | 2 +- Cargo.toml | 13 ++- Cargo.toml.orig | 6 +- METADATA | 8 +- src/lib.rs | 287 +++++++++++++-------------------------------------- tests/vsock.rs | 32 +++++- 7 files changed, 120 insertions(+), 235 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 diff --git a/Android.bp b/Android.bp index 17b9a91..4bace96 100644 --- a/Android.bp +++ b/Android.bp @@ -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: [ diff --git a/Cargo.toml b/Cargo.toml index 0002416..7cde53a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/METADATA b/METADATA index 768fa97..218588e 100644 --- a/METADATA +++ b/METADATA @@ -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/src/lib.rs b/src/lib.rs index aaeb393..e482e9f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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 { + 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 { - let mut vsock_addr = if let SockAddr::Vsock(addr) = addr { - addr.0 - } else { + pub fn bind(addr: &impl SockaddrLike) -> Result { + 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::() 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 { - 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 { - 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::() 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 { + 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> { - 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 { - let vsock_addr = if let SockAddr::Vsock(addr) = addr { - addr.0 - } else { + pub fn connect(addr: &impl SockaddrLike) -> Result { + 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::() 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::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 { - 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::() 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 { + Ok(getpeername(self.socket)?) } /// Virtio socket address of the local address associated with this connection. - pub fn local_addr(&self) -> Result { - 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::() 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 { + 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) -> 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::() 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) -> 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::() 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> { - 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 { - 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 { - 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); +} -- cgit v1.2.3 From 339b47bec656369992c52a10dd4b2c9226614764 Mon Sep 17 00:00:00 2001 From: David Brazdil Date: Tue, 18 Oct 2022 16:42:43 +0100 Subject: Make crate available to com.android.compos APEX Bug: 245727626 Test: atest -p packages/modules/Virtualization:avf-presubmit Change-Id: Ib92cfb24b77ff24f0c29a58dde50eed2465b65ed --- Android.bp | 1 + cargo2android.json | 1 + 2 files changed, 2 insertions(+) diff --git a/Android.bp b/Android.bp index 4bace96..12e52dd 100644 --- a/Android.bp +++ b/Android.bp @@ -32,6 +32,7 @@ rust_library { ], apex_available: [ "//apex_available:platform", + "com.android.compos", "com.android.virt", ], } 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, -- cgit v1.2.3 From 744ca8f7c300d961bb29c8112b100efd4e9eb11c Mon Sep 17 00:00:00 2001 From: David Brazdil Date: Mon, 23 Jan 2023 14:11:18 +0000 Subject: Update TEST_MAPPING Test: None Change-Id: I313f18587b0ab4c170d622987f2def60452d1ee0 --- TEST_MAPPING | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/TEST_MAPPING b/TEST_MAPPING index b7c1df9..778b383 100644 --- a/TEST_MAPPING +++ b/TEST_MAPPING @@ -1,19 +1,25 @@ // Generated by update_crate_tests.py for tests that depend on this crate. { "presubmit": [ + { + "name": "libpvmfw_avb.integration_test" + }, { "name": "microdroid_manager_test" }, { - "name": "virtualizationservice_device_test" + "name": "virtualizationmanager_device_test" } ], "presubmit-rust": [ + { + "name": "libpvmfw_avb.integration_test" + }, { "name": "microdroid_manager_test" }, { - "name": "virtualizationservice_device_test" + "name": "virtualizationmanager_device_test" } ] } -- cgit v1.2.3 From b2278b64871379b8eb927923ee12ba13e94b96f2 Mon Sep 17 00:00:00 2001 From: Jeff Vander Stoep Date: Mon, 30 Jan 2023 14:57:27 +0100 Subject: Update TEST_MAPPING Test: atest Change-Id: I3d2fbc930a4ae2b01dd190b9d23c215cebf071c6 --- TEST_MAPPING | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/TEST_MAPPING b/TEST_MAPPING index 778b383..23589d9 100644 --- a/TEST_MAPPING +++ b/TEST_MAPPING @@ -1,25 +1,11 @@ // Generated by update_crate_tests.py for tests that depend on this crate. { - "presubmit": [ + "imports": [ { - "name": "libpvmfw_avb.integration_test" + "path": "packages/modules/Virtualization/microdroid_manager" }, { - "name": "microdroid_manager_test" - }, - { - "name": "virtualizationmanager_device_test" - } - ], - "presubmit-rust": [ - { - "name": "libpvmfw_avb.integration_test" - }, - { - "name": "microdroid_manager_test" - }, - { - "name": "virtualizationmanager_device_test" + "path": "packages/modules/Virtualization/virtualizationmanager" } ] } -- cgit v1.2.3 From b0ed37f95d4949c55aa5eec54279b64d8c22613c Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Tue, 7 Mar 2023 17:25:09 -0800 Subject: Make vsock available to product and vendor Bug: 270690570 Test: mma in external/rust/crates Change-Id: If553c35d344e9a2f0f7dedb19f85f6a95b10223f --- Android.bp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Android.bp b/Android.bp index 12e52dd..10a6fa7 100644 --- a/Android.bp +++ b/Android.bp @@ -35,4 +35,6 @@ rust_library { "com.android.compos", "com.android.virt", ], + product_available: true, + vendor_available: true, } -- cgit v1.2.3