diff --git a/CHANGELOG.md b/CHANGELOG.md index 244455bdc4..9f59605c42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,8 @@ This project adheres to [Semantic Versioning](https://semver.org/). ### Fixed +- Fixed buffer overflow in nix::sys::socket::recvfrom. + (#[1763](https://github.com/nix-rust/nix/pull/1763)) - Enabled `SockaddrStorage::{as_link_addr, as_link_addr_mut}` for Linux-like operating systems. (#[1729](https://github.com/nix-rust/nix/pull/1729)) diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index 6386e62b6b..00b2ca703e 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -1912,8 +1912,8 @@ pub fn recvfrom(sockfd: RawFd, buf: &mut [u8]) -> Result<(usize, Option)> { unsafe { - let mut addr = mem::MaybeUninit::uninit(); - let mut len = mem::size_of::() as socklen_t; + let mut addr = mem::MaybeUninit::::uninit(); + let mut len = mem::size_of_val(&addr) as socklen_t; let ret = Errno::result(libc::recvfrom( sockfd, @@ -1923,7 +1923,10 @@ pub fn recvfrom(sockfd: RawFd, buf: &mut [u8]) addr.as_mut_ptr() as *mut libc::sockaddr, &mut len as *mut socklen_t))? as usize; - Ok((ret, T::from_raw(&addr.assume_init(), Some(len)))) + Ok((ret, T::from_raw( + addr.assume_init().as_ptr() as *const libc::sockaddr, + Some(len)) + )) } } diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs index 3a553d3a6a..63fe87b399 100644 --- a/test/sys/test_socket.rs +++ b/test/sys/test_socket.rs @@ -681,6 +681,44 @@ mod recvfrom { assert_eq!(&buf[..DATA.len()], DATA); } } + + #[test] + pub fn udp_inet6() { + let addr = std::net::Ipv6Addr::from_str("::1").unwrap(); + let rport = 6789; + let rstd_sa = SocketAddrV6::new(addr, rport, 0, 0); + let raddr = SockaddrIn6::from(rstd_sa); + let sport = 6790; + let sstd_sa = SocketAddrV6::new(addr, sport, 0, 0); + let saddr = SockaddrIn6::from(sstd_sa); + let rsock = socket( + AddressFamily::Inet6, + SockType::Datagram, + SockFlag::empty(), + None, + ) + .expect("receive socket failed"); + bind(rsock, &raddr).unwrap(); + let ssock = socket( + AddressFamily::Inet6, + SockType::Datagram, + SockFlag::empty(), + None, + ) + .expect("send socket failed"); + bind(ssock, &saddr).unwrap(); + let from = sendrecv( + rsock, + ssock, + move |s, m, flags| sendto(s, m, &raddr, flags), + |_, _| {}, + ); + assert_eq!(AddressFamily::Inet6, from.unwrap().family().unwrap()); + let osent_addr = from.unwrap(); + let sent_addr = osent_addr.as_sockaddr_in6().unwrap(); + assert_eq!(sent_addr.ip(), addr); + assert_eq!(sent_addr.port(), sport); + } } // Test error handling of our recvmsg wrapper @@ -1734,7 +1772,7 @@ pub fn test_recv_ipv6pktinfo() { let (lo_name, lo) = match lo_ifaddr { Some(ifaddr) => ( ifaddr.interface_name, - ifaddr.address.expect("Expect IPv4 address on interface"), + ifaddr.address.expect("Expect IPv6 address on interface"), ), None => return, };