Upgrade to Pro — share decks privately, control downloads, hide ads and more …

eBPF verifier

Kazuo Moriwaka
November 08, 2018

eBPF verifier

eBPF verifiterでkernel内の関数を安全に呼びだせるように何をしているのか気になったので読んでみた

Kazuo Moriwaka

November 08, 2018
Tweet

More Decks by Kazuo Moriwaka

Other Decks in Technology

Transcript

  1. eBPF verifier Kazuo Moriwaka 2018-11-08 1

  2. eBPF (extended Berkeley Packet Filter) • BPFのISAを拡張したもの • 1.5〜4.0倍くらいに高速化 •

    フィルタリング以外のユースケースがいろ いろ ◦ seccomp, tracing, profiling, XDP+eBPF, Landlock…… • RHEL 7.6からtech previewで登場 アプリケーション verifier jit compiler eBPF bin eBPF map linux kernel 2
  3. eBPF (extended Berkeley Packet Filter) • BPFのISAを拡張したもの • 1.5〜4.0倍くらいに高速化 •

    フィルタリング以外のユースケースがいろ いろ ◦ seccomp, tracing, profiling, XDP+eBPF, Landlock…… • RHEL 7.6からtech previewで登場 アプリケーション verifier jit compiler eBPF bin eBPF map linux kernel 今日はここ 3
  4. eBPF spec 関数呼び出し? どうやって検証してる んやろ? → ソース読もう • 64bit の

    10レジスタ • スタック512bytes • maps データ領域 • bpf_call 命令で kernel内関数を呼び出し eBPF extends cBPF in multiple ways, including the ability to call a fixed set of in-kernel helper functions (via the BPF_CALL opcode extension provided by eBPF) and access shared data structures such as eBPF maps. man 2 bpf より 4
  5. eBPF velifier (1/2) ソースはkernel/bpf/verifier.c の bpf_check()。 めっちゃコメント書いてる。 ジャンプ命令とかが入っているところでち ぎって有向グラフ(DAG)を作る 1st

    passでのチェック • 命令数チェック。最大 BPF_MAXINSNS (4096)以上ある とNG • ループ検出。DAGにback-edge(前 に戻る辺)があればNG • 到達不可能な命令があれば NG • 境界の外に出るか不正な jumpが あればNG 5
  6. eBPF velifier (2/2) • 2nd pass. 全パス探索 ◦ 命令の総数が 64k以上だとNG

    (分岐があると複数回カウントされる ) ◦ 分岐の総数が1k以上だとNG ◦ レジスタに型をつけて追跡する。未初期化、スカラー、 MAPへのポインタ、スタックへのポインタ など。変な値をポインタとしてアクセスする、 alignmentしていないポインタ等をチェック 例) ポインタとポインタを加算するとスカラー型になる。そこへの jumpはNG ◦ 許可されるポインタの baseは4種類だけ: PTR_TO_MAP_VALUE, PTR_TO_CTX, PTR_TO_STACK, PTR_TO_SOCKET 6
  7. bpf_callでin-kernel関数を呼ぶときは……? • check_helper_call()関数で検査している • 呼べるのは include/uapi/linux/bpf.h の__BPF_FUNC_MAPPER で列挙してい る関数群だけ ◦

    call で呼ぶ関数の番号が __BPF_FUNC_MAX_ID 以上だとNG → 事前に定義した関数のみ • 引数の数と型、返り値の型をあらかじめ宣言しておき照合 ◦ 2nd passの型チェックに統合されている ◦ overrideできる一部の関数については protoを取得する関数はweak referenceで参照 7
  8. 関数型宣言の例 各関数にbpf_func_proto型で定義 • 関数そのものへのポインタ • GPL非互換なコードから呼ん でいいか • パケットへのアクセス有無 •

    返り値の型 • 関数への引数の型 const struct bpf_func_proto bpf_map_update_elem_proto = { .func = bpf_map_update_elem, .gpl_only = false, .pkt_access = true, .ret_type = RET_INTEGER, .arg1_type = ARG_CONST_MAP_PTR, .arg2_type = ARG_PTR_TO_MAP_KEY, .arg3_type = ARG_PTR_TO_MAP_VALUE, .arg4_type = ARG_ANYTHING, }; 8
  9. オチ ドキュメントに割と書いてた (linuxのDocumentation/networking/filter.txt) The eBPF verifier will check that registers

    match argument constraints. After the call register R0 will be set to return type of the function. (中略) If a function made accessible to eBPF program, it needs to be thought through from safety point of view. The verifier will guarantee that the function is called with valid arguments. 9
  10. See Also • man 2 bpf • ドキュメント: Documentation/networking/filter.txt •

    ソース: kernel/bpf/*, net/core/filter.c, include/uapi/linux/bpf.h • eBPF関連用語メモ http://bit.ly/2Q8jaCP bpf helper functionの定義とド キュメントがあるの でよい 「eBPFって何?」と いう人はこっちから どうぞ 10