wayvr: IPC: Fix dangling fds (#513)

This commit is contained in:
oo8dev 2026-05-07 22:06:54 +02:00 committed by GitHub
parent ec2e0501c1
commit cdd658d4ea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 53 additions and 38 deletions

View File

@ -42,35 +42,40 @@ pub fn send_packet(conn: &mut local_socket::Stream, data: &[u8]) -> anyhow::Resu
Ok(()) Ok(())
} }
fn read_check(expected_size: u32, res: std::io::Result<usize>) -> bool { fn read_check(expected_size: u32, res: std::io::Result<usize>) -> anyhow::Result<bool> {
match res { match res {
Ok(count) => { Ok(count) => {
if count == 0 { if count == 0 {
return false; anyhow::bail!("End of stream");
} }
if count as u32 == expected_size { if count as u32 == expected_size {
true // read succeeded return Ok(true); // read succeeded
} else { } else {
log::error!("count {count} is not {expected_size}"); log::error!("count {count} is not {expected_size}");
false return Ok(false);
} }
} }
Err(_e) => { Err(e) => match e.kind() {
//log::error!("failed to get packet size: {}", e); std::io::ErrorKind::WouldBlock => {
false // no incoming data (this socket is non-blocking), try again later
} return Ok(false);
}
_ => {
anyhow::bail!("Connection error: {:?}", e);
}
},
} }
} }
type Payload = SmallVec<[u8; 64]>; type Payload = SmallVec<[u8; 64]>;
fn read_payload(conn: &mut local_socket::Stream, size: u32) -> Option<Payload> { fn read_payload(conn: &mut local_socket::Stream, size: u32) -> anyhow::Result<Option<Payload>> {
let mut payload = Payload::new(); let mut payload = Payload::new();
payload.resize(size as usize, 0); payload.resize(size as usize, 0);
if read_check(size, conn.read(&mut payload)) { if read_check(size, conn.read(&mut payload))? {
Some(payload) Ok(Some(payload))
} else { } else {
None Ok(None)
} }
} }
@ -433,36 +438,33 @@ impl Connection {
Ok(()) Ok(())
} }
fn process_check_payload(&mut self, params: &mut TickParams, payload: Payload) -> bool { fn process_check_payload(
log::debug!("payload size {}", payload.len()); &mut self,
params: &mut TickParams,
payload: Payload,
) -> anyhow::Result<()> {
if let Err(e) = self.process_payload(params, payload) { if let Err(e) = self.process_payload(params, payload) {
log::error!("Invalid payload from the client, closing connection: {e}");
// send also error message directly to the client before disconnecting // send also error message directly to the client before disconnecting
self.kill(format!("{e}").as_str()); self.kill(format!("{e}").as_str());
false anyhow::bail!("Invalid payload from the client, closing connection: {e}");
} else {
true
} }
Ok(())
} }
fn read_packet(&mut self, params: &mut TickParams) -> bool { fn read_packet(&mut self, params: &mut TickParams) -> anyhow::Result<bool> {
if let Some(payload_size) = self.next_packet { if let Some(payload_size) = self.next_packet {
let Some(payload) = read_payload(&mut self.conn, payload_size) else { let Some(payload) = read_payload(&mut self.conn, payload_size)? else {
// still failed to read payload, try in next tick // still failed to read payload, try in the next tick
return false; return Ok(false);
}; };
if !self.process_check_payload(params, payload) { self.process_check_payload(params, payload)?;
return false;
}
self.next_packet = None; self.next_packet = None;
} }
let mut buf_packet_header: [u8; 4] = [0; 4]; let mut buf_packet_header: [u8; 4] = [0; 4];
if !read_check(4, self.conn.read(&mut buf_packet_header)) { if !read_check(4, self.conn.read(&mut buf_packet_header))? {
return false; return Ok(false);
} }
let payload_size = u32::from_be_bytes(buf_packet_header[0..4].try_into().unwrap()); // 0-3 bytes (u32 size) let payload_size = u32::from_be_bytes(buf_packet_header[0..4].try_into().unwrap()); // 0-3 bytes (u32 size)
@ -475,30 +477,43 @@ impl Connection {
"Client sent a packet header with the size over {size_limit} bytes, closing connection." "Client sent a packet header with the size over {size_limit} bytes, closing connection."
); );
self.kill("Too big packet received (over 128 KiB)"); self.kill("Too big packet received (over 128 KiB)");
return false; return Ok(false);
} }
let Some(payload) = read_payload(&mut self.conn, payload_size) else { let Some(payload) = read_payload(&mut self.conn, payload_size)? else {
// failed to read payload, try in next tick // failed to read payload, try in next tick
self.next_packet = Some(payload_size); self.next_packet = Some(payload_size);
return false; return Ok(false);
}; };
if !self.process_check_payload(params, payload) { self.process_check_payload(params, payload)?;
return false;
}
true Ok(true)
} }
fn tick(&mut self, params: &mut TickParams) { fn tick(&mut self, params: &mut TickParams) {
while self.read_packet(params) {} loop {
match self.read_packet(params) {
Ok(loop_further) => {
if !loop_further {
break;
}
}
Err(e) => {
log::debug!("Disconnecting client: {:?}", e);
self.alive = false;
break;
}
}
}
} }
} }
impl Drop for Connection { impl Drop for Connection {
fn drop(&mut self) { fn drop(&mut self) {
log::info!("Connection closed"); if let Some(auth) = &self.auth {
log::info!("IPC: Client \"{}\" disconnected.", auth.client_name);
}
} }
} }