Repository navigation
[BUG] Fix misaligned sockaddr_in access in SocketAddr - #4725
Conversation
|
|
|
/easycla |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4725 +/- ##
==========================================
+ Coverage 86.57% 86.60% +0.03%
==========================================
Files 529 530 +1
Lines 20996 21010 +14
==========================================
+ Hits 18176 18194 +18
+ Misses 2820 2816 -4
🚀 New features to boost your workflow:
|
2d24ffe to
af1a2cc
Compare
|
Thanks for picking this up. There is a new clang-tidy warning (edit) Full warning is: |
There was a problem hiding this comment.
checked this against marcalff's #4629 notes. it matches except the (u_long, uint16_t) constructor, where the note kept the cast (edited). outside the header and its test, the only SocketAddr users are the two in http_server.h, both go through the updated Socket methods, and nothing relied on the removed conversion operators. 21 of 21 socket tests pass at af1a2cc with Apple clang 21, plain and under UBSan, and with GCC 16. making addr_len() return the storage size fails bind() on macOS, and two of the new tests catch it.
one thing on ConstructsFromHostOrderAddressAndPort. ported onto the old header (sa_family, minus the addr() test), it fails with GCC 16 as described, but passes with Apple clang 21 at -O0 through -O3, because clang places padded so the member lands 4-byte aligned.
static_assert(alignof(decltype(SocketTools::SocketAddr::m_data)) >= alignof(sockaddr_in), "") fails on the old header with both compilers. could the test assert that in the next push?
marcalff
left a comment
There was a problem hiding this comment.
Thanks for the contribution.
This is a much better patch for this issue.
Please see some comments, and also the CI failure on clang-tidy.
I will approve and merge once comments are addressed, the patch looks good overall.
SocketAddr(u_long, uint16_t) bound a sockaddr_in reference to the sockaddr storage through a reinterpret_cast. sockaddr is not aligned for a sockaddr_in on every ABI (alignment 1 on macOS and 2 on Linux versus 4), so the access is undefined and UBSan reports it: socket_tools.h:180:29: runtime error: reference binding to misaligned address 0x00016bda6551 for type 'sockaddr_in', which requires 4 byte alignment Store the address in a sockaddr_storage, which is the socket API's type for an address of any family and is aligned for all of them, and build the IPv4 address in a local sockaddr_in that is copied into the storage, as the string constructor already does. Replace the sockaddr conversion operators with addr() and addr_len(): the storage is larger than a sockaddr_in and passing its full size as the address length to bind() or connect() is rejected on some platforms, so addr_len() is the length of a sockaddr_in, the only family stored. getsockname() and accept() keep passing the full storage size, which is the buffer capacity for those output parameters. The default constructor sets AF_UNSPEC explicitly, and the tests read the family through ss_family. New tests cover the integer constructor at an address only sockaddr_storage alignment can guarantee, the accessors, and a bind/getsockname/connect/accept round trip on the loopback interface. Fixes open-telemetry#4307
af1a2cc to
776f5b5
Compare
|
Thanks for the review. All four comments are addressed in 776f5b5, which is also rebased on current main:
Locally: socket_tools_test 20/20 in a normal build and under UBSan (no runtime errors), url_parser_test 36/36, curl_http_test 39 pass with the usual 1 skip. |
Fixes #4307
Changes
SocketAddrwas accessing asockaddr_inthrough a cast that could produce a misaligned reference. UBSan reports this in the existing implementation.The change makes
SocketAddrstore asockaddr_storageinstead, so the address has the alignment required by the supported socket address types.The default constructor now initializes the family to
AF_UNSPEC. I also addedaddr()andaddr_len()accessors and updated the bind/connect call sites to use them with the correct IPv4 address length.This follows the general approach @marcalff suggested in the earlier PR discussions.
Testing
I added a padded-structure regression test that fails against the original header even without sanitizers.
UBSan reports a misaligned
sockaddr_inreference before the fix. The updated implementation passes the regression test, both normally and under UBSan.All 21 socket tests pass in both configurations.
A CHANGELOG entry is included.
For significant contributions please make sure you have completed the following items:
CHANGELOG.mdupdated for non-trivial changes