From 5b234c31f4b52c8568aad84b593cfa1058a9e806 Mon Sep 17 00:00:00 2001 From: Michael Baikov Date: Wed, 30 Oct 2024 10:17:13 -0400 Subject: [PATCH 1/2] Use as_mut_ptr() to initialize msg_name in pack_mhdr_to_receive The msg_name field points to a caller-allocated buffer that is used to return the source address if the socket is unconnected. The caller should set msg_namelen to the size of this buffer before this call; upon return from a successful call, msg_namelen will contain the length of the returned address. If the application does not need to know the source address, msg_name can be specified as NULL. In case we use () msgname_len gets initialized with 0, but a dangling pointer to the array with msg_name. This works for the first iteration somehow, but after that kernel sets msgname_len to a non-zero and second invocation with the same MultiHeader fails Fixes https://github.com/nix-rust/nix/issues/2506 --- src/sys/socket/mod.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index dd74013c64..e7ab78e1e1 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -2059,7 +2059,10 @@ unsafe fn pack_mhdr_to_receive( let mut mhdr = mem::MaybeUninit::::zeroed(); let p = mhdr.as_mut_ptr(); unsafe { - (*p).msg_name = address as *mut c_void; + // it is important to use as_mut_ptr() here since S can be + // a zero sized type representing by a dangling pointer. + // as_mut_ptr() handles this case and uses a null pointer instead + (*p).msg_name = (*address).as_mut_ptr() as *mut c_void; (*p).msg_namelen = S::size(); (*p).msg_iov = iov_buffer as *mut iovec; (*p).msg_iovlen = iov_buffer_len as _; From 97623d9d8d2876aa8878d23b15d20e9bba618ff2 Mon Sep 17 00:00:00 2001 From: Michael Baikov Date: Sat, 2 Nov 2024 06:38:48 -0400 Subject: [PATCH 2/2] CI doesn't check for rustfmt but I'm tired of picking stuff --- src/sys/socket/mod.rs | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/sys/socket/mod.rs b/src/sys/socket/mod.rs index e7ab78e1e1..13fe86867a 100644 --- a/src/sys/socket/mod.rs +++ b/src/sys/socket/mod.rs @@ -39,10 +39,20 @@ pub use self::addr::{SockaddrLike, SockaddrStorage}; pub use self::addr::{AddressFamily, UnixAddr}; #[cfg(not(solarish))] pub use self::addr::{AddressFamily, UnixAddr}; -#[cfg(not(any(solarish, target_os = "haiku", target_os = "hurd", target_os = "redox")))] +#[cfg(not(any( + solarish, + target_os = "haiku", + target_os = "hurd", + target_os = "redox" +)))] #[cfg(feature = "net")] pub use self::addr::{LinkAddr, SockaddrIn, SockaddrIn6}; -#[cfg(any(solarish, target_os = "haiku", target_os = "hurd", target_os = "redox"))] +#[cfg(any( + solarish, + target_os = "haiku", + target_os = "hurd", + target_os = "redox" +))] #[cfg(feature = "net")] pub use self::addr::{SockaddrIn, SockaddrIn6}; @@ -851,17 +861,17 @@ pub enum ControlMessageOwned { #[cfg_attr(docsrs, doc(cfg(feature = "net")))] Ipv6HopLimit(i32), - /// Retrieve the DSCP (ToS) header field of the incoming IPv4 packet. + /// Retrieve the DSCP (ToS) header field of the incoming IPv4 packet. #[cfg(any(linux_android, target_os = "freebsd"))] #[cfg(feature = "net")] #[cfg_attr(docsrs, doc(cfg(feature = "net")))] Ipv4Tos(u8), - /// Retrieve the DSCP (Traffic Class) header field of the incoming IPv6 packet. + /// Retrieve the DSCP (Traffic Class) header field of the incoming IPv6 packet. #[cfg(any(linux_android, target_os = "freebsd"))] #[cfg(feature = "net")] #[cfg_attr(docsrs, doc(cfg(feature = "net")))] - Ipv6TClass(i32), + Ipv6TClass(i32), /// UDP Generic Receive Offload (GRO) allows receiving multiple UDP /// packets from a single sender. @@ -1119,7 +1129,7 @@ impl ControlMessageOwned { (_, _) => { let sl = unsafe { std::slice::from_raw_parts(p, len) }; let ucmsg = UnknownCmsg { - cmsg_header: *header, + cmsg_header: *header, data_bytes: Vec::::from(sl), }; ControlMessageOwned::Unknown(ucmsg) @@ -2520,4 +2530,3 @@ pub fn shutdown(df: RawFd, how: Shutdown) -> Result<()> { Errno::result(shutdown(df, how)).map(drop) } } -