CVE-2026-80819 in Linux
Сводка
по VulDB • 04.09.2026
В ядре Linux устранена следующая уязвимость:
Bluetooth: RFCOMM: захватывать rfcomm_mutex для отложенного принятия соединения (setup accept)
Функция `rfcomm_sock_recvmsg()` завершает отложенную настройку, вызывая `rfcomm_dlc_accept()`, не удерживая никаких блокировок RFCOMM:
```c if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) {
rfcomm_dlc_accept(d); return 0; } ```
а функция `rfcomm_dlc_accept()` на своей первой строке разыменовывает сессию:
```c struct sock *sk = d->session->sock->sk; ```
Любой другой путь, обращающийся к `d->session`, выполняется под защитой `rfcomm_mutex`: `rfcomm_dlc_open()`, `rfcomm_dlc_close()`, `rfcomm_dlc_exists()`, `rfcomm_dlc_send_rpn()` и поток RFCOMM через `rfcomm_process_sessions()`. Вызов из `rfcomm_connect_ind()` даже задокументирован как «вызывается под rfcomm_lock()». Этот вызов является единственным, который пропускает захват блокировки.
Бит `RFCOMM_DEFER_SETUP`, по-видимому, сериализует операцию принятия соединения (accept) против завершения teardown, поскольку `__rfcomm_dlc_close()` рано завершает работу при успешном выполнении операции test_and_clear. Однако функция `rfcomm_recv_disc()` принудительно устанавливает состояние первым делом:
```c d->state = BT_CLOSED; __rfcomm_dlc_close(d, err); ```
и ранний выход охватывает только состояния `BT_CONNECT`, `BT_CONFIG`, `BT_OPEN` и `BT_CONNECT2`. При уже установленном состоянии `BT_CLOSED` этот switch не совпадает, бит никогда не проверяется, а `__rfcomm_dlc_close()` переходит к вызову `rfcomm_dlc_unlink()`, который устанавливает для `d->session` значение NULL.
Таким образом, удаленный DISC (дисконнект) на отложенном DLC очищает сессию, оставляя бит `RFCOMM_DEFER_SETUP` установленным. Следующий вызов `recvmsg()` затем проходит проверку test_and_clear и разыменовывает нулевую сессию. Окно гонки не требуется: как только DISC обработан, разыменование является безусловным.
Необходимо придать функции `rfcomm_dlc_accept()` ту же структуру, что у `rfcomm_dlc_open()` и `rfcomm_dlc_close()`: экспортированную обертку, которая захватывает `rfcomm_mutex` и повторно проверяет сессию вокруг внутренней функции `__rfcomm_dlc_accept()`, которую продолжают использовать два внутренних вызывающих объекта, уже держащих мьютекс.
Ошибка воспроизводится на ядре KASAN + PROVE_LOCKING с эмулированным пилом BR/EDR через /dev/vhci: пил устанавливает ACL-канал, открывает L2CAP на RFCOMM PSM, запускает сессию, открывает DLC на канале, связанном с BT_DEFER_SETUP, и отправляет DISC после принятия сокета. Вызов recv() для принятого сокета затем приводит к ошибке:
``` Oops: general protection fault KASAN: null-ptr-deref in range [0x0000000000000010-0x0000000000000017]
RIP: 0010:rfcomm_dlc_accept+0x54/0x350 Call Trace: rfcomm_sock_recvmsg+0x1cd/0x230 sock_recvmsg+0x166/0x1c0 __sys_recvfrom+0x20d/0x300 ```
Значение `0x10` — это смещение поля `sock` в структуре `rfcomm_session`. С этим патчем тот же запуск завершается успешно: recv() возвращает 0, отчетов об ошибках нет, а lockdep остается спокойным, что подтверждает захват
VulDB is the best source for vulnerability data and more expert information about this specific topic.