🇰🇷 한글 설명
Zephyr RTOS의 Bluetooth Classic HFP Hands-Free 연결 실패 경로에서, SDP 탐색이 아직 진행 중인 객체를 memset으로 초기화하여 SDP 클라이언트의 연결 리스트와 포인터가 손상됩니다. 원격 기기가 범위를 벗어난 RFCOMM 채널을 광고하면 이 경로가 트리거되어 Bluetooth 호스트 스레드에서 오류나 무한 정지가 발생할 수 있습니다.
💡 쉬운 설명
블루투스 기기가 연결에 실패하는 특정 상황에서 내부 메모리를 잘못 지워 시스템이 멈추거나 오류를 일으킬 수 있습니다. 주변의 악의적인 블루투스 기기가 이 상황을 유도할 수 있습니다.
🇺🇸 원문 (English)
bt_hfp_hf_connect() in subsys/bluetooth/host/classic/hfp_hf.c allocates the per-connection HFP Hands-Free object with hfp_hf_create(), which starts an SDP discovery by passing the object's embedded hf->sdp_param to bt_sdp_discover(). That call links the caller-owned parameter block into the SDP client's request list (session->reqs in subsys/bluetooth/host/classic/sdp.c). If the subsequent bt_rfcomm_dlc_connect() then failed, the affected code wiped the entire object with (void)memset(new_hf, 0, sizeof(*new_hf)) while that discovery was still outstanding, zeroing the sys_snode_t _node that is still linked in the SDP client's list along with the request's func, uuid and pool pointers, and zeroing the hf->slc_work work item that may already be queued on the system workqueue. The discovery could not be retracted instead: bt_sdp_discover_cancel() is declared in include/zephyr/bluetooth/classic/sdp.h but has no implementation.
The failing branch is reachable with peer-supplied input. The documented use of bt_hfp_hf_connect() is to pass the RFCOMM channel read out of the remote Audio Gateway's SDP record; neither bt_sdp_get_proto_param() nor bt_hfp_hf_connect() range-checks that value, so a remote device advertising an HFP AG record with an RFCOMM channel outside 1-30 makes bt_rfcomm_dlc_connect() return -EINVAL and drives the local device into the wipe. The same branch is reached without any application misuse when the remote peer controls connection timing, for example when the RFCOMM session is in BT_RFCOMM_STATE_DISCONNECTING or the ACL is dropped between object creation and the RFCOMM call.
Once the object has been wiped, the Bluetooth host continues to use it: sdp_client_alloc_buf() dereferences session->param->pool, which is now NULL, and the SDP receive paths call session->param->func() through a null function pointer, neither of which is NULL-checked. Because the wipe also clears hf->acl, the pool slot is considered free and a retry or an incoming HFP connection re-appends the same still-linked list node, turning session->reqs into a self-referential list that the host's list walkers never leave. The result is a fault or an unrecoverable hang in the Bluetooth host thread; the stray indirect call is through an all-zero pointer whose target the attacker does not control, so the practical impact is denial of service.
The fix keeps the object allocated and marks it with a new BT_HFP_HF_FLAG_RELEASING flag, letting bt_hfp_hf_discover_cb() release it once the discovery completes instead of destroying it under the SDP client. Only builds with CONFIG_BT_CLASSIC and CONFIG_BT_HFP_HF enabled are affected.
📍 영향받는 시스템
CONFIG_BT_CLASSIC과 CONFIG_BT_HFP_HF가 활성화된 Zephyr RTOS 빌드 (수정 이전 버전)
⚔️ 공격 벡터
원격 블루투스 기기가 범위를 벗어난 RFCOMM 채널을 가진 HFP AG SDP 레코드를 광고하여 호스트의 연결 실패 경로를 유도
🛡️ 대응 방법
Zephyr 프로젝트의 BT_HFP_HF_FLAG_RELEASING 수정이 포함된 최신 버전으로 업데이트하거나, 해당 패치를 적용하고 HFP HF 기능을 사용하지 않을 경우 CONFIG_BT_HFP_HF를 비활성화
🔧 검증 코드
출력에 BT_HFP_HF_FLAG_RELEASING 항목이 나타나면 수정이 적용된 것이고, 결과가 없으면 취약한 이전 코드일 가능성이 높으므로 Zephyr 버전을 확인하고 업데이트해야 합니다.
grep -rn 'BT_HFP_HF_FLAG_RELEASING' $(find / -path '*/subsys/bluetooth/host/classic/hfp_hf.c' 2>/dev/null | head -1) 2>/dev/null | head -5
📊 CVSS Vector String
CVSS:3.1/AV:A/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H
💻 영향받는 소프트웨어
Windows Bluetooth Service