New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
sockaddr_storage
shouldn't have internal padding bytes
#3004
Comments
Since the __ss_align and __ss_pad2 fields are private, it should be no problem to change them to make all padding bytes explicit. Would you submit a PR for that? |
I made #3010 to change the structure on Linux. I'm not very familiar with other platforms, but I think this should be changed on Fuchsia as well? Lines 910 to 914 in 73c25f4
|
Rearrange `sockaddr_storage` padding/alignment fields on Linux and Fuchsia Part of #3004. Previously on Linux, the `sockaddr_storage` structure had padding bytes between the `ss_family` and `__ss_align` fields. The `__ss_align` field has now been moved to the end of the structure to eliminate these padding bytes, matching recent glibc versions: https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/bits/socket.h;h=4f1f810ea1d9bf00ff428e4e7c49a52c71620775;hb=c804cd1c00adde061ca51711f63068c103e94eef#l190 After the PR on Linux x86-64: ``` print-type-size type: `unix::linux_like::sockaddr_storage`: 128 bytes, alignment: 8 bytes print-type-size field `.ss_family`: 2 bytes print-type-size field `.__ss_pad2`: 118 bytes print-type-size field `.__ss_align`: 8 bytes ``` These moved fields are private but they are used in the `sockaddr_storage`s `PartialEq`, `Debug`, and `Hash` implementations, so the exact behaviour may change slightly, but I don't think anyone should be depending on this. ~(It looks like [Fuchsia](https://github.com/rust-lang/libc/blob/73c25f4e9d66054d1496c693b72d60caea00c4a9/src/fuchsia/mod.rs#L910) has the same issue, but I didn't modify its structure because I don't know much about it, or how to test it.)~
Closing since #3010 fixes this on Linux and Fuchsia. If anyone finds other platforms with this issue it can be reopened, but I'm not familiar enough with other platforms to know if it is or not. |
A common use-case of
sockaddr_storage
is to store a socket address in asockaddr_storage
, inspect thess_family
field and the socket address length, and then cast it to the correct socket address type (for examplesockaddr_in
). For example, this is what the nix crate currently does using a union: https://github.com/nix-rust/nix/blob/fbebb21dd8df447a1408795b4b5706d9ca6c55df/src/sys/socket/addr.rs#L1537-L1540The rust libc library defines
sockaddr_storage
as the following on Linux:On Linux x86-64, this results in the following representation:
From what I understand, the 6 padding bytes in
sockaddr_storage
should cause a cast from memory initialized as asockaddr_storage
to another type likesockaddr_in
to invoke UB since these padding bytes are considered to be uninitialized memory. For example these padding bytes ofsockaddr_storage
overlap with thesockaddr_in.sin_port
field, so reading thesin_port
field after casting from asockaddr_storage
would be UB. And in the nix case, thess: libc::sockaddr_storage = mem::zeroed()
may also not zero these 6 padding bytes, possibly leading to UB when it's later read as a different socket address type if those padding bytes weren't overwritten during theptr::copy
.On recent glibc versions (such as 2.31 on Ubuntu 20.04), they define
sockaddr_storage
as:Since they have the padding/alignment fields in the opposite order from rust's libc definition (have the char array field first), there are no padding bytes:
The order of these fields was changed in this 2016 glibc patch: "Make padding in struct sockaddr_storage explicit [BZ #20111]" https://patchwork.sourceware.org/project/glibc/patch/fea4fa60-be9c-7cc2-b09c-c48845fe603f@redhat.com/
The text was updated successfully, but these errors were encountered: