• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 The Chromium OS Authors. All rights reserved.
2 // SPDX-License-Identifier: Apache-2.0
3 
4 //! Structs for Unix Domain Socket listener and endpoint.
5 
6 use std::any::Any;
7 use std::fs::File;
8 use std::io::ErrorKind;
9 use std::io::IoSlice;
10 use std::io::IoSliceMut;
11 use std::marker::PhantomData;
12 use std::path::Path;
13 use std::path::PathBuf;
14 
15 use base::AsRawDescriptor;
16 use base::FromRawDescriptor;
17 use base::IntoRawDescriptor;
18 use base::RawDescriptor;
19 use base::ScmSocket;
20 
21 use crate::connection::Endpoint as EndpointTrait;
22 use crate::connection::Listener as ListenerTrait;
23 use crate::connection::Req;
24 use crate::message::*;
25 use crate::take_single_file;
26 use crate::unix::SystemListener;
27 use crate::Error;
28 use crate::Result;
29 use crate::SystemStream;
30 
31 /// Unix domain socket listener for accepting incoming connections.
32 pub struct Listener {
33     fd: SystemListener,
34     drop_path: Option<Box<dyn Any>>,
35 }
36 
37 impl Listener {
38     /// Create a unix domain socket listener.
39     ///
40     /// # Return:
41     /// * - the new Listener object on success.
42     /// * - SocketError: failed to create listener socket.
new<P: AsRef<Path>>(path: P, unlink: bool) -> Result<Self>43     pub fn new<P: AsRef<Path>>(path: P, unlink: bool) -> Result<Self> {
44         if unlink {
45             let _ = std::fs::remove_file(&path);
46         }
47         let fd = SystemListener::bind(&path).map_err(Error::SocketError)?;
48 
49         struct DropPath {
50             path: PathBuf,
51         }
52 
53         impl Drop for DropPath {
54             fn drop(&mut self) {
55                 let _ = std::fs::remove_file(&self.path);
56             }
57         }
58 
59         Ok(Listener {
60             fd,
61             drop_path: Some(Box::new(DropPath {
62                 path: path.as_ref().to_owned(),
63             })),
64         })
65     }
66 
67     /// Take and return the resources that the parent process needs to keep alive as long as the
68     /// child process lives, in case of incoming fork.
take_resources_for_parent(&mut self) -> Option<Box<dyn Any>>69     pub fn take_resources_for_parent(&mut self) -> Option<Box<dyn Any>> {
70         self.drop_path.take()
71     }
72 }
73 
74 impl ListenerTrait for Listener {
75     type Connection = SystemStream;
76     type Endpoint = Endpoint<MasterReq>;
77 
78     /// Accept an incoming connection.
79     ///
80     /// # Return:
81     /// * - Some(SystemListener): new SystemListener object if new incoming connection is available.
82     /// * - None: no incoming connection available.
83     /// * - SocketError: errors from accept().
accept(&mut self) -> Result<Option<Self::Endpoint>>84     fn accept(&mut self) -> Result<Option<Self::Endpoint>> {
85         loop {
86             match self.fd.accept() {
87                 Ok((stream, _addr)) => {
88                     return Ok(Some(Endpoint {
89                         sock: stream,
90                         _r: PhantomData,
91                     }))
92                 }
93                 Err(e) => {
94                     match e.kind() {
95                         // No incoming connection available.
96                         ErrorKind::WouldBlock => return Ok(None),
97                         // New connection closed by peer.
98                         ErrorKind::ConnectionAborted => return Ok(None),
99                         // Interrupted by signals, retry
100                         ErrorKind::Interrupted => continue,
101                         _ => return Err(Error::SocketError(e)),
102                     }
103                 }
104             }
105         }
106     }
107 
108     /// Change blocking status on the listener.
109     ///
110     /// # Return:
111     /// * - () on success.
112     /// * - SocketError: failure from set_nonblocking().
set_nonblocking(&self, block: bool) -> Result<()>113     fn set_nonblocking(&self, block: bool) -> Result<()> {
114         self.fd.set_nonblocking(block).map_err(Error::SocketError)
115     }
116 }
117 
118 impl AsRawDescriptor for Listener {
as_raw_descriptor(&self) -> RawDescriptor119     fn as_raw_descriptor(&self) -> RawDescriptor {
120         self.fd.as_raw_descriptor()
121     }
122 }
123 
124 /// Unix domain socket endpoint for vhost-user connection.
125 pub struct Endpoint<R: Req> {
126     sock: SystemStream,
127     _r: PhantomData<R>,
128 }
129 
130 impl<R: Req> From<SystemStream> for Endpoint<R> {
from(sock: SystemStream) -> Self131     fn from(sock: SystemStream) -> Self {
132         Self {
133             sock,
134             _r: PhantomData,
135         }
136     }
137 }
138 
139 impl<R: Req> EndpointTrait<R> for Endpoint<R> {
140     /// Create a new stream by connecting to server at `str`.
141     ///
142     /// # Return:
143     /// * - the new Endpoint object on success.
144     /// * - SocketConnect: failed to connect to peer.
connect<P: AsRef<Path>>(path: P) -> Result<Self>145     fn connect<P: AsRef<Path>>(path: P) -> Result<Self> {
146         let sock = SystemStream::connect(path).map_err(Error::SocketConnect)?;
147         Ok(Self::from(sock))
148     }
149 
150     /// Sends bytes from scatter-gather vectors over the socket with optional attached file
151     /// descriptors.
152     ///
153     /// # Return:
154     /// * - number of bytes sent on success
155     /// * - SocketRetry: temporary error caused by signals or short of resources.
156     /// * - SocketBroken: the underline socket is broken.
157     /// * - SocketError: other socket related errors.
send_iovec(&mut self, iovs: &[IoSlice], fds: Option<&[RawDescriptor]>) -> Result<usize>158     fn send_iovec(&mut self, iovs: &[IoSlice], fds: Option<&[RawDescriptor]>) -> Result<usize> {
159         let rfds = match fds {
160             Some(rfds) => rfds,
161             _ => &[],
162         };
163         self.sock.send_bufs_with_fds(iovs, rfds).map_err(Into::into)
164     }
165 
166     /// Reads bytes from the socket into the given scatter/gather vectors with optional attached
167     /// file.
168     ///
169     /// The underlying communication channel is a Unix domain socket in STREAM mode. It's a little
170     /// tricky to pass file descriptors through such a communication channel. Let's assume that a
171     /// sender sending a message with some file descriptors attached. To successfully receive those
172     /// attached file descriptors, the receiver must obey following rules:
173     ///   1) file descriptors are attached to a message.
174     ///   2) message(packet) boundaries must be respected on the receive side.
175     /// In other words, recvmsg() operations must not cross the packet boundary, otherwise the
176     /// attached file descriptors will get lost.
177     /// Note that this function wraps received file descriptors as `File`.
178     ///
179     /// # Return:
180     /// * - (number of bytes received, [received files]) on success
181     /// * - Disconnect: the connection is closed.
182     /// * - SocketRetry: temporary error caused by signals or short of resources.
183     /// * - SocketBroken: the underline socket is broken.
184     /// * - SocketError: other socket related errors.
recv_into_bufs( &mut self, bufs: &mut [IoSliceMut], allow_fd: bool, ) -> Result<(usize, Option<Vec<File>>)>185     fn recv_into_bufs(
186         &mut self,
187         bufs: &mut [IoSliceMut],
188         allow_fd: bool,
189     ) -> Result<(usize, Option<Vec<File>>)> {
190         let mut fd_array = if allow_fd {
191             vec![0; MAX_ATTACHED_FD_ENTRIES]
192         } else {
193             vec![]
194         };
195         let mut iovs: Vec<_> = bufs.iter_mut().map(|s| IoSliceMut::new(s)).collect();
196         let (bytes, fds) = self.sock.recv_iovecs_with_fds(&mut iovs, &mut fd_array)?;
197 
198         // 0-bytes indicates that the connection is closed.
199         if bytes == 0 {
200             return Err(Error::Disconnect);
201         }
202 
203         let files = match fds {
204             0 => None,
205             n => {
206                 let files = fd_array
207                     .iter()
208                     .take(n)
209                     .map(|fd| {
210                         // Safe because we have the ownership of `fd`.
211                         unsafe { File::from_raw_descriptor(*fd as RawDescriptor) }
212                     })
213                     .collect();
214                 Some(files)
215             }
216         };
217 
218         Ok((bytes, files))
219     }
220 
create_slave_request_endpoint( &mut self, files: Option<Vec<File>>, ) -> Result<Box<dyn EndpointTrait<SlaveReq>>>221     fn create_slave_request_endpoint(
222         &mut self,
223         files: Option<Vec<File>>,
224     ) -> Result<Box<dyn EndpointTrait<SlaveReq>>> {
225         let file = take_single_file(files).ok_or(Error::InvalidMessage)?;
226         // Safe because we own the file
227         let tube = unsafe { SystemStream::from_raw_descriptor(file.into_raw_descriptor()) };
228         Ok(Box::new(Endpoint::from(tube)))
229     }
230 }
231 
232 impl<T: Req> AsRawDescriptor for Endpoint<T> {
as_raw_descriptor(&self) -> RawDescriptor233     fn as_raw_descriptor(&self) -> RawDescriptor {
234         self.sock.as_raw_descriptor()
235     }
236 }
237 
238 impl<T: Req> AsMut<SystemStream> for Endpoint<T> {
as_mut(&mut self) -> &mut SystemStream239     fn as_mut(&mut self) -> &mut SystemStream {
240         &mut self.sock
241     }
242 }
243 
244 #[cfg(test)]
245 mod tests {
246     use std::io::Read;
247     use std::io::Seek;
248     use std::io::SeekFrom;
249     use std::io::Write;
250     use std::mem;
251     use std::slice;
252 
253     use tempfile::tempfile;
254     use tempfile::Builder;
255     use tempfile::TempDir;
256 
257     use super::*;
258     use crate::connection::EndpointExt;
259 
temp_dir() -> TempDir260     fn temp_dir() -> TempDir {
261         Builder::new().prefix("/tmp/vhost_test").tempdir().unwrap()
262     }
263 
264     #[test]
create_listener()265     fn create_listener() {
266         let dir = temp_dir();
267         let mut path = dir.path().to_owned();
268         path.push("sock");
269         let listener = Listener::new(&path, true).unwrap();
270 
271         assert!(listener.as_raw_descriptor() > 0);
272     }
273 
274     #[test]
accept_connection()275     fn accept_connection() {
276         let dir = temp_dir();
277         let mut path = dir.path().to_owned();
278         path.push("sock");
279         let mut listener = Listener::new(&path, true).unwrap();
280         listener.set_nonblocking(true).unwrap();
281 
282         // accept on a fd without incoming connection
283         let conn = listener.accept().unwrap();
284         assert!(conn.is_none());
285     }
286 
287     #[test]
send_data()288     fn send_data() {
289         let dir = temp_dir();
290         let mut path = dir.path().to_owned();
291         path.push("sock");
292         let mut listener = Listener::new(&path, true).unwrap();
293         listener.set_nonblocking(true).unwrap();
294         let mut master = Endpoint::<MasterReq>::connect(&path).unwrap();
295         let mut slave = listener.accept().unwrap().unwrap();
296 
297         let buf1 = vec![0x1, 0x2, 0x3, 0x4];
298         let mut len = master.send_slice(IoSlice::new(&buf1[..]), None).unwrap();
299         assert_eq!(len, 4);
300         let (bytes, buf2, _) = slave.recv_into_buf(0x1000).unwrap();
301         assert_eq!(bytes, 4);
302         assert_eq!(&buf1[..], &buf2[..bytes]);
303 
304         len = master.send_slice(IoSlice::new(&buf1[..]), None).unwrap();
305         assert_eq!(len, 4);
306         let (bytes, buf2, _) = slave.recv_into_buf(0x2).unwrap();
307         assert_eq!(bytes, 2);
308         assert_eq!(&buf1[..2], &buf2[..]);
309         let (bytes, buf2, _) = slave.recv_into_buf(0x2).unwrap();
310         assert_eq!(bytes, 2);
311         assert_eq!(&buf1[2..], &buf2[..]);
312     }
313 
314     #[test]
send_fd()315     fn send_fd() {
316         let dir = temp_dir();
317         let mut path = dir.path().to_owned();
318         path.push("sock");
319         let mut listener = Listener::new(&path, true).unwrap();
320         listener.set_nonblocking(true).unwrap();
321         let mut master = Endpoint::<MasterReq>::connect(&path).unwrap();
322         let mut slave = listener.accept().unwrap().unwrap();
323 
324         let mut fd = tempfile().unwrap();
325         write!(fd, "test").unwrap();
326 
327         // Normal case for sending/receiving file descriptors
328         let buf1 = vec![0x1, 0x2, 0x3, 0x4];
329         let len = master
330             .send_slice(IoSlice::new(&buf1[..]), Some(&[fd.as_raw_descriptor()]))
331             .unwrap();
332         assert_eq!(len, 4);
333 
334         let (bytes, buf2, files) = slave.recv_into_buf(4).unwrap();
335         assert_eq!(bytes, 4);
336         assert_eq!(&buf1[..], &buf2[..]);
337         assert!(files.is_some());
338         let files = files.unwrap();
339         {
340             assert_eq!(files.len(), 1);
341             let mut file = &files[0];
342             let mut content = String::new();
343             file.seek(SeekFrom::Start(0)).unwrap();
344             file.read_to_string(&mut content).unwrap();
345             assert_eq!(content, "test");
346         }
347 
348         // Following communication pattern should work:
349         // Sending side: data(header, body) with fds
350         // Receiving side: data(header) with fds, data(body)
351         let len = master
352             .send_slice(
353                 IoSlice::new(&buf1[..]),
354                 Some(&[
355                     fd.as_raw_descriptor(),
356                     fd.as_raw_descriptor(),
357                     fd.as_raw_descriptor(),
358                 ]),
359             )
360             .unwrap();
361         assert_eq!(len, 4);
362 
363         let (bytes, buf2, files) = slave.recv_into_buf(0x2).unwrap();
364         assert_eq!(bytes, 2);
365         assert_eq!(&buf1[..2], &buf2[..]);
366         assert!(files.is_some());
367         let files = files.unwrap();
368         {
369             assert_eq!(files.len(), 3);
370             let mut file = &files[1];
371             let mut content = String::new();
372             file.seek(SeekFrom::Start(0)).unwrap();
373             file.read_to_string(&mut content).unwrap();
374             assert_eq!(content, "test");
375         }
376         let (bytes, buf2, files) = slave.recv_into_buf(0x2).unwrap();
377         assert_eq!(bytes, 2);
378         assert_eq!(&buf1[2..], &buf2[..]);
379         assert!(files.is_none());
380 
381         // Following communication pattern should not work:
382         // Sending side: data(header, body) with fds
383         // Receiving side: data(header), data(body) with fds
384         let len = master
385             .send_slice(
386                 IoSlice::new(&buf1[..]),
387                 Some(&[
388                     fd.as_raw_descriptor(),
389                     fd.as_raw_descriptor(),
390                     fd.as_raw_descriptor(),
391                 ]),
392             )
393             .unwrap();
394         assert_eq!(len, 4);
395 
396         let buf4 = slave.recv_data(2).unwrap();
397         assert_eq!(buf4.len(), 2);
398         assert_eq!(&buf1[..2], &buf4[..]);
399         let (bytes, buf2, files) = slave.recv_into_buf(0x2).unwrap();
400         assert_eq!(bytes, 2);
401         assert_eq!(&buf1[2..], &buf2[..]);
402         assert!(files.is_none());
403 
404         // Following communication pattern should work:
405         // Sending side: data, data with fds
406         // Receiving side: data, data with fds
407         let len = master.send_slice(IoSlice::new(&buf1[..]), None).unwrap();
408         assert_eq!(len, 4);
409         let len = master
410             .send_slice(
411                 IoSlice::new(&buf1[..]),
412                 Some(&[
413                     fd.as_raw_descriptor(),
414                     fd.as_raw_descriptor(),
415                     fd.as_raw_descriptor(),
416                 ]),
417             )
418             .unwrap();
419         assert_eq!(len, 4);
420 
421         let (bytes, buf2, files) = slave.recv_into_buf(0x4).unwrap();
422         assert_eq!(bytes, 4);
423         assert_eq!(&buf1[..], &buf2[..]);
424         assert!(files.is_none());
425 
426         let (bytes, buf2, files) = slave.recv_into_buf(0x2).unwrap();
427         assert_eq!(bytes, 2);
428         assert_eq!(&buf1[..2], &buf2[..]);
429         assert!(files.is_some());
430         let files = files.unwrap();
431         {
432             assert_eq!(files.len(), 3);
433             let mut file = &files[1];
434             let mut content = String::new();
435             file.seek(SeekFrom::Start(0)).unwrap();
436             file.read_to_string(&mut content).unwrap();
437             assert_eq!(content, "test");
438         }
439         let (bytes, buf2, files) = slave.recv_into_buf(0x2).unwrap();
440         assert_eq!(bytes, 2);
441         assert_eq!(&buf1[2..], &buf2[..]);
442         assert!(files.is_none());
443 
444         // Following communication pattern should not work:
445         // Sending side: data1, data2 with fds
446         // Receiving side: data + partial of data2, left of data2 with fds
447         let len = master.send_slice(IoSlice::new(&buf1[..]), None).unwrap();
448         assert_eq!(len, 4);
449         let len = master
450             .send_slice(
451                 IoSlice::new(&buf1[..]),
452                 Some(&[
453                     fd.as_raw_descriptor(),
454                     fd.as_raw_descriptor(),
455                     fd.as_raw_descriptor(),
456                 ]),
457             )
458             .unwrap();
459         assert_eq!(len, 4);
460 
461         let v = slave.recv_data(5).unwrap();
462         assert_eq!(v.len(), 5);
463 
464         let (bytes, _, files) = slave.recv_into_buf(0x4).unwrap();
465         assert_eq!(bytes, 3);
466         assert!(files.is_none());
467 
468         // If the target fd array is too small, extra file descriptors will get lost.
469         let len = master
470             .send_slice(
471                 IoSlice::new(&buf1[..]),
472                 Some(&[
473                     fd.as_raw_descriptor(),
474                     fd.as_raw_descriptor(),
475                     fd.as_raw_descriptor(),
476                 ]),
477             )
478             .unwrap();
479         assert_eq!(len, 4);
480 
481         let (bytes, _, files) = slave.recv_into_buf(0x4).unwrap();
482         assert_eq!(bytes, 4);
483         assert!(files.is_some());
484     }
485 
486     #[test]
send_recv()487     fn send_recv() {
488         let dir = temp_dir();
489         let mut path = dir.path().to_owned();
490         path.push("sock");
491         let mut listener = Listener::new(&path, true).unwrap();
492         listener.set_nonblocking(true).unwrap();
493         let mut master = Endpoint::<MasterReq>::connect(&path).unwrap();
494         let mut slave = listener.accept().unwrap().unwrap();
495 
496         let mut hdr1 =
497             VhostUserMsgHeader::new(MasterReq::GET_FEATURES, 0, mem::size_of::<u64>() as u32);
498         hdr1.set_need_reply(true);
499         let features1 = 0x1u64;
500         master.send_message(&hdr1, &features1, None).unwrap();
501 
502         let mut features2 = 0u64;
503         let slice = unsafe {
504             slice::from_raw_parts_mut(
505                 (&mut features2 as *mut u64) as *mut u8,
506                 mem::size_of::<u64>(),
507             )
508         };
509         let (hdr2, bytes, files) = slave.recv_body_into_buf(slice).unwrap();
510         assert_eq!(hdr1, hdr2);
511         assert_eq!(bytes, 8);
512         assert_eq!(features1, features2);
513         assert!(files.is_none());
514 
515         master.send_header(&hdr1, None).unwrap();
516         let (hdr2, files) = slave.recv_header().unwrap();
517         assert_eq!(hdr1, hdr2);
518         assert!(files.is_none());
519     }
520 }
521