Skip to content

Commit 6a00d3e

Browse files
committed
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.
1 parent 9793aaf commit 6a00d3e

File tree

2 files changed

+52
-2
lines changed

2 files changed

+52
-2
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,16 @@
33
All notable changes to this project will be documented in this file.
44
This project adheres to [Semantic Versioning](https://semver.org/).
55

6+
## [Unreleased] - ReleaseDate
7+
### Added
8+
### Changed
9+
### Fixed
10+
11+
- Fixed `UnixAddr::size` on Linux-based OSes.
12+
(#[1702](https://github.com/nix-rust/nix/pull/1702))
13+
14+
### Removed
15+
616
## [0.24.0] - 2022-04-21
717
### Added
818

src/sys/socket/addr.rs

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -953,6 +953,10 @@ impl SockaddrLike for UnixAddr {
953953
ptr::copy(addr as *const u8, sup, su_len as usize);
954954
Some(Self::from_raw_parts(su, su_len as u8))
955955
}
956+
957+
fn size() -> libc::socklen_t where Self: Sized {
958+
mem::size_of::<libc::sockaddr_un>() as libc::socklen_t
959+
}
956960
}
957961

958962
impl AsRef<libc::sockaddr_un> for UnixAddr {
@@ -2615,11 +2619,12 @@ mod tests {
26152619
}
26162620

26172621
mod link {
2622+
use super::*;
26182623
#[cfg(any(target_os = "ios",
26192624
target_os = "macos",
26202625
target_os = "illumos"
26212626
))]
2622-
use super::{*, super::super::socklen_t};
2627+
use super::super::super::socklen_t;
26232628

26242629
/// Don't panic when trying to display an empty datalink address
26252630
#[cfg(any(target_os = "dragonfly",
@@ -2701,6 +2706,25 @@ mod tests {
27012706
assert_eq!(sock_addr.as_link_addr().unwrap().addr(),
27022707
Some([24u8, 101, 144, 221, 76, 176]));
27032708
}
2709+
2710+
#[test]
2711+
fn size() {
2712+
#[cfg(any(target_os = "dragonfly",
2713+
target_os = "freebsd",
2714+
target_os = "ios",
2715+
target_os = "macos",
2716+
target_os = "netbsd",
2717+
target_os = "illumos",
2718+
target_os = "openbsd"))]
2719+
let l = mem::size_of::<libc::sockaddr_dl>();
2720+
#[cfg(any(
2721+
target_os = "android",
2722+
target_os = "fuchsia",
2723+
target_os = "illumos",
2724+
target_os = "linux"))]
2725+
let l = mem::size_of::<libc::sockaddr_ll>();
2726+
assert_eq!( LinkAddr::size() as usize, l);
2727+
}
27042728
}
27052729

27062730
mod sockaddr_in {
@@ -2713,6 +2737,12 @@ mod tests {
27132737
let addr = SockaddrIn::from_str(s).unwrap();
27142738
assert_eq!(s, format!("{}", addr));
27152739
}
2740+
2741+
#[test]
2742+
fn size() {
2743+
assert_eq!(mem::size_of::<libc::sockaddr_in>(),
2744+
SockaddrIn::size() as usize);
2745+
}
27162746
}
27172747

27182748
mod sockaddr_in6 {
@@ -2725,10 +2755,15 @@ mod tests {
27252755
let addr = SockaddrIn6::from_str(s).unwrap();
27262756
assert_eq!(s, format!("{}", addr));
27272757
}
2758+
2759+
#[test]
2760+
fn size() {
2761+
assert_eq!(mem::size_of::<libc::sockaddr_in6>(),
2762+
SockaddrIn6::size() as usize);
2763+
}
27282764
}
27292765

27302766
mod unixaddr {
2731-
#[cfg(any(target_os = "android", target_os = "linux"))]
27322767
use super::*;
27332768

27342769
#[cfg(any(target_os = "android", target_os = "linux"))]
@@ -2742,5 +2777,10 @@ mod tests {
27422777
assert_eq!(sun_path1, sun_path2);
27432778
}
27442779

2780+
#[test]
2781+
fn size() {
2782+
assert_eq!(mem::size_of::<libc::sockaddr_un>(),
2783+
UnixAddr::size() as usize);
2784+
}
27452785
}
27462786
}

0 commit comments

Comments
 (0)