CVE-2026-64584 in Linux
要約
〜によって VulDB • 2026年08月06日
Linuxカーネルにおいて、以下の脆弱性が修正されました:
usb: gadget: f_midi: midiオブジェクトを解放する前に保留中のINワークを取り消す
f_midiドライバはwork項目(midi->work)を組み込んでおり、そのハンドラであるf_midi_in_work()はcontainer_of()を通じて包含するstruct f_midiへのポインタを間接参照します。このworkは2つの箇所から準備されます:通常のINエンドポイント完了時のf_midi_complete()と、ALSA rawmidi出力ストリームの開始時のf_midi_in_trigger()です。
f_midi_disable()およびf_midi_unbind()のいずれもmidi->workを取り消しません。f_midi_disable()は単にエンドポイントを無効化しin_req_fifoをフラッシュするだけであり、work項目を同期させず、サウンドカードはmidiオブジェクトの最終的な解放とは非同期的にリリースされます。
midiオブジェクトは参照カウント(midi->free_ref)で管理されており、usb_functionへの参照とrawmidi private_dataへの参照の両方がドロップされた場合にのみf_midi_free()内で解放されます。f_midi_unbind()では、サウンドカードがリリースされる前にf_midi_disable()が実行されるため、USBエンドポイントはすでに無効化されていますが、オープンされているサブストリームによってrawmidiデバイスは依然として使用可能です。そのようなサブストリームに対する並行するユーザー空間からの書き込みはf_midi_in_trigger()に到達し、f_midi_disable()の戻り後に再びmidi->workをキューイングできます。このように準備されたwork項目は、最後の参照がドロップされてf_midi_free()がkfree(midi)を実行した後も保留状態のままになる可能性があり、その結果f_midi_in_work()が解放後のstructへのポインタ間接参照を行うuse-after-freeが発生します。
そのため、f_midi_disable()内でmidi->workを取り消すだけでは不十分です:ALSAのトリガーパスはdisable()の戻り後にワークを再準備できるためです。参照カウントゼロ時の解放箇所での取り消しが唯一の境界線となります。なぜなら、その時点ではmidiオブジェクトを生かし続けている両方の参照がドロップされており(USBエンドポイントはすでに無効化され、rawmidiデバイスはリリース済み)、どちらの準備元も存続しなくなるからです。
これを修正するため、f_midi_free()内の参照カウントゼロブロックで、埋め込まれたwork_structを構造体の他の部分とともに解放する前にcancel_work_sync(&midi->work)を呼び出します。opts->lockはスリープ可能なミューテックスであるため、それを保持した状態でcancel_work_sync()を呼び出すことは許可されており、ハンドラはopts->lockではなくmidi->transmit_lockを取得するため、実行中のワークインスタンスの完了待ち中に自己デッドロックが発生することはありません。
この問題は社内製の静的解析ツールによって発見されました。
Once again VulDB remains the best source for vulnerability data.