🇰🇷 한글 설명
Zephyr Bluetooth Classic AVDTP 계층에서 세션 해제 작업이 시스템 작업 큐에 대기 중인 상태에서 같은 구조체를 재사용하면, 시스템 워크 큐의 대기 리스트가 손상되어 장치 전체가 작업을 실행하지 못하는 서비스 거부 취약점입니다. 이미 페어링된 BR/EDR 장치가 하나의 L2CAP 시그널링 PDU에 연결 해제 요청과 새 연결 요청을 연달아 담아 보내면 재현됩니다. 두 개의 커밋을 함께 적용해야 완전히 해결됩니다.
💡 쉬운 설명
블루투스 연결을 끊는 작업이 끝나기 전에 같은 연결 정보를 다시 쓰면서 장치의 작업 목록이 망가집니다. 이로 인해 장치가 더 이상 작업을 처리하지 못하고 재부팅이 필요해질 수 있습니다.
🇺🇸 원문 (English)
The Bluetooth Classic AVDTP layer defers releasing a session's stream endpoints: bt_avdtp_l2cap_disconnected() in subsys/bluetooth/host/classic/avdtp.c ends with k_work_submit(&session->_release_work), placing the embedded struct k_work on the system work queue's pending list. When the same struct bt_avdtp object is immediately reused for a new signalling connection, the session memory is re-initialized — a2dp_get_connection() in subsys/bluetooth/host/classic/a2dp.c memset()s the whole struct bt_a2dp, and bt_avdtp_l2cap_accept() / bt_avdtp_connect() call k_work_init() on session->_release_work — while that work item is still linked into k_sys_work_q.pending. Zeroing a linked sys_snode_t truncates the list while its tail pointer keeps pointing past the truncation.
The reuse window is deterministic rather than a race. All host RX processing runs on the Bluetooth RX work queue at a cooperative priority (CONFIG_BT_RX_PRIO), while _release_work is submitted to the lower-priority system work queue, so the release handler cannot run until the RX thread blocks. Because l2cap_br_recv() processes every signalling command contained in a single L2CAP signalling PDU back-to-back, a peer can send one PDU holding an L2CAP Disconnection Request for the AVDTP signalling channel followed by a Connection Request for PSM 0x0019; the second command reaches the session-reuse path with the release work provably still queued. The peer must already hold an encrypted AVDTP signalling channel, i.e. be a paired/bonded BR/EDR device.
The result is corruption of the global system work queue's pending list: either the queue silently stops executing any work at all (subsequent submissions are appended to a chain the head can no longer reach, and the orphaned items keep their K_WORK_QUEUED flag forever) or, in the tail variant, the list acquires a self-referencing node that the queue thread spins on. The written values are pointers to other struct k_work objects and are not attacker-controlled, so the impact is a device-wide, reboot-required denial of service rather than a controllable write primitive. Only builds with CONFIG_BT_CLASSIC and CONFIG_BT_A2DP are affected.
The fix is a two-commit unit, and neither commit closes the path on its own. ec822ceed83b adds a pending-release check to bt_avdtp_connect() and bt_avdtp_l2cap_accept(), but the A2DP upper layer's a2dp_get_connection() memset()s the session — including the queued work item's list node and flags — before those checks run, so k_work_busy_get() would observe an already-cleared state. 2bd5ea88c69b closes that by making a2dp_get_connection() itself skip the reuse and return NULL while the release work is still pending, which both callers already handle by rejecting the connection attempt. Apply both commits together; either one alone leaves the device vulnerable.
📍 영향받는 시스템
Zephyr RTOS의 CONFIG_BT_CLASSIC 및 CONFIG_BT_A2DP가 활성화된 빌드
⚔️ 공격 벡터
이미 페어링된 주변 BR/EDR 장치가 하나의 L2CAP 시그널링 PDU에 Disconnection Request와 PSM 0x0019 Connection Request를 연속으로 담아 전송
🛡️ 대응 방법
ec822ceed83b와 2bd5ea88c69b 두 커밋을 함께 적용하여 펌웨어를 Zephyr 최신 버전으로 업데이트
🔧 검증 코드
두 커밋 해시가 모두 출력되면 패치가 적용된 것이며, 하나만 나오거나 아무것도 나오지 않으면 취약한 상태입니다.
git -C zephyr log --oneline 2>/dev/null | grep -E '2bd5ea88c69b|ec822ceed83b'
📊 CVSS Vector String
CVSS:3.1/AV:A/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
💻 영향받는 소프트웨어
Windows Bluetooth Service