From 3921199e0580ca5039fdac05b085d557a1c4771a Mon Sep 17 00:00:00 2001 From: Ayushi Khopkar Date: Tue, 11 May 2021 10:11:25 +0530 Subject: [PATCH] Added automotiveCanV1.0_fuzzer Test: adb shell /data/fuzz/${TARGET_ARCH}/automotiveCanV1.0_fuzzer/automotiveCanV1.0_fuzzer Bug: 187130380 Change-Id: Iaadc96da6f6114512674d797e6cbc74b5405da14 --- automotive/can/1.0/default/Android.bp | 27 ++- .../can/1.0/default/tests/fuzzer/Android.bp | 45 ++++ .../tests/fuzzer/AutomotiveCanV1_0Fuzzer.cpp | 202 ++++++++++++++++++ .../tests/fuzzer/AutomotiveCanV1_0Fuzzer.h | 129 +++++++++++ 4 files changed, 396 insertions(+), 7 deletions(-) create mode 100644 automotive/can/1.0/default/tests/fuzzer/Android.bp create mode 100644 automotive/can/1.0/default/tests/fuzzer/AutomotiveCanV1_0Fuzzer.cpp create mode 100644 automotive/can/1.0/default/tests/fuzzer/AutomotiveCanV1_0Fuzzer.h diff --git a/automotive/can/1.0/default/Android.bp b/automotive/can/1.0/default/Android.bp index c0c17e27f5..31eabf6ce8 100644 --- a/automotive/can/1.0/default/Android.bp +++ b/automotive/can/1.0/default/Android.bp @@ -46,13 +46,7 @@ cc_binary { 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 @@ cc_binary { "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 0000000000..6f196316d2 --- /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 0000000000..96110dbe40 --- /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 iftypesResult; + mCanController->getSupportedInterfaceTypes(hidl_utils::fill(&iftypesResult)); +} + +hidl_vec CanFuzzer::getBusNames() { + hidl_vec 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( + 0, kInterfaceTypeLength - 1)]; + std::string configName; + + if (const bool shouldInvokeValidBus = mFuzzedDataProvider->ConsumeBool(); + (shouldInvokeValidBus) && (mBusNames.size() > 0)) { + const size_t busNameIndex = + mFuzzedDataProvider->ConsumeIntegralInRange(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(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(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(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(0, mBusNames.size() - 1); + configName = mBusNames[busNameIndex]; + } else { + configName = mFuzzedDataProvider->ConsumeRandomLengthString(kMaxCharacters); + } + + const size_t numInvocations = + mFuzzedDataProvider->ConsumeIntegralInRange(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(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 numPayloadBytes = + mFuzzedDataProvider->ConsumeIntegralInRange(0, kMaxPayloadBytes); + hidl_vec payload(numPayloadBytes); + for (uint32_t j = 0; j < numPayloadBytes; ++j) { + payload[j] = mFuzzedDataProvider->ConsumeIntegral(); + } + msg.payload = payload; + msg.remoteTransmissionRequest = mFuzzedDataProvider->ConsumeBool(); + msg.isExtendedId = mFuzzedDataProvider->ConsumeBool(); + sendingBus.send(msg); + } else { + auto listeningBus = makeBus(); + uint32_t numFilters = + mFuzzedDataProvider->ConsumeIntegralInRange(1, kMaxFilters); + hidl_vec filterVector(numFilters); + for (uint32_t k = 0; k < numFilters; ++k) { + filterVector[k].id = mFuzzedDataProvider->ConsumeIntegral(); + filterVector[k].mask = mFuzzedDataProvider->ConsumeIntegral(); + filterVector[k].rtr = + kFilterFlag[mFuzzedDataProvider->ConsumeIntegralInRange( + 0, kFilterFlagLength - 1)]; + filterVector[k].extendedFormat = + kFilterFlag[mFuzzedDataProvider->ConsumeIntegralInRange( + 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::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 0000000000..930cddd89b --- /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 +#include +#include +#include + +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 onReceive(const can::V1_0::CanMessage& msg) override { + std::unique_lock lock(mMessagesGuard); + mMessages.push_back(msg); + mMessagesUpdated.notify_one(); + return {}; + } + + virtual ~CanMessageListener() { + if (mCloseHandle) { + mCloseHandle->close(); + } + } + + void assignCloseHandle(sp closeHandle) { mCloseHandle = closeHandle; } + + private: + sp mCloseHandle; + + std::mutex mMessagesGuard; + std::condition_variable mMessagesUpdated GUARDED_BY(mMessagesGuard); + std::vector mMessages GUARDED_BY(mMessagesGuard); +}; + +struct Bus { + DISALLOW_COPY_AND_ASSIGN(Bus); + + Bus(sp 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 get() { return mBus; } + + sp listen(const hidl_vec& filter) { + sp listener = sp::make(); + + if (!mBus) { + return listener; + } + Result result; + sp 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 mController; + sp mBus; +}; + +class CanFuzzer { + public: + ~CanFuzzer() { deInit(); } + bool init(); + void process(const uint8_t* data, size_t size); + void deInit(); + + private: + Bus makeBus(); + hidl_vec getBusNames(); + void getSupportedInterfaceTypes(); + void invokeBus(); + void invokeController(); + void invokeUpInterface(); + void invokeDownInterface(); + FuzzedDataProvider* mFuzzedDataProvider = nullptr; + sp mCanController = nullptr; + hidl_vec mBusNames = {}; + unsigned mLastInterface = 0; +}; +} // namespace android::hardware::automotive::can::V1_0::implementation::fuzzer + +#endif // __AUTOMOTIVE_CAN_V1_0_FUZZER_H__