summaryrefslogtreecommitdiff
path: root/src/sys/socket
diff options
context:
space:
mode:
authorAlan Somers <asomers@gmail.com>2022-04-22 11:49:34 -0600
committerAlan Somers <asomers@gmail.com>2022-04-22 14:40:42 -0600
commitdb969c59e9a96ee27f9116c3e6dfa455545be764 (patch)
tree8c0fe64a1e084e83ab80e12aa86672f9813bb3f9 /src/sys/socket
parent9793aafb9cdcfbe0b8c00a7ec96d95451d6e9f1a (diff)
downloadnix-db969c59e9a96ee27f9116c3e6dfa455545be764.zip
Fix UnixAddr::size on Linux and Android
SockaddrLike::size() is meant to return the amount of space that can be used to store the sockaddr. But on Linux-based OSes, UnixAddr contains an extra field to store the address's length. This field is not part of the address, and should not contribute to the value of size(). This bug can't cause an out-of-bounds write, and every OS that we test on can tolerate the greater-than-expected length, but it might confuse applications that implement functions similar to getsockname in userland.
Diffstat (limited to 'src/sys/socket')
-rw-r--r--src/sys/socket/addr.rs43
1 files changed, 41 insertions, 2 deletions
diff --git a/src/sys/socket/addr.rs b/src/sys/socket/addr.rs
index e2321cb7..52d60ac9 100644
--- a/src/sys/socket/addr.rs
+++ b/src/sys/socket/addr.rs
@@ -953,6 +953,10 @@ impl SockaddrLike for UnixAddr {
ptr::copy(addr as *const u8, sup, su_len as usize);
Some(Self::from_raw_parts(su, su_len as u8))
}
+
+ fn size() -> libc::socklen_t where Self: Sized {
+ mem::size_of::<libc::sockaddr_un>() as libc::socklen_t
+ }
}
impl AsRef<libc::sockaddr_un> for UnixAddr {
@@ -2615,11 +2619,12 @@ mod tests {
}
mod link {
+ use super::*;
#[cfg(any(target_os = "ios",
target_os = "macos",
target_os = "illumos"
))]
- use super::{*, super::super::socklen_t};
+ use super::super::super::socklen_t;
/// Don't panic when trying to display an empty datalink address
#[cfg(any(target_os = "dragonfly",
@@ -2701,6 +2706,24 @@ mod tests {
assert_eq!(sock_addr.as_link_addr().unwrap().addr(),
Some([24u8, 101, 144, 221, 76, 176]));
}
+
+ #[test]
+ fn size() {
+ #[cfg(any(target_os = "dragonfly",
+ target_os = "freebsd",
+ target_os = "ios",
+ target_os = "macos",
+ target_os = "netbsd",
+ target_os = "illumos",
+ target_os = "openbsd"))]
+ let l = mem::size_of::<libc::sockaddr_dl>();
+ #[cfg(any(
+ target_os = "android",
+ target_os = "fuchsia",
+ target_os = "linux"))]
+ let l = mem::size_of::<libc::sockaddr_ll>();
+ assert_eq!( LinkAddr::size() as usize, l);
+ }
}
mod sockaddr_in {
@@ -2713,6 +2736,12 @@ mod tests {
let addr = SockaddrIn::from_str(s).unwrap();
assert_eq!(s, format!("{}", addr));
}
+
+ #[test]
+ fn size() {
+ assert_eq!(mem::size_of::<libc::sockaddr_in>(),
+ SockaddrIn::size() as usize);
+ }
}
mod sockaddr_in6 {
@@ -2725,10 +2754,15 @@ mod tests {
let addr = SockaddrIn6::from_str(s).unwrap();
assert_eq!(s, format!("{}", addr));
}
+
+ #[test]
+ fn size() {
+ assert_eq!(mem::size_of::<libc::sockaddr_in6>(),
+ SockaddrIn6::size() as usize);
+ }
}
mod unixaddr {
- #[cfg(any(target_os = "android", target_os = "linux"))]
use super::*;
#[cfg(any(target_os = "android", target_os = "linux"))]
@@ -2742,5 +2776,10 @@ mod tests {
assert_eq!(sun_path1, sun_path2);
}
+ #[test]
+ fn size() {
+ assert_eq!(mem::size_of::<libc::sockaddr_un>(),
+ UnixAddr::size() as usize);
+ }
}
}