wireless/bluetooth: Validate the L2CAP header on the first ACL fragment. - #20204
Merged
Merged
Conversation
bt_conn_receive() read the 4-octet L2CAP header out of the first fragment of a PDU without checking that 4 octets had been received, and then computed the outstanding length by subtracting the fragment length from the declared PDU length. Two problems follow. A fragment shorter than the header was parsed from whatever happened to follow it in the buffer. And a fragment carrying more data than the PDU it declares made the subtraction wrap, because conn->rx_len is 16 bits: the connection was then left expecting up to 65535 further octets, holding the partial PDU and accumulating later fragments against an expectation that could never be satisfied. Check that the fragment is long enough to hold a header before reading it, and that it does not exceed the PDU it declares before computing what remains. Drop the fragment and reset the reassembly state otherwise. Ref: Core v6.0, Vol 3, Part A, 3.1 (B-frame format) Ref: Core v6.0, Vol 4, Part E, 5.4.2 (HCI ACL Data packets) Testing: builds for sim:bluetooth with Make; every commit in this series verified to build individually. Not yet exercised at runtime - the scriptable controller adds the truncated and oversized fragment cases separately. Signed-off-by: Alan C. Assis <acassis@gmail.com> Assisted-by: Claude Code Opus 5
acassis
requested review from
jerpelea,
pkarashchenko,
tmedicci and
xiaoxiang781216
as code owners
September 20, 2026 11:35
xiaoxiang781216
previously approved these changes
Sep 20, 2026
This PR fixes the bad aligment reported by nxstyle. Signed-off-by: Alan C. Assis <acassis@gmail.com>
Contributor
Author
|
@xiaoxiang781216 please review again, the CI was reporting bad alignment on original file |
Contributor
Author
|
The issue is caused by a random esptool BUG that was fixed on version 5.3.0, adding it here: |
xiaoxiang781216
approved these changes
Sep 22, 2026
jerpelea
approved these changes
Sep 22, 2026
JorgeGzm
approved these changes
Sep 22, 2026
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.
Summary
bt_conn_receive() read the 4-octet L2CAP header out of the first fragment of a PDU without checking that 4 octets had been received, and then computed the outstanding length by subtracting the fragment length from the declared PDU length.
Two problems follow. A fragment shorter than the header was parsed from whatever happened to follow it in the buffer. And a fragment carrying more data than the PDU it declares made the subtraction wrap, because conn->rx_len is 16 bits: the connection was then left expecting up to 65535 further octets, holding the partial PDU and accumulating later fragments against an expectation that could never be satisfied.
Check that the fragment is long enough to hold a header before reading it, and that it does not exceed the PDU it declares before computing what remains. Drop the fragment and reset the reassembly state otherwise.
Impact
Improvement
Testing
Before this change, a fragment of 10 octets declaring a 2-octet PDU:
4 + 2 - 10 is -4, so the connection is left expecting 65532 further
octets and holding the fragment. A 2-octet fragment sent next, shorter
than the header itself:
The length of 2 was read from beyond the two octets that arrived, and the
connection is parked again; the "Unexpected first L2CAP frame" line is
the earlier underflow surfacing.
After, both fragments are dropped and nothing is parked:
The second fragment produces no "First, len" line, because the header is
no longer read before its presence is checked.