diff --git a/changelog/2249.fixed.md b/changelog/2249.fixed.md new file mode 100644 index 0000000000..7905070efb --- /dev/null +++ b/changelog/2249.fixed.md @@ -0,0 +1 @@ +Fixed `recvm(m)sg` not checking the address family field of the received address. diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index a37e123616..a729845e27 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -1719,7 +1719,7 @@ where // as long as we are not reading past the index writen by recvmmsg - address // will be initialized - let address = unsafe { self.rmm.addresses[self.current_index].assume_init() }; + let address = self.rmm.addresses[self.current_index]; self.current_index += 1; Some(unsafe { @@ -1727,7 +1727,7 @@ where mmsghdr.msg_hdr, mmsghdr.msg_len as isize, self.rmm.msg_controllen, - address, + &address, ) }) } @@ -1881,7 +1881,7 @@ unsafe fn read_mhdr<'a, 'i, S>( mhdr: msghdr, r: isize, msg_controllen: usize, - mut address: S, + address: &mem::MaybeUninit, ) -> RecvMsg<'a, 'i, S> where S: SockaddrLike { @@ -1901,15 +1901,16 @@ unsafe fn read_mhdr<'a, 'i, S>( } }; - // Ignore errors if this socket address has statically-known length - // - // This is to ensure that unix socket addresses have their length set appropriately. - let _ = unsafe { address.set_length(mhdr.msg_namelen as usize) }; + let addr_len = mhdr.msg_namelen; + + let address = unsafe { + S::from_raw(address.as_ptr().cast(), Some(addr_len)) + }; RecvMsg { bytes: r as usize, cmsghdr, - address: Some(address), + address, flags: MsgFlags::from_bits_truncate(mhdr.msg_flags), mhdr, iobufs: std::marker::PhantomData, @@ -2039,7 +2040,7 @@ pub fn recvmsg<'a, 'outer, 'inner, S>(fd: RawFd, iov: &'outer mut [IoSliceMut<'i let r = Errno::result(ret)?; - Ok(unsafe { read_mhdr(mhdr, r, msg_controllen, address.assume_init()) }) + Ok(unsafe { read_mhdr(mhdr, r, msg_controllen, &address) }) } } @@ -2215,7 +2216,7 @@ pub fn recvfrom( &mut len as *mut socklen_t, ))? as usize; - Ok((ret, T::from_raw(addr.assume_init().as_ptr(), Some(len)))) + Ok((ret, T::from_raw(addr.as_ptr().cast(), Some(len)))) } } diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs index 12729b23a4..74e341caec 100644 --- a/test/sys/test_socket.rs +++ b/test/sys/test_socket.rs @@ -2828,3 +2828,87 @@ fn test_icmp_protocol() { sendto(owned_fd.as_raw_fd(), &packet, &dest_addr, MsgFlags::empty()) .unwrap(); } + +#[test] +fn test_recvmsg_wrong_addr_type() { + use std::io::{IoSlice, IoSliceMut}; + + use nix::sys::socket::*; + + let send = socket( + AddressFamily::Inet, + SockType::Datagram, + SockFlag::empty(), + SockProtocol::Udp, + ) + .unwrap(); + + let recv = socket( + AddressFamily::Inet, + SockType::Datagram, + SockFlag::empty(), + SockProtocol::Udp, + ) + .unwrap(); + + let addr = "127.0.0.1:6803".parse::().unwrap(); + + bind(recv.as_raw_fd(), &addr).unwrap(); + + sendmsg( + send.as_raw_fd(), + &[IoSlice::new(&[0x69; 42][..])], + &[], + MsgFlags::empty(), + Some(&addr), + ) + .unwrap(); + + // To make apple happy + let mut buf = [0u8; 42]; + let mut iov = [IoSliceMut::new(&mut buf)]; + + let r = recvmsg::( + recv.as_raw_fd(), + &mut iov, + None, + MsgFlags::empty(), + ) + .unwrap(); + + assert!(r.address.is_none()); +} + +#[test] +fn test_recvfrom_wrong_addr_type() { + use nix::sys::socket::*; + + let send = socket( + AddressFamily::Inet, + SockType::Datagram, + SockFlag::empty(), + SockProtocol::Udp, + ) + .unwrap(); + + let recv = socket( + AddressFamily::Inet, + SockType::Datagram, + SockFlag::empty(), + SockProtocol::Udp, + ) + .unwrap(); + + let addr = "127.0.0.1:6804".parse::().unwrap(); + + bind(recv.as_raw_fd(), &addr).unwrap(); + + sendto(send.as_raw_fd(), &[0x69; 42], &addr, MsgFlags::empty()).unwrap(); + + // To make apple happy + let mut buf = [0u8; 42]; + + let (_, addr) = recvfrom::(recv.as_raw_fd(), &mut buf).unwrap(); + + assert!(addr.is_none()); +}