Skip to content

Commit c80828e

Browse files
committed
PR suggestion: Set the length later instead of using from_raw
1 parent 96fa5a8 commit c80828e

File tree

2 files changed

+114
-17
lines changed

2 files changed

+114
-17
lines changed

src/sys/socket/addr.rs

Lines changed: 98 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,22 @@ impl SockaddrLike for UnixAddr {
763763
{
764764
mem::size_of::<libc::sockaddr_un>() as libc::socklen_t
765765
}
766+
767+
unsafe fn set_length(&mut self, new_length: usize) -> std::result::Result<(), SocketAddressLengthNotDynamic> {
768+
cfg_if! {
769+
if #[cfg(any(target_os = "android",
770+
target_os = "fuchsia",
771+
target_os = "illumos",
772+
target_os = "linux",
773+
target_os = "redox",
774+
))] {
775+
self.sun_len = new_length as u8;
776+
} else {
777+
self.sun.sun_len = new_length as u8;
778+
}
779+
};
780+
Ok(())
781+
}
766782
}
767783

768784
impl AsRef<libc::sockaddr_un> for UnixAddr {
@@ -912,8 +928,30 @@ pub trait SockaddrLike: private::SockaddrLikePriv {
912928
{
913929
mem::size_of::<Self>() as libc::socklen_t
914930
}
931+
932+
/// Set the length of this socket address
933+
///
934+
/// This method may only be called on socket addresses whose lenghts are dynamic, and it
935+
/// returns an error if called on a type whose length is static.
936+
///
937+
/// # Safety
938+
///
939+
/// `new_length` must be a valid length for this type of address. Specifically, reads of that
940+
/// length from `self` must be valid.
941+
unsafe fn set_length(&mut self, new_length: usize) -> std::result::Result<(), SocketAddressLengthNotDynamic>;
915942
}
916943

944+
/// The error returned by [`SockaddrLike::set_length`] on an address whose length is statically
945+
/// fixed.
946+
#[derive(Copy, Clone, Debug)]
947+
pub struct SocketAddressLengthNotDynamic;
948+
impl fmt::Display for SocketAddressLengthNotDynamic {
949+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
950+
f.write_str("Attempted to set length on socket whose length is statically fixed")
951+
}
952+
}
953+
impl std::error::Error for SocketAddressLengthNotDynamic {}
954+
917955
impl private::SockaddrLikePriv for () {
918956
fn as_mut_ptr(&mut self) -> *mut libc::sockaddr {
919957
ptr::null_mut()
@@ -946,6 +984,10 @@ impl SockaddrLike for () {
946984
fn len(&self) -> libc::socklen_t {
947985
0
948986
}
987+
988+
unsafe fn set_length(&mut self, _new_length: usize) -> std::result::Result<(), SocketAddressLengthNotDynamic> {
989+
Err(SocketAddressLengthNotDynamic)
990+
}
949991
}
950992

951993
/// An IPv4 socket address
@@ -1015,6 +1057,10 @@ impl SockaddrLike for SockaddrIn {
10151057
}
10161058
Some(Self(ptr::read_unaligned(addr as *const _)))
10171059
}
1060+
1061+
unsafe fn set_length(&mut self, _new_length: usize) -> std::result::Result<(), SocketAddressLengthNotDynamic> {
1062+
Err(SocketAddressLengthNotDynamic)
1063+
}
10181064
}
10191065

10201066
#[cfg(feature = "net")]
@@ -1134,6 +1180,10 @@ impl SockaddrLike for SockaddrIn6 {
11341180
}
11351181
Some(Self(ptr::read_unaligned(addr as *const _)))
11361182
}
1183+
1184+
unsafe fn set_length(&mut self, _new_length: usize) -> std::result::Result<(), SocketAddressLengthNotDynamic> {
1185+
Err(SocketAddressLengthNotDynamic)
1186+
}
11371187
}
11381188

11391189
#[cfg(feature = "net")]
@@ -1361,6 +1411,27 @@ impl SockaddrLike for SockaddrStorage {
13611411
None => mem::size_of_val(self) as libc::socklen_t,
13621412
}
13631413
}
1414+
1415+
unsafe fn set_length(&mut self, new_length: usize) -> std::result::Result<(), SocketAddressLengthNotDynamic> {
1416+
match self.as_unix_addr_mut() {
1417+
Some(addr) => {
1418+
cfg_if! {
1419+
if #[cfg(any(target_os = "android",
1420+
target_os = "fuchsia",
1421+
target_os = "illumos",
1422+
target_os = "linux",
1423+
target_os = "redox",
1424+
))] {
1425+
addr.sun_len = new_length as u8;
1426+
} else {
1427+
addr.sun.sun_len = new_length as u8;
1428+
}
1429+
}
1430+
Ok(())
1431+
},
1432+
None => Err(SocketAddressLengthNotDynamic),
1433+
}
1434+
}
13641435
}
13651436

13661437
macro_rules! accessors {
@@ -1754,6 +1825,10 @@ pub mod netlink {
17541825
}
17551826
Some(Self(ptr::read_unaligned(addr as *const _)))
17561827
}
1828+
1829+
unsafe fn set_length(&mut self, _new_length: usize) -> std::result::Result<(), SocketAddressLengthNotDynamic> {
1830+
Err(SocketAddressLengthNotDynamic)
1831+
}
17571832
}
17581833

17591834
impl AsRef<libc::sockaddr_nl> for NetlinkAddr {
@@ -1803,6 +1878,10 @@ pub mod alg {
18031878
}
18041879
Some(Self(ptr::read_unaligned(addr as *const _)))
18051880
}
1881+
1882+
unsafe fn set_length(&mut self, _new_length: usize) -> std::result::Result<(), SocketAddressLengthNotDynamic> {
1883+
Err(SocketAddressLengthNotDynamic)
1884+
}
18061885
}
18071886

18081887
impl AsRef<libc::sockaddr_alg> for AlgAddr {
@@ -1902,7 +1981,7 @@ pub mod sys_control {
19021981
use std::{fmt, mem, ptr};
19031982
use std::os::unix::io::RawFd;
19041983
use crate::{Errno, Result};
1905-
use super::{private, SockaddrLike};
1984+
use super::{private, SockaddrLike, SocketAddressLengthNotDynamic};
19061985

19071986
// FIXME: Move type into `libc`
19081987
#[repr(C)]
@@ -1943,6 +2022,10 @@ pub mod sys_control {
19432022
}
19442023
Some(Self(ptr::read_unaligned(addr as *const _)))
19452024
}
2025+
2026+
unsafe fn set_length(&mut self, _new_length: usize) -> std::result::Result<(), SocketAddressLengthNotDynamic> {
2027+
Err(SocketAddressLengthNotDynamic)
2028+
}
19462029
}
19472030

19482031
impl AsRef<libc::sockaddr_ctl> for SysControlAddr {
@@ -2007,7 +2090,7 @@ pub mod sys_control {
20072090
mod datalink {
20082091
feature! {
20092092
#![feature = "net"]
2010-
use super::{fmt, mem, private, ptr, SockaddrLike};
2093+
use super::{fmt, mem, private, ptr, SockaddrLike, SocketAddressLengthNotDynamic};
20112094

20122095
/// Hardware Address
20132096
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
@@ -2085,6 +2168,10 @@ mod datalink {
20852168
}
20862169
Some(Self(ptr::read_unaligned(addr as *const _)))
20872170
}
2171+
2172+
unsafe fn set_length(&mut self, _new_length: usize) -> std::result::Result<(), SocketAddressLengthNotDynamic> {
2173+
Err(SocketAddressLengthNotDynamic)
2174+
}
20882175
}
20892176

20902177
impl AsRef<libc::sockaddr_ll> for LinkAddr {
@@ -2110,7 +2197,7 @@ mod datalink {
21102197
mod datalink {
21112198
feature! {
21122199
#![feature = "net"]
2113-
use super::{fmt, mem, private, ptr, SockaddrLike};
2200+
use super::{fmt, mem, private, ptr, SockaddrLike, SocketAddressLengthNotDynamic};
21142201

21152202
/// Hardware Address
21162203
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
@@ -2209,6 +2296,10 @@ mod datalink {
22092296
}
22102297
Some(Self(ptr::read_unaligned(addr as *const _)))
22112298
}
2299+
2300+
unsafe fn set_length(&mut self, _new_length: usize) -> std::result::Result<(), SocketAddressLengthNotDynamic> {
2301+
Err(SocketAddressLengthNotDynamic)
2302+
}
22122303
}
22132304

22142305
impl AsRef<libc::sockaddr_dl> for LinkAddr {
@@ -2257,6 +2348,10 @@ pub mod vsock {
22572348
}
22582349
Some(Self(ptr::read_unaligned(addr as *const _)))
22592350
}
2351+
2352+
unsafe fn set_length(&mut self, _new_length: usize) -> std::result::Result<(), SocketAddressLengthNotDynamic> {
2353+
Err(SocketAddressLengthNotDynamic)
2354+
}
22602355
}
22612356

22622357
impl AsRef<libc::sockaddr_vm> for VsockAddr {

src/sys/socket/mod.rs

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1627,7 +1627,7 @@ impl<S> MultiHeaders<S> {
16271627
None => (std::ptr::null(), 0),
16281628
};
16291629
let msg_hdr = unsafe {
1630-
pack_mhdr_to_receive(std::ptr::null(), 0, ptr, cap, <S as addr::private::SockaddrLikePriv>::as_mut_ptr(address.assume_init_mut()).cast())
1630+
pack_mhdr_to_receive(std::ptr::null(), 0, ptr, cap, address.assume_init_mut())
16311631
};
16321632
libc::mmsghdr {
16331633
msg_hdr,
@@ -1763,7 +1763,7 @@ where
17631763
mmsghdr.msg_hdr,
17641764
mmsghdr.msg_len as isize,
17651765
self.rmm.msg_controllen,
1766-
Some(address),
1766+
address,
17671767
)
17681768
})
17691769
}
@@ -1916,7 +1916,7 @@ unsafe fn read_mhdr<'a, 'i, S>(
19161916
mhdr: msghdr,
19171917
r: isize,
19181918
msg_controllen: usize,
1919-
address: Option<S>,
1919+
mut address: S,
19201920
) -> RecvMsg<'a, 'i, S>
19211921
where S: SockaddrLike
19221922
{
@@ -1932,10 +1932,15 @@ unsafe fn read_mhdr<'a, 'i, S>(
19321932
}.as_ref()
19331933
};
19341934

1935+
// Ignore errors if this socket address has statically-known length
1936+
//
1937+
// This is to ensure that unix socket addresses have their length set appropriately.
1938+
let _ = unsafe { address.set_length(mhdr.msg_namelen as usize) };
1939+
19351940
RecvMsg {
19361941
bytes: r as usize,
19371942
cmsghdr,
1938-
address,
1943+
address: Some(address),
19391944
flags: MsgFlags::from_bits_truncate(mhdr.msg_flags),
19401945
mhdr,
19411946
iobufs: std::marker::PhantomData,
@@ -1953,19 +1958,19 @@ unsafe fn read_mhdr<'a, 'i, S>(
19531958
/// headers are not used
19541959
///
19551960
/// Buffers must remain valid for the whole lifetime of msghdr
1956-
unsafe fn pack_mhdr_to_receive(
1961+
unsafe fn pack_mhdr_to_receive<S>(
19571962
iov_buffer: *const IoSliceMut,
19581963
iov_buffer_len: usize,
19591964
cmsg_buffer: *const u8,
19601965
cmsg_capacity: usize,
1961-
address: *mut libc::sockaddr_storage,
1962-
) -> msghdr {
1966+
address: *mut S,
1967+
) -> msghdr where S: SockaddrLike {
19631968
// Musl's msghdr has private fields, so this is the only way to
19641969
// initialize it.
19651970
let mut mhdr = mem::MaybeUninit::<msghdr>::zeroed();
19661971
let p = mhdr.as_mut_ptr();
19671972
(*p).msg_name = address as *mut c_void;
1968-
(*p).msg_namelen = mem::size_of::<libc::sockaddr_storage>() as u32;
1973+
(*p).msg_namelen = S::size();
19691974
(*p).msg_iov = iov_buffer as *mut iovec;
19701975
(*p).msg_iovlen = iov_buffer_len as _;
19711976
(*p).msg_control = cmsg_buffer as *mut c_void;
@@ -2047,23 +2052,20 @@ pub fn recvmsg<'a, 'outer, 'inner, S>(fd: RawFd, iov: &'outer mut [IoSliceMut<'i
20472052
where S: SockaddrLike + 'a,
20482053
'inner: 'outer
20492054
{
2050-
let mut address: libc::sockaddr_storage = unsafe { mem::MaybeUninit::zeroed().assume_init() };
2051-
let address_ptr: *mut libc::sockaddr_storage = &mut address as *mut libc::sockaddr_storage;
2055+
let mut address: mem::MaybeUninit<S> = mem::MaybeUninit::zeroed();
20522056

20532057
let (msg_control, msg_controllen) = cmsg_buffer.as_mut()
20542058
.map(|v| (v.as_mut_ptr(), v.capacity()))
20552059
.unwrap_or((ptr::null_mut(), 0));
20562060
let mut mhdr = unsafe {
2057-
pack_mhdr_to_receive(iov.as_ref().as_ptr(), iov.len(), msg_control, msg_controllen, address_ptr)
2061+
pack_mhdr_to_receive(iov.as_ref().as_ptr(), iov.len(), msg_control, msg_controllen, address.as_mut_ptr())
20582062
};
20592063

20602064
let ret = unsafe { libc::recvmsg(fd, &mut mhdr, flags.bits()) };
20612065

20622066
let r = Errno::result(ret)?;
20632067

2064-
let address = unsafe { S::from_raw(address_ptr.cast::<libc::sockaddr>(), Some(mhdr.msg_namelen)) };
2065-
2066-
Ok(unsafe { read_mhdr(mhdr, r, msg_controllen, address) })
2068+
Ok(unsafe { read_mhdr(mhdr, r, msg_controllen, address.assume_init()) })
20672069
}
20682070
}
20692071

0 commit comments

Comments
 (0)