summary refs log tree commit diff
path: root/pkgs/applications/virtualization/cloud-hypervisor/vhost/0001-vhost-fix-receiving-reply-payloads.patch
blob: 1b013b922d6f9f5981116a4c9c929b80c0140922 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
From a1434fa3cb740ecf675c56db746f5098e6267a12 Mon Sep 17 00:00:00 2001
From: David Stevens <stevensd@chromium.org>
Date: Wed, 15 Jun 2022 15:56:18 +0900
Subject: [PATCH 1/3] vhost: fix receiving reply payloads

The existing code confuses the length of the request with the length of
the reply in recv_reply_with_payload. This makes it impossible to use
for any requests where the reply differs in size. Fix this by
determining payload size after reading the reply header.

(cherry-picked from crosvm commit 31f04e92709980a4ffc56b1631f8b4be437cc2fe)

Co-authored-by: Alyssa Ross <hi@alyssa.is>
Signed-off-by: Alyssa Ross <hi@alyssa.is>
---
 crates/vhost/src/vhost_user/connection.rs | 29 ++++++++++-------------
 crates/vhost/src/vhost_user/master.rs     | 16 +++----------
 2 files changed, 15 insertions(+), 30 deletions(-)

diff --git a/crates/vhost/src/vhost_user/connection.rs b/crates/vhost/src/vhost_user/connection.rs
index 4a62e12..3c308a8 100644
--- a/crates/vhost/src/vhost_user/connection.rs
+++ b/crates/vhost/src/vhost_user/connection.rs
@@ -551,7 +551,7 @@ impl<R: Req> Endpoint<R> {
     /// accepted and all other file descriptor will be discard silently.
     ///
     /// # Return:
-    /// * - (message header, message body, size of payload, [received files]) on success.
+    /// * - (message header, message body, payload, [received files]) on success.
     /// * - SocketRetry: temporary error caused by signals or short of resources.
     /// * - SocketBroken: the underline socket is broken.
     /// * - SocketError: other socket related errors.
@@ -560,15 +560,13 @@ impl<R: Req> Endpoint<R> {
     #[cfg_attr(feature = "cargo-clippy", allow(clippy::type_complexity))]
     pub fn recv_payload_into_buf<T: ByteValued + Sized + VhostUserMsgValidator>(
         &mut self,
-        buf: &mut [u8],
-    ) -> Result<(VhostUserMsgHeader<R>, T, usize, Option<Vec<File>>)> {
-        let mut hdr = VhostUserMsgHeader::default();
+    ) -> Result<(VhostUserMsgHeader<R>, T, Vec<u8>, Option<Vec<File>>)> {
         let mut body: T = Default::default();
+        let (hdr, files) = self.recv_header()?;
+
+        let payload_size = hdr.get_size() as usize - mem::size_of::<T>();
+        let mut buf: Vec<u8> = vec![0; payload_size];
         let mut iovs = [
-            iovec {
-                iov_base: (&mut hdr as *mut VhostUserMsgHeader<R>) as *mut c_void,
-                iov_len: mem::size_of::<VhostUserMsgHeader<R>>(),
-            },
             iovec {
                 iov_base: (&mut body as *mut T) as *mut c_void,
                 iov_len: mem::size_of::<T>(),
@@ -578,19 +576,16 @@ impl<R: Req> Endpoint<R> {
                 iov_len: buf.len(),
             },
         ];
-        // SAFETY: Safe because we own hdr and body and have a mutable borrow of buf, and
-        // hdr and body are ByteValued, and it's safe to fill a byte slice with
-        // arbitrary data.
-        let (bytes, files) = unsafe { self.recv_into_iovec_all(&mut iovs[..])? };
-
-        let total = mem::size_of::<VhostUserMsgHeader<R>>() + mem::size_of::<T>();
-        if bytes < total {
+        // SAFETY: Safe because we own body and buf, and body is ByteValued, and it's safe
+        // to fill a byte slice with arbitrary data.
+        let (bytes, more_files) = unsafe { self.recv_into_iovec_all(&mut iovs)? };
+        if bytes < hdr.get_size() as usize {
             return Err(Error::PartialMessage);
-        } else if !hdr.is_valid() || !body.is_valid() {
+        } else if !body.is_valid() || more_files.is_some() {
             return Err(Error::InvalidMessage);
         }
 
-        Ok((hdr, body, bytes - total, files))
+        Ok((hdr, body, buf, files))
     }
 }
 
diff --git a/crates/vhost/src/vhost_user/master.rs b/crates/vhost/src/vhost_user/master.rs
index feeb984..89aec20 100644
--- a/crates/vhost/src/vhost_user/master.rs
+++ b/crates/vhost/src/vhost_user/master.rs
@@ -673,23 +673,13 @@ impl MasterInternal {
         &mut self,
         hdr: &VhostUserMsgHeader<MasterReq>,
     ) -> VhostUserResult<(T, Vec<u8>, Option<Vec<File>>)> {
-        if mem::size_of::<T>() > MAX_MSG_SIZE
-            || hdr.get_size() as usize <= mem::size_of::<T>()
-            || hdr.get_size() as usize > MAX_MSG_SIZE
-            || hdr.is_reply()
-        {
+        if mem::size_of::<T>() > MAX_MSG_SIZE || hdr.is_reply() {
             return Err(VhostUserError::InvalidParam);
         }
         self.check_state()?;
 
-        let mut buf: Vec<u8> = vec![0; hdr.get_size() as usize - mem::size_of::<T>()];
-        let (reply, body, bytes, files) = self.main_sock.recv_payload_into_buf::<T>(&mut buf)?;
-        if !reply.is_reply_for(hdr)
-            || reply.get_size() as usize != mem::size_of::<T>() + bytes
-            || files.is_some()
-            || !body.is_valid()
-            || bytes != buf.len()
-        {
+        let (reply, body, buf, files) = self.main_sock.recv_payload_into_buf::<T>()?;
+        if !reply.is_reply_for(hdr) || files.is_some() || !body.is_valid() {
             return Err(VhostUserError::InvalidMessage);
         }
 
-- 
2.42.0