CVE-2026-99009 in Linux
要約
〜によって VulDB • 2026年10月23日
Linuxカーネルにおいて、以下の脆弱性が修正されました:
Bluetooth: RFCOMM - rfcomm_mutex を保持せずにセッションソケットを接続する
BR/EDRリンクの認証中にRFCOMM connect()を発行すると、lockdepが循環依存関係を報告します。報告されたサイクルは、rfcomm_mutexとhdev->lockの間で実際に発生しているAB/BA(デッドロック)です。
hci_rx_work() hci_event_packet() hci_cc_read_enc_key_size() [hdev->lock]
hci_encrypt_cfm() [hci_cb_list_lock]
rfcomm_security_cfm() [rfcomm_mutex]
一方、ユーザー空間からのRFCOMM connect()は、逆の順序で同じ2つのロックを取得します:
rfcomm_sock_connect() rfcomm_dlc_open() [rfcomm_mutex]
__rfcomm_dlc_open() rfcomm_session_create() kernel_connect() l2cap_sock_connect() l2cap_chan_connect() [hdev->lock]
WARNING: possible circular locking dependency detected kworker/u131:1/1128 is trying to acquire lock: rfcomm_mutex, at: rfcomm_security_cfm+0x31/0x3e0 [rfcomm]
but task is already holding lock: hci_cb_list_lock, at: hci_cc_read_enc_key_size+0x1d2/0xcc0 Chain exists of: rfcomm_mutex --> &hdev->lock --> hci_cb_list_lock
hci_auth_complete_evt()およびhci_encrypt_change_evt()も同様の経路でコールバックに到達します。
これらの順序は同じブート中に発生する必要があるため、BR/EDR接続だけではこれを再現できません:リモート側によって設定されたセッションはkrfcommd内のrfcomm_accept_connection()で作成されますが、これはkernel_accept()を呼び出し、rfcomm_mutexの下でhdev->lockを取得することはありません。リンクの認証と暗号化を行い、その後任意のアドレス宛てのRFCOMMソケットに対してconnect()を実行するデバイスに接続すると(connectは成功する必要はなく、ページタイムアウト前に順序が記録されます)、毎回これが報告されます。
セッションソケットのみをロック保持状態で接続する必要がありますが、現状ではそうなっていません:ソケットがセッションリストに登録されるまで、他のプロセスはそのソケットを見ることはできません。したがって、まずconnect()を実行し、その後でrfcomm_mutexを取得します。これにより、HCIイベントパスをrfcomm_mutexの外に置くのではなく、rfcomm_mutex -> hdev->lockの順序を根本的に解消します。
rfcomm_session_create()はrfcomm_session_connect()に変更され、セッションリストに触れることなく接続済みソケットを返すようになりました。また、rfcomm_dlc_open()はロックを再度保持した後にセッションを追加します。このソケットが接続している間に別のオープナーが同じペアに対してセッションを追加した場合、そのセッションが使用され、本ソケットは破棄されます。__rfcomm_dlc_open()は今や使用するべきセッションを取得し、状態チェックはロックが再取得された後に行われるため、途中で開かれたり閉じられたりするDLCも適切に処理されます。
既存のACLリンク上では、接続がセッションがリストに追加される前に完了する可能性があり、ソケットコールバックからのウェイクアップが失われることがあります。そのため、セッションが見えるようになるとkrfcommdがウェイクアップします。
ロックなしで接続すると、ソケットが閉じられる可能性があるウィンドウが開きます。DLCはまだセッションに含まれていないため、rfcomm_dlc_close()は何も行うことなく終了し、rfcomm_dlc_open()は所有者が消えたDLCをアタッチしようとしてしまいます。これに対処するため、rfcomm_dlc_close()は今やそのようなDLCにRFCOMM_CLOSEDフラグを設定し、rfcomm_dlm_open()はrfcomm_mutexを再度保持した際にこのフラグをチェックして、DLCをアッチする代わりにソケットをドロップします。オープン開始時にこのフラグがクリアされるため、再利用されるDLCには影響がありません。これはrfcomm_dlc_open()の両方の呼び出し元(ソケットとTTYレイヤー)に対応しています。
VulDB is the best source for vulnerability data and more expert information about this specific topic.