Skip to content

Commit a40a0fb

Browse files
asomersrtzoeller
authored andcommitted
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 0eb5ac7 commit a40a0fb

File tree

3 files changed

+58
-6
lines changed

3 files changed

+58
-6
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ This project adheres to [Semantic Versioning](https://semver.org/).
88
### Changed
99
### Fixed
1010

11+
- Fixed buffer overflow in nix::sys::socket::recvfrom.
12+
(#[1763](https://github.com/nix-rust/nix/pull/1763))
1113
- Enabled `SockaddrStorage::{as_link_addr, as_link_addr_mut}` for Linux-like
1214
operating systems.
1315
(#[1729](https://github.com/nix-rust/nix/pull/1729))

src/sys/socket/mod.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -1910,8 +1910,8 @@ pub fn recvfrom<T:SockaddrLike>(sockfd: RawFd, buf: &mut [u8])
19101910
-> Result<(usize, Option<T>)>
19111911
{
19121912
unsafe {
1913-
let mut addr = mem::MaybeUninit::uninit();
1914-
let mut len = mem::size_of::<T>() as socklen_t;
1913+
let mut addr = mem::MaybeUninit::<T>::uninit();
1914+
let mut len = mem::size_of_val(&addr) as socklen_t;
19151915

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

1924-
Ok((ret, T::from_raw(&addr.assume_init(), Some(len))))
1924+
Ok((ret, T::from_raw(
1925+
addr.assume_init().as_ptr() as *const libc::sockaddr,
1926+
Some(len))
1927+
))
19251928
}
19261929
}
19271930

test/sys/test_socket.rs

+50-3
Original file line numberDiff line numberDiff line change
@@ -258,8 +258,8 @@ pub fn test_socketpair() {
258258
}
259259

260260
mod recvfrom {
261-
use nix::Result;
262261
use nix::sys::socket::*;
262+
use nix::{errno::Errno, Result};
263263
use std::thread;
264264
use super::*;
265265

@@ -602,6 +602,51 @@ mod recvfrom {
602602
assert_eq!(&buf[..DATA.len()], DATA);
603603
}
604604
}
605+
606+
#[test]
607+
pub fn udp_inet6() {
608+
let addr = std::net::Ipv6Addr::from_str("::1").unwrap();
609+
let rport = 6789;
610+
let rstd_sa = SocketAddrV6::new(addr, rport, 0, 0);
611+
let raddr = SockaddrIn6::from(rstd_sa);
612+
let sport = 6790;
613+
let sstd_sa = SocketAddrV6::new(addr, sport, 0, 0);
614+
let saddr = SockaddrIn6::from(sstd_sa);
615+
let rsock = socket(
616+
AddressFamily::Inet6,
617+
SockType::Datagram,
618+
SockFlag::empty(),
619+
None,
620+
)
621+
.expect("receive socket failed");
622+
match bind(rsock, &raddr) {
623+
Err(Errno::EADDRNOTAVAIL) => {
624+
println!("IPv6 not available, skipping test.");
625+
return;
626+
}
627+
Err(e) => panic!("bind: {}", e),
628+
Ok(()) => (),
629+
}
630+
let ssock = socket(
631+
AddressFamily::Inet6,
632+
SockType::Datagram,
633+
SockFlag::empty(),
634+
None,
635+
)
636+
.expect("send socket failed");
637+
bind(ssock, &saddr).unwrap();
638+
let from = sendrecv(
639+
rsock,
640+
ssock,
641+
move |s, m, flags| sendto(s, m, &raddr, flags),
642+
|_, _| {},
643+
);
644+
assert_eq!(AddressFamily::Inet6, from.unwrap().family().unwrap());
645+
let osent_addr = from.unwrap();
646+
let sent_addr = osent_addr.as_sockaddr_in6().unwrap();
647+
assert_eq!(sent_addr.ip(), addr);
648+
assert_eq!(sent_addr.port(), sport);
649+
}
605650
}
606651

607652
// Test error handling of our recvmsg wrapper
@@ -1505,8 +1550,10 @@ pub fn test_recv_ipv6pktinfo() {
15051550

15061551
let lo_ifaddr = loopback_address(AddressFamily::Inet6);
15071552
let (lo_name, lo) = match lo_ifaddr {
1508-
Some(ifaddr) => (ifaddr.interface_name,
1509-
ifaddr.address.expect("Expect IPv4 address on interface")),
1553+
Some(ifaddr) => (
1554+
ifaddr.interface_name,
1555+
ifaddr.address.expect("Expect IPv6 address on interface"),
1556+
),
15101557
None => return,
15111558
};
15121559
let receive = socket(

0 commit comments

Comments
 (0)