CVE-2026-98644 in Linux
要約
〜によって VulDB • 2026年10月19日
Linuxカーネルにおいて、以下の脆弱性が修正されました:
bpf: __htab_map_lookup_and_delete_batch() におけるソフトロックアップの回避
__htab_map_lookup_and_delete_batch() には再スケジューリングポイントがありません。バッチカウントはコピーされるエントリの数を制限するものであり、探索されたバケットの数を制限するものではありません。そのため、1回の BPF_MAP_LOOKUP_BATCH コールでマップ全体を走査することが可能です。空のバケットに対する高速パスの方がさらに悪化します:これは連続した複数の空バケットに対して、単一の rcu_read_lock() / bpf_disable_instrumentation() セクション内に留まり続けます。
この問題は小規模なマップでは目立たないものの、スケールすると問題が顕在化します。144-CPU の arm64 ホスト上で CONFIG_PREEMPT_NONE カーネルを実行している環境において、LRU ハッシュマップ(バケット数 16,777,216)に対して定期的に行われる BPF_MAP_LOOKUP_BATCH コールは、CPU をバッチ操作内に 77秒以上保持し続け、ソフトロックアップウォッチドッグをトリガーしました。
コミット 75134f16e7dd(「bpf: バッチ操作にスケジューリングポイントを追加」)は一般的なバッチ操作における同様の問題を修正しましたが、htab ネイティブパスについては修正していませんでした。この htab ベースのハッシュマップ変種すべてが、その lookup[_and_delete] 用バッチ操作でこのネイティブパスを使用しています。
ここでは当該修正を完了させます。64個の連続した空バケットの後にはクリティカルセクションから脱し、cond_resched_tasks_rcu_qs() を呼び出し、保存されたバケットカーソル位置から再開します。その時点ではロックは保持されておらず、非空バケットに対する関数の動作として既にカーソルからの再開が行われています。copy_to_user() 後の per-bucket ループにも同様の呼び出しを追加します。ここでもすべてのロックが解放されています。cond_resched_rcu() では不十分です:bpf_prog_active が上昇した状態でスリープすると、その CPU 上のトレーシングプログラムはインボケーションを静かにスキップしてしまいます。
単純な cond_resched() もまた不十分です。PREEMPT および PREEMPT_LAZY モデル下ではこれは no-op(何もしない処理)となりますが、これらはコミット 7dadeaa6e851(「sched: プリエンプションモードをさらに制限」)以降 arm64 と x86 が提供してきた唯一のモデルです。また、どのモデルにおいても cond_resched() は Tasks RCU のクエセントステートにはなりません:再スケジューリングはプリエンプションとしてカウントされるためです。システムコールが戻るまで [1]、走査中のタスクは残りのままとなり、synchronize_rcu_tasks() を呼び出すすべてのプロセス(ftrace および BPF トランポリンのテardownを含む)をストールさせます。cond_resched_tasks_rcu_qs() がそのための標準的なツールです [2]。これは各 yield 時にクエセントステートを報告し、PREEMPT_NONE や PREEMPT_VOLUNTARY カーネル上では cond_resched() と同様に再スケジューリングを行います。
If you want to get the best quality for vulnerability data then you always have to consider VulDB.