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

Linuxカーネルのファジングツールsyzkaller / Linux kernel fuzzing tool syzkaller

fujiihda
December 13, 2019

Linuxカーネルのファジングツールsyzkaller / Linux kernel fuzzing tool syzkaller

syzkaller/syzbot は、2 年で 1500 件以上の Linux カーネルの不具合修正に貢献しています。自らが生成した複数の仮想マシンに対して問題の起きそうな入力を送り続けることで未発見の不具合を発見します。最小限の入力で不具合を再現させるための再試行を繰り返し、最終的には不具合を再現するための C 言語のプログラム生成を試みます。

syzkaller の概要
syzkaller のドキュメント調査結果
syzkaller のソースコード調査結果
syzkaller の動作確認結果 (未発見の不具合の発見)

fujiihda

December 13, 2019
Tweet

More Decks by fujiihda

Other Decks in Technology

Transcript

  1. © 2019 NTT DATA Corporation
    2019年12月13日
    株式会社NTTデータ 藤井 秀行
    Linux カーネルのファジングツール syzkaller

    View Slide

  2. © 2019 NTT DATA Corporation 2
    Whois セキュリティ専門家でもなく、カーネル分野で突出してもいないけれど、いろいろできる
    名前
    • 藤井 秀行 (ふじい ひでゆき)
    業務経歴
    • 入社以来 OSS に関わる業務を担当
    • 最近はパブリッククラウド (GCP等) で
    コンテナしつつ、技術系コミュニティの
    オーガナイザ
    直近 1 年くらいの主なアウトプット
    • RHEL 8 の新機能と検証結果の紹介
    • Linux 特権機能使用制御技術 ~コンテナセキュリティ~
    • コンテナ管理ツール機能調査 ~Podman~
    • Container-native Virtualization ~コンテナの中で無理やり仮想マシンを動かす~
    年度 案件名 技術
    2013-
    2015
    Hinemos
    Hinemos と Hinemos が含む OSS 全般、
    各社ハイパーバイザとクラウド、Linux 全般
    2016-
    2017
    某OSSセンタ
    ユーザサポート
    ほぼすべての OSS ミドルウェア全般を広く
    浅く、Linux 全般
    2018-
    2019.9
    某OSSセンタ
    OS 担当
    Linux カーネル、コンテナ技術、NFS
    2019.10-
    new
    クラウド技術
    センタ
    パブリッククラウド全般、コンテナ技術、
    マイグレーション技術、 SRE ???

    View Slide

  3. © 2019 NTT DATA Corporation 3
    掲載内容は個人の見解であり、
    所属する企業やコミュニティの立場、
    戦略、意見を代表するものではありません
    はじめに

    View Slide

  4. © 2019 NTT DATA Corporation 4
    • 社内ネットワークではやらないでください
    • 社内のマシンではやらないでください
    • プライベート環境などの完全に隔離された
    環境で自己責任でやってください
    警告

    View Slide

  5. © 2019 NTT DATA Corporation 5
    本日の流れ
    1. 背景
    2. テーマ選定
    3. 実施内容
    4. ドキュメント調査
    5. ソースコード調査
    6. syzkaller の動作確認
    7. まとめ
    8. 個人的な振り返り
    9. 今後
    時間の都合上ここに注力

    View Slide

  6. © 2019 NTT DATA Corporation 6
    背景 (ファジングと Linux のセキュリティ品質向上)
    • ファジングは未知の不具合や脆弱性の検出に適したテスト手法
    – 検査対象にランダムな入力データを送ることで意図的に例外を発生させる
    • ファジングがセキュリティ品質に与える影響が話題に
    – Open Source Summit Japan 2019 では、カーネルのリードメンテナなどの複数講演者がファジングの貢献に言及
    • 2017 年前後を境としてファジングをはじめとする自動化された高度なテスト技術が普及
    • リリース前にセキュリティ脆弱性が修正されるようになり CVE の件数は減少傾向
    0
    100
    200
    300
    400
    500
    600
    700
    800
    900
    1000
    0
    2000
    4000
    6000
    8000
    10000
    12000
    14000
    16000
    18000
    20000
    2012 2013 2014 2015 2016 2017 2018 2019
    全体 Linux
    (件) (件)
    (年)
    (予測)
    図:ソフトウェア全体および Linux の CVE 件数の推移

    View Slide

  7. © 2019 NTT DATA Corporation 7
    テーマ選定
    • 選定理由
    – カーネルの世界に大きな影響を与えたわりに情報がない (特に日本語は皆無)
    • 最新技術が投入されているはずの仕組み、設計、実装に興味がある
    • 使われている技術や考え方が他分野に転用可能かもしれない
    – syzkaller を通じてカーネルのエンジニアとしてレベルアップしたい
    • syzkaller で発見したカーネルの不具合修正には逆アセンブルが有効なことも

    View Slide

  8. © 2019 NTT DATA Corporation 8
    • ドキュメント調査 (英語)
    – 公式ドキュメントの調査
    – 開発者による講演資料 / 講演映像の調査
    – 学術論文の調査
    – セキュリティカンファレンスの講演資料 / 講演映像の調査
    – コミュニティの調査 (開発者の SNS 等を含む)
    • ソースコード調査 (ほぼ Go 言語)
    – Go 言語の言語仕様の差異の把握
    – Go 言語の開発環境構築および手順の確立
    – 全体構成把握および関数名とコメント文の斜め読み
    – 処理の順にソースコードの関数を追いかける
    • syzkaller の動作確認 (未発見の不具合の発見)
    – 環境構築および構築手順の確立
    – ファジング実行と挙動の確認
    – カーネルの I/O スケジューラに関連する use-after-free の
    新規不具合の発見
    – 再現用の C 言語のプログラム生成
    全体像、各種構成要素、
    大まかな処理の流れ
    の解明
    ソースコードにしかない
    動作の仕組みや細かい
    処理の流れを解明
    動かして理解しつつ
    未発見の不具合を探す
    実施内容

    View Slide

  9. © 2019 NTT DATA Corporation 9
    ドキュメント調査
    (論文等のサーベイ)

    View Slide

  10. © 2019 NTT DATA Corporation 10
    ドキュメント調査 - ファジング技術の肝
    • 検査対象で問題が起きそうな入力データを生成する仕組みが高度なファジングの肝
    – この仕組みの高度化が発見困難な不具合の発見を可能にする
    – ファジングの入力データを生成する仕組みを分類した結果は次のとおりで、syzkaller はレベル 4
    – ファジングのターゲットはネットワーク越し限定からそうでないもの (例:syzkaller) まで多岐に渡る
    レベル 仕組み 効率 網羅 備考
    1 プロトコル等を考慮しない完全な
    ランダム
    × ○ 実際の入力とは程遠い入力パターンが生成
    される
    2 キャプチャしたパケットをテンプ
    レートとしてその一部を改変
    △ × キャプチャした範囲内の入力パターンしか生
    成されない
    3 プロトコル仕様や問題の起きそう
    な入力パターンを人間が実装し
    ておき活用
    ○ ○ 主要な商用ツールで採用されている手法
    4 レベル 3 に加えてソースコードの
    カバレッジを活用
    ◎ ○
    syzkaller が採用している手法で、入力を変
    異させるときの分岐条件にソースコードを活
    用する
    表:ファジングの入力データを生成する仕組みの分類

    View Slide

  11. © 2019 NTT DATA Corporation 11
    ドキュメント調査 - syzkaller とは
    • Google の Dmitry Vyukov さんによって開発された
    カーネルのファジングツール
    • 2 年間でカバレッジを 7 %カバーした時点で 、
    1500 件以上のカーネルの不具合修正に貢献
    • 特徴
    – ハイブリッドな仕組みにより効率良くシステムコールの
    シーケンスを生成
    • 攻撃対象プロトコル (システムコール) のテンプ
    レートが実装されている
    • ソースコードのコンパイル時にコンパイラが出力
    するカバレッジを利用して入力を変える
    – 不具合発見の一連の流れがほぼすべて自動化
    • 自らが生成した複数の試験対象の仮想マシンに
    対して問題の起きそうな入力を送り続けて、
    デバッグ支援機構を活用してその挙動を観測
    • 発見した不具合を最小限の入力で再現させる
    ための再試行を自ら繰り返し、不具合を再現する
    ための C 言語のプログラム生成を試みる
    図:syzkaller の構成図
    ユーザ空間
    カーネル
    VMs (試験対象)
    syzkaller サーバ (仮想化ホスト)
    sshd
    syz-
    fuzzer
    syz-
    manager
    workdir/crashes/*
    workdir/corpus/*
    VMs 管理
    rpc
    ssh, scp
    invoke
    syscalls
    カバレッジ
    syz-
    executor
    syz-
    executor
    syz-
    executor
    syz-
    executor
    カバレッジ
    テストケース
    ファジング対象のカーネル (KCOV 有効)
    UI
    操作
    # ./bin/syz-manager -config my.cfg
    各構成要素の詳細は
    次ページから解説

    View Slide

  12. © 2019 NTT DATA Corporation 12
    (参考) ドキュメント調査 - Sanitizer とは
    • カーネルに存在する複数のデバッグ支援機構
    – 動的テストツール
    – コンパイラの機能 (gcc および C 言語で利用可能)
    – メモリを破壊したことや違反したことなどをはっきり示すもの
    – 不具合を示してくれるのでファジングを補助してくれる
    – エラーが起きたら、エラーの深刻度に関わらず、
    カーネルパニックを発生させる設定を使用する*1
    (コンソールにパニックメッセージを出力)
    • syzkaller で使用している主な Sanitizer
    – KASAN (Kernel Address Sanitizer)
    • メモリアクセスエラーを検出
    – KMSAN (Kernel Memory Sanitizer)
    • 初期化されていない読み取りを検出
    – KTSAN (Kernel Thread Sanitizer)
    • 異なるスレッド間のデータの競合状態を検出
    – UBSAN (Undefined Behavior Sanitizer)
    • 未定義の動作を引き起こす機能の使用を検出
    ユーザ空間
    カーネル
    VMs (試験対象)
    syzkaller サーバ (仮想化ホスト)
    sshd
    syz-
    fuzzer
    syz-
    manager
    workdir/crashes/*
    workdir/corpus/*
    VMs 管理
    rpc
    ssh, scp
    invoke
    syscalls
    カバレッジ
    syz-
    executor
    syz-
    executor
    syz-
    executor
    syz-
    executor
    カバレッジ
    テストケース
    ファジング対象のカーネル (KCOV 有効)
    UI
    操作
    図:syzkaller の構成図
    *1 厳密には warning などの文字列を syzkaller が検出し、カーネルパニック前に止めることもある

    View Slide

  13. © 2019 NTT DATA Corporation 13
    (参考) ドキュメント調査 - KCOV (Kernel Code Coverage) とは
    • コンパイラ (gcc) によって提供される機能
    • カバレッジガイドファジングに適した形式でカーネルコードカバレッジ
    情報を生成
    • 使い方:CONFIG_KCOV = y
    • 条件:gcc 6.1.0 以降 (バージョン 231296 以降)
    ユーザ空間
    カーネル
    VMs (試験対象)
    syzkaller サーバ (仮想化ホスト)
    sshd
    syz-
    fuzzer
    syz-
    manager
    workdir/crashes/*
    workdir/corpus/*
    VMs 管理
    rpc
    ssh, scp
    invoke
    syscalls
    カバレッジ
    syz-
    executor
    syz-
    executor
    syz-
    executor
    syz-
    executor
    カバレッジ
    テストケース
    ファジング対象のカーネル (KCOV 有効)
    UI
    操作
    図:syzkaller の構成図
    __fuzz_coverage();
    if (...)
    {
    __fuzz_coverage();
    ...
    }
    __fuzz_coverage();
    if (...)
    {
    ...
    }
    図:KCOV 無効時と KCOV 有効時のイメージ

    View Slide

  14. © 2019 NTT DATA Corporation 14
    ドキュメント調査 - syzkaller の全体像
    • syz-manager
    – 仮想化ホスト上に存在するプロセス
    – 試験対象としての VMs の管理 (起動、監視、再起動)
    • この VMs はカーネルパニックのたびに再起動
    – 試験対象としての VMs 内で syz-fuzzer プロセスを起動
    – syz-fuzzer プロセスに指示を送る
    – workdir 上のコーパスとクラッシュ (次ページで説明) を更新
    ユーザ空間
    カーネル
    VMs (試験対象)
    syzkaller サーバ (仮想化ホスト)
    sshd
    syz-
    fuzzer
    syz-
    manager
    workdir/crashes/*
    workdir/corpus/*
    VMs 管理
    rpc
    ssh, scp
    invoke
    syscalls
    カバレッジ
    syz-
    executor
    syz-
    executor
    syz-
    executor
    syz-
    executor
    カバレッジ
    テストケース
    ファジング対象のカーネル (KCOV 有効)
    UI
    操作
    図:syzkaller の構成図

    View Slide

  15. © 2019 NTT DATA Corporation 15
    ドキュメント調査 - syzkaller の全体像
    • workdir/crashes/*
    – クラッシュに関わるアウトプット
    – アスタリスクにはハッシュ値が名前のフォルダが生成される
    – フォルダ内に次の情報を含む
    • description 事象を特定する件名
    • logN (N=0~99) syzkaller のログ
    • reportN (N=0~99) カーネルクラッシュレポート
    • repro.cprog 再現用の C 言語のプログラム
    • repro.log
    • repro.prog
    • repro.report
    • repro.stats
    • reproM (M=0~9)
    • workdir/corpus/*
    – コーパスは個別ファイルとして格納されているファズターゲット
    の入力セット
    – 理想的なコーパスは最大限のコードカバレッジを提供する
    最小限の入力セット
    ユーザ空間
    カーネル
    VMs (試験対象)
    syzkaller サーバ (仮想化ホスト)
    sshd
    syz-
    fuzzer
    syz-
    manager
    workdir/crashes/*
    workdir/corpus/*
    VMs 管理
    rpc
    ssh, scp
    invoke
    syscalls
    カバレッジ
    syz-
    executor
    syz-
    executor
    syz-
    executor
    syz-
    executor
    カバレッジ
    テストケース
    ファジング対象のカーネル (KCOV 有効)
    UI
    操作
    図:syzkaller の構成図

    View Slide

  16. © 2019 NTT DATA Corporation 16
    ドキュメント調査 - syzkaller の全体像
    • syz-fuzzer
    – 先述の不安定な試験対象 VMs 内に存在するプロセス
    – テストケース (入力) を生成、突然変異、最小化
    – 任意の数の syz-executor プロセスを起動
    – コーパスで入力を変える???
    → ドキュメント調査だけでは、なにをいっているのか
    いまいちわからなかった・・・
    ソースコードを調査した結果:
    コーパスの有無で条件分岐して Generate 関数
    もしくは Mutate 関数のいずれかを呼び出すことで
    システムコールのシーケンスを決める
    (詳細はソースコードを追いかけるときに説明)
    ユーザ空間
    カーネル
    VMs (試験対象)
    syzkaller サーバ (仮想化ホスト)
    sshd
    syz-
    fuzzer
    syz-
    manager
    workdir/crashes/*
    workdir/corpus/*
    VMs 管理
    rpc
    ssh, scp
    invoke
    syscalls
    カバレッジ
    syz-
    executor
    syz-
    executor
    syz-
    executor
    syz-
    executor
    カバレッジ
    テストケース
    ファジング対象のカーネル (KCOV 有効)
    UI
    操作
    図:syzkaller の構成図

    View Slide

  17. © 2019 NTT DATA Corporation 17
    ドキュメント調査 - syzkaller の全体像
    • syz-executor
    – 先述の不安定な試験対象 VMs 内に任意の個数存在するプロセス
    – syz-fuzzer から syscalls のシーケンスを受け取る
    – syscalls のシーケンスを実行する
    – syscalls の実行結果を syz-fuzzer に送り返す
    – 単一の executor プロセスのことを Proc とも呼ぶ
    • Proc がカーネルに送るデータは ProgData とも呼ぶ
    ユーザ空間
    カーネル
    VMs (試験対象)
    syzkaller サーバ (仮想化ホスト)
    sshd
    syz-
    fuzzer
    syz-
    manager
    workdir/crashes/*
    workdir/corpus/*
    VMs 管理
    rpc
    ssh, scp
    invoke
    syscalls
    カバレッジ
    syz-
    executor
    syz-
    executor
    syz-
    executor
    syz-
    executor
    カバレッジ
    テストケース
    ファジング対象のカーネル (KCOV 有効)
    UI
    操作
    図:syzkaller の構成図

    View Slide

  18. © 2019 NTT DATA Corporation 18
    ソースコード調査

    View Slide

  19. © 2019 NTT DATA Corporation 19
    ソースコード調査 - どの処理を深く調べるか
    • 一連の流れのなかで面白そうな処理 (核となる executor) に
    関連するソースコードを処理順に追う
    1. ssh で fuzzer が呼ばれたあとに executor を呼ぶまでの処理 (主に fuzzer)
    https://github.com/google/syzkaller/blob/master/syz-fuzzer/fuzzer.go
    2. executor が呼ばれたあとに syscalls 生成までの処理 (主に executor)
    https://github.com/google/syzkaller/blob/master/syz-fuzzer/proc.go
    https://github.com/google/syzkaller/tree/master/pkg/ipc/ipc.go
    ユーザ空間
    カーネル
    VMs (試験対象)
    syzkaller サーバ (仮想化ホスト)
    sshd
    syz-
    fuzzer
    syz-
    manager
    workdir/crashes/*
    workdir/corpus/*
    VMs 管理
    rpc
    ssh, scp
    invoke
    syscalls
    カバレッジ
    syz-
    executor
    syz-
    executor
    syz-
    executor
    syz-
    executor
    カバレッジ
    テストケース
    ファジング対象のカーネル (KCOV 有効)
    UI
    操作
    # ./bin/syz-manager -config my.cfg
    図:syzkaller の構成図
    1
    2

    View Slide

  20. © 2019 NTT DATA Corporation 20
    ソースコード調査 - fuzzer (syz-fuzzer/fuzzer.go)
    func main() {
    (中略)
    for pid := 0; pid < *flagProcs; pid++ {
    proc, err := newProc(fuzzer, pid)
    if err != nil {
    log.Fatalf("failed to create proc: %v", err)
    }
    fuzzer.procs = append(fuzzer.procs, proc)
    go proc.loop()
    }
    fuzzer.pollLoop()
    }
    ユーザ空間
    カーネル
    VMs (試験対象)
    syzkaller サーバ (仮想化ホスト)
    sshd
    syz-
    fuzzer
    syz-
    manager
    workdir/crashes/*
    workdir/corpus/*
    VMs 管理
    rpc
    ssh, scp
    invoke
    syscalls
    カバレッジ
    syz-
    executor
    syz-
    executor
    syz-
    executor
    syz-
    executor
    カバレッジ
    テストケース
    ファジング対象のカーネル (KCOV 有効)
    UI
    操作
    引数として与えた
    FlagProcs の数だけ
    Proc (executor の
    プロセス) を生成
    ゴルーチン (Go 言語で
    言語仕様として提供され
    る並列処理の機能) で
    syz-fuzzer/proc.go の
    loop 関数を呼び出す
    https://github.com/google/syzkaller/blob/master/syz-fuzzer/fuzzer.go
    # ./bin/syz-manager -config my.cfg
    図:syzkaller の構成図
    1

    View Slide

  21. © 2019 NTT DATA Corporation 21
    ソースコード調査 - executor (syz-fuzzer/proc.go)
    ユーザ空間
    カーネル
    VMs (試験対象)
    syzkaller サーバ (仮想化ホスト)
    sshd
    syz-
    fuzzer
    syz-
    manager
    workdir/crashes/*
    workdir/corpus/*
    VMs 管理
    rpc
    ssh, scp
    invoke
    syscalls
    カバレッジ
    syz-
    executor
    syz-
    executor
    syz-
    executor
    syz-
    executor
    カバレッジ
    テストケース
    ファジング対象のカーネル (KCOV 有効)
    UI
    操作
    func (proc *Proc) loop() {
    generatePeriod := 100
    if proc.fuzzer.config.Flags&ipc.FlagSignal == 0 {
    // If we don't have real coverage signal, generate programs more frequently
    // because fallback signal is weak.
    generatePeriod = 2
    }
    for i := 0; ; i++ {
    item := proc.fuzzer.workQueue.dequeue()
    if item != nil {
    (中略)
    }
    ct := proc.fuzzer.choiceTable
    corpus := proc.fuzzer.corpusSnapshot()
    if len(corpus) == 0 || i%generatePeriod == 0 {
    // Generate a new prog.
    p := proc.fuzzer.target.Generate(proc.rnd, programLength, ct)
    log.Logf(1, "#%v: generated", proc.pid)
    proc.execute(proc.execOpts, p, ProgNormal, StatGenerate)
    } else {
    // Mutate an existing prog.
    p := corpus[proc.rnd.Intn(len(corpus))].Clone()
    p.Mutate(proc.rnd, programLength, ct, corpus)
    log.Logf(1, "#%v: mutated", proc.pid)
    proc.execute(proc.execOpts, p, ProgNormal, StatFuzz)
    }
    }
    }
    https://github.com/google/syzkaller/blob/master/syz-fuzzer/proc.go
    コーパス (ファズターゲット
    の入力セット) の有無で条
    件分岐して、次のいずれか
    の関数を呼び出す
    Generate 関数
    を呼び、引数
    StatGenerate
    で execute 関
    数を呼ぶ
    Mutate 関数を
    呼び、引数
    StatFuzz で
    execute 関数
    を呼ぶ
    図:syzkaller の構成図
    2

    View Slide

  22. © 2019 NTT DATA Corporation 22
    ソースコード調査 - executor (syz-fuzzer/proc.go)
    ユーザ空間
    カーネル
    VMs (試験対象)
    syzkaller サーバ (仮想化ホスト)
    sshd
    syz-
    fuzzer
    syz-
    manager
    workdir/crashes/*
    workdir/corpus/*
    VMs 管理
    rpc
    ssh, scp
    invoke
    syscalls
    カバレッジ
    syz-
    executor
    syz-
    executor
    syz-
    executor
    syz-
    executor
    カバレッジ
    テストケース
    ファジング対象のカーネル (KCOV 有効)
    UI
    操作
    func (proc *Proc) execute(execOpts *ipc.ExecOpts, p *prog.Prog, flags ProgTypes,
    stat Stat) *ipc.ProgInfo {
    info := proc.executeRaw(execOpts, p, stat)
    calls, extra := proc.fuzzer.checkNewSignal(p, info)
    for _, callIndex := range calls {
    proc.enqueueCallTriage(p, flags, callIndex, info.Calls[callIndex])
    }
    if extra {
    proc.enqueueCallTriage(p, flags, -1, info.Extra)
    }
    return info
    }
    https://github.com/google/syzkaller/blob/master/syz-fuzzer/proc.go
    executeRaw
    関数を呼び
    出す
    図:syzkaller の構成図
    2

    View Slide

  23. © 2019 NTT DATA Corporation 23
    ソースコード調査 - executor (syz-fuzzer/proc.go)
    ユーザ空間
    カーネル
    VMs (試験対象)
    syzkaller サーバ (仮想化ホスト)
    sshd
    syz-
    fuzzer
    syz-
    manager
    workdir/crashes/*
    workdir/corpus/*
    VMs 管理
    rpc
    ssh, scp
    invoke
    syscalls
    カバレッジ
    syz-
    executor
    syz-
    executor
    syz-
    executor
    syz-
    executor
    カバレッジ
    テストケース
    ファジング対象のカーネル (KCOV 有効)
    UI
    操作
    func (proc *Proc) executeRaw(opts *ipc.ExecOpts, p *prog.Prog, stat Stat) *ipc.ProgInfo {
    if opts.Flags&ipc.FlagDedupCover == 0 {
    log.Fatalf("dedup cover is not enabled")
    }
    // Limit concurrency window and do leak checking once in a while.
    ticket := proc.fuzzer.gate.Enter()
    defer proc.fuzzer.gate.Leave(ticket)
    proc.logProgram(opts, p)
    for try := 0; ; try++ {
    atomic.AddUint64(&proc.fuzzer.stats[stat], 1)
    output, info, hanged, err := proc.env.Exec(opts, p)
    if err != nil {
    if try > 10 {
    log.Fatalf("executor %v failed %v times:¥n%v", proc.pid, try, err)
    }
    log.Logf(4, "fuzzer detected executor failure='%v', retrying #%d", err, try+1)
    debug.FreeOSMemory()
    time.Sleep(time.Second)
    continue
    }
    log.Logf(2, "result hanged=%v: %s", hanged, output)
    return info
    }
    }
    https://github.com/google/syzkaller/blob/master/syz-fuzzer/proc.go
    env.Exec 関数
    を呼び出す
    図:syzkaller の構成図
    2

    View Slide

  24. © 2019 NTT DATA Corporation 24
    ソースコード調査 - executor (pkg/ipc/ipc.go)
    ユーザ空間
    カーネル
    VMs (試験対象)
    syzkaller サーバ (仮想化ホスト)
    sshd
    syz-
    fuzzer
    syz-
    manager
    workdir/crashes/*
    workdir/corpus/*
    VMs 管理
    rpc
    ssh, scp
    invoke
    syscalls
    カバレッジ
    syz-
    executor
    syz-
    executor
    syz-
    executor
    syz-
    executor
    カバレッジ
    テストケース
    ファジング対象のカーネル (KCOV 有効)
    UI
    操作
    func (env *Env) Exec(opts *ExecOpts, p *prog.Prog) (output []byte, info *ProgInfo, hanged bool, err0
    error) {
    // Copy-in serialized program.
    progSize, err := p.SerializeForExec(env.in)
    if err != nil {
    err0 = fmt.Errorf("failed to serialize: %v", err)
    return
    }
    var progData []byte
    if env.config.Flags&FlagUseShmem == 0 {
    progData = env.in[:progSize]
    }
    // Zero out the first two words (ncmd and nsig), so that we don't have garbage there
    // if executor crashes before writing non-garbage there.
    for i := 0; i < 4; i++ {
    env.out[i] = 0
    }
    atomic.AddUint64(&env.StatExecs, 1)
    if env.cmd == nil {
    if p.Target.OS == "akaros" {
    // On akaros executor is actually ssh,
    // starting them too frequently leads to timeouts.
    <-rateLimit.C
    }
    tmpDirPath := "./"
    if p.Target.OS == "fuchsia" {
    tmpDirPath = "/data/"
    }
    atomic.AddUint64(&env.StatRestarts, 1)
    env.cmd, err0 = makeCommand(env.pid, env.bin, env.config, env.inFile, env.outFile, env.out,
    tmpDirPath)
    (以下省略)
    https://github.com/google/syzkaller/tree/master/pkg/ipc/ipc.go
    makeCommand
    関数を呼び出す
    図:syzkaller の構成図
    2

    View Slide

  25. © 2019 NTT DATA Corporation 25
    ソースコード調査 - executor (pkg/ipc/ipc.go)
    ユーザ空間
    カーネル
    VMs (試験対象)
    syzkaller サーバ (仮想化ホスト)
    sshd
    syz-
    fuzzer
    syz-
    manager
    workdir/crashes/*
    workdir/corpus/*
    VMs 管理
    rpc
    ssh, scp
    invoke
    syscalls
    カバレッジ
    syz-
    executor
    syz-
    executor
    syz-
    executor
    syz-
    executor
    カバレッジ
    テストケース
    ファジング対象のカーネル (KCOV 有効)
    UI
    操作
    func makeCommand(pid int, bin []string, config *Config, inFile, outFile *os.File, outmem []byte,
    tmpDirPath string) (*command, error) {
    (中略)
    // executor->ipc command pipe.
    inrp, inwp, err := os.Pipe()
    if err != nil {
    return nil, fmt.Errorf("failed to create pipe: %v", err)
    }
    defer inwp.Close()
    c.inrp = inrp
    // ipc->executor command pipe.
    outrp, outwp, err := os.Pipe()
    if err != nil {
    return nil, fmt.Errorf("failed to create pipe: %v", err)
    }
    defer outrp.Close()
    c.outwp = outwp
    c.readDone = make(chan []byte, 1)
    c.exited = make(chan struct{})
    cmd := osutil.Command(bin[0], bin[1:]...)
    if inFile != nil && outFile != nil {
    cmd.ExtraFiles = []*os.File{inFile, outFile}
    }
    cmd.Env = []string{}
    cmd.Dir = dir
    cmd.Stdin = outrp
    cmd.Stdout = inwp
    (以下省略)
    https://github.com/google/syzkaller/tree/master/pkg/ipc/ipc.go
    osutil.Command
    で executor 実行
    executor の標準
    入力を os のパイ
    プにつなぐ
    入出力リダイレクト
    図:syzkaller の構成図
    2

    View Slide

  26. © 2019 NTT DATA Corporation 26
    ソースコード調査 - executor (pkg/ipc/ipc.go)
    ユーザ空間
    カーネル
    VMs (試験対象)
    syzkaller サーバ (仮想化ホスト)
    sshd
    syz-
    fuzzer
    syz-
    manager
    workdir/crashes/*
    workdir/corpus/*
    VMs 管理
    rpc
    ssh, scp
    invoke
    syscalls
    カバレッジ
    syz-
    executor
    syz-
    executor
    syz-
    executor
    syz-
    executor
    カバレッジ
    テストケース
    ファジング対象のカーネル (KCOV 有効)
    UI
    操作
    func (c *command) exec(opts *ExecOpts, progData []byte) (output []byte, hanged bool, err0 error) {
    req := &executeReq{
    magic: inMagic,
    envFlags: uint64(c.config.Flags),
    execFlags: uint64(opts.Flags),
    pid: uint64(c.pid),
    faultCall: uint64(opts.FaultCall),
    faultNth: uint64(opts.FaultNth),
    progSize: uint64(len(progData)),
    }
    reqData := (*[unsafe.Sizeof(*req)]byte)(unsafe.Pointer(req))[:]
    if _, err := c.outwp.Write(reqData); err != nil {
    output = <-c.readDone
    err0 = fmt.Errorf("executor %v: failed to write control pipe: %v", c.pid, err)
    return
    }
    if progData != nil {
    if _, err := c.outwp.Write(progData); err != nil {
    output = <-c.readDone
    err0 = fmt.Errorf("executor %v: failed to write control pipe: %v", c.pid, err)
    return
    }
    }
    https://github.com/google/syzkaller/tree/master/pkg/ipc/ipc.go
    progData を
    継続して送る
    図:syzkaller の構成図
    2

    View Slide

  27. © 2019 NTT DATA Corporation 27
    syzkaller の動作確認

    View Slide

  28. © 2019 NTT DATA Corporation 28
    syzkaller の動作確認 - ファジング実行時の画面の一部抜粋
    # ./bin/syz-manager -config=my.cfg
    2019/06/05 03:53:20 loading corpus...
    2019/06/05 03:53:20 serving http on http://127.0.0.1:56741
    2019/06/05 03:53:20 serving rpc on tcp://[::]:37545
    2019/06/05 03:53:20 booting test machines...
    2019/06/05 03:53:20 wait for the connection from test machine...
    2019/06/05 03:54:08 machine check:
    2019/06/05 03:54:08 syscalls : 1380/2699
    2019/06/05 03:54:08 code coverage : enabled
    2019/06/05 03:54:08 comparison tracing : CONFIG_KCOV_ENABLE_COMPARISONS is not enabled
    2019/06/05 03:54:08 extra coverage : extra coverage is not supported by the kernel
    2019/06/05 03:54:08 setuid sandbox : enabled
    2019/06/05 03:54:08 namespace sandbox : /proc/self/ns/user does not exist
    2019/06/05 03:54:08 Android sandbox : /sys/fs/selinux/policy does not exist
    2019/06/05 03:54:08 fault injection : CONFIG_FAULT_INJECTION is not enabled
    2019/06/05 03:54:08 leak checking : CONFIG_DEBUG_KMEMLEAK is not enabled
    2019/06/05 03:54:08 net packet injection : /dev/net/tun does not exist
    2019/06/05 03:54:08 net device setup : enabled
    2019/06/05 03:54:08 corpus : 3844 (0 deleted)
    2019/06/05 03:54:10 VMs 4, executed 0, cover 0, crashes 0, repro 0
    2019/06/05 03:54:20 VMs 4, executed 36, cover 3836, crashes 0, repro 0
    2019/06/05 03:54:30 VMs 4, executed 776, cover 20662, crashes 0, repro 0
    (中略)
    2019/06/05 04:10:00 VMs 4, executed 70734, cover 62967, crashes 0, repro 0
    2019/06/05 04:10:05 vm-3: crash: no output from test machine
    2019/06/05 04:10:10 VMs 3, executed 70918, cover 62967, crashes 1, repro 0
    (中略)
    2019/06/05 04:14:02 VMs 4, executed 87377, cover 63959, crashes 1, repro 0
    2019/06/05 04:14:05 vm-2: crash: no output from test machine
    2019/06/05 04:14:12 VMs 3, executed 87614, cover 63960, crashes 2, repro 0
    (中略)
    2019/06/05 04:14:32 VMs 4, executed 87978, cover 63995, crashes 2, repro 0
    2019/06/05 04:14:40 vm-3: crash: KASAN: use-after-free Read in blk_mq_free_rqs
    2019/06/05 04:14:41 vm-1: running for 20m42.241115632s, restarting
    2019/06/05 04:14:41 vm-0: running for 20m33.97704277s, restarting
    2019/06/05 04:14:41 vm-2: running for 9.643775512s, restarting
    2019/06/05 04:14:42 reproducing crash 'KASAN: use-after-free Read in blk_mq_free_rqs': 1158 programs, 4 VMs, timeouts [15s 1m0s 6m0s]
    2019/06/05 04:14:42 VMs 0, executed 87978, cover 63995, crashes 3, repro 1
    (繰り返す)
    起動からわずか
    20 分程で不具合
    らしいものを発見
    クラッシュ時に
    事象を取り逃す
    こともある
    同上
    再現を試みる

    View Slide

  29. © 2019 NTT DATA Corporation 29
    # cat bd744ffeabd8fcd8ae152d0c44dde8112311663f/repro.cprog
    // autogenerated by syzkaller (https://github.com/google/syzkaller)
    #define _GNU_SOURCE
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    uint64_t r[1] = {0xffffffffffffffff};
    int main(void)
    {
    syscall(__NR_mmap, 0x20000000, 0x1000000, 3, 0x32, -1, 0);
    intptr_t res = 0;
    memcpy((void *)0x20000040, "/dev/loop-control¥000", 18);
    res = syscall(__NR_openat, 0xffffffffffffff9c, 0x20000040, 0x181000, 0);
    if (res != -1)
    r[0] = res;
    syscall(__NR_ioctl, r[0], 0x4c81, 0);
    return 0;
    }
    syzkaller の動作確認 - 前ページの事象を再現する C 言語のプログラム
    autogenerated
    by syzkaller

    View Slide

  30. © 2019 NTT DATA Corporation 30
    まとめ、振り返り、今後

    View Slide

  31. © 2019 NTT DATA Corporation 31
    まとめ
    • ドキュメント調査 (英語)
    – 公式ドキュメントの調査
    – 開発者による講演資料 / 講演映像の調査
    – 学術論文の調査
    – セキュリティカンファレンスの講演資料 / 講演映像の調査
    – コミュニティの調査 (開発者の SNS 等を含む)
    • ソースコード調査 (ほぼ Go 言語)
    – Go 言語の言語仕様の差異の把握
    – Go 言語の開発環境構築および手順の確立
    – 全体構成把握および関数名とコメント文の斜め読み
    – 処理の順にソースコードの関数を追いかける
    • syzkaller の動作確認 (未発見の不具合の発見)
    – 環境構築および構築手順の確立
    – ファジング実行と挙動の確認
    – カーネルの I/O スケジューラに関連する use-after-free の
    新規不具合の発見
    – 再現用の C 言語のプログラム生成
    全体像、各種構成要素、
    大まかな処理の流れ
    の解明
    ソースコードにしかない
    動作の仕組みや細かい
    処理の流れを解明
    動かして理解しつつ
    未発見の不具合を探す



    View Slide

  32. © 2019 NTT DATA Corporation 32
    個人的な振り返り (自分向け教訓)
    • 知識ゼロから知らない言語の処理を追うときこそ急がば回れ
    – いきなりソースコード斜め読みは精神的に辛い (熟練者向けなので個人的にはおすすめしない)
    – たとえ遠回りに見えても、以下からはじめるとよい
    • 開発環境構築
    • 言語仕様把握
    • 各コンポーネントの役割や処理の流れを把握
    • 実機による簡単な動作確認
    • 不具合は常に最新版で探し、見つけたら放置せずに即直せ
    – カーネルの不具合は、(素晴らしいことだが) 見つけたらすぐに直さないと、誰かが修正する
    (c3e2219216c92919a6bd1711f340f5faa98695e6)
    – 長期間放置されている不具合は、発生条件が不明確なものや修正が困難なものばかり
    (https://syzkaller.appspot.com/upstream)

    View Slide

  33. © 2019 NTT DATA Corporation 33
    今後
    • これから調べたい
    – テストケース (入力) を生成する仕組みのさらなる深掘り
    • テストケース (入力) の最小化
    • テストケース (入力) の突然変異
    – ファジング対象をシステムコール単位で絞り込む (できること確認済)
    • クラウドで提供されるマネージドなコンテナサービスは、
    システムコールが限定されていることがあり、
    その制限で有効なシステムコールのみに絞り込んで
    ファジングする
    – ファジング対象を機能単位で絞り込む (できること確認済)
    • ファイルシステムやネットワークなどの一部の機能
    に限定してファジングする
    • 今日のファジングネタの続き
    – 4月 にやります!(昨日急遽決定)
    – テーマ: Nested Virtualization のできる某クラウドベンダの
    マシンリソースでお金をかけずにごりごりファジングする話 (仮)

    View Slide

  34. © 2019 NTT DATA Corporation 34
    • 社内ネットワークではやらないでください
    • 社内のマシンではやらないでください
    • プライベート環境などの完全に隔離された
    環境で自己責任でやってください
    警告 (再)

    View Slide

  35. © 2019 NTT DATA Corporation

    View Slide

  36. © 2019 NTT DATA Corporation 36
    (参考) my.cfg
    # cat my.cfg
    {
    "target": "linux/amd64",
    "http": "127.0.0.1:56741",
    "workdir": "/root/gopath/src/github.com/google/syzkaller/workdir",
    "kernel_obj": "/root/kernel",
    "image": "/root/wheezy.img",
    "sshkey": "/root/wheezy.img.key",
    "syzkaller": "/root/gopath/src/github.com/google/syzkaller",
    "procs": 8,
    "type": "qemu",
    "vm": {
    "count": 4,
    "kernel": "/root/kernel/arch/x86/boot/bzImage",
    "cpu": 4,
    "mem": 4096
    }
    }

    View Slide

  37. © 2019 NTT DATA Corporation 37
    (参考) バージョン
    • syzkaller:bfb4a51e30c8c04658a2675333b9b89a9d327c4a など (その時の最新版)
    • gcc:gcc-9.0.0-20181231.tar.gz
    • Go 言語:go1.8.1.linux-amd64.tar.gz
    • kernel:788a024921c48985939f8241c1ff862a7374d8f9 など (その時の最新版)

    View Slide

  38. © 2019 NTT DATA Corporation 38
    (参考) 検出した不具合と不具合らしきもの

    View Slide