Skip to content

Commit 5fe8a3f

Browse files
committed
Fix a buffer overflow in sys::socket::recvfrom
IPv4 and stream sockets are unaffected, but for datagram sockets of other address types libc::recvfrom might overwrite part of the stack. Fixes #1762
1 parent e5f354c commit 5fe8a3f

File tree

3 files changed

+47
-4
lines changed

3 files changed

+47
-4
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ This project adheres to [Semantic Versioning](https://semver.org/).
4444

4545
### Fixed
4646

47+
- Fixed buffer overflow in nix::sys::socket::recvfrom.
48+
(#[1763](https://github.com/nix-rust/nix/pull/1763))
4749
- Enabled `SockaddrStorage::{as_link_addr, as_link_addr_mut}` for Linux-like
4850
operating systems.
4951
(#[1729](https://github.com/nix-rust/nix/pull/1729))

src/sys/socket/mod.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1912,8 +1912,8 @@ pub fn recvfrom<T:SockaddrLike>(sockfd: RawFd, buf: &mut [u8])
19121912
-> Result<(usize, Option<T>)>
19131913
{
19141914
unsafe {
1915-
let mut addr = mem::MaybeUninit::uninit();
1916-
let mut len = mem::size_of::<T>() as socklen_t;
1915+
let mut addr = mem::MaybeUninit::<T>::uninit();
1916+
let mut len = mem::size_of_val(&addr) as socklen_t;
19171917

19181918
let ret = Errno::result(libc::recvfrom(
19191919
sockfd,
@@ -1923,7 +1923,10 @@ pub fn recvfrom<T:SockaddrLike>(sockfd: RawFd, buf: &mut [u8])
19231923
addr.as_mut_ptr() as *mut libc::sockaddr,
19241924
&mut len as *mut socklen_t))? as usize;
19251925

1926-
Ok((ret, T::from_raw(&addr.assume_init(), Some(len))))
1926+
Ok((ret, T::from_raw(
1927+
addr.assume_init().as_ptr() as *const libc::sockaddr,
1928+
Some(len))
1929+
))
19271930
}
19281931
}
19291932

test/sys/test_socket.rs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,44 @@ mod recvfrom {
681681
assert_eq!(&buf[..DATA.len()], DATA);
682682
}
683683
}
684+
685+
#[test]
686+
pub fn udp_inet6() {
687+
let addr = std::net::Ipv6Addr::from_str("::1").unwrap();
688+
let rport = 6789;
689+
let rstd_sa = SocketAddrV6::new(addr, rport, 0, 0);
690+
let raddr = SockaddrIn6::from(rstd_sa);
691+
let sport = 6790;
692+
let sstd_sa = SocketAddrV6::new(addr, sport, 0, 0);
693+
let saddr = SockaddrIn6::from(sstd_sa);
694+
let rsock = socket(
695+
AddressFamily::Inet6,
696+
SockType::Datagram,
697+
SockFlag::empty(),
698+
None,
699+
)
700+
.expect("receive socket failed");
701+
bind(rsock, &raddr).unwrap();
702+
let ssock = socket(
703+
AddressFamily::Inet6,
704+
SockType::Datagram,
705+
SockFlag::empty(),
706+
None,
707+
)
708+
.expect("send socket failed");
709+
bind(ssock, &saddr).unwrap();
710+
let from = sendrecv(
711+
rsock,
712+
ssock,
713+
move |s, m, flags| sendto(s, m, &raddr, flags),
714+
|_, _| {},
715+
);
716+
assert_eq!(AddressFamily::Inet6, from.unwrap().family().unwrap());
717+
let osent_addr = from.unwrap();
718+
let sent_addr = osent_addr.as_sockaddr_in6().unwrap();
719+
assert_eq!(sent_addr.ip(), addr);
720+
assert_eq!(sent_addr.port(), sport);
721+
}
684722
}
685723

686724
// Test error handling of our recvmsg wrapper
@@ -1734,7 +1772,7 @@ pub fn test_recv_ipv6pktinfo() {
17341772
let (lo_name, lo) = match lo_ifaddr {
17351773
Some(ifaddr) => (
17361774
ifaddr.interface_name,
1737-
ifaddr.address.expect("Expect IPv4 address on interface"),
1775+
ifaddr.address.expect("Expect IPv6 address on interface"),
17381776
),
17391777
None => return,
17401778
};

0 commit comments

Comments
 (0)