Skip to content

Invalid layout assumptions for std::net::SocketAddrV{4, 6} #462

@a1phyr

Description

@a1phyr

shadowsocks-rs assumes that the layout of std::net::SocketAddrV{4,6} matches libc::sockaddr, but std makes no such promise. See rust-lang/rust#78802 for more details.

Example fixes: tokio-rs/mio#1388, rust-lang/socket2#120.

Example occurrences of this issue in this project (probably not exhaustive):

match *bind_addr {
SocketAddr::V4(ref v4) => {
pnl.af = libc::AF_INET as libc::sa_family_t;
let sockaddr: *const libc::sockaddr_in = v4 as *const SocketAddrV4 as *const _;
let addr: *const libc::in_addr = &((*sockaddr).sin_addr) as *const _;
let port: libc::in_port_t = (*sockaddr).sin_port;
ptr::copy_nonoverlapping(addr, &mut pnl.daddr.pfa.v4, mem::size_of_val(&pnl.daddr.pfa.v4));
pnl.set_dport(port);
}
SocketAddr::V6(ref v6) => {
pnl.af = libc::AF_INET6 as libc::sa_family_t;
let sockaddr: *const libc::sockaddr_in6 = v6 as *const SocketAddrV6 as *const _;
let addr: *const libc::in6_addr = &((*sockaddr).sin6_addr) as *const _;
let port: libc::in_port_t = (*sockaddr).sin6_port;
ptr::copy_nonoverlapping(addr, &mut pnl.daddr.pfa.v6, mem::size_of_val(&pnl.daddr.pfa.v6));
pnl.set_dport(port);
}
}
match *peer_addr {
SocketAddr::V4(ref v4) => {
if pnl.af != libc::AF_INET as libc::sa_family_t {
return Err(Error::new(ErrorKind::InvalidInput, "client addr must be ipv4"));
}
let sockaddr: *const libc::sockaddr_in = v4 as *const SocketAddrV4 as *const _;
let addr: *const libc::in_addr = &((*sockaddr).sin_addr) as *const _;
let port: libc::in_port_t = (*sockaddr).sin_port;
ptr::copy_nonoverlapping(addr, &mut pnl.saddr.pfa.v4, mem::size_of_val(&pnl.saddr.pfa.v4));
pnl.set_sport(port);
}
SocketAddr::V6(ref v6) => {
if pnl.af != libc::AF_INET6 as libc::sa_family_t {
return Err(Error::new(ErrorKind::InvalidInput, "client addr must be ipv6"));
}
let sockaddr: *const libc::sockaddr_in6 = v6 as *const SocketAddrV6 as *const _;
let addr: *const libc::in6_addr = &((*sockaddr).sin6_addr) as *const _;
let port: libc::in_port_t = (*sockaddr).sin6_port;
ptr::copy_nonoverlapping(addr, &mut pnl.saddr.pfa.v6, mem::size_of_val(&pnl.saddr.pfa.v6));
pnl.set_sport(port);
}
}

pub fn sockaddr_to_std(saddr: &libc::sockaddr_storage) -> io::Result<SocketAddr> {
match saddr.ss_family as libc::c_int {
libc::AF_INET => unsafe {
let addr: SocketAddrV4 = mem::transmute_copy(saddr);
Ok(SocketAddr::V4(addr))
},
libc::AF_INET6 => unsafe {
let addr: SocketAddrV6 = mem::transmute_copy(saddr);
Ok(SocketAddr::V6(addr))
},
_ => {
let err = Error::new(ErrorKind::InvalidData, "family must be either AF_INET or AF_INET6");
Err(err)
}
}
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions