mirror of
https://gitee.com/openharmony/third_party_rust_nix
synced 2024-11-27 01:20:41 +00:00
Merge #1871
1871: Fix using SockaddrStorage to store Unix domain addresses on Linux r=rtzoeller a=asomers Since it has variable length, the user of a sockaddr_un must keep track of its true length. On the BSDs, this is handled by the builtin sun_len field. But on Linux-like operating systems it isn't. Fix this bug by explicitly tracking it for SockaddrStorage just like we already do for UnixAddr. Fixes #1866 Co-authored-by: Alan Somers <asomers@gmail.com>
This commit is contained in:
commit
9ea1493a81
@ -6,7 +6,9 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
## [Unreleased] - ReleaseDate
|
||||
### Added
|
||||
|
||||
- Add `MntFlags` and `unmount` on all of the BSDs.
|
||||
- Added `SockaddrStorage::{as_unix_addr, as_unix_addr_mut}`
|
||||
([#1871](https://github.com/nix-rust/nix/pull/1871))
|
||||
- Added `MntFlags` and `unmount` on all of the BSDs.
|
||||
([#1849](https://github.com/nix-rust/nix/pull/1849))
|
||||
- Added a 'Statfs::flags' method.
|
||||
([#1849](https://github.com/nix-rust/nix/pull/1849))
|
||||
@ -44,6 +46,8 @@ This project adheres to [Semantic Versioning](https://semver.org/).
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed using `SockaddrStorage` to store a Unix-domain socket address on Linux.
|
||||
([#1871](https://github.com/nix-rust/nix/pull/1871))
|
||||
- Fix microsecond calculation for `TimeSpec`.
|
||||
([#1801](https://github.com/nix-rust/nix/pull/1801))
|
||||
- Fix `User::from_name` and `Group::from_name` panicking
|
||||
|
@ -1536,6 +1536,17 @@ impl SockaddrLike for SockaddrStorage {
|
||||
let mut ss: libc::sockaddr_storage = mem::zeroed();
|
||||
let ssp = &mut ss as *mut libc::sockaddr_storage as *mut u8;
|
||||
ptr::copy(addr as *const u8, ssp, len as usize);
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "fuchsia",
|
||||
target_os = "illumos",
|
||||
target_os = "linux"
|
||||
))]
|
||||
if i32::from(ss.ss_family) == libc::AF_UNIX {
|
||||
// Safe because we UnixAddr is strictly smaller than
|
||||
// SockaddrStorage, and we just initialized the structure.
|
||||
(*(&mut ss as *mut libc::sockaddr_storage as *mut UnixAddr)).sun_len = len as u8;
|
||||
}
|
||||
Some(Self { ss })
|
||||
}
|
||||
} else {
|
||||
@ -1597,6 +1608,21 @@ impl SockaddrLike for SockaddrStorage {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "fuchsia",
|
||||
target_os = "illumos",
|
||||
target_os = "linux"
|
||||
))]
|
||||
fn len(&self) -> libc::socklen_t {
|
||||
match self.as_unix_addr() {
|
||||
// The UnixAddr type knows its own length
|
||||
Some(ua) => ua.len(),
|
||||
// For all else, we're just a boring SockaddrStorage
|
||||
None => mem::size_of_val(self) as libc::socklen_t
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! accessors {
|
||||
@ -1634,6 +1660,64 @@ macro_rules! accessors {
|
||||
}
|
||||
|
||||
impl SockaddrStorage {
|
||||
/// Downcast to an immutable `[UnixAddr]` reference.
|
||||
pub fn as_unix_addr(&self) -> Option<&UnixAddr> {
|
||||
cfg_if! {
|
||||
if #[cfg(any(target_os = "android",
|
||||
target_os = "fuchsia",
|
||||
target_os = "illumos",
|
||||
target_os = "linux"
|
||||
))]
|
||||
{
|
||||
let p = unsafe{ &self.ss as *const libc::sockaddr_storage };
|
||||
// Safe because UnixAddr is strictly smaller than
|
||||
// sockaddr_storage, and we're fully initialized
|
||||
let len = unsafe {
|
||||
(*(p as *const UnixAddr )).sun_len as usize
|
||||
};
|
||||
} else {
|
||||
let len = self.len() as usize;
|
||||
}
|
||||
}
|
||||
// Sanity checks
|
||||
if self.family() != Some(AddressFamily::Unix) ||
|
||||
len < offset_of!(libc::sockaddr_un, sun_path) ||
|
||||
len > mem::size_of::<libc::sockaddr_un>() {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe{&self.su})
|
||||
}
|
||||
}
|
||||
|
||||
/// Downcast to a mutable `[UnixAddr]` reference.
|
||||
pub fn as_unix_addr_mut(&mut self) -> Option<&mut UnixAddr> {
|
||||
cfg_if! {
|
||||
if #[cfg(any(target_os = "android",
|
||||
target_os = "fuchsia",
|
||||
target_os = "illumos",
|
||||
target_os = "linux"
|
||||
))]
|
||||
{
|
||||
let p = unsafe{ &self.ss as *const libc::sockaddr_storage };
|
||||
// Safe because UnixAddr is strictly smaller than
|
||||
// sockaddr_storage, and we're fully initialized
|
||||
let len = unsafe {
|
||||
(*(p as *const UnixAddr )).sun_len as usize
|
||||
};
|
||||
} else {
|
||||
let len = self.len() as usize;
|
||||
}
|
||||
}
|
||||
// Sanity checks
|
||||
if self.family() != Some(AddressFamily::Unix) ||
|
||||
len < offset_of!(libc::sockaddr_un, sun_path) ||
|
||||
len > mem::size_of::<libc::sockaddr_un>() {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe{&mut self.su})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
accessors! {as_alg_addr, as_alg_addr_mut, AlgAddr,
|
||||
AddressFamily::Alg, libc::sockaddr_alg, alg}
|
||||
@ -3063,6 +3147,44 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
mod sockaddr_storage {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn from_sockaddr_un_named() {
|
||||
let ua = UnixAddr::new("/var/run/mysock").unwrap();
|
||||
let ptr = ua.as_ptr() as *const libc::sockaddr;
|
||||
let ss = unsafe {
|
||||
SockaddrStorage::from_raw(ptr, Some(ua.len()))
|
||||
}.unwrap();
|
||||
assert_eq!(ss.len(), ua.len());
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[test]
|
||||
fn from_sockaddr_un_abstract_named() {
|
||||
let name = String::from("nix\0abstract\0test");
|
||||
let ua = UnixAddr::new_abstract(name.as_bytes()).unwrap();
|
||||
let ptr = ua.as_ptr() as *const libc::sockaddr;
|
||||
let ss = unsafe {
|
||||
SockaddrStorage::from_raw(ptr, Some(ua.len()))
|
||||
}.unwrap();
|
||||
assert_eq!(ss.len(), ua.len());
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
#[test]
|
||||
fn from_sockaddr_un_abstract_unnamed() {
|
||||
let empty = String::new();
|
||||
let ua = UnixAddr::new_abstract(empty.as_bytes()).unwrap();
|
||||
let ptr = ua.as_ptr() as *const libc::sockaddr;
|
||||
let ss = unsafe {
|
||||
SockaddrStorage::from_raw(ptr, Some(ua.len()))
|
||||
}.unwrap();
|
||||
assert_eq!(ss.len(), ua.len());
|
||||
}
|
||||
}
|
||||
|
||||
mod unixaddr {
|
||||
use super::*;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user