Linux KernelにeBPF周りの複数の脆弱性(CVE-2017-17862, CVE-2017-17863, CVE-2017-17864) — | サイオスOSS | サイオステクノロジー

Linux KernelにeBPF周りの複数の脆弱性(CVE-2017-17862, CVE-2017-17863, CVE-2017-17864)

12/24/2017にLinux KernelにeBPF周りの複数の脆弱性情報(CVE-2017-17862, CVE-2017-17863, CVE-2017-17864)が公開されています。今回はこの脆弱性の概要と、各ディストリビューションの対応について簡単にまとめてみます。

こんにちは。SIOS OSSエバンジェリスト/セキュリティ担当の面 和毅です。

12/24/2017にLinux KernelにeBPF周りの複数の脆弱性情報(CVE-2017-17862, CVE-2017-17863, CVE-2017-17864)が公開されています。今回はこの脆弱性の概要と、各ディストリビューションの対応について簡単にまとめてみます。



修正方法

各ディストリビューションの情報を確認してください。

CVE概要(詳細はCVEのサイトをご確認ください)

  • http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-17862
    • ローカルユーザによるDoSの可能性

    • Linux Kernel 4.14.8以前のkernel/bpf/verifier.cでは、JITコンパイラによって処理されているにも関わらず到達不能なコードを無視しています。ローカルユーザはこれを悪用してDoSを引き起こす事が出来る可能性があります。

      素のカーネルでは、この修正のために、sanitize_dead_code()が導入されています。

      +/* The verifier does more data flow analysis than llvm and will not explore
      + * branches that are dead at run time. Malicious programs can have dead code
      + * too. Therefore replace all dead at-run-time code with nops.
      + */
      +static void sanitize_dead_code(struct bpf_verifier_env *env)
      +{
      +	struct bpf_insn_aux_data *aux_data = env->insn_aux_data;
      +	struct bpf_insn nop = BPF_MOV64_REG(BPF_REG_0, BPF_REG_0);
      +	struct bpf_insn *insn = env->prog->insnsi;
      +	const int insn_cnt = env->prog->len;
      +	int i;
      +
      +	for (i = 0; i < insn_cnt; i++) {
      +		if (aux_data[i].seen)
      +			continue;
      +		memcpy(insn + i, &nop;, sizeof(nop));
      +	}
      +}
      
  • http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-17863
    • ローカルユーザによるDoS(整数オーバーフロー、または不正なメモリアクセス)の可能性

    • Linux Kernel 4.9.71までの4.9.x系では、kernel/bpf/verifier.c で BPF stackとポインタの値の関係をチェックしていませんでした。ローカルのユーザはこれを悪用して、DoS(整数オーバーフロー、または不正なメモリアクセス)を引き起こす事が出来る可能性があります。

      素のカーネルでは修正はcheck_alu_op()関数に対して

      diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
      index 2f19c94..b03af36 100644
      --- a/kernel/bpf/verifier.c
      +++ b/kernel/bpf/verifier.c
      @@ -1861,10 +1861,28 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
      ((BPF_SRC(insn->code) == BPF_X &&
      regs[insn->src_reg].type == CONST_IMM) ||
      BPF_SRC(insn->code) == BPF_K)) {
      -			if (BPF_SRC(insn->code) == BPF_X)
      +			if (BPF_SRC(insn->code) == BPF_X) {
      +				/* check in case the register contains a big
      +				 * 64-bit value
      +				 */
      --省略--
      

      のように施されています。

  • http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-17864
    • ローカルユーザによる機密情報読み出しの可能性

    • Linux Kernel 4.14.8以前では、kernel/bpf/verifier.c でUNKNOWN_VALUEデータタイプとpointerのデータタイプの states_equal比較演算のところで誤った扱いがあったため、ローカルのユーザはこれを悪用して機密情報を読み出すことが可能です(”pointerリーク”の可能性です)。

      この修正は、素のカーネルではkernel/bpf/verifier.cのstatic bool states_equal()に対して

      ---
      --- a/kernel/bpf/verifier.c
      +++ b/kernel/bpf/verifier.c
      @@ -2722,11 +2722,12 @@ static bool states_equal(struct bpf_veri
      /* If we didn't map access then again we don't care about the
      * mismatched range values and it's ok if our old type was
      -		 * UNKNOWN and we didn't go to a NOT_INIT'ed reg.
      +		 * UNKNOWN and we didn't go to a NOT_INIT'ed or pointer reg.
      */
      if (rold->type == NOT_INIT ||
      (!varlen_map_access && rold->type == UNKNOWN_VALUE &&
      -		     rcur->type != NOT_INIT))
      +		     rcur->type != NOT_INIT &&
      +		     !__is_pointer_value(env->allow_ptr_leaks, rcur)))
      continue;
      /* Don't care about the reg->id in this case. */
      

      のように施されています。


主なディストリビューションの対応方法

詳細は、各ディストリビューションの提供元にご確認ください


対処方法

各ディストリビューションの案内に従い、アップデートを行ってください。全てのRed Hat製品でパッチが行き渡っているかを確認するには、Red Hat Satelliteを使うと管理が便利でしょう。

Red Hat Satelliteを用いた一般的なErattaの適用は、『Red Hat Satellite 6でerrataを適用してみる』
参考にして下さい。

また、OSの再起動が発生しますので、pacemakerなどOSSのクラスタ製品LifeKeeperなどの商用のクラスタリング製品を使うとサービス断の時間を最小限にすることが出来ます。

[参考]

bpf: fix branch pruning logic

bpf: reject out-of-bounds stack pointer calculation

https://anonscm.debian.org/cgit/kernel/linux.git/tree/debian/patches/bugfix/all/bpf-verifier-fix-states_equal-comparison-of-pointer-and-unknown.patch?h=stretch-security

セキュリティ系連載案内

—–

タイトルとURLをコピーしました