• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use std::ffi::OsString;
6 use std::fs::remove_file;
7 use std::io;
8 use std::mem;
9 use std::ops::Deref;
10 use std::os::unix::{
11     ffi::{OsStrExt, OsStringExt},
12     io::{AsRawFd, FromRawFd, RawFd},
13 };
14 use std::path::Path;
15 use std::path::PathBuf;
16 use std::ptr::null_mut;
17 use std::time::Duration;
18 
19 // Offset of sun_path in structure sockaddr_un.
sun_path_offset() -> usize20 fn sun_path_offset() -> usize {
21     // Prefer 0 to null() so that we do not need to subtract from the `sub_path` pointer.
22     #[allow(clippy::zero_ptr)]
23     let addr = 0 as *const libc::sockaddr_un;
24     // Safe because we only use the dereference to create a pointer to the desired field in
25     // calculating the offset.
26     unsafe { &(*addr).sun_path as *const _ as usize }
27 }
28 
29 // Return `sockaddr_un` for a given `path`
sockaddr_un<P: AsRef<Path>>(path: P) -> io::Result<(libc::sockaddr_un, libc::socklen_t)>30 fn sockaddr_un<P: AsRef<Path>>(path: P) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> {
31     let mut addr = libc::sockaddr_un {
32         sun_family: libc::AF_UNIX as libc::sa_family_t,
33         sun_path: [0; 108],
34     };
35 
36     // Check if the input path is valid. Since
37     // * The pathname in sun_path should be null-terminated.
38     // * The length of the pathname, including the terminating null byte,
39     //   should not exceed the size of sun_path.
40     //
41     // and our input is a `Path`, we only need to check
42     // * If the string size of `Path` should less than sizeof(sun_path)
43     // and make sure `sun_path` ends with '\0' by initialized the sun_path with zeros.
44     //
45     // Empty path name is valid since abstract socket address has sun_paht[0] = '\0'
46     let bytes = path.as_ref().as_os_str().as_bytes();
47     if bytes.len() >= addr.sun_path.len() {
48         return Err(io::Error::new(
49             io::ErrorKind::InvalidInput,
50             "Input path size should be less than the length of sun_path.",
51         ));
52     };
53 
54     // Copy data from `path` to `addr.sun_path`
55     for (dst, src) in addr.sun_path.iter_mut().zip(bytes) {
56         *dst = *src as libc::c_char;
57     }
58 
59     // The addrlen argument that describes the enclosing sockaddr_un structure
60     // should have a value of at least:
61     //
62     //     offsetof(struct sockaddr_un, sun_path) + strlen(addr.sun_path) + 1
63     //
64     // or, more simply, addrlen can be specified as sizeof(struct sockaddr_un).
65     let len = sun_path_offset() + bytes.len() + 1;
66     Ok((addr, len as libc::socklen_t))
67 }
68 
69 /// A Unix `SOCK_SEQPACKET` socket point to given `path`
70 pub struct UnixSeqpacket {
71     fd: RawFd,
72 }
73 
74 impl UnixSeqpacket {
75     /// Open a `SOCK_SEQPACKET` connection to socket named by `path`.
76     ///
77     /// # Arguments
78     /// * `path` - Path to `SOCK_SEQPACKET` socket
79     ///
80     /// # Returns
81     /// A `UnixSeqpacket` structure point to the socket
82     ///
83     /// # Errors
84     /// Return `io::Error` when error occurs.
connect<P: AsRef<Path>>(path: P) -> io::Result<Self>85     pub fn connect<P: AsRef<Path>>(path: P) -> io::Result<Self> {
86         // Safe socket initialization since we handle the returned error.
87         let fd = unsafe {
88             match libc::socket(libc::AF_UNIX, libc::SOCK_SEQPACKET, 0) {
89                 -1 => return Err(io::Error::last_os_error()),
90                 fd => fd,
91             }
92         };
93 
94         let (addr, len) = sockaddr_un(path.as_ref())?;
95         // Safe connect since we handle the error and use the right length generated from
96         // `sockaddr_un`.
97         unsafe {
98             let ret = libc::connect(fd, &addr as *const _ as *const _, len);
99             if ret < 0 {
100                 return Err(io::Error::last_os_error());
101             }
102         }
103         Ok(UnixSeqpacket { fd })
104     }
105 
106     /// Creates a pair of connected `SOCK_SEQPACKET` sockets.
107     ///
108     /// Both returned file descriptors have the `CLOEXEC` flag set.s
pair() -> io::Result<(UnixSeqpacket, UnixSeqpacket)>109     pub fn pair() -> io::Result<(UnixSeqpacket, UnixSeqpacket)> {
110         let mut fds = [0, 0];
111         unsafe {
112             // Safe because we give enough space to store all the fds and we check the return value.
113             let ret = libc::socketpair(
114                 libc::AF_UNIX,
115                 libc::SOCK_SEQPACKET | libc::SOCK_CLOEXEC,
116                 0,
117                 &mut fds[0],
118             );
119             if ret == 0 {
120                 Ok((
121                     UnixSeqpacket::from_raw_fd(fds[0]),
122                     UnixSeqpacket::from_raw_fd(fds[1]),
123                 ))
124             } else {
125                 Err(io::Error::last_os_error())
126             }
127         }
128     }
129 
130     /// Clone the underlying FD.
try_clone(&self) -> io::Result<Self>131     pub fn try_clone(&self) -> io::Result<Self> {
132         // Calling `dup` is safe as the kernel doesn't touch any user memory it the process.
133         let new_fd = unsafe { libc::dup(self.fd) };
134         if new_fd < 0 {
135             Err(io::Error::last_os_error())
136         } else {
137             Ok(UnixSeqpacket { fd: new_fd })
138         }
139     }
140 
141     /// Gets the number of bytes that can be read from this socket without blocking.
get_readable_bytes(&self) -> io::Result<usize>142     pub fn get_readable_bytes(&self) -> io::Result<usize> {
143         let mut byte_count = 0 as libc::c_int;
144         let ret = unsafe { libc::ioctl(self.fd, libc::FIONREAD, &mut byte_count) };
145         if ret < 0 {
146             Err(io::Error::last_os_error())
147         } else {
148             Ok(byte_count as usize)
149         }
150     }
151 
152     /// Write data from a given buffer to the socket fd
153     ///
154     /// # Arguments
155     /// * `buf` - A reference to the data buffer.
156     ///
157     /// # Returns
158     /// * `usize` - The size of bytes written to the buffer.
159     ///
160     /// # Errors
161     /// Returns error when `libc::write` failed.
send(&self, buf: &[u8]) -> io::Result<usize>162     pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
163         // Safe since we make sure the input `count` == `buf.len()` and handle the returned error.
164         unsafe {
165             let ret = libc::write(self.fd, buf.as_ptr() as *const _, buf.len());
166             if ret < 0 {
167                 Err(io::Error::last_os_error())
168             } else {
169                 Ok(ret as usize)
170             }
171         }
172     }
173 
174     /// Read data from the socket fd to a given buffer
175     ///
176     /// # Arguments
177     /// * `buf` - A mut reference to the data buffer.
178     ///
179     /// # Returns
180     /// * `usize` - The size of bytes read to the buffer.
181     ///
182     /// # Errors
183     /// Returns error when `libc::read` failed.
recv(&self, buf: &mut [u8]) -> io::Result<usize>184     pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
185         // Safe since we make sure the input `count` == `buf.len()` and handle the returned error.
186         unsafe {
187             let ret = libc::read(self.fd, buf.as_mut_ptr() as *mut _, buf.len());
188             if ret < 0 {
189                 Err(io::Error::last_os_error())
190             } else {
191                 Ok(ret as usize)
192             }
193         }
194     }
195 
set_timeout(&self, timeout: Option<Duration>, kind: libc::c_int) -> io::Result<()>196     fn set_timeout(&self, timeout: Option<Duration>, kind: libc::c_int) -> io::Result<()> {
197         let timeval = match timeout {
198             Some(t) => {
199                 if t.as_secs() == 0 && t.subsec_micros() == 0 {
200                     return Err(io::Error::new(
201                         io::ErrorKind::InvalidInput,
202                         "zero timeout duration is invalid",
203                     ));
204                 }
205                 // subsec_micros fits in i32 because it is defined to be less than one million.
206                 let nsec = t.subsec_micros() as i32;
207                 libc::timeval {
208                     tv_sec: t.as_secs() as libc::time_t,
209                     tv_usec: libc::suseconds_t::from(nsec),
210                 }
211             }
212             None => libc::timeval {
213                 tv_sec: 0,
214                 tv_usec: 0,
215             },
216         };
217         // Safe because we own the fd, and the length of the pointer's data is the same as the
218         // passed in length parameter. The level argument is valid, the kind is assumed to be valid,
219         // and the return value is checked.
220         let ret = unsafe {
221             libc::setsockopt(
222                 self.fd,
223                 libc::SOL_SOCKET,
224                 kind,
225                 &timeval as *const libc::timeval as *const libc::c_void,
226                 mem::size_of::<libc::timeval>() as libc::socklen_t,
227             )
228         };
229         if ret < 0 {
230             Err(io::Error::last_os_error())
231         } else {
232             Ok(())
233         }
234     }
235 
236     /// Sets or removes the timeout for read/recv operations on this socket.
set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()>237     pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
238         self.set_timeout(timeout, libc::SO_RCVTIMEO)
239     }
240 
241     /// Sets or removes the timeout for write/send operations on this socket.
set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()>242     pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
243         self.set_timeout(timeout, libc::SO_SNDTIMEO)
244     }
245 }
246 
247 impl Drop for UnixSeqpacket {
drop(&mut self)248     fn drop(&mut self) {
249         // Safe if the UnixSeqpacket is created from Self::connect.
250         unsafe {
251             libc::close(self.fd);
252         }
253     }
254 }
255 
256 impl FromRawFd for UnixSeqpacket {
257     // Unsafe in drop function
from_raw_fd(fd: RawFd) -> Self258     unsafe fn from_raw_fd(fd: RawFd) -> Self {
259         Self { fd }
260     }
261 }
262 
263 impl AsRawFd for UnixSeqpacket {
as_raw_fd(&self) -> RawFd264     fn as_raw_fd(&self) -> RawFd {
265         self.fd
266     }
267 }
268 
269 /// Like a `UnixListener` but for accepting `UnixSeqpacket` type sockets.
270 pub struct UnixSeqpacketListener {
271     fd: RawFd,
272 }
273 
274 impl UnixSeqpacketListener {
275     /// Creates a new `UnixSeqpacketListener` bound to the given path.
bind<P: AsRef<Path>>(path: P) -> io::Result<Self>276     pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<Self> {
277         // Safe socket initialization since we handle the returned error.
278         let fd = unsafe {
279             match libc::socket(libc::AF_UNIX, libc::SOCK_SEQPACKET, 0) {
280                 -1 => return Err(io::Error::last_os_error()),
281                 fd => fd,
282             }
283         };
284 
285         let (addr, len) = sockaddr_un(path.as_ref())?;
286         // Safe connect since we handle the error and use the right length generated from
287         // `sockaddr_un`.
288         unsafe {
289             let ret = handle_eintr_errno!(libc::bind(fd, &addr as *const _ as *const _, len));
290             if ret < 0 {
291                 return Err(io::Error::last_os_error());
292             }
293             let ret = handle_eintr_errno!(libc::listen(fd, 128));
294             if ret < 0 {
295                 return Err(io::Error::last_os_error());
296             }
297         }
298         Ok(UnixSeqpacketListener { fd })
299     }
300 
301     /// Blocks for and accepts a new incoming connection and returns the socket associated with that
302     /// connection.
303     ///
304     /// The returned socket has the close-on-exec flag set.
accept(&self) -> io::Result<UnixSeqpacket>305     pub fn accept(&self) -> io::Result<UnixSeqpacket> {
306         // Safe because we own this fd and the kernel will not write to null pointers.
307         let ret = unsafe { libc::accept4(self.fd, null_mut(), null_mut(), libc::SOCK_CLOEXEC) };
308         if ret < 0 {
309             return Err(io::Error::last_os_error());
310         }
311         // Safe because we checked the return value of accept. Therefore, the return value must be a
312         // valid socket.
313         Ok(unsafe { UnixSeqpacket::from_raw_fd(ret) })
314     }
315 
316     /// Gets the path that this listener is bound to.
path(&self) -> io::Result<PathBuf>317     pub fn path(&self) -> io::Result<PathBuf> {
318         let mut addr = libc::sockaddr_un {
319             sun_family: libc::AF_UNIX as libc::sa_family_t,
320             sun_path: [0; 108],
321         };
322         let sun_path_offset = (&addr.sun_path as *const _ as usize
323             - &addr.sun_family as *const _ as usize)
324             as libc::socklen_t;
325         let mut len = mem::size_of::<libc::sockaddr_un>() as libc::socklen_t;
326         // Safe because the length given matches the length of the data of the given pointer, and we
327         // check the return value.
328         let ret = unsafe {
329             handle_eintr_errno!(libc::getsockname(
330                 self.fd,
331                 &mut addr as *mut libc::sockaddr_un as *mut libc::sockaddr,
332                 &mut len
333             ))
334         };
335         if ret < 0 {
336             return Err(io::Error::last_os_error());
337         }
338         if addr.sun_family != libc::AF_UNIX as libc::sa_family_t
339             || addr.sun_path[0] == 0
340             || len < 1 + sun_path_offset
341         {
342             return Err(io::Error::new(
343                 io::ErrorKind::InvalidInput,
344                 "getsockname on socket returned invalid value",
345             ));
346         }
347 
348         let path_os_str = OsString::from_vec(
349             addr.sun_path[..(len - sun_path_offset - 1) as usize]
350                 .iter()
351                 .map(|&c| c as _)
352                 .collect(),
353         );
354         Ok(path_os_str.into())
355     }
356 }
357 
358 impl Drop for UnixSeqpacketListener {
drop(&mut self)359     fn drop(&mut self) {
360         // Safe if the UnixSeqpacketListener is created from Self::listen.
361         unsafe {
362             libc::close(self.fd);
363         }
364     }
365 }
366 
367 impl FromRawFd for UnixSeqpacketListener {
368     // Unsafe in drop function
from_raw_fd(fd: RawFd) -> Self369     unsafe fn from_raw_fd(fd: RawFd) -> Self {
370         Self { fd }
371     }
372 }
373 
374 impl AsRawFd for UnixSeqpacketListener {
as_raw_fd(&self) -> RawFd375     fn as_raw_fd(&self) -> RawFd {
376         self.fd
377     }
378 }
379 
380 /// Used to attempt to clean up a `UnixSeqpacketListener` after it is dropped.
381 pub struct UnlinkUnixSeqpacketListener(pub UnixSeqpacketListener);
382 impl AsRef<UnixSeqpacketListener> for UnlinkUnixSeqpacketListener {
as_ref(&self) -> &UnixSeqpacketListener383     fn as_ref(&self) -> &UnixSeqpacketListener {
384         &self.0
385     }
386 }
387 
388 impl AsRawFd for UnlinkUnixSeqpacketListener {
as_raw_fd(&self) -> RawFd389     fn as_raw_fd(&self) -> RawFd {
390         self.0.as_raw_fd()
391     }
392 }
393 
394 impl Deref for UnlinkUnixSeqpacketListener {
395     type Target = UnixSeqpacketListener;
deref(&self) -> &Self::Target396     fn deref(&self) -> &Self::Target {
397         &self.0
398     }
399 }
400 
401 impl Drop for UnlinkUnixSeqpacketListener {
drop(&mut self)402     fn drop(&mut self) {
403         if let Ok(path) = self.0.path() {
404             if let Err(e) = remove_file(path) {
405                 warn!("failed to remove control socket file: {:?}", e);
406             }
407         }
408     }
409 }
410 
411 #[cfg(test)]
412 mod tests {
413     use super::*;
414     use std::env;
415     use std::path::PathBuf;
416 
tmpdir() -> PathBuf417     fn tmpdir() -> PathBuf {
418         env::temp_dir()
419     }
420 
421     #[test]
sockaddr_un_zero_length_input()422     fn sockaddr_un_zero_length_input() {
423         let _res = sockaddr_un(Path::new("")).expect("sockaddr_un failed");
424     }
425 
426     #[test]
sockaddr_un_long_input_err()427     fn sockaddr_un_long_input_err() {
428         let res = sockaddr_un(Path::new(&"a".repeat(108)));
429         assert!(res.is_err());
430     }
431 
432     #[test]
sockaddr_un_long_input_pass()433     fn sockaddr_un_long_input_pass() {
434         let _res = sockaddr_un(Path::new(&"a".repeat(107))).expect("sockaddr_un failed");
435     }
436 
437     #[test]
sockaddr_un_len_check()438     fn sockaddr_un_len_check() {
439         let (_addr, len) = sockaddr_un(Path::new(&"a".repeat(50))).expect("sockaddr_un failed");
440         assert_eq!(len, (sun_path_offset() + 50 + 1) as u32);
441     }
442 
443     #[test]
sockaddr_un_pass()444     fn sockaddr_un_pass() {
445         let path_size = 50;
446         let (addr, len) =
447             sockaddr_un(Path::new(&"a".repeat(path_size))).expect("sockaddr_un failed");
448         assert_eq!(len, (sun_path_offset() + path_size + 1) as u32);
449         assert_eq!(addr.sun_family, libc::AF_UNIX as libc::sa_family_t);
450 
451         // Check `sun_path` in returned `sockaddr_un`
452         let mut ref_sun_path = [0 as libc::c_char; 108];
453         for i in 0..path_size {
454             ref_sun_path[i] = 'a' as libc::c_char;
455         }
456 
457         for (addr_char, ref_char) in addr.sun_path.iter().zip(ref_sun_path.iter()) {
458             assert_eq!(addr_char, ref_char);
459         }
460     }
461 
462     #[test]
unix_seqpacket_path_not_exists()463     fn unix_seqpacket_path_not_exists() {
464         let res = UnixSeqpacket::connect("/path/not/exists");
465         assert!(res.is_err());
466     }
467 
468     #[test]
unix_seqpacket_listener_path()469     fn unix_seqpacket_listener_path() {
470         let mut socket_path = tmpdir();
471         socket_path.push("unix_seqpacket_listener_path");
472         let listener = UnlinkUnixSeqpacketListener(
473             UnixSeqpacketListener::bind(&socket_path)
474                 .expect("failed to create UnixSeqpacketListener"),
475         );
476         let listener_path = listener.path().expect("failed to get socket listener path");
477         assert_eq!(socket_path, listener_path);
478     }
479 
480     #[test]
unix_seqpacket_path_exists_pass()481     fn unix_seqpacket_path_exists_pass() {
482         let mut socket_path = tmpdir();
483         socket_path.push("path_to_socket");
484         let _listener = UnlinkUnixSeqpacketListener(
485             UnixSeqpacketListener::bind(&socket_path)
486                 .expect("failed to create UnixSeqpacketListener"),
487         );
488         let _res =
489             UnixSeqpacket::connect(socket_path.as_path()).expect("UnixSeqpacket::connect failed");
490     }
491 
492     #[test]
unix_seqpacket_path_listener_accept()493     fn unix_seqpacket_path_listener_accept() {
494         let mut socket_path = tmpdir();
495         socket_path.push("path_listerner_accept");
496         let listener = UnlinkUnixSeqpacketListener(
497             UnixSeqpacketListener::bind(&socket_path)
498                 .expect("failed to create UnixSeqpacketListener"),
499         );
500         let s1 =
501             UnixSeqpacket::connect(socket_path.as_path()).expect("UnixSeqpacket::connect failed");
502 
503         let s2 = listener.accept().expect("UnixSeqpacket::accept failed");
504 
505         let data1 = &[0, 1, 2, 3, 4];
506         let data2 = &[10, 11, 12, 13, 14];
507         s2.send(data2).expect("failed to send data2");
508         s1.send(data1).expect("failed to send data1");
509         let recv_data = &mut [0; 5];
510         s2.recv(recv_data).expect("failed to recv data");
511         assert_eq!(data1, recv_data);
512         s1.recv(recv_data).expect("failed to recv data");
513         assert_eq!(data2, recv_data);
514     }
515 
516     #[test]
unix_seqpacket_zero_timeout()517     fn unix_seqpacket_zero_timeout() {
518         let (s1, _s2) = UnixSeqpacket::pair().expect("failed to create socket pair");
519         // Timeouts less than a microsecond are too small and round to zero.
520         s1.set_read_timeout(Some(Duration::from_nanos(10)))
521             .expect_err("successfully set zero timeout");
522     }
523 
524     #[test]
unix_seqpacket_read_timeout()525     fn unix_seqpacket_read_timeout() {
526         let (s1, _s2) = UnixSeqpacket::pair().expect("failed to create socket pair");
527         s1.set_read_timeout(Some(Duration::from_millis(1)))
528             .expect("failed to set read timeout for socket");
529         let _ = s1.recv(&mut [0]);
530     }
531 
532     #[test]
unix_seqpacket_write_timeout()533     fn unix_seqpacket_write_timeout() {
534         let (s1, _s2) = UnixSeqpacket::pair().expect("failed to create socket pair");
535         s1.set_write_timeout(Some(Duration::from_millis(1)))
536             .expect("failed to set write timeout for socket");
537     }
538 
539     #[test]
unix_seqpacket_send_recv()540     fn unix_seqpacket_send_recv() {
541         let (s1, s2) = UnixSeqpacket::pair().expect("failed to create socket pair");
542         let data1 = &[0, 1, 2, 3, 4];
543         let data2 = &[10, 11, 12, 13, 14];
544         s2.send(data2).expect("failed to send data2");
545         s1.send(data1).expect("failed to send data1");
546         let recv_data = &mut [0; 5];
547         s2.recv(recv_data).expect("failed to recv data");
548         assert_eq!(data1, recv_data);
549         s1.recv(recv_data).expect("failed to recv data");
550         assert_eq!(data2, recv_data);
551     }
552 
553     #[test]
unix_seqpacket_send_fragments()554     fn unix_seqpacket_send_fragments() {
555         let (s1, s2) = UnixSeqpacket::pair().expect("failed to create socket pair");
556         let data1 = &[0, 1, 2, 3, 4];
557         let data2 = &[10, 11, 12, 13, 14, 15, 16];
558         s1.send(data1).expect("failed to send data1");
559         s1.send(data2).expect("failed to send data2");
560 
561         let recv_data = &mut [0; 32];
562         let size = s2.recv(recv_data).expect("failed to recv data");
563         assert_eq!(size, data1.len());
564         assert_eq!(data1, &recv_data[0..size]);
565 
566         let size = s2.recv(recv_data).expect("failed to recv data");
567         assert_eq!(size, data2.len());
568         assert_eq!(data2, &recv_data[0..size]);
569     }
570 
571     #[test]
unix_seqpacket_get_readable_bytes()572     fn unix_seqpacket_get_readable_bytes() {
573         let (s1, s2) = UnixSeqpacket::pair().expect("failed to create socket pair");
574         assert_eq!(s1.get_readable_bytes().unwrap(), 0);
575         assert_eq!(s2.get_readable_bytes().unwrap(), 0);
576         let data1 = &[0, 1, 2, 3, 4];
577         s1.send(data1).expect("failed to send data");
578 
579         assert_eq!(s1.get_readable_bytes().unwrap(), 0);
580         assert_eq!(s2.get_readable_bytes().unwrap(), data1.len());
581 
582         let recv_data = &mut [0; 5];
583         s2.recv(recv_data).expect("failed to recv data");
584         assert_eq!(s1.get_readable_bytes().unwrap(), 0);
585         assert_eq!(s2.get_readable_bytes().unwrap(), 0);
586     }
587 }
588