私は論文を書いていますが、現在のセットアップに関する意見をいただければ幸いです。libfuzzer を使用してターゲットの Go アプリケーションをファジングしたいので、次のようにしました。
テストする go 関数を呼び出すメイン パッケージを作成しました。コード:
package main
import "C"
import "$PACKAGE"
func main(){}
//export Fuzz
func Fuzz(data []byte){
$PACKAGE.Fuzz(data) //actual Fuzzing function, which instruments the function under test
}
llvm-go
アプリケーションを実際に共有ライブラリとしてビルドするには、メインパッケージが必要です。ここで二重の抽象化を行う理由は、ビルド パイプラインを go-fuzz と互換性を持たせたいからです。go-fuzz は、"Fuzz" 関数名をファジング エントリ ポイントとして使用します。私のセットアップでは、libfuzzer を利用するために必要なコードをラップするだけです。
次に、アプリケーションをコンパイルしますllvm-go
。
これで、Go 共有ライブラリを計測する方法が 2 つあります。動的にロードするか、バイナリに静的にリンクするかです。静的にリンクされたコードを使用して問題を説明します。そのために、Go 共有ライブラリを計測するファジング スタブを作成しました。
// fuzz_target.cc
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <dlfcn.h>
#include "golang-app.h"
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
void *handle;
char *error;
GoSlice data = {(void*)Data, static_cast<long long>(Size), static_cast<long long>(Size)};
Fuzz(data);
return 0; // Non-zero return values are reserved for future use.
}
次に、次のようにコンパイルしました。
clang -g -O1 -fsanitize=fuzzer,address -o fuzz fuzzing-entry_static.cc ../golang-app.so
ここで、コードを実行すると、次の 2 つの問題が発生します。
master@thesis:~/go-libfuzz$ ./fuzz-static ./corpus/ -timeout=12
INFO: Seed: 2260122321
INFO: Loaded 1 modules (1 inline 8-bit counters): 1 [0x787f60, 0x787f61),
INFO: Loaded 1 PC tables (1 PCs): 1 [0x565bd0,0x565be0),
INFO: 11 files found in ./corpus/
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 18061 bytes
INFO: seed corpus: files: 11 min: 450b max: 18061b total: 76971b rss: 51Mb
#12 INITED cov: 1 ft: 1 corp: 1/450b exec/s: 0 rss: 53Mb
#13 REDUCE cov: 1 ft: 1 corp: 1/282b exec/s: 0 rss: 53Mb L: 282/282 MS: 1 EraseBytes-
[...]
#193 REDUCE cov: 1 ft: 1 corp: 1/1b exec/s: 0 rss: 56Mb L: 1/1 MS: 1 EraseBytes-
#65536 pulse cov: 1 ft: 1 corp: 1/1b exec/s: 21845 rss: 63Mb
#131072 pulse cov: 1 ft: 1 corp: 1/1b exec/s: 26214 rss: 68Mb
#262144 pulse cov: 1 ft: 1 corp: 1/1b exec/s: 26214 rss: 79Mb
#524288 pulse cov: 1 ft: 1 corp: 1/1b exec/s: 27594 rss: 100Mb
#1048576 pulse cov: 1 ft: 1 corp: 1/1b exec/s: 27594 rss: 142Mb
#2097152 pulse cov: 1 ft: 1 corp: 1/1b exec/s: 27962 rss: 226Mb
カバレッジと機能は増加していないようで、メモリ要件は実行ごとに増加します。ファザーの実行に環境変数を追加することで、別の SO 投稿のおかげでメモリの増加を修正できました。ASAN_OPTIONS=quarantine_size_mb=20 ./fuzz-target -timeout=12
ただし、おそらく主な問題は、実際のターゲットが 2 つのレベルの抽象化の下に「埋もれている」ことです: LLVMFuzzerTestOneInput --calls-> main.go を介した共有 Go ライブラリ。 --> ファジング関数 --calls--> ターゲット関数。ただし、これらの各関数は、データを変更せずに直接次のレイヤーに渡すだけであることに注意してください。これが正しく機能していることを確認するには、どのような手順を実行できますか? 私は何か間違ったことをしていますか?