Merge "Added automotiveCanV1.0_fuzzer" am: 20b69d76d0
Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/1991533 Change-Id: Iccc4e6a9349cc2fc865dfdbd608462673318e964
This commit is contained in:
commit
96c8da665f
4 changed files with 396 additions and 7 deletions
|
@ -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: [
|
||||
|
@ -66,3 +60,22 @@ cc_binary {
|
|||
],
|
||||
vintf_fragments: ["manifest_android.hardware.automotive.can@1.0.xml"],
|
||||
}
|
||||
|
||||
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: ["."],
|
||||
}
|
||||
|
|
45
automotive/can/1.0/default/tests/fuzzer/Android.bp
Normal file
45
automotive/can/1.0/default/tests/fuzzer/Android.bp
Normal file
|
@ -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,
|
||||
},
|
||||
}
|
|
@ -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
|
|
@ -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__
|
Loading…
Reference in a new issue