diff --git a/qemu-display/Cargo.toml b/qemu-display/Cargo.toml index b127f68..b0f16ed 100644 --- a/qemu-display/Cargo.toml +++ b/qemu-display/Cargo.toml @@ -10,7 +10,7 @@ edition = "2018" cfg-if = "1.0" log = "0.4" derivative = "2.2.0" -zbus = { version = "3.0", features = ["xml"] } +zbus = { version = "3.2", features = ["xml"] } zvariant = { version = "3.0", features = ["serde_bytes"] } libc = "0.2.86" enumflags2 = { version = "0.7", features = ["serde"] } diff --git a/qemu-display/src/audio.rs b/qemu-display/src/audio.rs index da82bad..92f952b 100644 --- a/qemu-display/src/audio.rs +++ b/qemu-display/src/audio.rs @@ -244,7 +244,11 @@ impl Audio { pub async fn register_out_listener(&mut self, handler: H) -> Result<()> { let (p0, p1) = UnixStream::pair()?; - let p0 = util::prepare_uds_pass(&p0)?; + let p0 = util::prepare_uds_pass( + #[cfg(windows)] + self.proxy.inner().connection(), + &p0, + )?; self.proxy.register_out_listener(p0).await?; let c = zbus::ConnectionBuilder::unix_stream(p1) .p2p() @@ -260,7 +264,11 @@ impl Audio { pub async fn register_in_listener(&mut self, handler: H) -> Result<()> { let (p0, p1) = UnixStream::pair()?; - let p0 = util::prepare_uds_pass(&p0)?; + let p0 = util::prepare_uds_pass( + #[cfg(windows)] + self.proxy.inner().connection(), + &p0, + )?; self.proxy.register_in_listener(p0).await?; let c = zbus::ConnectionBuilder::unix_stream(p1) .p2p() diff --git a/qemu-display/src/console.rs b/qemu-display/src/console.rs index c85d660..0cea8a9 100644 --- a/qemu-display/src/console.rs +++ b/qemu-display/src/console.rs @@ -87,7 +87,11 @@ impl Console { pub async fn register_listener(&self, handler: H) -> Result<()> { let (p0, p1) = UnixStream::pair()?; - let p0 = util::prepare_uds_pass(&p0)?; + let p0 = util::prepare_uds_pass( + #[cfg(windows)] + self.proxy.inner().connection(), + &p0, + )?; self.proxy.register_listener(p0).await?; let c = zbus::ConnectionBuilder::unix_stream(p1) .p2p() diff --git a/qemu-display/src/util.rs b/qemu-display/src/util.rs index b849b22..2d08af1 100644 --- a/qemu-display/src/util.rs +++ b/qemu-display/src/util.rs @@ -14,11 +14,11 @@ use std::os::windows::io::AsRawSocket; #[cfg(windows)] use uds_windows::UnixStream; #[cfg(windows)] -use windows::Win32::Networking::WinSock::{WSADuplicateSocketW, SOCKET, WSAPROTOCOL_INFOW}; +use windows::Win32::Networking::WinSock::SOCKET; #[cfg(windows)] use windows::Win32::System::Threading::PROCESS_DUP_HANDLE; -pub fn prepare_uds_pass(us: &UnixStream) -> Result { +pub fn prepare_uds_pass(#[cfg(windows)] conn: &zbus::Connection, us: &UnixStream) -> Result { #[cfg(unix)] { Ok(us.as_raw_fd().into()) @@ -26,21 +26,9 @@ pub fn prepare_uds_pass(us: &UnixStream) -> Result { #[cfg(windows)] { - let pid = win32::unix_stream_get_peer_pid(us)?; - let p = win32::ProcessHandle::open(Some(pid), PROCESS_DUP_HANDLE)?; - let mut info = unsafe { std::mem::zeroed() }; - if unsafe { - WSADuplicateSocketW(SOCKET(us.as_raw_socket() as _), p.process_id(), &mut info) - } != 0 - { - return Err(crate::Error::Io(win32::wsa_last_err())); - } - let info = unsafe { - std::slice::from_raw_parts( - &info as *const _ as *const u8, - std::mem::size_of::(), - ) - }; - Ok(info.to_vec()) + // FIXME: we should use GetConnectionCredentials to work with a bus + let pid = conn.peer_pid()?.unwrap(); + let p = win32::ProcessHandle::open(Some(pid as _), PROCESS_DUP_HANDLE)?; + p.duplicate_socket(SOCKET(us.as_raw_socket() as _)) } } diff --git a/qemu-display/src/win32.rs b/qemu-display/src/win32.rs index 013bb0e..d66f151 100644 --- a/qemu-display/src/win32.rs +++ b/qemu-display/src/win32.rs @@ -1,6 +1,6 @@ use std::io; -use uds_windows::UnixStream; use windows::Win32::Foundation::{CloseHandle, HANDLE}; +use windows::Win32::Networking::WinSock::{WSADuplicateSocketW, SOCKET, WSAPROTOCOL_INFOW}; use windows::Win32::System::Threading::PROCESS_ACCESS_RIGHTS; pub type Fd = Vec; @@ -36,6 +36,20 @@ impl ProcessHandle { unsafe { GetProcessId(self.0) } } + + pub fn duplicate_socket(&self, sock: SOCKET) -> crate::Result { + let mut info = unsafe { std::mem::zeroed() }; + if unsafe { WSADuplicateSocketW(sock, self.process_id(), &mut info) } != 0 { + return Err(crate::Error::Io(wsa_last_err())); + } + let info = unsafe { + std::slice::from_raw_parts( + &info as *const _ as *const u8, + std::mem::size_of::(), + ) + }; + Ok(info.to_vec()) + } } pub(crate) fn wsa_last_err() -> io::Error { @@ -44,42 +58,3 @@ pub(crate) fn wsa_last_err() -> io::Error { let err = unsafe { WSAGetLastError() }; io::Error::from_raw_os_error(err.0) } - -// Get the process ID of the connected peer -pub fn unix_stream_get_peer_pid(stream: &UnixStream) -> Result { - use std::os::windows::io::AsRawSocket; - use windows::Win32::Networking::WinSock::{ - WSAIoctl, IOC_OUT, IOC_VENDOR, SOCKET, SOCKET_ERROR, - }; - - macro_rules! _WSAIOR { - ($x:expr, $y:expr) => { - IOC_OUT | $x | $y - }; - } - - let socket = stream.as_raw_socket(); - const SIO_AF_UNIX_GETPEERPID: u32 = _WSAIOR!(IOC_VENDOR, 256); - let mut ret = 0 as u32; - let mut bytes = 0; - - let r = unsafe { - WSAIoctl( - SOCKET(socket as _), - SIO_AF_UNIX_GETPEERPID, - 0 as *mut _, - 0, - &mut ret as *mut _ as *mut _, - std::mem::size_of_val(&ret) as u32, - &mut bytes, - 0 as *mut _, - None, - ) - }; - - if r == SOCKET_ERROR { - return Err(wsa_last_err()); - } - - Ok(ret) -} diff --git a/qemu-rdw/src/main.rs b/qemu-rdw/src/main.rs index f3782e6..028d3f5 100644 --- a/qemu-rdw/src/main.rs +++ b/qemu-rdw/src/main.rs @@ -208,7 +208,12 @@ impl App { use uds_windows::UnixStream; let (p0, p1) = UnixStream::pair().unwrap(); - let fd = util::prepare_uds_pass(&p1).unwrap(); + let fd = util::prepare_uds_pass( + #[cfg(windows)] + c.proxy.inner().connection(), + &p1, + ) + .unwrap(); if c.proxy.register(fd).await.is_ok() { let mut reader = BufReader::new(p0.try_clone().unwrap()); let mut line = String::new();