Added automotiveCanV1.0_fuzzer
Test: adb shell /data/fuzz/${TARGET_ARCH}/automotiveCanV1.0_fuzzer/automotiveCanV1.0_fuzzer
Bug: 187130380
Change-Id: Iaadc96da6f6114512674d797e6cbc74b5405da14
diff --git a/automotive/can/1.0/default/Android.bp b/automotive/can/1.0/default/Android.bp
index c0c17e2..31eabf6 100644
--- a/automotive/can/1.0/default/Android.bp
+++ b/automotive/can/1.0/default/Android.bp
@@ -46,13 +46,7 @@
vendor: true,
relative_install_path: "hw",
srcs: [
- "CanBus.cpp",
- "CanBusNative.cpp",
- "CanBusVirtual.cpp",
- "CanBusSlcan.cpp",
- "CanController.cpp",
- "CanSocket.cpp",
- "CloseHandle.cpp",
+ ":automotiveCanV1.0_sources",
"service.cpp",
],
shared_libs: [
@@ -65,3 +59,22 @@
"libnl++",
],
}
+
+filegroup {
+ name: "automotiveCanV1.0_sources",
+ srcs: [
+ "CanBus.cpp",
+ "CanBusNative.cpp",
+ "CanBusVirtual.cpp",
+ "CanBusSlcan.cpp",
+ "CanController.cpp",
+ "CanSocket.cpp",
+ "CloseHandle.cpp",
+ ],
+}
+
+cc_library_headers {
+ name: "automotiveCanV1.0_headers",
+ vendor: true,
+ export_include_dirs: ["."],
+}
diff --git a/automotive/can/1.0/default/tests/fuzzer/Android.bp b/automotive/can/1.0/default/tests/fuzzer/Android.bp
new file mode 100644
index 0000000..6f19631
--- /dev/null
+++ b/automotive/can/1.0/default/tests/fuzzer/Android.bp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2022 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_fuzz {
+ name: "automotiveCanV1.0_fuzzer",
+ vendor: true,
+ defaults: ["android.hardware.automotive.can@defaults"],
+ srcs: [
+ "AutomotiveCanV1_0Fuzzer.cpp",
+ ":automotiveCanV1.0_sources",
+ ],
+ header_libs: [
+ "automotiveCanV1.0_headers",
+ "android.hardware.automotive.can@hidl-utils-lib",
+ ],
+ shared_libs: [
+ "android.hardware.automotive.can@1.0",
+ "libhidlbase",
+ ],
+ static_libs: [
+ "android.hardware.automotive.can@libnetdevice",
+ "android.hardware.automotive@libc++fs",
+ "libnl++",
+ ],
+ fuzz_config: {
+ cc: [
+ "android-media-fuzzing-reports@google.com",
+ ],
+ componentid: 533764,
+ },
+}
diff --git a/automotive/can/1.0/default/tests/fuzzer/AutomotiveCanV1_0Fuzzer.cpp b/automotive/can/1.0/default/tests/fuzzer/AutomotiveCanV1_0Fuzzer.cpp
new file mode 100644
index 0000000..96110db
--- /dev/null
+++ b/automotive/can/1.0/default/tests/fuzzer/AutomotiveCanV1_0Fuzzer.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2022 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 "AutomotiveCanV1_0Fuzzer.h"
+
+namespace android::hardware::automotive::can::V1_0::implementation::fuzzer {
+
+constexpr CanController::InterfaceType kInterfaceType[] = {CanController::InterfaceType::VIRTUAL,
+ CanController::InterfaceType::SOCKETCAN,
+ CanController::InterfaceType::SLCAN};
+constexpr FilterFlag kFilterFlag[] = {FilterFlag::DONT_CARE, FilterFlag::SET, FilterFlag::NOT_SET};
+constexpr size_t kInterfaceTypeLength = std::size(kInterfaceType);
+constexpr size_t kFilterFlagLength = std::size(kFilterFlag);
+constexpr size_t kMaxCharacters = 30;
+constexpr size_t kMaxPayloadBytes = 64;
+constexpr size_t kMaxFilters = 20;
+constexpr size_t kMaxSerialNumber = 1000;
+constexpr size_t kMaxBuses = 10;
+constexpr size_t kMaxRepeat = 5;
+
+Bus CanFuzzer::makeBus() {
+ ICanController::BusConfig config = {};
+ if (mBusNames.size() > 0 && mLastInterface < mBusNames.size()) {
+ config.name = mBusNames[mLastInterface++];
+ } else {
+ config.name = mFuzzedDataProvider->ConsumeRandomLengthString(kMaxCharacters);
+ }
+ config.interfaceId.virtualif({mFuzzedDataProvider->ConsumeRandomLengthString(kMaxCharacters)});
+ return Bus(mCanController, config);
+}
+
+void CanFuzzer::getSupportedInterfaceTypes() {
+ hidl_vec<CanController::InterfaceType> iftypesResult;
+ mCanController->getSupportedInterfaceTypes(hidl_utils::fill(&iftypesResult));
+}
+
+hidl_vec<hidl_string> CanFuzzer::getBusNames() {
+ hidl_vec<hidl_string> services = {};
+ if (auto manager = hidl::manager::V1_2::IServiceManager::getService(); manager) {
+ manager->listManifestByInterface(ICanBus::descriptor, hidl_utils::fill(&services));
+ }
+ return services;
+}
+
+void CanFuzzer::invokeUpInterface() {
+ const CanController::InterfaceType iftype =
+ kInterfaceType[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(
+ 0, kInterfaceTypeLength - 1)];
+ std::string configName;
+
+ if (const bool shouldInvokeValidBus = mFuzzedDataProvider->ConsumeBool();
+ (shouldInvokeValidBus) && (mBusNames.size() > 0)) {
+ const size_t busNameIndex =
+ mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, mBusNames.size() - 1);
+ configName = mBusNames[busNameIndex];
+ } else {
+ configName = mFuzzedDataProvider->ConsumeRandomLengthString(kMaxCharacters);
+ }
+ const std::string ifname = mFuzzedDataProvider->ConsumeRandomLengthString(kMaxCharacters);
+
+ ICanController::BusConfig config = {.name = configName};
+
+ if (iftype == CanController::InterfaceType::SOCKETCAN) {
+ CanController::BusConfig::InterfaceId::Socketcan socketcan = {};
+ if (const bool shouldPassSerialSocket = mFuzzedDataProvider->ConsumeBool();
+ shouldPassSerialSocket) {
+ socketcan.serialno(
+ {mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(0, kMaxSerialNumber)});
+ } else {
+ socketcan.ifname(ifname);
+ }
+ config.interfaceId.socketcan(socketcan);
+ } else if (iftype == CanController::InterfaceType::SLCAN) {
+ CanController::BusConfig::InterfaceId::Slcan slcan = {};
+ if (const bool shouldPassSerialSlcan = mFuzzedDataProvider->ConsumeBool();
+ shouldPassSerialSlcan) {
+ slcan.serialno(
+ {mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(0, kMaxSerialNumber)});
+ } else {
+ slcan.ttyname(ifname);
+ }
+ config.interfaceId.slcan(slcan);
+ } else if (iftype == CanController::InterfaceType::VIRTUAL) {
+ config.interfaceId.virtualif({ifname});
+ }
+
+ const size_t numInvocations =
+ mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kMaxRepeat);
+ for (size_t i = 0; i < numInvocations; ++i) {
+ mCanController->upInterface(config);
+ }
+}
+
+void CanFuzzer::invokeDownInterface() {
+ hidl_string configName;
+ if (const bool shouldInvokeValidBus = mFuzzedDataProvider->ConsumeBool();
+ (shouldInvokeValidBus) && (mBusNames.size() > 0)) {
+ const size_t busNameIndex =
+ mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, mBusNames.size() - 1);
+ configName = mBusNames[busNameIndex];
+ } else {
+ configName = mFuzzedDataProvider->ConsumeRandomLengthString(kMaxCharacters);
+ }
+
+ const size_t numInvocations =
+ mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(0, kMaxRepeat);
+ for (size_t i = 0; i < numInvocations; ++i) {
+ mCanController->downInterface(configName);
+ }
+}
+
+void CanFuzzer::invokeController() {
+ getSupportedInterfaceTypes();
+ invokeUpInterface();
+ invokeDownInterface();
+}
+
+void CanFuzzer::invokeBus() {
+ const size_t numBuses = mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(1, kMaxBuses);
+ for (size_t i = 0; i < numBuses; ++i) {
+ if (const bool shouldSendMessage = mFuzzedDataProvider->ConsumeBool(); shouldSendMessage) {
+ auto sendingBus = makeBus();
+ CanMessage msg = {.id = mFuzzedDataProvider->ConsumeIntegral<uint32_t>()};
+ uint32_t numPayloadBytes =
+ mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(0, kMaxPayloadBytes);
+ hidl_vec<uint8_t> payload(numPayloadBytes);
+ for (uint32_t j = 0; j < numPayloadBytes; ++j) {
+ payload[j] = mFuzzedDataProvider->ConsumeIntegral<uint32_t>();
+ }
+ msg.payload = payload;
+ msg.remoteTransmissionRequest = mFuzzedDataProvider->ConsumeBool();
+ msg.isExtendedId = mFuzzedDataProvider->ConsumeBool();
+ sendingBus.send(msg);
+ } else {
+ auto listeningBus = makeBus();
+ uint32_t numFilters =
+ mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(1, kMaxFilters);
+ hidl_vec<CanMessageFilter> filterVector(numFilters);
+ for (uint32_t k = 0; k < numFilters; ++k) {
+ filterVector[k].id = mFuzzedDataProvider->ConsumeIntegral<uint32_t>();
+ filterVector[k].mask = mFuzzedDataProvider->ConsumeIntegral<uint32_t>();
+ filterVector[k].rtr =
+ kFilterFlag[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(
+ 0, kFilterFlagLength - 1)];
+ filterVector[k].extendedFormat =
+ kFilterFlag[mFuzzedDataProvider->ConsumeIntegralInRange<size_t>(
+ 0, kFilterFlagLength - 1)];
+ filterVector[k].exclude = mFuzzedDataProvider->ConsumeBool();
+ }
+ auto listener = listeningBus.listen(filterVector);
+ }
+ }
+}
+
+void CanFuzzer::deInit() {
+ mCanController.clear();
+ if (mFuzzedDataProvider) {
+ delete mFuzzedDataProvider;
+ }
+ mBusNames = {};
+}
+
+void CanFuzzer::process(const uint8_t* data, size_t size) {
+ mFuzzedDataProvider = new FuzzedDataProvider(data, size);
+ invokeController();
+ invokeBus();
+}
+
+bool CanFuzzer::init() {
+ mCanController = sp<CanController>::make();
+ if (!mCanController) {
+ return false;
+ }
+ mBusNames = getBusNames();
+ return true;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ if (size < 1) {
+ return 0;
+ }
+ CanFuzzer canFuzzer;
+ if (canFuzzer.init()) {
+ canFuzzer.process(data, size);
+ }
+ return 0;
+}
+
+} // namespace android::hardware::automotive::can::V1_0::implementation::fuzzer
diff --git a/automotive/can/1.0/default/tests/fuzzer/AutomotiveCanV1_0Fuzzer.h b/automotive/can/1.0/default/tests/fuzzer/AutomotiveCanV1_0Fuzzer.h
new file mode 100644
index 0000000..930cddd
--- /dev/null
+++ b/automotive/can/1.0/default/tests/fuzzer/AutomotiveCanV1_0Fuzzer.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2022 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 __AUTOMOTIVE_CAN_V1_0_FUZZER_H__
+#define __AUTOMOTIVE_CAN_V1_0_FUZZER_H__
+#include <CanController.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <hidl-utils/hidl-utils.h>
+
+namespace android::hardware::automotive::can::V1_0::implementation::fuzzer {
+
+using ::android::sp;
+
+struct CanMessageListener : public can::V1_0::ICanMessageListener {
+ DISALLOW_COPY_AND_ASSIGN(CanMessageListener);
+
+ CanMessageListener() {}
+
+ virtual Return<void> onReceive(const can::V1_0::CanMessage& msg) override {
+ std::unique_lock<std::mutex> lock(mMessagesGuard);
+ mMessages.push_back(msg);
+ mMessagesUpdated.notify_one();
+ return {};
+ }
+
+ virtual ~CanMessageListener() {
+ if (mCloseHandle) {
+ mCloseHandle->close();
+ }
+ }
+
+ void assignCloseHandle(sp<ICloseHandle> closeHandle) { mCloseHandle = closeHandle; }
+
+ private:
+ sp<ICloseHandle> mCloseHandle;
+
+ std::mutex mMessagesGuard;
+ std::condition_variable mMessagesUpdated GUARDED_BY(mMessagesGuard);
+ std::vector<can::V1_0::CanMessage> mMessages GUARDED_BY(mMessagesGuard);
+};
+
+struct Bus {
+ DISALLOW_COPY_AND_ASSIGN(Bus);
+
+ Bus(sp<ICanController> controller, const ICanController::BusConfig& config)
+ : mIfname(config.name), mController(controller) {
+ const auto result = controller->upInterface(config);
+ const auto manager = hidl::manager::V1_2::IServiceManager::getService();
+ const auto service = manager->get(ICanBus::descriptor, config.name);
+ mBus = ICanBus::castFrom(service);
+ }
+
+ virtual ~Bus() { reset(); }
+
+ void reset() {
+ mBus.clear();
+ if (mController) {
+ mController->downInterface(mIfname);
+ mController.clear();
+ }
+ }
+
+ ICanBus* operator->() const { return mBus.get(); }
+ sp<ICanBus> get() { return mBus; }
+
+ sp<CanMessageListener> listen(const hidl_vec<CanMessageFilter>& filter) {
+ sp<CanMessageListener> listener = sp<CanMessageListener>::make();
+
+ if (!mBus) {
+ return listener;
+ }
+ Result result;
+ sp<ICloseHandle> closeHandle;
+ mBus->listen(filter, listener, hidl_utils::fill(&result, &closeHandle)).assertOk();
+ listener->assignCloseHandle(closeHandle);
+
+ return listener;
+ }
+
+ void send(const CanMessage& msg) {
+ if (!mBus) {
+ return;
+ }
+ mBus->send(msg);
+ }
+
+ private:
+ const std::string mIfname;
+ sp<ICanController> mController;
+ sp<ICanBus> mBus;
+};
+
+class CanFuzzer {
+ public:
+ ~CanFuzzer() { deInit(); }
+ bool init();
+ void process(const uint8_t* data, size_t size);
+ void deInit();
+
+ private:
+ Bus makeBus();
+ hidl_vec<hidl_string> getBusNames();
+ void getSupportedInterfaceTypes();
+ void invokeBus();
+ void invokeController();
+ void invokeUpInterface();
+ void invokeDownInterface();
+ FuzzedDataProvider* mFuzzedDataProvider = nullptr;
+ sp<CanController> mCanController = nullptr;
+ hidl_vec<hidl_string> mBusNames = {};
+ unsigned mLastInterface = 0;
+};
+} // namespace android::hardware::automotive::can::V1_0::implementation::fuzzer
+
+#endif // __AUTOMOTIVE_CAN_V1_0_FUZZER_H__