message_impl: reject SOME/IP messages whose length < 8#1041
Open
SoundMatt wants to merge 1 commit into
Open
Conversation
header_.length_ is wire-controlled and covers the SOME/IP fields
after the length field (the 8-byte trailer: request_id + protocol
version + interface version + message type + return code) plus the
payload. A valid message therefore has length >= 8.
If a peer encodes length < 8, the unsigned subtraction at line 40
payload_->set_capacity(header_.length_ - VSOMEIP_SOMEIP_HEADER_SIZE);
wraps to a value near 0xFFFFFFF8 and is passed to
payload_impl::set_capacity, which calls std::vector::reserve.
That asks for a ~4 GB allocation per malformed message — pure
memory-pressure DoS. The subsequent payload_->deserialize correctly
rejects the read because the wrapped capacity exceeds remaining_,
so this isn't memory-corruption, but on a 64-bit Linux host with
overcommit the giant reserve still allocates large amounts of
virtual memory.
Reachable via routing_manager_client::on_message → SEND_ID →
send_command::deserialize → deserializer::deserialize_message →
message_impl::deserialize: any peer that can put a SOME/IP frame
on the routing socket can trigger it once per message.
Fix: reject the message before the subtraction when
header_.length_ < VSOMEIP_SOMEIP_HEADER_SIZE.
Signed-off-by: Matt Jones <47545907+SoundMatt@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
message_impl::deserialize(implementation/message/src/message_impl.cpp:36-44) computes the payload capacity by subtracting the 8-byte trailer size from the wire-encoded length:header_.length_isuint32_tandVSOMEIP_SOMEIP_HEADER_SIZEis8. A peer encodinglength < 8in the SOME/IP wire header wraps the subtraction to a value near0xFFFFFFF8, whichpayload_impl::set_capacitypasses tostd::vector::reserve. That tries to allocate ~4 GB per malformed message.The subsequent
payload_->deserializecorrectly refuses the read (because the (wrapped) capacity exceeds the deserializer's remaining bytes), so this isn't memory corruption — but on a 64-bit Linux host with overcommit the giant reserve still allocates a large virtual region per message, and on a 32-bit host or with overcommit off it throwsbad_alloconce per message. Either way it's a memory-pressure / DoS primitive against the routing manager from any peer that can put a SOME/IP frame on the routing socket.Reachable path:
routing_manager_client::on_message→SEND_ID→send_command::deserialize→deserializer::deserialize_message→message_impl::deserialize.Fix
One-line guard: if
header_.length_ < VSOMEIP_SOMEIP_HEADER_SIZE, returnfalsebefore the subtraction. The SOME/IP spec requireslengthto cover at least the 8-byte trailer (request_id + protocol version + interface version + message type + return code), so this is the actual minimum value the protocol allows; nothing legitimate is rejected.Net diff: +12 / −0 (most of which is the explanatory comment).
Notes
This is the second of a small set of audit-found bugs in vsomeip's protocol layer. The first is in flight as #1040 (routing_info_entry bounds checks). I have a couple more I'd like to bring up in separate PRs (one in
service_discovery/configuration_option_impl::deserialize, one indeserializer::look_ahead); happy to file them one at a time as this lands.I haven't been able to run the full test suite locally on macOS yet (boost+CMake setup pending). Pointers on the canonical way to add a malformed-input regression test for this entry would be appreciated and I'd happily follow up with a test commit on this branch.