Skip to content

Commit 241c9d3

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 241c9d3

File tree

2 files changed

+48
-2
lines changed

2 files changed

+48
-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: 38 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,21 @@ 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(target_os = "android", target_os = "linux"))]
2721+
let l = mem::size_of::<libc::sockaddr_ll>();
2722+
assert_eq!( LinkAddr::size() as usize, l);
2723+
}
27042724
}
27052725

27062726
mod sockaddr_in {
@@ -2713,6 +2733,12 @@ mod tests {
27132733
let addr = SockaddrIn::from_str(s).unwrap();
27142734
assert_eq!(s, format!("{}", addr));
27152735
}
2736+
2737+
#[test]
2738+
fn size() {
2739+
assert_eq!(mem::size_of::<libc::sockaddr_in>(),
2740+
SockaddrIn::size() as usize);
2741+
}
27162742
}
27172743

27182744
mod sockaddr_in6 {
@@ -2725,10 +2751,15 @@ mod tests {
27252751
let addr = SockaddrIn6::from_str(s).unwrap();
27262752
assert_eq!(s, format!("{}", addr));
27272753
}
2754+
2755+
#[test]
2756+
fn size() {
2757+
assert_eq!(mem::size_of::<libc::sockaddr_in6>(),
2758+
SockaddrIn6::size() as usize);
2759+
}
27282760
}
27292761

27302762
mod unixaddr {
2731-
#[cfg(any(target_os = "android", target_os = "linux"))]
27322763
use super::*;
27332764

27342765
#[cfg(any(target_os = "android", target_os = "linux"))]
@@ -2742,5 +2773,10 @@ mod tests {
27422773
assert_eq!(sun_path1, sun_path2);
27432774
}
27442775

2776+
#[test]
2777+
fn size() {
2778+
assert_eq!(mem::size_of::<libc::sockaddr_un>(),
2779+
UnixAddr::size() as usize);
2780+
}
27452781
}
27462782
}

0 commit comments

Comments
 (0)