diff options
author | Alan Somers <asomers@gmail.com> | 2020-05-16 16:49:41 -0600 |
---|---|---|
committer | Alan Somers <asomers@gmail.com> | 2020-06-27 17:34:16 -0600 |
commit | d6f04717ba3cca1b1b13db5e6d10e6fbe34e96c7 (patch) | |
tree | 7408f7c532b0c8eb93f3d3d8031b7cd52da62145 /src/sys/socket/mod.rs | |
parent | f4fc06dbe0008768ccce068f9a9b11d91a4190d2 (diff) | |
download | nix-d6f04717ba3cca1b1b13db5e6d10e6fbe34e96c7.zip |
Make sys::socket::sockaddr_storage a safe function
It already fully validated its arguments, so there's no need for it to
be `unsafe`.
Diffstat (limited to 'src/sys/socket/mod.rs')
-rw-r--r-- | src/sys/socket/mod.rs | 39 |
1 files changed, 29 insertions, 10 deletions
diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index b972835f..41bc7aa9 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -1606,16 +1606,19 @@ pub fn getsockname(fd: RawFd) -> Result<SockAddr> { } } -/// Return the appropriate `SockAddr` type from a `sockaddr_storage` of a certain -/// size. In C this would usually be done by casting. The `len` argument +/// Return the appropriate `SockAddr` type from a `sockaddr_storage` of a +/// certain size. +/// +/// In C this would usually be done by casting. The `len` argument /// should be the number of bytes in the `sockaddr_storage` that are actually /// allocated and valid. It must be at least as large as all the useful parts /// of the structure. Note that in the case of a `sockaddr_un`, `len` need not /// include the terminating null. -pub unsafe fn sockaddr_storage_to_addr( +pub fn sockaddr_storage_to_addr( addr: &sockaddr_storage, len: usize) -> Result<SockAddr> { + assert!(len <= mem::size_of::<sockaddr_un>()); if len < mem::size_of_val(&addr.ss_family) { return Err(Error::Sys(Errno::ENOTCONN)); } @@ -1623,32 +1626,48 @@ pub unsafe fn sockaddr_storage_to_addr( match c_int::from(addr.ss_family) { libc::AF_INET => { assert_eq!(len as usize, mem::size_of::<sockaddr_in>()); - let ret = *(addr as *const _ as *const sockaddr_in); - Ok(SockAddr::Inet(InetAddr::V4(ret))) + let sin = unsafe { + *(addr as *const sockaddr_storage as *const sockaddr_in) + }; + Ok(SockAddr::Inet(InetAddr::V4(sin))) } libc::AF_INET6 => { assert_eq!(len as usize, mem::size_of::<sockaddr_in6>()); - Ok(SockAddr::Inet(InetAddr::V6(*(addr as *const _ as *const sockaddr_in6)))) + let sin6 = unsafe { + *(addr as *const _ as *const sockaddr_in6) + }; + Ok(SockAddr::Inet(InetAddr::V6(sin6))) } libc::AF_UNIX => { - let sun = *(addr as *const _ as *const sockaddr_un); let pathlen = len - offset_of!(sockaddr_un, sun_path); + let sun = unsafe { + *(addr as *const _ as *const sockaddr_un) + }; Ok(SockAddr::Unix(UnixAddr(sun, pathlen))) } #[cfg(any(target_os = "android", target_os = "linux"))] libc::AF_NETLINK => { use libc::sockaddr_nl; - Ok(SockAddr::Netlink(NetlinkAddr(*(addr as *const _ as *const sockaddr_nl)))) + let snl = unsafe { + *(addr as *const _ as *const sockaddr_nl) + }; + Ok(SockAddr::Netlink(NetlinkAddr(snl))) } #[cfg(any(target_os = "android", target_os = "linux"))] libc::AF_ALG => { use libc::sockaddr_alg; - Ok(SockAddr::Alg(AlgAddr(*(addr as *const _ as *const sockaddr_alg)))) + let salg = unsafe { + *(addr as *const _ as *const sockaddr_alg) + }; + Ok(SockAddr::Alg(AlgAddr(salg))) } #[cfg(target_os = "linux")] libc::AF_VSOCK => { use libc::sockaddr_vm; - Ok(SockAddr::Vsock(VsockAddr(*(addr as *const _ as *const sockaddr_vm)))) + let svm = unsafe { + *(addr as *const _ as *const sockaddr_vm) + }; + Ok(SockAddr::Vsock(VsockAddr(svm))) } af => panic!("unexpected address family {}", af), } |