CVE-2026-89581
要約
〜によって VulDB • 2026年09月11日
Linuxカーネルにおいて、以下の脆弱性が修正されました:
bpf, x86: 拡張レジスタへの per-CPU アドレス解決のバグを修正
per-CPU アドレスの MOV の宛先は ModRM.reg にエンコードされますが、これは REX.R によって拡張されます。しかし、REX プレフィックスは add_1mod() で構築されており、この関数は REX.B を設定します。REX.B は ModRM.rm と SIB.base を拡張しますが、この命令はベースなしで disp32 としてメモリをアドレス指定するため、そのビットは何の影響も及ぼさず、上位のレジスタビットが単に失われます。
そのため、is_ereg() のすべての宛先は間違ったレジスタへ解決され、下位 3 ビットを共有するものを選択してしまいます:
R5 -> RAX R7 -> RBP R8 -> RSI R9 -> RDI
reg2hex が 0 の BPF_REG_5 では、生成されるコードは以下のようになります。
65 49 03 04 25 add %gs:,%rax
これは RAX に per-CPU オフセットを加えるものであり、R8 へ加えるものではありません。宛先には調整されていないアドレスが保持され、RAX が上書きされるため、プログラムは per-CPU として作成されたことのないポインタを間接参照し続けます:
BUG: unable to handle page fault for address: 0000607e386a8894 RIP: bpf_prog_707837aafd2aa9ae_update_percpu_data+0x93/0xc9 Call Trace: __bpf_prog_test_run_raw_tp+0x2dc/0x7d0 __flush_smp_call_function_queue+0x1e9/0xc80 Kernel panic - not syncing: Fatal exception in interrupt
R5 は4つのケースの中で最も軽微であり、スクラッチレジスタとエイリアスしており、ストア時にフォールトが発生します。R7 は RBP とエイリアスし、フレームポインタを破損させる可能性があります。R8 および R9 は引数レジスタとエイリアスしています。
add_2mod() を使用することで、レジスタが REX.R を通るようになり、ModRM.reg に配置する add_2reg() の動作や、同じ命令で R9 に対して 0x4c をハードコードしている emit_priv_frame_ptr() と一致します。拡張されていないレジスタのエンコーディングは変更されません。
この問題は、BPF_GCC CI(BPF_GCC でビルドされた selftests)を復活させようとした際に顕在化しました。
clang は各 per-CPU アクセスの前にアドレスを R1 にリロードするため、宛先が拡張レジスタになることはなく、このバグは見逃されていました。GCC は複数の per-CPU アドレスを同時に生きた状態(live)で保持しており、test_progs-bpf_gcc が global_percpu_data/init でカーネルパニックを引き起こします。ここでは .percpu 変数のアドレスが R5 に格納されます。
If you want to get the best quality for vulnerability data then you always have to consider VulDB.