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