vmm_vhost/
backend_server.rs

1// Copyright (C) 2019 Alibaba Cloud Computing. All rights reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use std::fs::File;
5use std::mem;
6
7use base::AsRawDescriptor;
8use base::RawDescriptor;
9use base::SafeDescriptor;
10use zerocopy::FromBytes;
11use zerocopy::Immutable;
12use zerocopy::IntoBytes;
13use zerocopy::Ref;
14
15use crate::into_single_file;
16use crate::message::*;
17use crate::Connection;
18use crate::Error;
19use crate::FrontendReq;
20use crate::Result;
21use crate::SharedMemoryRegion;
22
23/// Trait for vhost-user backends.
24///
25/// Each method corresponds to a vhost-user protocol method. See the specification for details.
26#[allow(missing_docs)]
27pub trait Backend {
28    fn set_owner(&mut self) -> Result<()>;
29    fn reset_owner(&mut self) -> Result<()>;
30    fn get_features(&mut self) -> Result<u64>;
31    fn set_features(&mut self, features: u64) -> Result<()>;
32    fn set_mem_table(&mut self, ctx: &[VhostUserMemoryRegion], files: Vec<File>) -> Result<()>;
33    fn set_vring_num(&mut self, index: u32, num: u32) -> Result<()>;
34    fn set_vring_addr(
35        &mut self,
36        index: u32,
37        flags: VhostUserVringAddrFlags,
38        descriptor: u64,
39        used: u64,
40        available: u64,
41        log: u64,
42    ) -> Result<()>;
43    // TODO: b/331466964 - Argument type is wrong for packed queues.
44    fn set_vring_base(&mut self, index: u32, base: u32) -> Result<()>;
45    // TODO: b/331466964 - Return type is wrong for packed queues.
46    fn get_vring_base(&mut self, index: u32) -> Result<VhostUserVringState>;
47    fn set_vring_kick(&mut self, index: u8, fd: Option<File>) -> Result<()>;
48    fn set_vring_call(&mut self, index: u8, fd: Option<File>) -> Result<()>;
49    fn set_vring_err(&mut self, index: u8, fd: Option<File>) -> Result<()>;
50
51    fn get_protocol_features(&mut self) -> Result<VhostUserProtocolFeatures>;
52    fn set_protocol_features(&mut self, features: u64) -> Result<()>;
53    fn get_queue_num(&mut self) -> Result<u64>;
54    fn set_vring_enable(&mut self, index: u32, enable: bool) -> Result<()>;
55    fn get_config(
56        &mut self,
57        offset: u32,
58        size: u32,
59        flags: VhostUserConfigFlags,
60    ) -> Result<Vec<u8>>;
61    fn set_config(&mut self, offset: u32, buf: &[u8], flags: VhostUserConfigFlags) -> Result<()>;
62    fn set_backend_req_fd(&mut self, _vu_req: Connection) {}
63    fn get_inflight_fd(
64        &mut self,
65        inflight: &VhostUserInflight,
66    ) -> Result<(VhostUserInflight, File)>;
67    fn set_inflight_fd(&mut self, inflight: &VhostUserInflight, file: File) -> Result<()>;
68    fn get_max_mem_slots(&mut self) -> Result<u64>;
69    fn add_mem_region(&mut self, region: &VhostUserSingleMemoryRegion, fd: File) -> Result<()>;
70    fn remove_mem_region(&mut self, region: &VhostUserSingleMemoryRegion) -> Result<()>;
71    fn set_device_state_fd(
72        &mut self,
73        transfer_direction: VhostUserTransferDirection,
74        migration_phase: VhostUserMigrationPhase,
75        fd: File,
76    ) -> Result<Option<File>>;
77    fn check_device_state(&mut self) -> Result<()>;
78    fn get_shmem_config(&mut self) -> Result<Vec<SharedMemoryRegion>>;
79}
80
81impl<'a> AsMut<dyn Backend + 'a> for dyn Backend + 'a {
82    fn as_mut(&mut self) -> &mut (dyn Backend + 'a) {
83        self
84    }
85}
86
87impl<'a, T> Backend for T
88where
89    T: AsMut<dyn Backend + 'a>,
90{
91    fn set_owner(&mut self) -> Result<()> {
92        self.as_mut().set_owner()
93    }
94
95    fn reset_owner(&mut self) -> Result<()> {
96        self.as_mut().reset_owner()
97    }
98
99    fn get_features(&mut self) -> Result<u64> {
100        self.as_mut().get_features()
101    }
102
103    fn set_features(&mut self, features: u64) -> Result<()> {
104        self.as_mut().set_features(features)
105    }
106
107    fn set_mem_table(&mut self, ctx: &[VhostUserMemoryRegion], files: Vec<File>) -> Result<()> {
108        self.as_mut().set_mem_table(ctx, files)
109    }
110
111    fn set_vring_num(&mut self, index: u32, num: u32) -> Result<()> {
112        self.as_mut().set_vring_num(index, num)
113    }
114
115    fn set_vring_addr(
116        &mut self,
117        index: u32,
118        flags: VhostUserVringAddrFlags,
119        descriptor: u64,
120        used: u64,
121        available: u64,
122        log: u64,
123    ) -> Result<()> {
124        self.as_mut()
125            .set_vring_addr(index, flags, descriptor, used, available, log)
126    }
127
128    fn set_vring_base(&mut self, index: u32, base: u32) -> Result<()> {
129        self.as_mut().set_vring_base(index, base)
130    }
131
132    fn get_vring_base(&mut self, index: u32) -> Result<VhostUserVringState> {
133        self.as_mut().get_vring_base(index)
134    }
135
136    fn set_vring_kick(&mut self, index: u8, fd: Option<File>) -> Result<()> {
137        self.as_mut().set_vring_kick(index, fd)
138    }
139
140    fn set_vring_call(&mut self, index: u8, fd: Option<File>) -> Result<()> {
141        self.as_mut().set_vring_call(index, fd)
142    }
143
144    fn set_vring_err(&mut self, index: u8, fd: Option<File>) -> Result<()> {
145        self.as_mut().set_vring_err(index, fd)
146    }
147
148    fn get_protocol_features(&mut self) -> Result<VhostUserProtocolFeatures> {
149        self.as_mut().get_protocol_features()
150    }
151
152    fn set_protocol_features(&mut self, features: u64) -> Result<()> {
153        self.as_mut().set_protocol_features(features)
154    }
155
156    fn get_queue_num(&mut self) -> Result<u64> {
157        self.as_mut().get_queue_num()
158    }
159
160    fn set_vring_enable(&mut self, index: u32, enable: bool) -> Result<()> {
161        self.as_mut().set_vring_enable(index, enable)
162    }
163
164    fn get_config(
165        &mut self,
166        offset: u32,
167        size: u32,
168        flags: VhostUserConfigFlags,
169    ) -> Result<Vec<u8>> {
170        self.as_mut().get_config(offset, size, flags)
171    }
172
173    fn set_config(&mut self, offset: u32, buf: &[u8], flags: VhostUserConfigFlags) -> Result<()> {
174        self.as_mut().set_config(offset, buf, flags)
175    }
176
177    fn set_backend_req_fd(&mut self, vu_req: Connection) {
178        self.as_mut().set_backend_req_fd(vu_req)
179    }
180
181    fn get_inflight_fd(
182        &mut self,
183        inflight: &VhostUserInflight,
184    ) -> Result<(VhostUserInflight, File)> {
185        self.as_mut().get_inflight_fd(inflight)
186    }
187
188    fn set_inflight_fd(&mut self, inflight: &VhostUserInflight, file: File) -> Result<()> {
189        self.as_mut().set_inflight_fd(inflight, file)
190    }
191
192    fn get_max_mem_slots(&mut self) -> Result<u64> {
193        self.as_mut().get_max_mem_slots()
194    }
195
196    fn add_mem_region(&mut self, region: &VhostUserSingleMemoryRegion, fd: File) -> Result<()> {
197        self.as_mut().add_mem_region(region, fd)
198    }
199
200    fn remove_mem_region(&mut self, region: &VhostUserSingleMemoryRegion) -> Result<()> {
201        self.as_mut().remove_mem_region(region)
202    }
203
204    fn set_device_state_fd(
205        &mut self,
206        transfer_direction: VhostUserTransferDirection,
207        migration_phase: VhostUserMigrationPhase,
208        fd: File,
209    ) -> Result<Option<File>> {
210        self.as_mut()
211            .set_device_state_fd(transfer_direction, migration_phase, fd)
212    }
213
214    fn check_device_state(&mut self) -> Result<()> {
215        self.as_mut().check_device_state()
216    }
217
218    fn get_shmem_config(&mut self) -> Result<Vec<SharedMemoryRegion>> {
219        self.as_mut().get_shmem_config()
220    }
221}
222
223/// Handles requests from a vhost-user connection by dispatching them to [[Backend]] methods.
224pub struct BackendServer<S: Backend> {
225    /// Underlying connection for communication.
226    connection: Connection,
227    // the vhost-user backend device object
228    backend: S,
229
230    virtio_features: u64,
231    acked_virtio_features: u64,
232    protocol_features: VhostUserProtocolFeatures,
233    acked_protocol_features: u64,
234
235    /// Sending ack for messages without payload.
236    reply_ack_enabled: bool,
237}
238
239impl<S: Backend> AsRef<S> for BackendServer<S> {
240    fn as_ref(&self) -> &S {
241        &self.backend
242    }
243}
244
245impl<S: Backend> BackendServer<S> {
246    pub fn new(connection: Connection, backend: S) -> Self {
247        BackendServer {
248            connection,
249            backend,
250            virtio_features: 0,
251            acked_virtio_features: 0,
252            protocol_features: VhostUserProtocolFeatures::empty(),
253            acked_protocol_features: 0,
254            reply_ack_enabled: false,
255        }
256    }
257
258    /// Receives and validates a vhost-user message header and optional files.
259    ///
260    /// Since the length of vhost-user messages are different among message types, regular
261    /// vhost-user messages are sent via an underlying communication channel in stream mode.
262    /// (e.g. `SOCK_STREAM` in UNIX)
263    /// So, the logic of receiving and handling a message consists of the following steps:
264    ///
265    /// 1. Receives a message header and optional attached file.
266    /// 2. Validates the message header.
267    /// 3. Check if optional payloads is expected.
268    /// 4. Wait for the optional payloads.
269    /// 5. Receives optional payloads.
270    /// 6. Processes the message.
271    ///
272    /// This method [`BackendServer::recv_header()`] is in charge of the step (1) and (2),
273    /// [`BackendServer::needs_wait_for_payload()`] is (3), and
274    /// [`BackendServer::process_message()`] is (5) and (6). We need to have the three method
275    /// separately for multi-platform supports; [`BackendServer::recv_header()`] and
276    /// [`BackendServer::process_message()`] need to be separated because the way of waiting for
277    /// incoming messages differs between Unix and Windows so it's the caller's responsibility to
278    /// wait before [`BackendServer::process_message()`].
279    ///
280    /// Note that some vhost-user protocol variant such as VVU doesn't assume stream mode. In this
281    /// case, a message header and its body are sent together so the step (4) is skipped. We handle
282    /// this case in [`BackendServer::needs_wait_for_payload()`].
283    ///
284    /// The following pseudo code describes how a caller should process incoming vhost-user
285    /// messages:
286    /// ```ignore
287    /// loop {
288    ///   // block until a message header comes.
289    ///   // The actual code differs, depending on platforms.
290    ///   connection.wait_readable().unwrap();
291    ///
292    ///   // (1) and (2)
293    ///   let (hdr, files) = backend_server.recv_header();
294    ///
295    ///   // (3)
296    ///   if backend_server.needs_wait_for_payload(&hdr) {
297    ///     // (4) block until a payload comes if needed.
298    ///     connection.wait_readable().unwrap();
299    ///   }
300    ///
301    ///   // (5) and (6)
302    ///   backend_server.process_message(&hdr, &files).unwrap();
303    /// }
304    /// ```
305    pub fn recv_header(&mut self) -> Result<(VhostUserMsgHeader, Vec<File>)> {
306        // The underlying communication channel is a Unix domain socket in
307        // stream mode, and recvmsg() is a little tricky here. To successfully
308        // receive attached file descriptors, we need to receive messages and
309        // corresponding attached file descriptors in this way:
310        // . recv messsage header and optional attached file
311        // . validate message header
312        // . recv optional message body and payload according size field in
313        //   message header
314        // . validate message body and optional payload
315        let (hdr, files) = match self.connection.recv_header() {
316            Ok((hdr, files)) => (hdr, files),
317            Err(Error::Disconnect) => {
318                // If the client closed the connection before sending a header, this should be
319                // handled as a legal exit.
320                return Err(Error::ClientExit);
321            }
322            Err(e) => {
323                return Err(e);
324            }
325        };
326
327        if !hdr.is_valid() {
328            return Err(Error::InvalidMessage);
329        }
330
331        self.check_attached_files(&hdr, &files)?;
332
333        Ok((hdr, files))
334    }
335
336    /// Returns whether the caller needs to wait for the incoming message before calling
337    /// [`BackendServer::process_message`].
338    ///
339    /// See [`BackendServer::recv_header`]'s doc comment for the usage.
340    pub fn needs_wait_for_payload(&self, hdr: &VhostUserMsgHeader) -> bool {
341        // Since the vhost-user protocol uses stream mode, we need to wait until an additional
342        // payload is available if exists.
343        hdr.get_size() != 0
344    }
345
346    /// Main entrance to request from the communication channel.
347    ///
348    /// Receive and handle one incoming request message from the frontend.
349    /// See [`BackendServer::recv_header`]'s doc comment for the usage.
350    ///
351    /// # Return:
352    /// * `Ok(())`: one request was successfully handled.
353    /// * `Err(ClientExit)`: the frontend closed the connection properly. This isn't an actual
354    ///   failure.
355    /// * `Err(Disconnect)`: the connection was closed unexpectedly.
356    /// * `Err(InvalidMessage)`: the vmm sent a illegal message.
357    /// * other errors: failed to handle a request.
358    pub fn process_message(&mut self, hdr: VhostUserMsgHeader, files: Vec<File>) -> Result<()> {
359        let (buf, extra_files) = self.connection.recv_body_bytes(&hdr)?;
360        let size = buf.len();
361        if !extra_files.is_empty() {
362            return Err(Error::InvalidMessage);
363        }
364
365        // TODO: The error handling here is inconsistent. Sometimes we report the error to the
366        // client and keep going, sometimes we report the error and then close the connection,
367        // sometimes we just close the connection.
368        match hdr.get_code() {
369            Ok(FrontendReq::SET_OWNER) => {
370                self.check_request_size(&hdr, size, 0)?;
371                let res = self.backend.set_owner();
372                self.send_ack_message(&hdr, res.is_ok())?;
373                res?;
374            }
375            Ok(FrontendReq::RESET_OWNER) => {
376                self.check_request_size(&hdr, size, 0)?;
377                let res = self.backend.reset_owner();
378                self.send_ack_message(&hdr, res.is_ok())?;
379                res?;
380            }
381            Ok(FrontendReq::GET_FEATURES) => {
382                self.check_request_size(&hdr, size, 0)?;
383                let mut features = self.backend.get_features()?;
384
385                // Don't advertise packed queues even if the device does. We don't handle them
386                // properly yet at the protocol layer.
387                // TODO: b/331466964 - Remove once support is added.
388                features &= !(1 << VIRTIO_F_RING_PACKED);
389
390                let msg = VhostUserU64::new(features);
391                self.send_reply_message(&hdr, &msg)?;
392                self.virtio_features = features;
393                self.update_reply_ack_flag();
394            }
395            Ok(FrontendReq::SET_FEATURES) => {
396                let mut msg = self.extract_request_body::<VhostUserU64>(&hdr, size, &buf)?;
397
398                // Don't allow packed queues even if the device does. We don't handle them
399                // properly yet at the protocol layer.
400                // TODO: b/331466964 - Remove once support is added.
401                msg.value &= !(1 << VIRTIO_F_RING_PACKED);
402
403                let res = self.backend.set_features(msg.value);
404                self.acked_virtio_features = msg.value;
405                self.update_reply_ack_flag();
406                self.send_ack_message(&hdr, res.is_ok())?;
407                res?;
408            }
409            Ok(FrontendReq::SET_MEM_TABLE) => {
410                let res = self.set_mem_table(&hdr, size, &buf, files);
411                self.send_ack_message(&hdr, res.is_ok())?;
412                res?;
413            }
414            Ok(FrontendReq::SET_VRING_NUM) => {
415                let msg = self.extract_request_body::<VhostUserVringState>(&hdr, size, &buf)?;
416                let res = self.backend.set_vring_num(msg.index, msg.num);
417                self.send_ack_message(&hdr, res.is_ok())?;
418                res?;
419            }
420            Ok(FrontendReq::SET_VRING_ADDR) => {
421                let msg = self.extract_request_body::<VhostUserVringAddr>(&hdr, size, &buf)?;
422                let flags = match VhostUserVringAddrFlags::from_bits(msg.flags) {
423                    Some(val) => val,
424                    None => return Err(Error::InvalidMessage),
425                };
426                let res = self.backend.set_vring_addr(
427                    msg.index,
428                    flags,
429                    msg.descriptor,
430                    msg.used,
431                    msg.available,
432                    msg.log,
433                );
434                self.send_ack_message(&hdr, res.is_ok())?;
435                res?;
436            }
437            Ok(FrontendReq::SET_VRING_BASE) => {
438                let msg = self.extract_request_body::<VhostUserVringState>(&hdr, size, &buf)?;
439                let res = self.backend.set_vring_base(msg.index, msg.num);
440                self.send_ack_message(&hdr, res.is_ok())?;
441                res?;
442            }
443            Ok(FrontendReq::GET_VRING_BASE) => {
444                let msg = self.extract_request_body::<VhostUserVringState>(&hdr, size, &buf)?;
445                let reply = self.backend.get_vring_base(msg.index)?;
446                self.send_reply_message(&hdr, &reply)?;
447            }
448            Ok(FrontendReq::SET_VRING_CALL) => {
449                self.check_request_size(&hdr, size, mem::size_of::<VhostUserU64>())?;
450                let (index, file) = self.handle_vring_fd_request(&buf, files)?;
451                let res = self.backend.set_vring_call(index, file);
452                self.send_ack_message(&hdr, res.is_ok())?;
453                res?;
454            }
455            Ok(FrontendReq::SET_VRING_KICK) => {
456                self.check_request_size(&hdr, size, mem::size_of::<VhostUserU64>())?;
457                let (index, file) = self.handle_vring_fd_request(&buf, files)?;
458                let res = self.backend.set_vring_kick(index, file);
459                self.send_ack_message(&hdr, res.is_ok())?;
460                res?;
461            }
462            Ok(FrontendReq::SET_VRING_ERR) => {
463                self.check_request_size(&hdr, size, mem::size_of::<VhostUserU64>())?;
464                let (index, file) = self.handle_vring_fd_request(&buf, files)?;
465                let res = self.backend.set_vring_err(index, file);
466                self.send_ack_message(&hdr, res.is_ok())?;
467                res?;
468            }
469            Ok(FrontendReq::GET_PROTOCOL_FEATURES) => {
470                self.check_request_size(&hdr, size, 0)?;
471                let features = self.backend.get_protocol_features()?;
472                let msg = VhostUserU64::new(features.bits());
473                self.send_reply_message(&hdr, &msg)?;
474                self.protocol_features = features;
475                self.update_reply_ack_flag();
476            }
477            Ok(FrontendReq::SET_PROTOCOL_FEATURES) => {
478                let msg = self.extract_request_body::<VhostUserU64>(&hdr, size, &buf)?;
479                let res = self.backend.set_protocol_features(msg.value);
480                self.acked_protocol_features = msg.value;
481                self.update_reply_ack_flag();
482                self.send_ack_message(&hdr, res.is_ok())?;
483                res?;
484            }
485            Ok(FrontendReq::GET_QUEUE_NUM) => {
486                if self.acked_protocol_features & VhostUserProtocolFeatures::MQ.bits() == 0 {
487                    return Err(Error::InvalidOperation);
488                }
489                self.check_request_size(&hdr, size, 0)?;
490                let num = self.backend.get_queue_num()?;
491                let msg = VhostUserU64::new(num);
492                self.send_reply_message(&hdr, &msg)?;
493            }
494            Ok(FrontendReq::SET_VRING_ENABLE) => {
495                let msg = self.extract_request_body::<VhostUserVringState>(&hdr, size, &buf)?;
496                if self.acked_virtio_features & 1 << VHOST_USER_F_PROTOCOL_FEATURES == 0 {
497                    return Err(Error::InvalidOperation);
498                }
499                let enable = match msg.num {
500                    1 => true,
501                    0 => false,
502                    _ => {
503                        return Err(Error::InvalidParam(
504                            "SET_VRING_ENABLE: num out of range (must be [0, 1])",
505                        ))
506                    }
507                };
508
509                let res = self.backend.set_vring_enable(msg.index, enable);
510                self.send_ack_message(&hdr, res.is_ok())?;
511                res?;
512            }
513            Ok(FrontendReq::GET_CONFIG) => {
514                if self.acked_protocol_features & VhostUserProtocolFeatures::CONFIG.bits() == 0 {
515                    return Err(Error::InvalidOperation);
516                }
517                self.check_request_size(&hdr, size, hdr.get_size() as usize)?;
518                self.get_config(&hdr, &buf)?;
519            }
520            Ok(FrontendReq::SET_CONFIG) => {
521                if self.acked_protocol_features & VhostUserProtocolFeatures::CONFIG.bits() == 0 {
522                    return Err(Error::InvalidOperation);
523                }
524                self.check_request_size(&hdr, size, hdr.get_size() as usize)?;
525                let res = self.set_config(&buf);
526                self.send_ack_message(&hdr, res.is_ok())?;
527                res?;
528            }
529            Ok(FrontendReq::SET_BACKEND_REQ_FD) => {
530                if self.acked_protocol_features & VhostUserProtocolFeatures::BACKEND_REQ.bits() == 0
531                {
532                    return Err(Error::InvalidOperation);
533                }
534                self.check_request_size(&hdr, size, hdr.get_size() as usize)?;
535                let res = self.set_backend_req_fd(files);
536                self.send_ack_message(&hdr, res.is_ok())?;
537                res?;
538            }
539            Ok(FrontendReq::GET_INFLIGHT_FD) => {
540                if self.acked_protocol_features & VhostUserProtocolFeatures::INFLIGHT_SHMFD.bits()
541                    == 0
542                {
543                    return Err(Error::InvalidOperation);
544                }
545
546                let msg = self.extract_request_body::<VhostUserInflight>(&hdr, size, &buf)?;
547                let (inflight, file) = self.backend.get_inflight_fd(&msg)?;
548                let reply_hdr = self.new_reply_header::<VhostUserInflight>(&hdr, 0)?;
549                self.connection.send_message(
550                    &reply_hdr,
551                    &inflight,
552                    Some(&[file.as_raw_descriptor()]),
553                )?;
554            }
555            Ok(FrontendReq::SET_INFLIGHT_FD) => {
556                if self.acked_protocol_features & VhostUserProtocolFeatures::INFLIGHT_SHMFD.bits()
557                    == 0
558                {
559                    return Err(Error::InvalidOperation);
560                }
561                let file = into_single_file(files).ok_or(Error::IncorrectFds)?;
562                let msg = self.extract_request_body::<VhostUserInflight>(&hdr, size, &buf)?;
563                let res = self.backend.set_inflight_fd(&msg, file);
564                self.send_ack_message(&hdr, res.is_ok())?;
565                res?;
566            }
567            Ok(FrontendReq::GET_MAX_MEM_SLOTS) => {
568                if self.acked_protocol_features
569                    & VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS.bits()
570                    == 0
571                {
572                    return Err(Error::InvalidOperation);
573                }
574                self.check_request_size(&hdr, size, 0)?;
575                let num = self.backend.get_max_mem_slots()?;
576                let msg = VhostUserU64::new(num);
577                self.send_reply_message(&hdr, &msg)?;
578            }
579            Ok(FrontendReq::ADD_MEM_REG) => {
580                if self.acked_protocol_features
581                    & VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS.bits()
582                    == 0
583                {
584                    return Err(Error::InvalidOperation);
585                }
586                let file = into_single_file(files).ok_or(Error::InvalidParam(
587                    "ADD_MEM_REG: exactly one file must be provided",
588                ))?;
589                let msg =
590                    self.extract_request_body::<VhostUserSingleMemoryRegion>(&hdr, size, &buf)?;
591                let res = self.backend.add_mem_region(&msg, file);
592                self.send_ack_message(&hdr, res.is_ok())?;
593                res?;
594            }
595            Ok(FrontendReq::REM_MEM_REG) => {
596                if self.acked_protocol_features
597                    & VhostUserProtocolFeatures::CONFIGURE_MEM_SLOTS.bits()
598                    == 0
599                {
600                    return Err(Error::InvalidOperation);
601                }
602
603                let msg =
604                    self.extract_request_body::<VhostUserSingleMemoryRegion>(&hdr, size, &buf)?;
605                let res = self.backend.remove_mem_region(&msg);
606                self.send_ack_message(&hdr, res.is_ok())?;
607                res?;
608            }
609            Ok(FrontendReq::SET_DEVICE_STATE_FD) => {
610                if self.acked_protocol_features & VhostUserProtocolFeatures::DEVICE_STATE.bits()
611                    == 0
612                {
613                    return Err(Error::InvalidOperation);
614                }
615                // Read request.
616                let msg =
617                    self.extract_request_body::<DeviceStateTransferParameters>(&hdr, size, &buf)?;
618                let transfer_direction = match msg.transfer_direction {
619                    0 => VhostUserTransferDirection::Save,
620                    1 => VhostUserTransferDirection::Load,
621                    _ => return Err(Error::InvalidMessage),
622                };
623                let migration_phase = match msg.migration_phase {
624                    0 => VhostUserMigrationPhase::Stopped,
625                    _ => return Err(Error::InvalidMessage),
626                };
627                // Call backend.
628                let res = self.backend.set_device_state_fd(
629                    transfer_direction,
630                    migration_phase,
631                    files.into_iter().next().ok_or(Error::IncorrectFds)?,
632                );
633                // Send response.
634                let (msg, fds) = match &res {
635                    Ok(None) => (VhostUserU64::new(0x100), None),
636                    Ok(Some(file)) => (VhostUserU64::new(0), Some(file.as_raw_descriptor())),
637                    // Just in case, set the "invalid FD" flag on error.
638                    Err(_) => (VhostUserU64::new(0x101), None),
639                };
640                let reply_hdr: VhostUserMsgHeader =
641                    self.new_reply_header::<VhostUserU64>(&hdr, 0)?;
642                self.connection.send_message(
643                    &reply_hdr,
644                    &msg,
645                    fds.as_ref().map(std::slice::from_ref),
646                )?;
647                res?;
648            }
649            Ok(FrontendReq::CHECK_DEVICE_STATE) => {
650                if self.acked_protocol_features & VhostUserProtocolFeatures::DEVICE_STATE.bits()
651                    == 0
652                {
653                    return Err(Error::InvalidOperation);
654                }
655                let res = self.backend.check_device_state();
656                let msg = VhostUserU64::new(if res.is_ok() { 0 } else { 1 });
657                self.send_reply_message(&hdr, &msg)?;
658                res?;
659            }
660            Ok(FrontendReq::GET_SHMEM_CONFIG) => {
661                let msg = VhostUserShMemConfig::new(&self.backend.get_shmem_config()?);
662                self.send_reply_message(&hdr, &msg)?;
663            }
664            _ => {
665                return Err(Error::InvalidMessage);
666            }
667        }
668        Ok(())
669    }
670
671    fn new_reply_header<T: Sized>(
672        &self,
673        req: &VhostUserMsgHeader,
674        payload_size: usize,
675    ) -> Result<VhostUserMsgHeader> {
676        Ok(VhostUserMsgHeader::new_reply_header(
677            req.get_code::<FrontendReq>()
678                .map_err(|_| Error::InvalidMessage)?,
679            (mem::size_of::<T>()
680                .checked_add(payload_size)
681                .ok_or(Error::OversizedMsg)?)
682            .try_into()
683            .map_err(Error::InvalidCastToInt)?,
684        ))
685    }
686
687    /// Sends reply back to Vhost frontend in response to a message.
688    fn send_ack_message(&mut self, req: &VhostUserMsgHeader, success: bool) -> Result<()> {
689        if self.reply_ack_enabled && req.is_need_reply() {
690            let hdr: VhostUserMsgHeader = self.new_reply_header::<VhostUserU64>(req, 0)?;
691            let val = if success { 0 } else { 1 };
692            let msg = VhostUserU64::new(val);
693            self.connection.send_message(&hdr, &msg, None)?;
694        }
695        Ok(())
696    }
697
698    fn send_reply_message<T: IntoBytes + Immutable>(
699        &mut self,
700        req: &VhostUserMsgHeader,
701        msg: &T,
702    ) -> Result<()> {
703        let hdr = self.new_reply_header::<T>(req, 0)?;
704        self.connection.send_message(&hdr, msg, None)?;
705        Ok(())
706    }
707
708    fn send_reply_with_payload<T: IntoBytes + Immutable>(
709        &mut self,
710        req: &VhostUserMsgHeader,
711        msg: &T,
712        payload: &[u8],
713    ) -> Result<()> {
714        let hdr = self.new_reply_header::<T>(req, payload.len())?;
715        self.connection
716            .send_message_with_payload(&hdr, msg, payload, None)?;
717        Ok(())
718    }
719
720    fn set_mem_table(
721        &mut self,
722        hdr: &VhostUserMsgHeader,
723        size: usize,
724        buf: &[u8],
725        files: Vec<File>,
726    ) -> Result<()> {
727        self.check_request_size(hdr, size, hdr.get_size() as usize)?;
728
729        let (msg, regions) =
730            Ref::<_, VhostUserMemory>::from_prefix(buf).map_err(|_| Error::InvalidMessage)?;
731        if !msg.is_valid() {
732            return Err(Error::InvalidMessage);
733        }
734
735        // validate number of fds matching number of memory regions
736        if files.len() != msg.num_regions as usize {
737            return Err(Error::InvalidMessage);
738        }
739
740        let (regions, excess) = Ref::<_, [VhostUserMemoryRegion]>::from_prefix_with_elems(
741            regions,
742            msg.num_regions as usize,
743        )
744        .map_err(|_| Error::InvalidMessage)?;
745        if !excess.is_empty() {
746            return Err(Error::InvalidMessage);
747        }
748
749        // Validate memory regions
750        for region in regions.iter() {
751            if !region.is_valid() {
752                return Err(Error::InvalidMessage);
753            }
754        }
755
756        self.backend.set_mem_table(&regions, files)
757    }
758
759    fn get_config(&mut self, hdr: &VhostUserMsgHeader, buf: &[u8]) -> Result<()> {
760        let (msg, payload) =
761            Ref::<_, VhostUserConfig>::from_prefix(buf).map_err(|_| Error::InvalidMessage)?;
762        if !msg.is_valid() {
763            return Err(Error::InvalidMessage);
764        }
765        if payload.len() != msg.size as usize {
766            return Err(Error::InvalidMessage);
767        }
768        let flags = match VhostUserConfigFlags::from_bits(msg.flags) {
769            Some(val) => val,
770            None => return Err(Error::InvalidMessage),
771        };
772        let res = self.backend.get_config(msg.offset, msg.size, flags);
773
774        // The response payload size MUST match the request payload size on success. A zero length
775        // response is used to indicate an error.
776        match res {
777            Ok(ref buf) if buf.len() == msg.size as usize => {
778                let reply = VhostUserConfig::new(msg.offset, buf.len() as u32, flags);
779                self.send_reply_with_payload(hdr, &reply, buf.as_slice())?;
780            }
781            Ok(_) => {
782                let reply = VhostUserConfig::new(msg.offset, 0, flags);
783                self.send_reply_message(hdr, &reply)?;
784            }
785            Err(_) => {
786                let reply = VhostUserConfig::new(msg.offset, 0, flags);
787                self.send_reply_message(hdr, &reply)?;
788            }
789        }
790        Ok(())
791    }
792
793    fn set_config(&mut self, buf: &[u8]) -> Result<()> {
794        let (msg, payload) =
795            Ref::<_, VhostUserConfig>::from_prefix(buf).map_err(|_| Error::InvalidMessage)?;
796        if !msg.is_valid() {
797            return Err(Error::InvalidMessage);
798        }
799        if payload.len() != msg.size as usize {
800            return Err(Error::InvalidMessage);
801        }
802        let flags: VhostUserConfigFlags = match VhostUserConfigFlags::from_bits(msg.flags) {
803            Some(val) => val,
804            None => return Err(Error::InvalidMessage),
805        };
806
807        self.backend.set_config(msg.offset, payload, flags)
808    }
809
810    fn set_backend_req_fd(&mut self, files: Vec<File>) -> Result<()> {
811        let file = into_single_file(files).ok_or(Error::InvalidMessage)?;
812        let fd: SafeDescriptor = file.into();
813        let connection = Connection::try_from(fd).map_err(|_| Error::InvalidMessage)?;
814        self.backend.set_backend_req_fd(connection);
815        Ok(())
816    }
817
818    /// Parses an incoming |SET_VRING_KICK| or |SET_VRING_CALL| message into a
819    /// Vring number and an fd.
820    fn handle_vring_fd_request(
821        &mut self,
822        buf: &[u8],
823        files: Vec<File>,
824    ) -> Result<(u8, Option<File>)> {
825        let (msg, _) = VhostUserU64::read_from_prefix(buf).map_err(|_| Error::InvalidMessage)?;
826        if !msg.is_valid() {
827            return Err(Error::InvalidMessage);
828        }
829
830        // Bits (0-7) of the payload contain the vring index. Bit 8 is the
831        // invalid FD flag (VHOST_USER_VRING_NOFD_MASK).
832        // This bit is set when there is no file descriptor
833        // in the ancillary data. This signals that polling will be used
834        // instead of waiting for the call.
835        // If Bit 8 is unset, the data must contain a file descriptor.
836        let has_fd = (msg.value & 0x100u64) == 0;
837
838        let file = into_single_file(files);
839
840        if has_fd && file.is_none() || !has_fd && file.is_some() {
841            return Err(Error::InvalidMessage);
842        }
843
844        Ok((msg.value as u8, file))
845    }
846
847    fn check_request_size(
848        &self,
849        hdr: &VhostUserMsgHeader,
850        size: usize,
851        expected: usize,
852    ) -> Result<()> {
853        if hdr.get_size() as usize != expected
854            || hdr.is_reply()
855            || hdr.get_version() != 0x1
856            || size != expected
857        {
858            return Err(Error::InvalidMessage);
859        }
860        Ok(())
861    }
862
863    fn check_attached_files(&self, hdr: &VhostUserMsgHeader, files: &[File]) -> Result<()> {
864        match hdr.get_code() {
865            Ok(FrontendReq::SET_MEM_TABLE)
866            | Ok(FrontendReq::SET_VRING_CALL)
867            | Ok(FrontendReq::SET_VRING_KICK)
868            | Ok(FrontendReq::SET_VRING_ERR)
869            | Ok(FrontendReq::SET_LOG_BASE)
870            | Ok(FrontendReq::SET_LOG_FD)
871            | Ok(FrontendReq::SET_BACKEND_REQ_FD)
872            | Ok(FrontendReq::SET_INFLIGHT_FD)
873            | Ok(FrontendReq::ADD_MEM_REG)
874            | Ok(FrontendReq::SET_DEVICE_STATE_FD) => Ok(()),
875            Err(_) => Err(Error::InvalidMessage),
876            _ if !files.is_empty() => Err(Error::InvalidMessage),
877            _ => Ok(()),
878        }
879    }
880
881    fn extract_request_body<T: Sized + FromBytes + VhostUserMsgValidator>(
882        &self,
883        hdr: &VhostUserMsgHeader,
884        size: usize,
885        buf: &[u8],
886    ) -> Result<T> {
887        self.check_request_size(hdr, size, mem::size_of::<T>())?;
888        let (body, _) = T::read_from_prefix(buf).map_err(|_| Error::InvalidMessage)?;
889        if body.is_valid() {
890            Ok(body)
891        } else {
892            Err(Error::InvalidMessage)
893        }
894    }
895
896    fn update_reply_ack_flag(&mut self) {
897        let pflag = VhostUserProtocolFeatures::REPLY_ACK;
898        self.reply_ack_enabled = (self.virtio_features & 1 << VHOST_USER_F_PROTOCOL_FEATURES) != 0
899            && self.protocol_features.contains(pflag)
900            && (self.acked_protocol_features & pflag.bits()) != 0;
901    }
902}
903
904impl<S: Backend> AsRawDescriptor for BackendServer<S> {
905    fn as_raw_descriptor(&self) -> RawDescriptor {
906        // TODO(b/221882601): figure out if this used for polling.
907        self.connection.as_raw_descriptor()
908    }
909}
910
911#[cfg(test)]
912mod tests {
913    use base::INVALID_DESCRIPTOR;
914
915    use super::*;
916    use crate::test_backend::TestBackend;
917    use crate::Connection;
918
919    #[test]
920    fn test_backend_server_new() {
921        let (p1, _p2) = Connection::pair().unwrap();
922        let backend = TestBackend::new();
923        let handler = BackendServer::new(p1, backend);
924
925        assert!(handler.as_raw_descriptor() != INVALID_DESCRIPTOR);
926    }
927}