Added libHidlBase_parcel_fuzzer
Test: ./libHidlBase_parcel_fuzzer
exec/s: 1000
Bug: 193202093
Change-Id: I2e77ccc12afaaa76c45580676a6e916ea9924ebf
diff --git a/fuzzer/Android.bp b/fuzzer/Android.bp
new file mode 100644
index 0000000..5f95ce7
--- /dev/null
+++ b/fuzzer/Android.bp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+cc_defaults {
+ name: "libHidlBase_fuzzer_defaults",
+ host_supported: true,
+ static_libs: [
+ "libhidlbase",
+ "libbase",
+ "liblog",
+ "libcutils",
+ "libutils",
+ "libprocessgroup",
+ "libjsoncpp",
+ "libcgrouprc",
+ "libcgrouprc_format",
+ "libfmq",
+ ],
+ target: {
+ android: {
+ shared_libs: [
+ "libvndksupport",
+ ],
+ },
+ },
+ fuzz_config: {
+ cc: [
+ "android-media-fuzzing-reports@google.com",
+ ],
+ componentid: 155276,
+ hotlists: [
+ "4593311",
+ ],
+ description: "The fuzzers target the APIs of libhidlbase library",
+ vector: "local_no_privileges_required",
+ service_privilege: "privileged",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
+ },
+}
+
+cc_fuzz {
+ name: "libHidlBase_parcel_fuzzer",
+ srcs: ["libHidlBase_parcel_fuzzer.cpp",],
+ defaults: ["libHidlBase_fuzzer_defaults"],
+}
diff --git a/fuzzer/README.md b/fuzzer/README.md
new file mode 100644
index 0000000..709cc19
--- /dev/null
+++ b/fuzzer/README.md
@@ -0,0 +1,29 @@
+# Fuzzer for libhidlbase
+
+## Table of contents
++ [libHidlBase_parcel_fuzzer](#libHidlBaseParcel)
+
+# <a name="libHidlBaseParcel"></a> Fuzzer for libHidlBaseParcel
+
+libHidlBaseParcel supports the following parameters:
+
+1. ParentHandle (parameter name: "parentHandle")
+2. ParentOffset (parameter name: "parentOffset")
+3. HidlString (parameter name: "hidlString")
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+|`parentHandle`| `Integer` |Value obtained from FuzzedDataProvider|
+|`parentOffset`| `Integer` |Value obtained from FuzzedDataProvider|
+|`hidlString`| `Structure` |Value obtained from FuzzedDataProvider|
+
+#### Steps to run
+1. Build the fuzzer
+```
+ $ make libHidlBase_parcel_fuzzer
+```
+2. To run on device
+```
+ $ adb sync data
+ $ adb shell /data/fuzz/arm64/libHidlBase_parcel_fuzzer/libHidlBase_parcel_fuzzer
+```
diff --git a/fuzzer/libHidlBase_fuzzer_helper.h b/fuzzer/libHidlBase_fuzzer_helper.h
new file mode 100644
index 0000000..53726dc
--- /dev/null
+++ b/fuzzer/libHidlBase_fuzzer_helper.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2023 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.
+ *
+ */
+
+#ifndef _LIBHIDLBASE_FUZZER_HELPER_H
+#define _LIBHIDLBASE_FUZZER_HELPER_H
+
+#include <fuzzer/FuzzedDataProvider.h>
+#include <hidl/HidlBinderSupport.h>
+
+using namespace android;
+using namespace hardware;
+using namespace details;
+
+constexpr uint32_t kMaxBytes = 256;
+constexpr uint32_t kMin = 0;
+
+hidl_string createHidlString(FuzzedDataProvider& fdp) {
+ auto invokeHidlString = fdp.PickValueInArray<const std::function<hidl_string()>>({
+ [&]() { return hidl_string(fdp.ConsumeRandomLengthString(kMaxBytes)); },
+ [&]() { return hidl_string((fdp.ConsumeRandomLengthString(kMaxBytes)).c_str()); },
+ [&]() {
+ std::string testString = fdp.ConsumeRandomLengthString(kMaxBytes);
+ return hidl_string(testString.c_str(),
+ fdp.ConsumeIntegralInRange<uint32_t>(kMin, testString.length()));
+ },
+ [&]() { return fdp.ConsumeRandomLengthString(kMaxBytes); },
+ });
+ return invokeHidlString();
+}
+
+hidl_memory createHidlMemory(FuzzedDataProvider& fdp) {
+ if (fdp.ConsumeBool()) {
+ return hidl_memory();
+ }
+ return hidl_memory(createHidlString(fdp), hidl_handle(),
+ fdp.ConsumeIntegral<uint64_t>() /* size */);
+}
+
+Status createStatus(FuzzedDataProvider& fdp) {
+ auto invokeStatus = fdp.PickValueInArray<const std::function<Status()>>({
+ [&]() { return Status::fromExceptionCode(fdp.ConsumeIntegral<uint32_t>()); },
+ [&]() {
+ return Status::fromExceptionCode(
+ fdp.ConsumeIntegral<uint32_t>(),
+ (fdp.ConsumeRandomLengthString(kMaxBytes)).c_str());
+ },
+ [&]() { return Status::fromStatusT(fdp.ConsumeIntegral<uint32_t>()); },
+ [&]() { return Status(); },
+ });
+ return invokeStatus();
+}
+
+#endif // _LIBHIDLBASE_FUZZER_HELPER_H
diff --git a/fuzzer/libHidlBase_parcel_fuzzer.cpp b/fuzzer/libHidlBase_parcel_fuzzer.cpp
new file mode 100644
index 0000000..88c20c3
--- /dev/null
+++ b/fuzzer/libHidlBase_parcel_fuzzer.cpp
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2023 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 <hidl/HidlBinderSupport.h>
+#include <libHidlBase_fuzzer_helper.h>
+
+constexpr size_t kMinByte = 0;
+constexpr size_t kMaxByte = 256;
+constexpr uint32_t kNumFds = 0;
+constexpr uint32_t kNumInts = 1;
+constexpr uint32_t kMinSize = 1;
+constexpr uint32_t kMaxSize = 1000;
+constexpr uint32_t kMax = 1024;
+
+class HidlBaseParcelFuzzer {
+ public:
+ HidlBaseParcelFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){};
+ void process();
+
+ private:
+ void createRandomParcel(Parcel& parcel);
+
+ FuzzedDataProvider mFdp;
+};
+
+void HidlBaseParcelFuzzer::createRandomParcel(Parcel& parcel) {
+ uint32_t iterCount = mFdp.ConsumeIntegralInRange<uint32_t>(kMin, kMax);
+ for (uint32_t idx = 0; idx < iterCount; ++idx) {
+ auto invokeHidlBaseParcelWriteAPI = mFdp.PickValueInArray<const std::function<void()>>({
+ [&]() {
+ hidl_memory memory;
+ native_handle_t* testNativeHandle = nullptr;
+ if (mFdp.ConsumeBool()) {
+ memory = createHidlMemory(mFdp);
+ } else {
+ hidl_string hidlString = createHidlString(mFdp);
+ testNativeHandle = native_handle_create(
+ mFdp.ConsumeIntegralInRange<uint32_t>(kMin, NATIVE_HANDLE_MAX_FDS),
+ mFdp.ConsumeIntegralInRange<uint32_t>(kMin,
+ NATIVE_HANDLE_MAX_INTS));
+ memory = hidl_memory(hidlString, testNativeHandle,
+ mFdp.ConsumeIntegral<uint64_t>());
+ }
+ writeEmbeddedToParcel(
+ memory, &parcel,
+ mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize),
+ mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize));
+ native_handle_close(testNativeHandle);
+ native_handle_delete(testNativeHandle);
+ },
+ [&]() {
+ MQDescriptorSync<uint8_t> descriptorSync;
+ auto testHandle = native_handle_create(kNumFds, kNumInts);
+ uint32_t size = sizeof(uint8_t);
+ testHandle->data[0] = size;
+ uint32_t bufferSize = mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize);
+ if (mFdp.ConsumeBool()) {
+ std::vector<GrantorDescriptor> grantDescriptor(bufferSize);
+ for (size_t idx = 0; idx < bufferSize; ++idx) {
+ grantDescriptor[idx] = {mFdp.ConsumeIntegral<uint32_t>() /* flags */,
+ mFdp.ConsumeIntegral<uint32_t>() /* fdIndex */,
+ mFdp.ConsumeIntegral<uint32_t>() /* offset */,
+ mFdp.ConsumeIntegral<uint64_t>() /* extent */};
+ }
+ descriptorSync =
+ MQDescriptorSync<uint8_t>{grantDescriptor, testHandle, size};
+ } else {
+ descriptorSync = MQDescriptorSync<uint8_t>{bufferSize, testHandle, size,
+ mFdp.ConsumeBool()};
+ }
+ writeEmbeddedToParcel(
+ descriptorSync, &parcel,
+ mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize),
+ mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize));
+ },
+ [&]() {
+ native_handle_t* testNativeHandle = native_handle_create(
+ mFdp.ConsumeIntegralInRange<uint32_t>(kMin, NATIVE_HANDLE_MAX_FDS),
+ mFdp.ConsumeIntegralInRange<uint32_t>(kMin, NATIVE_HANDLE_MAX_INTS));
+ writeEmbeddedToParcel(
+ testNativeHandle, &parcel,
+ mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize),
+ mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize));
+ native_handle_close(testNativeHandle);
+ native_handle_delete(testNativeHandle);
+ },
+ [&]() {
+ Status status = createStatus(mFdp);
+ writeToParcel(status, &parcel);
+ },
+ [&]() {
+ auto parcelSize = mFdp.ConsumeIntegralInRange<size_t>(kMinByte, kMaxByte);
+ std::vector<uint8_t> data = mFdp.ConsumeBytes<uint8_t>(parcelSize);
+ parcel.write(data.data(), data.size());
+ },
+ });
+ invokeHidlBaseParcelWriteAPI();
+ }
+}
+
+void HidlBaseParcelFuzzer::process() {
+ Parcel parcel;
+ size_t originalPosition = parcel.dataPosition();
+ createRandomParcel(parcel);
+ parcel.setDataPosition(originalPosition);
+ while (mFdp.remaining_bytes()) {
+ auto invokeHidlBaseParcelAPI = mFdp.PickValueInArray<const std::function<void()>>({
+ [&]() {
+ hidl_memory memory = createHidlMemory(mFdp);
+ readEmbeddedFromParcel(
+ memory, parcel,
+ mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize),
+ mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize));
+ },
+ [&]() {
+ MQDescriptorSync<uint8_t> descriptorSync;
+ readEmbeddedFromParcel(
+ descriptorSync, parcel,
+ mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize),
+ mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize));
+ },
+ [&]() {
+ hidl_handle handle;
+ readEmbeddedFromParcel(
+ handle, parcel,
+ mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize),
+ mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize));
+ },
+ [&]() {
+ hidl_string hidlString = createHidlString(mFdp);
+ readEmbeddedFromParcel(
+ hidlString, parcel,
+ mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize),
+ mFdp.ConsumeIntegralInRange<uint32_t>(kMinSize, kMaxSize));
+ },
+ [&]() {
+ Status status = createStatus(mFdp);
+ readFromParcel(&status, parcel);
+ },
+ });
+ invokeHidlBaseParcelAPI();
+ }
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ HidlBaseParcelFuzzer hidlBaseParcelFuzzer(data, size);
+ hidlBaseParcelFuzzer.process();
+ return 0;
+}