fix(sdk/ble): bound BLE reassembly pre-allocation to chunk count#428
Open
dsmfa10 wants to merge 1 commit into
Open
fix(sdk/ble): bound BLE reassembly pre-allocation to chunk count#428dsmfa10 wants to merge 1 commit into
dsmfa10 wants to merge 1 commit into
Conversation
`ReassemblyBuffer::reassemble` pre-allocated `Vec::with_capacity(expected_size)` where `expected_size` is the peer-supplied `payload_len` (u32). A single small chunk (`total_chunks = 1`) declaring a ~4 GiB `payload_len` made the buffer "complete" and triggered a multi-gigabyte allocation before the integrity and size checks ran — a memory-exhaustion DoS from one frame. Cap the capacity hint at `total_chunks * MAX_BLE_CHUNK_SIZE` (the maximum the chunks could actually hold). The exact reassembled length is still validated against `expected_size` afterward, so correctness is unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
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
ReassemblyBuffer::reassemblepre-allocates the output buffer fromexpected_size, which is the peer-suppliedpayload_len(u32, read from thechunk header). A single chunk with
total_chunks = 1and a declaredpayload_lenof ~4 GiB makesis_complete()true and triggers a multi-gigabyteVec::with_capacitybefore the integrity and size checks run — a memoryexhaustion DoS from one crafted frame.
Evidence
MAX_BLE_CHUNK_SIZE = 400, so a real payload can be at mosttotal_chunks * 400bytes — far smaller than theu32payload_lenan attackercan claim.
Fix
Cap the pre-allocation hint to what the chunks could actually hold. The exact
length is still validated against
expected_sizeafterward, so correctness isunchanged; this only prevents the oversized speculative allocation.
Verification
cargo check -p dsm_sdkclean. The post-reassemblyresult.len() != expected_sizecheck and the BLAKE3 frame-commitment integrity check are untouched, so a frame
that lied about
payload_lenstill fails — it just can no longer force a giantallocation first.
Notes
A secondary observation from the audit (not fixed here):
total_chunks/chunk_indexare truncatedu32 -> u16; out-of-range values are accepted thenfail integrity rather than being rejected up front. Low impact; left as-is.
CI gates & coverage
Full verification for this PR runs in CI — Rust (
cargo fmt --check,clippy -D warnings, workspace tests), Frontend, Android Unit Tests,Coverage, SPDX headers, CodeQL (see the PR's Checks tab). The local
check noted above is a subset; the broader mandated gates (full workspace test
suite, codegen/scan, Android, Frontend) run in CI, not locally — none is
silently skipped.