-
Notifications
You must be signed in to change notification settings - Fork 718
Closed
Description
The SockaddrStorage type "forgets" the address length, which causes incorrect and unexpected behaviour. I think this is a more fundamental issue with how nix represents socket addresses.
Example:
use std::os::unix::io::AsRawFd;
use std::os::unix::net::UnixListener;
use nix::sys::socket::{connect, getsockname, socket};
use nix::sys::socket::{AddressFamily, SockFlag, SockType, SockaddrStorage};
let listener = UnixListener::bind("/tmp/example.sock").unwrap();
let listener_fd = listener.as_raw_fd();
let listener_addr: SockaddrStorage = getsockname(listener_fd).unwrap();
let peer_fd = socket(AddressFamily::Unix, SockType::Stream, SockFlag::empty(), None).unwrap();
// this panics
connect(peer_fd, &listener_addr).unwrap();If we look at the strace, we can see that nix is proving the wrong sockaddr length to connect(), which represents an incorrect address. This is equally important for abstract named and unnamed unix sockets.
socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0) = 3
bind(3, {sa_family=AF_UNIX, sun_path="/tmp/example.sock"}, 20) = 0
listen(3, 4294967295) = 0
getsockname(3, {sa_family=AF_UNIX, sun_path="/tmp/example.sock"}, [128->20]) = 0
write(1, "SockaddrStorage { ss: sockaddr_s"..., 91SockaddrStorage { ss: sockaddr_storage { ss_family: 1, __ss_align: 8299682679707492728 } }
) = 91
socket(AF_UNIX, SOCK_STREAM, 0) = 4
connect(4, {sa_family=AF_UNIX, sun_path="/tmp/example.sock"}, 128) = -1 EINVAL (Invalid argument)
When you're writing code that has to support many different socket address types, this means that SockaddrStorage is unusable. We're currently sticking with the deprecated nix::sys::socket::SockAddr for now as it doesn't have this issue.