summary refs log tree commit diff
path: root/devices/src/virtio/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'devices/src/virtio/gpu')
-rw-r--r--devices/src/virtio/gpu/mod.rs78
-rw-r--r--devices/src/virtio/gpu/protocol.rs25
2 files changed, 85 insertions, 18 deletions
diff --git a/devices/src/virtio/gpu/mod.rs b/devices/src/virtio/gpu/mod.rs
index 29142ea..97c84d5 100644
--- a/devices/src/virtio/gpu/mod.rs
+++ b/devices/src/virtio/gpu/mod.rs
@@ -8,6 +8,7 @@ mod protocol;
 use std::cell::RefCell;
 use std::collections::VecDeque;
 use std::i64;
+use std::io::Read;
 use std::mem::{self, size_of};
 use std::num::NonZeroU8;
 use std::os::unix::io::{AsRawFd, RawFd};
@@ -124,7 +125,14 @@ impl Frontend {
                 mem,
             ),
             GpuCommand::ResourceAttachBacking(info) => {
-                if reader.available_bytes() != 0 {
+                let available_bytes = match reader.available_bytes() {
+                    Ok(count) => count,
+                    Err(e) => {
+                        debug!("invalid descriptor: {}", e);
+                        0
+                    }
+                };
+                if available_bytes != 0 {
                     let entry_count = info.nr_entries.to_native() as usize;
                     let mut iovecs = Vec::with_capacity(entry_count);
                     for _ in 0..entry_count {
@@ -247,10 +255,17 @@ impl Frontend {
                 )
             }
             GpuCommand::CmdSubmit3d(info) => {
-                if reader.available_bytes() != 0 {
+                let available_bytes = match reader.available_bytes() {
+                    Ok(count) => count,
+                    Err(e) => {
+                        debug!("invalid descriptor: {}", e);
+                        0
+                    }
+                };
+                if available_bytes != 0 {
                     let cmd_size = info.size.to_native() as usize;
                     let mut cmd_buf = vec![0; cmd_size];
-                    if reader.read(&mut cmd_buf[..]).is_ok() {
+                    if reader.read_exact(&mut cmd_buf[..]).is_ok() {
                         self.backend
                             .submit_command(info.hdr.ctx_id.to_native(), &mut cmd_buf[..])
                     } else {
@@ -263,7 +278,14 @@ impl Frontend {
                 }
             }
             GpuCommand::AllocationMetadata(info) => {
-                if reader.available_bytes() != 0 {
+                let available_bytes = match reader.available_bytes() {
+                    Ok(count) => count,
+                    Err(e) => {
+                        debug!("invalid descriptor: {}", e);
+                        0
+                    }
+                };
+                if available_bytes != 0 {
                     let id = info.request_id.to_native();
                     let request_size = info.request_size.to_native();
                     let response_size = info.response_size.to_native();
@@ -275,7 +297,7 @@ impl Frontend {
 
                     let mut request_buf = vec![0; request_size as usize];
                     let response_buf = vec![0; response_size as usize];
-                    if reader.read(&mut request_buf[..]).is_ok() {
+                    if reader.read_exact(&mut request_buf[..]).is_ok() {
                         self.backend
                             .allocation_metadata(id, request_buf, response_buf)
                     } else {
@@ -286,7 +308,14 @@ impl Frontend {
                 }
             }
             GpuCommand::ResourceCreateV2(info) => {
-                if reader.available_bytes() != 0 {
+                let available_bytes = match reader.available_bytes() {
+                    Ok(count) => count,
+                    Err(e) => {
+                        debug!("invalid descriptor: {}", e);
+                        0
+                    }
+                };
+                if available_bytes != 0 {
                     let resource_id = info.resource_id.to_native();
                     let guest_memory_type = info.guest_memory_type.to_native();
                     let size = info.size.to_native();
@@ -314,7 +343,7 @@ impl Frontend {
                         }
                     }
 
-                    match reader.read(&mut args[..]) {
+                    match reader.read_exact(&mut args[..]) {
                         Ok(_) => self.backend.resource_create_v2(
                             resource_id,
                             guest_memory_type,
@@ -346,13 +375,23 @@ impl Frontend {
         let mut signal_used = false;
         while let Some(desc) = queue.pop(mem) {
             if Frontend::validate_desc(&desc) {
-                let mut reader = Reader::new(mem, desc.clone());
-                let mut writer = Writer::new(mem, desc.clone());
-                if let Some(ret_desc) =
-                    self.process_descriptor(mem, desc.index, &mut reader, &mut writer)
-                {
-                    queue.add_used(&mem, ret_desc.index, ret_desc.len);
-                    signal_used = true;
+                match (
+                    Reader::new(mem, desc.clone()),
+                    Writer::new(mem, desc.clone()),
+                ) {
+                    (Ok(mut reader), Ok(mut writer)) => {
+                        if let Some(ret_desc) =
+                            self.process_descriptor(mem, desc.index, &mut reader, &mut writer)
+                        {
+                            queue.add_used(&mem, ret_desc.index, ret_desc.len);
+                            signal_used = true;
+                        }
+                    }
+                    (_, Err(e)) | (Err(e), _) => {
+                        debug!("invalid descriptor: {}", e);
+                        queue.add_used(&mem, desc.index, 0);
+                        signal_used = true;
+                    }
                 }
             } else {
                 let likely_type = mem.read_obj_from_addr(desc.addr).unwrap_or(Le32::from(0));
@@ -391,7 +430,16 @@ impl Frontend {
         if resp.is_err() {
             debug!("{:?} -> {:?}", gpu_cmd, resp);
         }
-        if writer.available_bytes() != 0 {
+
+        let available_bytes = match writer.available_bytes() {
+            Ok(count) => count,
+            Err(e) => {
+                debug!("invalid descriptor: {}", e);
+                0
+            }
+        };
+
+        if available_bytes != 0 {
             let mut fence_id = 0;
             let mut ctx_id = 0;
             let mut flags = 0;
diff --git a/devices/src/virtio/gpu/protocol.rs b/devices/src/virtio/gpu/protocol.rs
index c6773dd..dacc850 100644
--- a/devices/src/virtio/gpu/protocol.rs
+++ b/devices/src/virtio/gpu/protocol.rs
@@ -7,6 +7,7 @@
 
 use std::cmp::min;
 use std::fmt::{self, Display};
+use std::io::{self, Write};
 use std::marker::PhantomData;
 use std::mem::{size_of, size_of_val};
 use std::str::from_utf8;
@@ -589,6 +590,8 @@ pub enum GpuCommandDecodeError {
     Memory(DescriptorError),
     /// The type of the command was invalid.
     InvalidType(u32),
+    /// An I/O error occurred.
+    IO(io::Error),
 }
 
 impl Display for GpuCommandDecodeError {
@@ -602,6 +605,7 @@ impl Display for GpuCommandDecodeError {
                 e,
             ),
             InvalidType(n) => write!(f, "invalid command type ({})", n),
+            IO(e) => write!(f, "an I/O error occurred: {}", e),
         }
     }
 }
@@ -612,6 +616,12 @@ impl From<DescriptorError> for GpuCommandDecodeError {
     }
 }
 
+impl From<io::Error> for GpuCommandDecodeError {
+    fn from(e: io::Error) -> GpuCommandDecodeError {
+        GpuCommandDecodeError::IO(e)
+    }
+}
+
 impl fmt::Debug for GpuCommand {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         use self::GpuCommand::*;
@@ -754,6 +764,8 @@ pub enum GpuResponseEncodeError {
     TooManyDisplays(usize),
     /// More planes than are valid were in a `OkResourcePlaneInfo`.
     TooManyPlanes(usize),
+    /// An I/O error occurred.
+    IO(io::Error),
 }
 
 impl Display for GpuResponseEncodeError {
@@ -768,6 +780,7 @@ impl Display for GpuResponseEncodeError {
             ),
             TooManyDisplays(n) => write!(f, "{} is more displays than are valid", n),
             TooManyPlanes(n) => write!(f, "{} is more planes than are valid", n),
+            IO(e) => write!(f, "an I/O error occurred: {}", e),
         }
     }
 }
@@ -778,6 +791,12 @@ impl From<DescriptorError> for GpuResponseEncodeError {
     }
 }
 
+impl From<io::Error> for GpuResponseEncodeError {
+    fn from(e: io::Error) -> GpuResponseEncodeError {
+        GpuResponseEncodeError::IO(e)
+    }
+}
+
 impl GpuResponse {
     /// Encodes a this `GpuResponse` into `resp` and the given set of metadata.
     pub fn encode(
@@ -823,7 +842,7 @@ impl GpuResponse {
             }
             GpuResponse::OkCapset(ref data) => {
                 resp.write_obj(hdr)?;
-                resp.write(data)?;
+                resp.write_all(data)?;
                 size_of_val(&hdr) + data.len()
             }
             GpuResponse::OkResourcePlaneInfo {
@@ -847,7 +866,7 @@ impl GpuResponse {
                     strides,
                     offsets,
                 };
-                if resp.available_bytes() >= size_of_val(&plane_info) {
+                if resp.available_bytes()? >= size_of_val(&plane_info) {
                     resp.write_obj(plane_info)?;
                     size_of_val(&plane_info)
                 } else {
@@ -869,7 +888,7 @@ impl GpuResponse {
                 };
 
                 resp.write_obj(resp_info)?;
-                resp.write(&res_info.response)?;
+                resp.write_all(&res_info.response)?;
                 size_of_val(&resp_info) + res_info.response.len()
             }
             _ => {