===================

このリポジトリには、セットアップスクリプトを含むすべてのソースが含まれています。 警告と対応するソースファイルを表示する素晴らしいUIを搭載しました。
Ubuntu >= 14.04.5 LTS
2018年2月16日:
事前に構築されたDockerコンテナでDR.CHECKERを使用する方法の詳細については、Docker Usageドキュメントを参照してください。
実装はLLVM、具体的にはLLVM 3.8に基づいています。また、ヘッダーを解析するためにc2xmlなどのツールが必要です。
まず、cmake(セットアップ/ビルドスクリプトで使用)とlibxml(c2xmlに必要)がインストールされていることを確認してください:
sudo apt-get install cmake libxml2-dev
次に、必要なツールをすべてダウンロードしてビルドする単一のスクリプトを作成しました。
cd helper_scripts
python setup_drchecker.py --help
usage: setup_drchecker.py [-h] [-b TARGET_BRANCH] [-o OUTPUT_FOLDER]
optional arguments:
-h, --help show this help message and exit
-b TARGET_BRANCH Branch (i.e. version) of the LLVM to setup. Default:
release_38 e.g., release_38
-o OUTPUT_FOLDER Folder where everything needs to be setup.
例:
python setup_drchecker.py -o drchecker_deps
セットアップを完了するには、ローカルのPATH環境変数の変更も必要です。セットアップスクリプトが正確な変更内容を表示します。
これはセットアップの成功に依存します。 すべてをビルドする単一のスクリプトがあります。どうぞ。
cd llvm_analysis
./build.sh
これはビルドの成功に依存します。 カーネルドライバでDR.CHECKERを実行するには、まずそれらをLLVMビットコードに変換する必要があります。
まず、ビルド可能なカーネルが必要です。つまり、通常のビルドセットアップ(make)を使用してカーネルをコンパイルできる必要があります。
最初にmakeコマンドの出力をキャプチャし、この出力から正確なコンパイルコマンドを抽出します。
make(またはmakeout.txt)の出力を生成V=1を渡し、出力をファイルにリダイレクトするだけです。
例:
make V=1 O=out ARCH=arm64 > makeout.txt 2>&1
注:マルチプロセス(-j)を使用しないでください。マルチプロセスモードで実行すると、複数のプロセスが出力ファイルに書き込もうとするため、出力ファイルが乱れます。
これで完了です。DR.CHECKERが以降を処理します。
DR.CHECKER解析を実行するにはいくつかのステップがあります。これらのステップはすべて単一のスクリプトhelper_scripts/runner_scripts/run_all.pyにまとめられています。
実行方法:
python run_all.py --help
usage: run_all.py [-h] [-l LLVM_BC_OUT] [-a CHIPSET_NUM] [-m MAKEOUT] [-g COMPILER_NAME] [-n ARCH_NUM] [-o OUT] [-k KERNEL_SRC_DIR] [-skb] [-skl] [-skp] [-ske] [-ski] [-f SOUNDY_ANALYSIS_OUT]
optional arguments:
-h, --help show this help message and exit
-l LLVM_BC_OUT Destination directory where all the generated bitcode files should be stored.
-a CHIPSET_NUM Chipset number. Valid chipset numbers are:
1(mediatek)|2(qualcomm)|3(huawei)|4(samsung)
-m MAKEOUT Path to the makeout.txt file.
-g COMPILER_NAME Name of the compiler used in the makeout.txt, This is
needed to filter out compilation commands. Ex: aarch64-linux-android-gcc
-n ARCH_NUM Destination architecture, 32 bit (1) or 64 bit (2).
-o OUT Path to the out folder. This is the folder, which
could be used as output directory during compiling
some kernels. (Note: Not all kernels needs a separate out folder)
-k KERNEL_SRC_DIR Base directory of the kernel sources.
-skb Skip LLVM Build (default: not skipped).
-skl Skip Dr Linker (default: not skipped).
-skp Skip Parsing Headers (default: not skipped).
-ske Skip Entry point identification (default: not
skipped).
-ski Skip Soundy Analysis (default: not skipped).
-f SOUNDY_ANALYSIS_OUT Path to the output folder where the soundy analysis output should be stored.
スクリプトはすべてのドライバに対してDR.CHECKERのビルド、リンク、実行を行います。そのため、**かなりの時間(45分~90分)**がかかる場合があります。個々のドライバでDR.CHECKERを手動で実行したい場合は、スタンドアロンを参照してください。
上記のスクリプトは、すべてのCPUコアを活用するためにマルチプロセッサモードで以下のタスクを実行します:
生成されたすべてのビットコードファイルは、引数-lに指定されたフォルダに配置されます。
このステップは、使用可能なコア数によってかなりの時間がかかります。
そのため、このステップを既に実行した場合は、-skbを渡すことでスキップできます。
これはリンクを実行し、すべてのビットコードファイルを調べて、リンクが必要な関連ビットコードファイルを特定し、それらをllvm-linkを使用して統合ビットコードファイル(対応するビットコードファイルと一緒に保存されます)にリンクします。
上記のステップと同様に、-sklを渡すことでスキップできます。
このステップは、ヘッダーファイル内のエントリポイント宣言を検索し、その設定をLLVMビルドディレクトリ下のhdr_file_config.txtファイルに保存します。
スキップするには:-skp
このステップは、すべてのドライバ統合ビットコードファイル全体のエントリポイントを特定します。
出力はLLVMビルドディレクトリ下のentry_point_out.txtファイルに保存されます。
ファイルentry_point_out.txtの内容例:
FileRead:hidraw_read:/home/drchecker/33.2.A.3.123/llvm_bc_out/drivers/hid/llvm_link_final/final_to_check.bc
FileWrite:hidraw_write:/home/drchecker/33.2.A.3.123/llvm_bc_out/drivers/hid/llvm_link_final/final_to_check.bc
IOCTL:hidraw_ioctl:/home/drchecker/33.2.A.3.123/llvm_bc_out/drivers/hid/llvm_link_final/final_to_check.bc
スキップするには:-ske
このステップは、entry_point_out.txtファイル内のすべてのエントリポイントに対してDR.CHECKERを実行します。各エントリポイントの出力は、オプション-fで指定されたフォルダに保存されます。
スキップするには:-ski
ここで、カーネルソースがある段階から脆弱性警告を取得する段階までの例を示します。
mediatekカーネル33.2.A.3.123.tar.bz2をアップロードしました。 まず、上記のファイルをダウンロードして展開します。
展開したファイルを~/mediatek_kernelというフォルダに保存したとします。
cd ~/mediatek_kernel
source ./env.sh
cd kernel-3.18
# 以下のステップはカーネルによっては不要な場合があります
mkdir out
make O=out ARCH=arm64 tubads_defconfig
# 次のコマンドはすべてのコンパイルコマンドをmakeout.txtにコピーします
make V=1 -j8 O=out ARCH=arm64 > makeout.txt 2>&1
cd <repo_path>/helper_scripts/runner_scripts
python run_all.py -l ~/mediatek_kernel/llvm_bitcode_out -a 1 -m ~/mediatek_kernel/kernel-3.18/makeout.txt -g aarch64-linux-android-gcc -n 2 -o ~/mediatek_kernel/kernel-3.18/out -k ~/mediatek_kernel/kernel-3.18 -f ~/mediatek_kernel/dr_checker_out
上記のコマンドは**かなりの時間(30分~1時間)**がかかります。
まず、すべての解析結果はフォルダ ~/mediatek_kernel/dr_checker_out(オプション-fに指定した引数) に保存されます。各エントリポイントに対して.jsonファイルが作成され、JSON形式のすべての警告が含まれています。これらのjsonファイルには、コンテキストごとに整理された警告が含まれています。
次に、フォルダ ~/mediatek_kernel/dr_checker_out/instr_warnings(オプション-fに指定した引数相対) には、命令の位置ごとに整理された警告が含まれています。
これらの警告は、Visualizerを使用して分析できます。
最後に、各エントリポイントの警告の種類ごとに整理された要約が、出力CSVファイル ~/mediatek_kernel/dr_checker_out/warnings_stats.csv(オプション-fに指定した引数相対) に書き込まれます。
-gの値オプション-gの値を指定するには、カーネルのコンパイルに使用された*-gccバイナリの名前を知る必要があります。
簡単な方法は、makeout.txt内でgccをgrepで検索することです。コンパイラコマンドが表示され、*-gccバイナリ名を確認できます。
上記の例では、ビルド例のmakeout.txtに対してgrep gccを実行すると、以下のような行が多数表示されます:
aarch64-linux-android-gcc -Wp,-MD,fs/jbd2/.transaction.o.d -nostdinc -isystem ...
したがって、-gの値はaarch64-linux-android-gccとなります。
ビルドするカーネルが32ビットの場合、バイナリはほぼ確実にarm-eabi-gccになります。
-aの値チップセットの種類に応じて、対応する番号を指定する必要があります。
-oの値これは、カーネルビルド中にmakeコマンドにO=オプションで指定したフォルダのパスです。
すべてのカーネルに個別の出力パスが必要なわけではありません。Oオプションを指定せずにカーネルをビルドすることもできます。その場合、run_all.pyの実行時にそのオプションに値を指定しないでください。
すべての警告を表示するWebベースのUIを提供しています。可視化を参照してください。
対応する#define DISABLE_*行のコメントを解除することで、1つ以上の脆弱性チェッカーを無効にできます。BugDetectorDriver.cppを参照。
お好みで、結果を後処理するスクリプトも提供しています。こちらをご覧ください。
お楽しみください!!