Skip to content

Commit 7cc33c1

Browse files
bors[bot]asomers
andauthored
Merge #1770
1770: Fix SockaddrLike::from_raw with unaligned inputs r=rtzoeller a=asomers The major users of this function are functions like gethostname, which will always properly align their buffers. But out-of-crate consumers could manually construct an unaligned buffer. Handle that correctly. Enable Clippy's cast_ptr_alignment lint. It's disabled by default as it reports many false positives, but it would've caught this problem. Reported-by: Miri Fixes: 1769 Co-authored-by: Alan Somers <asomers@gmail.com>
2 parents 14418f4 + ca2c920 commit 7cc33c1

File tree

4 files changed

+28
-21
lines changed

4 files changed

+28
-21
lines changed

.cirrus.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ build: &BUILD
2121
- $TOOL +$TOOLCHAIN $BUILD $ZFLAGS --target $TARGET --all-targets
2222
- $TOOL +$TOOLCHAIN doc $ZFLAGS --no-deps --target $TARGET
2323
- $TOOL +$TOOLCHAIN clippy $ZFLAGS --target $TARGET --all-targets -- -D warnings
24-
- if [ -z "$NOHACK" ]; then $TOOL +$TOOLCHAIN install cargo-hack; fi
24+
- if [ -z "$NOHACK" ]; then $TOOL +$TOOLCHAIN install --version 0.5.14 cargo-hack; fi
2525
- if [ -z "$NOHACK" ]; then $TOOL +$TOOLCHAIN hack $ZFLAGS check --target $TARGET --each-feature; fi
2626

2727
# Tests that do require executing the binaries

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
#![deny(missing_debug_implementations)]
5454
#![warn(missing_docs)]
5555
#![cfg_attr(docsrs, feature(doc_cfg))]
56+
#![deny(clippy::cast_ptr_alignment)]
5657

5758
// Re-exported external crates
5859
pub use libc;

src/sys/socket/addr.rs

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,7 +1195,7 @@ impl SockaddrLike for SockaddrIn {
11951195
if (*addr).sa_family as i32 != libc::AF_INET as i32 {
11961196
return None;
11971197
}
1198-
Some(SockaddrIn(*(addr as *const libc::sockaddr_in)))
1198+
Some(Self(ptr::read_unaligned(addr as *const _)))
11991199
}
12001200
}
12011201

@@ -1301,7 +1301,7 @@ impl SockaddrLike for SockaddrIn6 {
13011301
if (*addr).sa_family as i32 != libc::AF_INET6 as i32 {
13021302
return None;
13031303
}
1304-
Some(SockaddrIn6(*(addr as *const libc::sockaddr_in6)))
1304+
Some(Self(ptr::read_unaligned(addr as *const _)))
13051305
}
13061306
}
13071307

@@ -1870,21 +1870,21 @@ impl SockAddr {
18701870
Some(AddressFamily::Unix) => None,
18711871
#[cfg(feature = "net")]
18721872
Some(AddressFamily::Inet) => Some(SockAddr::Inet(
1873-
InetAddr::V4(*(addr as *const libc::sockaddr_in)))),
1873+
InetAddr::V4(ptr::read_unaligned(addr as *const _)))),
18741874
#[cfg(feature = "net")]
18751875
Some(AddressFamily::Inet6) => Some(SockAddr::Inet(
1876-
InetAddr::V6(*(addr as *const libc::sockaddr_in6)))),
1876+
InetAddr::V6(ptr::read_unaligned(addr as *const _)))),
18771877
#[cfg(any(target_os = "android", target_os = "linux"))]
18781878
Some(AddressFamily::Netlink) => Some(SockAddr::Netlink(
1879-
NetlinkAddr(*(addr as *const libc::sockaddr_nl)))),
1879+
NetlinkAddr(ptr::read_unaligned(addr as *const _)))),
18801880
#[cfg(all(feature = "ioctl",
18811881
any(target_os = "ios", target_os = "macos")))]
18821882
Some(AddressFamily::System) => Some(SockAddr::SysControl(
1883-
SysControlAddr(*(addr as *const libc::sockaddr_ctl)))),
1883+
SysControlAddr(ptr::read_unaligned(addr as *const _)))),
18841884
#[cfg(any(target_os = "android", target_os = "linux"))]
18851885
#[cfg(feature = "net")]
18861886
Some(AddressFamily::Packet) => Some(SockAddr::Link(
1887-
LinkAddr(*(addr as *const libc::sockaddr_ll)))),
1887+
LinkAddr(ptr::read_unaligned(addr as *const _)))),
18881888
#[cfg(any(target_os = "dragonfly",
18891889
target_os = "freebsd",
18901890
target_os = "ios",
@@ -1894,7 +1894,7 @@ impl SockAddr {
18941894
target_os = "openbsd"))]
18951895
#[cfg(feature = "net")]
18961896
Some(AddressFamily::Link) => {
1897-
let ether_addr = LinkAddr(*(addr as *const libc::sockaddr_dl));
1897+
let ether_addr = LinkAddr(ptr::read_unaligned(addr as *const _));
18981898
if ether_addr.is_empty() {
18991899
None
19001900
} else {
@@ -1903,7 +1903,7 @@ impl SockAddr {
19031903
},
19041904
#[cfg(any(target_os = "android", target_os = "linux"))]
19051905
Some(AddressFamily::Vsock) => Some(SockAddr::Vsock(
1906-
VsockAddr(*(addr as *const libc::sockaddr_vm)))),
1906+
VsockAddr(ptr::read_unaligned(addr as *const _)))),
19071907
// Other address families are currently not supported and simply yield a None
19081908
// entry instead of a proper conversion to a `SockAddr`.
19091909
Some(_) | None => None,
@@ -2104,7 +2104,7 @@ pub mod netlink {
21042104
if (*addr).sa_family as i32 != libc::AF_NETLINK as i32 {
21052105
return None;
21062106
}
2107-
Some(NetlinkAddr(*(addr as *const libc::sockaddr_nl)))
2107+
Some(Self(ptr::read_unaligned(addr as *const _)))
21082108
}
21092109
}
21102110

@@ -2148,7 +2148,7 @@ pub mod alg {
21482148
if (*addr).sa_family as i32 != libc::AF_ALG as i32 {
21492149
return None;
21502150
}
2151-
Some(AlgAddr(*(addr as *const libc::sockaddr_alg)))
2151+
Some(Self(ptr::read_unaligned(addr as *const _)))
21522152
}
21532153
}
21542154

@@ -2220,7 +2220,7 @@ feature! {
22202220
pub mod sys_control {
22212221
use crate::sys::socket::addr::AddressFamily;
22222222
use libc::{self, c_uchar};
2223-
use std::{fmt, mem};
2223+
use std::{fmt, mem, ptr};
22242224
use std::os::unix::io::RawFd;
22252225
use crate::{Errno, Result};
22262226
use super::{private, SockaddrLike};
@@ -2262,7 +2262,7 @@ pub mod sys_control {
22622262
if (*addr).sa_family as i32 != libc::AF_SYSTEM as i32 {
22632263
return None;
22642264
}
2265-
Some(SysControlAddr(*(addr as *const libc::sockaddr_ctl)))
2265+
Some(Self(ptr::read_unaligned(addr as *const _)))
22662266
}
22672267
}
22682268

@@ -2329,7 +2329,7 @@ pub mod sys_control {
23292329
mod datalink {
23302330
feature! {
23312331
#![feature = "net"]
2332-
use super::{fmt, mem, private, SockaddrLike};
2332+
use super::{fmt, mem, private, ptr, SockaddrLike};
23332333

23342334
/// Hardware Address
23352335
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
@@ -2405,7 +2405,7 @@ mod datalink {
24052405
if (*addr).sa_family as i32 != libc::AF_PACKET as i32 {
24062406
return None;
24072407
}
2408-
Some(LinkAddr(*(addr as *const libc::sockaddr_ll)))
2408+
Some(Self(ptr::read_unaligned(addr as *const _)))
24092409
}
24102410
}
24112411

@@ -2430,7 +2430,7 @@ mod datalink {
24302430
mod datalink {
24312431
feature! {
24322432
#![feature = "net"]
2433-
use super::{fmt, mem, private, SockaddrLike};
2433+
use super::{fmt, mem, private, ptr, SockaddrLike};
24342434

24352435
/// Hardware Address
24362436
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
@@ -2525,7 +2525,7 @@ mod datalink {
25252525
if (*addr).sa_family as i32 != libc::AF_LINK as i32 {
25262526
return None;
25272527
}
2528-
Some(LinkAddr(*(addr as *const libc::sockaddr_dl)))
2528+
Some(Self(ptr::read_unaligned(addr as *const _)))
25292529
}
25302530
}
25312531

@@ -2569,7 +2569,7 @@ pub mod vsock {
25692569
if (*addr).sa_family as i32 != libc::AF_VSOCK as i32 {
25702570
return None;
25712571
}
2572-
Some(VsockAddr(*(addr as *const libc::sockaddr_vm)))
2572+
Some(Self(ptr::read_unaligned(addr as *const _)))
25732573
}
25742574
}
25752575

@@ -2658,6 +2658,8 @@ mod tests {
26582658
}
26592659

26602660
mod link {
2661+
#![allow(clippy::cast_ptr_alignment)]
2662+
26612663
use super::*;
26622664
#[cfg(any(target_os = "ios",
26632665
target_os = "macos",
@@ -2698,8 +2700,11 @@ mod tests {
26982700
))]
26992701
#[test]
27002702
fn linux_loopback() {
2701-
let bytes = [17u8, 0, 0, 0, 1, 0, 0, 0, 4, 3, 0, 6, 1, 2, 3, 4, 5, 6, 0, 0];
2702-
let sa = bytes.as_ptr() as *const libc::sockaddr;
2703+
#[repr(align(2))]
2704+
struct Raw([u8; 20]);
2705+
2706+
let bytes = Raw([17u8, 0, 0, 0, 1, 0, 0, 0, 4, 3, 0, 6, 1, 2, 3, 4, 5, 6, 0, 0]);
2707+
let sa = bytes.0.as_ptr() as *const libc::sockaddr;
27032708
let len = None;
27042709
let sock_addr = unsafe { SockaddrStorage::from_raw(sa, len) }.unwrap();
27052710
assert_eq!(sock_addr.family(), Some(AddressFamily::Packet));

src/sys/socket/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -949,6 +949,7 @@ impl ControlMessageOwned {
949949

950950
#[cfg(any(target_os = "android", target_os = "linux"))]
951951
#[cfg(feature = "net")]
952+
#[allow(clippy::cast_ptr_alignment)] // False positive
952953
unsafe fn recv_err_helper<T>(p: *mut libc::c_uchar, len: usize) -> (libc::sock_extended_err, Option<T>) {
953954
let ee = p as *const libc::sock_extended_err;
954955
let err = ptr::read_unaligned(ee);

0 commit comments

Comments
 (0)