mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
net_util: queue_pair: Handle RX readv EINVAL gracefully
When readv from the TAP returns EINVAL the guest posted a buffer too small for the vnet_hdr. Return len 0 to the used ring and continue instead of killing the worker thread. Also move go_to_previous_position into the appropriate error branches only. Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This commit is contained in:
committed by
Rob Bradford
parent
02ea839838
commit
c71a8ea8dd
@@ -272,33 +272,41 @@ impl RxVirtio {
|
||||
};
|
||||
if result < 0 {
|
||||
let e = std::io::Error::last_os_error();
|
||||
exhausted_descs = false;
|
||||
queue.go_to_previous_position();
|
||||
|
||||
/* EAGAIN */
|
||||
if e.kind() == std::io::ErrorKind::WouldBlock {
|
||||
exhausted_descs = false;
|
||||
queue.go_to_previous_position();
|
||||
break;
|
||||
}
|
||||
|
||||
error!("net: rx: failed reading from tap: {e}");
|
||||
return Err(NetQueuePairError::ReadTap(e));
|
||||
}
|
||||
|
||||
if (result as usize) < vnet_hdr_len() {
|
||||
if e.raw_os_error() == Some(libc::EINVAL) {
|
||||
error!("net: rx: dropping undersized buffer: {e}");
|
||||
desc_chain
|
||||
.memory()
|
||||
.write_obj(0u16, num_buffers_addr)
|
||||
.map_err(NetQueuePairError::GuestMemory)?;
|
||||
0
|
||||
} else {
|
||||
queue.go_to_previous_position();
|
||||
error!("net: rx: failed reading from tap: {e}");
|
||||
return Err(NetQueuePairError::ReadTap(e));
|
||||
}
|
||||
} else if (result as usize) < vnet_hdr_len() {
|
||||
return Err(NetQueuePairError::InvalidVirtioNetHeader);
|
||||
} else {
|
||||
// Write num_buffers to guest memory. Always 1 because the
|
||||
// frame is never spread over more than one descriptor chain.
|
||||
desc_chain
|
||||
.memory()
|
||||
.write_obj(1u16, num_buffers_addr)
|
||||
.map_err(NetQueuePairError::GuestMemory)?;
|
||||
|
||||
self.counter_bytes += Wrapping(result as u64 - vnet_hdr_len() as u64);
|
||||
self.counter_frames += Wrapping(1);
|
||||
|
||||
result as u32
|
||||
}
|
||||
|
||||
// Write num_buffers to guest memory. We simply write 1 as we
|
||||
// never spread the frame over more than one descriptor chain.
|
||||
desc_chain
|
||||
.memory()
|
||||
.write_obj(1u16, num_buffers_addr)
|
||||
.map_err(NetQueuePairError::GuestMemory)?;
|
||||
|
||||
self.counter_bytes += Wrapping(result as u64 - vnet_hdr_len() as u64);
|
||||
self.counter_frames += Wrapping(1);
|
||||
|
||||
result as u32
|
||||
};
|
||||
|
||||
// For the sake of simplicity (keeping the handling of RX_QUEUE_EVENT and
|
||||
|
||||
Reference in New Issue
Block a user