BPFプログラムの作成方法、BPFの検証器、JITコンパイル機能:Berkeley Packet Filter(BPF)入門(3)(3/3 ページ)
Linuxにおける利用が急速に増えている「Berkeley Packet Filter(BPF)」について、基礎から応用まで幅広く紹介する連載。今回は、BPFプログラムの作成方法、BPFの検証器、JITコンパイル機能について解説します。
JITコンパイル機能
BPFは以下のアーキテクチャでJITコンパイルをサポートしています。
アーキテクチャ | 対応カーネル |
---|---|
x86-64 | 3.16 |
ARM 64 | 3.18 |
s390 | 4.1 |
PowerPC 64 | 4.8 |
SPARC 64 | 4.12 |
MIPS | 4.13 |
ARM 32 | 4.14 |
x86-32 | 4.18 |
JIT機能を利用する場合、「CONFIG_BPF_JIT」「CONFIG_HAVE_EBPF_JIT」カーネルオプションを有効化する必要があります。また、「CONFIG_BPF_JIT_ALWAYS_ON」オプションを有効化した場合、常にJITでBPFが実行されるようになり、カーネルのコードからBPFインタープリタが除去されます。
これは、PoCで、BPFインタープリタのコードがガジェットとして利用されてしまったSpectre Variant 2対策の一環として導入された機能です。
なお、Spectre Variant 1のPoCでもeBPFが利用されていましたが、このときはJIT化されたコードを投機実行させていたため、JITの無効化が有効な対策の一つとなります。
JITの機能は以下のprocfsからコントロールできます
- 「/proc/sys/net/core/bpf_jit_enable」
- 0:disable
- 1:JIT有効
- 2:デバッグモード。JITコンパイル結果をダンプする(「dmesg」で確認できる)
- 「CONFIG_BPF_JIT_ALWAYS_ON」が有効な場合利用不可
- 「tools/bpf/bpf_jit_diasm.c」によりJITの結果をディスアセンブル可能
- 「proc/sys/net/core/bpf_jit_harden」
- 0:disable
- 1:「JIT Spraying」と呼ばれる攻撃に対する緩和策であるConstant Blindingを実施
- 「/proc/sys/net/core/bpf_jit_kallsyms」
- 0:disable
- 1:「/proc/kallsysm」にJIT化されたプログラムのシンボルをエクスポート
- perfなどのツールからスタックトレースが取得可能
- 「bpf_jit_harden」が有効のとき、この機能は使用不可
eBPFのJITコンパイラのコード(x86)は「arch/x86/bpf_jit_comp.c」にあります。もともとeBPFのアーキテクチャはJITがしやすいように設計されており、基本的にeBPF命令は1つのCPU命令に対応して変換されています。
次回はネットワークに関連したBPFの利用について
今回はBPFの基礎として、BPFプログラムの作成方法、BPFの検証器、JITコンパイル機能などについて説明しました。
次回以降、本格的にBPFの機能を使っていきます。次回はネットワークに関連したBPFの利用について取り上げる予定です。
筆者紹介
味曽野 雅史(みその まさのり)
東京大学 大学院 情報理工学系研究科 博士課程
オペレーティングシステムや仮想化技術の研究に従事。
- メール:misono(at)os.ecc.u-tokyo.ac.jp
- ブログ:http://mmi.hatenablog.com/
Copyright © ITmedia, Inc. All Rights Reserved.
関連記事
- 2018年上半期に話題になったSpectreとその変異、Linuxカーネルでの対応まとめ
連載「OSS脆弱性ウォッチ」では、さまざまなオープンソースソフトウェアの脆弱性に関する情報を取り上げ、解説していく。2018年の上半期は、「Meltdown」「Spectre」とその変異(Variant)の脆弱性に悩まされた。今回はいつもとは異なり、上半期のまとめも兼ねて、Meltdown/Spectreの各変異をバージョンを追いかけながら整理する。 - 2017年版Linuxカーネル開発レポート公開――支援している企業トップ10とは?
The Linux Foundationは2017年版Linuxカーネル開発レポートを公開した。Linuxカーネル4.8から4.13までの開発に焦点を当て、カーネル開発に携わった開発者や変更数などについて言及した。 - Linuxカーネルのソースコードを読んで、システムコールを探る
C言語の「Hello World!」プログラムで使われる、「printf()」「main()」関数の中身を、デバッガによる解析と逆アセンブル、ソースコード読解などのさまざまな側面から探る連載。前回まで、printf()内の中身をさまざまな方法で探り、write()やint $0x80の呼び出しまでたどり着いた。今回は、さらにその先にあるLinuxカーネル側のシステムコールを見ていく。