update_engine: Add delta_performer_fuzzer
delta_performer operates on data it downloads from Omaha servers. Most
of the data is signed, but there are a few header bytes that are not
signed. It worth doing this fuzzer.
BUG=chromium:1014275
TEST=FEATURES=test USE="asan fuzzer" emerge-amd64-generic update_engine
Change-Id: I514bac5f8c4d28833cd01e1456481fb593c9f51a
Reviewed-on: https://chromium-review.googlesource.com/c/aosp/platform/system/update_engine/+/1860994
Reviewed-by: Manoj Gupta <[email protected]>
Tested-by: Amin Hassani <[email protected]>
diff --git a/BUILD.gn b/BUILD.gn
index 1e803a0..01207bd 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -50,7 +50,10 @@
}
if (use.fuzzer) {
- deps += [ ":update_engine_omaha_request_action_fuzzer" ]
+ deps += [
+ ":update_engine_delta_performer_fuzzer",
+ ":update_engine_omaha_request_action_fuzzer",
+ ]
}
}
@@ -553,6 +556,23 @@
# Fuzzer target.
if (use.fuzzer) {
+ executable("update_engine_delta_performer_fuzzer") {
+ sources = [
+ "payload_consumer/delta_performer_fuzzer.cc",
+ ]
+ configs += [
+ "//common-mk/common_fuzzer",
+ ":target_defaults",
+ ]
+ pkg_deps = [
+ "libbrillo-test-${libbase_ver}",
+ "libchrome-test-${libbase_ver}",
+ ]
+ deps = [
+ ":libupdate_engine",
+ ":update_engine_test_libs",
+ ]
+ }
executable("update_engine_omaha_request_action_fuzzer") {
sources = [
"omaha_request_action_fuzzer.cc",
diff --git a/payload_consumer/delta_performer_fuzzer.cc b/payload_consumer/delta_performer_fuzzer.cc
new file mode 100644
index 0000000..53b168a
--- /dev/null
+++ b/payload_consumer/delta_performer_fuzzer.cc
@@ -0,0 +1,103 @@
+//
+// Copyright 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <string>
+
+#include <base/logging.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+#include "update_engine/common/fake_boot_control.h"
+#include "update_engine/common/fake_hardware.h"
+#include "update_engine/common/prefs.h"
+#include "update_engine/payload_consumer/delta_performer.h"
+#include "update_engine/payload_consumer/download_action.h"
+#include "update_engine/payload_consumer/install_plan.h"
+
+namespace chromeos_update_engine {
+
+class FakeDownloadActionDelegate : public DownloadActionDelegate {
+ public:
+ FakeDownloadActionDelegate() = default;
+ ~FakeDownloadActionDelegate() = default;
+
+ // DownloadActionDelegate overrides;
+ void BytesReceived(uint64_t bytes_progressed,
+ uint64_t bytes_received,
+ uint64_t total) override{};
+
+ bool ShouldCancel(ErrorCode* cancel_reason) override { return false; };
+
+ void DownloadComplete() override{};
+
+ DISALLOW_COPY_AND_ASSIGN(FakeDownloadActionDelegate);
+};
+
+void FuzzDeltaPerformer(const uint8_t* data, size_t size) {
+ MemoryPrefs prefs;
+ FakeBootControl boot_control;
+ FakeHardware hardware;
+ FakeDownloadActionDelegate download_action_delegate;
+
+ FuzzedDataProvider data_provider(data, size);
+
+ InstallPlan install_plan{
+ .target_slot = 1,
+ .partitions = {InstallPlan::Partition{
+ .source_path = "/dev/zero",
+ .source_size = 4096,
+ .target_path = "/dev/null",
+ .target_size = 4096,
+ }},
+ };
+
+ InstallPlan::Payload payload{
+ .size = data_provider.ConsumeIntegralInRange<uint64_t>(0, 10000),
+ .metadata_size = data_provider.ConsumeIntegralInRange<uint64_t>(0, 1000),
+ .hash = data_provider.ConsumeBytes<uint8_t>(32),
+ .type = static_cast<InstallPayloadType>(
+ data_provider.ConsumeIntegralInRange(0, 3)),
+ .already_applied = data_provider.ConsumeBool(),
+ };
+
+ DeltaPerformer performer(&prefs,
+ &boot_control,
+ &hardware,
+ &download_action_delegate,
+ &install_plan,
+ &payload,
+ data_provider.ConsumeBool());
+ do {
+ auto chunk_size = data_provider.ConsumeIntegralInRange<size_t>(0, 100);
+ auto data = data_provider.ConsumeBytes<uint8_t>(chunk_size);
+ performer.Write(data.data(), data.size());
+ } while (data_provider.remaining_bytes() > 0);
+}
+
+} // namespace chromeos_update_engine
+
+class Environment {
+ public:
+ Environment() { logging::SetMinLogLevel(logging::LOG_FATAL); }
+};
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ if (size > 1000000) {
+ return 0;
+ }
+
+ static Environment env;
+ chromeos_update_engine::FuzzDeltaPerformer(data, size);
+ return 0;
+}