diff options
author | Calder Kitagawa <ckitagawa@chromium.org> | 2018-05-28 14:30:21 +0000 |
---|---|---|
committer | Edward Lesmes <ehmaldonado@google.com> | 2021-07-23 22:43:11 +0000 |
commit | 806fa630e61962fc2093be31eb3fad5fa745a27c (patch) | |
tree | 748f363f9ade33e7c598587e3e6ae5b98a61d079 | |
parent | 75569ad9940020e9730359c52bad857be7690025 (diff) | |
download | zucchini-806fa630e61962fc2093be31eb3fad5fa745a27c.tar.gz |
[Zucchini] ZTF Apply Fuzzer
This is part of a series of Fuzzers to be added to Zucchini for
security review. This tests the full patch application logic
exercising the patch reader and apply process. It covers ~33% of code
in 1000000 runs. The bulk of remaining code ~40% is covered by ZTF Gen
Fuzzer. With the remainder (~30%) being for DEX Disassembly (not in
launch scope), patch serialization (trusted input), and other
testing/debugging/error handling code which isn't triggered.
This already found a couple bugs fixed in
https://chromium-review.googlesource.com/c/chromium/src/+/1072272
With the supplied seed corpus the fuzzer reaches approximately 12000
execs/s.
The file format for the seed is a FilePair proto of a ZTF base file
and a patch file as used in Raw Apply. This reuses the same generator
and fuzzer as Raw Apply as the type of application is encoded in the
patch itself.
Bug: 835341
Change-Id: I00f28c768a6e1c7b8c5e95979b279d64785ef515
Reviewed-on: https://chromium-review.googlesource.com/1072231
Commit-Queue: Calder Kitagawa <ckitagawa@chromium.org>
Reviewed-by: Samuel Huang <huangs@chromium.org>
Reviewed-by: Max Moroz <mmoroz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#562260}
NOKEYCHECK=True
GitOrigin-RevId: 7206487ebd05fd4f30226ec59b730bb41c5013f2
-rw-r--r-- | BUILD.gn | 2 | ||||
-rw-r--r-- | fuzzers/BUILD.gn | 55 | ||||
-rw-r--r-- | fuzzers/apply_fuzzer.cc (renamed from fuzzers/raw_apply_fuzzer.cc) | 2 | ||||
-rwxr-xr-x | fuzzers/generate_fuzzer_data.py | 10 | ||||
-rw-r--r-- | fuzzers/testdata/new.ztf (renamed from fuzzers/testdata/new.ztxt) | 0 | ||||
-rw-r--r-- | fuzzers/testdata/old.ztf (renamed from fuzzers/testdata/old.ztxt) | 0 |
6 files changed, 54 insertions, 15 deletions
@@ -221,7 +221,7 @@ group("zucchini_fuzzers") { # Disabled on Windows due to crbug/844826. if (current_toolchain == host_toolchain && !is_win) { deps += [ - "//components/zucchini/fuzzers:zucchini_raw_apply_fuzzer", + "//components/zucchini/fuzzers:zucchini_apply_fuzzer", "//components/zucchini/fuzzers:zucchini_raw_gen_fuzzer", "//components/zucchini/fuzzers:zucchini_ztf_gen_fuzzer", ] diff --git a/fuzzers/BUILD.gn b/fuzzers/BUILD.gn index e11efc4..51680c3 100644 --- a/fuzzers/BUILD.gn +++ b/fuzzers/BUILD.gn @@ -39,7 +39,7 @@ proto_library("zucchini_file_pair_proto") { # Ensure protoc is available. # Disabled on Windows due to crbug/844826. if (current_toolchain == host_toolchain && !is_win) { - # Raw Apply Fuzzer: + # Raw Apply Fuzzer Seed: action("zucchini_raw_apply_seed") { script = "generate_fuzzer_data.py" @@ -49,8 +49,10 @@ if (current_toolchain == host_toolchain && !is_win) { "new_eventlog_provider.dll", # <new_file> "eventlog_provider.patch", # <patch_file> (temporary) - # <output_dir> - rebase_path("$target_gen_dir/testdata/raw_apply_fuzzer", root_build_dir), + # <output_file> + rebase_path( + "$target_gen_dir/testdata/apply_fuzzer/raw_apply_seed_proto.bin", + root_build_dir), ] # Files depended upon. @@ -62,7 +64,7 @@ if (current_toolchain == host_toolchain && !is_win) { # Outputs: necessary for validation. outputs = [ - "$target_gen_dir/testdata/raw_apply_fuzzer/seed_proto.bin", + "$target_gen_dir/testdata/apply_fuzzer/raw_apply_seed_proto.bin", ] deps = [ "//components/zucchini:zucchini", @@ -70,9 +72,43 @@ if (current_toolchain == host_toolchain && !is_win) { ] } - fuzzer_test("zucchini_raw_apply_fuzzer") { + # ZTF Apply Fuzzer Seed: + action("zucchini_ztf_apply_seed") { + script = "generate_fuzzer_data.py" + + # *.ztf files are expected to be valid ZTF format. + args = [ + "old.ztf", # <old_file> + "new.ztf", # <new_file> + "ztf.patch", # <patch_file> (temporary) + + # <output_file> + rebase_path( + "$target_gen_dir/testdata/apply_fuzzer/ztf_apply_seed_proto.bin", + root_build_dir), + ] + + # Files depended upon. sources = [ - "raw_apply_fuzzer.cc", + "create_seed_file_pair.py", + "testdata/new.ztf", + "testdata/old.ztf", + ] + + # Outputs: necessary for validation. + outputs = [ + "$target_gen_dir/testdata/apply_fuzzer/ztf_apply_seed_proto.bin", + ] + deps = [ + "//components/zucchini:zucchini", + "//third_party/protobuf:protoc", + ] + } + + # Apply Fuzzer: + fuzzer_test("zucchini_apply_fuzzer") { + sources = [ + "apply_fuzzer.cc", ] deps = [ ":zucchini_file_pair_proto", @@ -80,8 +116,11 @@ if (current_toolchain == host_toolchain && !is_win) { "//components/zucchini:zucchini_lib", "//third_party/libprotobuf-mutator", ] - seed_corpus = "$target_gen_dir/testdata/raw_apply_fuzzer" - seed_corpus_deps = [ ":zucchini_raw_apply_seed" ] + seed_corpus = "$target_gen_dir/testdata/apply_fuzzer" + seed_corpus_deps = [ + ":zucchini_raw_apply_seed", + ":zucchini_ztf_apply_seed", + ] } # Raw Gen Fuzzer: diff --git a/fuzzers/raw_apply_fuzzer.cc b/fuzzers/apply_fuzzer.cc index da3230a..4e9b342 100644 --- a/fuzzers/raw_apply_fuzzer.cc +++ b/fuzzers/apply_fuzzer.cc @@ -18,7 +18,7 @@ struct Environment { Environment() { - logging::SetMinLogLevel(3); // Disable console spamming. + logging::SetMinLogLevel(logging::LOG_FATAL); // Disable console spamming. } }; diff --git a/fuzzers/generate_fuzzer_data.py b/fuzzers/generate_fuzzer_data.py index c182baf..5a22109 100755 --- a/fuzzers/generate_fuzzer_data.py +++ b/fuzzers/generate_fuzzer_data.py @@ -28,14 +28,14 @@ def parse_args(): parser.add_argument('old_file', help='Old file to generate/apply patch.') parser.add_argument('new_file', help='New file to generate patch from.') parser.add_argument('patch_file', help='Patch filename to use.') - parser.add_argument('output_dir', - help='Directory to write binary protobuf to.') + parser.add_argument('output_file', help='File to write binary protobuf to.') return parser.parse_args() -def gen(old_file, new_file, patch_file, output_dir, is_raw, is_win): +def gen(old_file, new_file, patch_file, output_file, is_raw, is_win): """Generates a new patch and binary encodes a protobuf pair.""" # Create output directory if missing. + output_dir = os.path.dirname(output_file) if not os.path.exists(output_dir): os.makedirs(output_dir) @@ -61,7 +61,7 @@ def gen(old_file, new_file, patch_file, output_dir, is_raw, is_win): ret = subprocess.call([sys.executable, os.path.join(ABS_PATH, 'create_seed_file_pair.py'), os.path.abspath(protoc), old_file, patch_file, - os.path.join(output_dir, 'seed_proto.bin')], + output_file], stdout=subprocess.PIPE, stderr=subprocess.PIPE) os.remove(patch_file) @@ -73,7 +73,7 @@ def main(): return gen(os.path.join(ABS_TESTDATA_PATH, args.old_file), os.path.join(ABS_TESTDATA_PATH, args.new_file), os.path.join(ABS_TESTDATA_PATH, args.patch_file), - os.path.abspath(args.output_dir), + os.path.abspath(args.output_file), args.raw, platform.system() == 'Windows') diff --git a/fuzzers/testdata/new.ztxt b/fuzzers/testdata/new.ztf index 1b1876f..1b1876f 100644 --- a/fuzzers/testdata/new.ztxt +++ b/fuzzers/testdata/new.ztf diff --git a/fuzzers/testdata/old.ztxt b/fuzzers/testdata/old.ztf index 12dd536..12dd536 100644 --- a/fuzzers/testdata/old.ztxt +++ b/fuzzers/testdata/old.ztf |