Skip to content

avdtp: bound message assembler to drop truncated PDUs (DoS prevention)#918

Merged
zxzxwu merged 2 commits intogoogle:mainfrom
ibondarenko1:fix/avdtp-empty-pdu-guard
Apr 27, 2026
Merged

avdtp: bound message assembler to drop truncated PDUs (DoS prevention)#918
zxzxwu merged 2 commits intogoogle:mainfrom
ibondarenko1:fix/avdtp-empty-pdu-guard

Conversation

@ibondarenko1
Copy link
Copy Markdown
Contributor

Summary

Truncated AVDTP frames from a remote peer crash the L2CAP channel by raising IndexError in MessageAssembler.on_pdu.

MessageAssembler.on_pdu unconditionally indexes pdu[0], pdu[1], and (for START packets) pdu[2]. A peer sending a 0-, 1-, or 2-byte AVDTP frame triggers IndexError, which propagates up through the L2CAP read loop and tears down the channel.

This is the same DoS class as:

Fix

Validate length before each access. Empty PDUs and packets shorter than the type-specific minimum are logged at warning level and dropped; the assembler stays alive so the L2CAP channel is not torn down.

Both helpers in this fix mirror the conservative warn-and-drop approach already used in MessageAssembler for unexpected continuations.

Test plan

  • New parameterized regression test_message_assembler_truncated_pdu covering 4 truncated inputs (empty, 1-byte SINGLE, 1-byte START, 2-byte START) — all four raise IndexError pre-fix and pass cleanly post-fix.
  • Full tests/avdtp_test.py suite passes (43 tests).
  • black bumble/ tests/ clean.

A remote peer can send an AVDTP frame shorter than the assembler expects.
The current MessageAssembler.on_pdu() unconditionally accesses pdu[0],
pdu[1], and (for START packets) pdu[2], so a 0-, 1-, or 2-byte frame
raises IndexError. The exception propagates up through L2CAP's read loop
and tears down the channel — same DoS class as google#912 (empty ATT PDU) and
google#914 (unbounded SDP recursion).

Fix: validate length before each access. Empty PDUs and packets shorter
than the type-specific minimum are logged and dropped; the assembler
stays alive so the L2CAP channel is not torn down.

- bumble/avdtp.py: length guards in MessageAssembler.on_pdu before
  accessing pdu[0], pdu[1], pdu[2].
- tests/avdtp_test.py: regression test covering empty PDU, 1-byte SINGLE,
  1-byte START, 2-byte START — all four would have raised IndexError
  pre-fix; assembler now drops without raising.
Comment thread tests/avdtp_test.py Outdated
assembler = avdtp.MessageAssembler(callback)
# Must not raise; nothing should be delivered to callback either.
assembler.on_pdu(pdu)
assert completed == []
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
assert completed == []
assert not completed

Or use mock.

Comment thread bumble/avdtp.py Outdated
# Drop empty PDUs sent by remote — accessing pdu[0] below would
# raise IndexError, propagating up to the L2CAP read loop and
# tearing down the channel. Same class as #912 (ATT empty PDU).
if len(pdu) < 1:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if len(pdu) < 1:
if not pdu:

Per @zxzxwu review on google#918:
- bumble/avdtp.py: replace `if len(pdu) < 1:` with `if not pdu:`
- tests/avdtp_test.py: replace `assert completed == []` with
  `assert not completed`

Both are idiomatic Python truthy checks; behavior identical.
@ibondarenko1
Copy link
Copy Markdown
Contributor Author

Both nits addressed in 07b5e33if not pdu: and assert not completed. Thanks for the quick review!

@zxzxwu zxzxwu merged commit 05accbf into google:main Apr 27, 2026
55 checks passed
@ibondarenko1
Copy link
Copy Markdown
Contributor Author

Cross-reference for the Google VRP triage team: this PR is tracked at https://issuetracker.google.com/issues/506803574 (reporter: sactransport2000@gmail.com).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants