Skip to content

Commit

Permalink
Merge #1702
Browse files Browse the repository at this point in the history
1702: Fix UnixAddr::size on Linux and Android r=rtzoeller a=asomers

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.

Co-authored-by: Alan Somers <asomers@gmail.com>
  • Loading branch information
bors[bot] and asomers authored Apr 22, 2022
2 parents 9793aaf + db969c5 commit 2854888
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 2 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/).

## [Unreleased] - ReleaseDate
### Added
### Changed
### Fixed

- Fixed `UnixAddr::size` on Linux-based OSes.
(#[1702](https://github.com/nix-rust/nix/pull/1702))

### Removed

## [0.24.0] - 2022-04-21
### Added

Expand Down
43 changes: 41 additions & 2 deletions src/sys/socket/addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand All @@ -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"))]
Expand All @@ -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);
}
}
}

0 comments on commit 2854888

Please sign in to comment.