diff options
author | Kris Alder <kalder@google.com> | 2021-02-26 18:17:05 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2021-02-26 18:17:05 +0000 |
commit | fde1ef47a862f7302502568aeb48948cbdb0f85b (patch) | |
tree | 325b1176425577aea0237e8b75f9725a9aee0eea /automotive | |
parent | 338b7bb29590c2f9ecd3c20cee2f4511ffd3763e (diff) | |
parent | e33bc952cfb36dce2fd08b94c94ffe8c95bdc1ab (diff) | |
download | platform_hardware_interfaces-fde1ef47a862f7302502568aeb48948cbdb0f85b.tar.gz platform_hardware_interfaces-fde1ef47a862f7302502568aeb48948cbdb0f85b.tar.bz2 platform_hardware_interfaces-fde1ef47a862f7302502568aeb48948cbdb0f85b.zip |
Merge "Added vehicleManager_fuzzer" am: e33bc952cf
Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/1510958
MUST ONLY BE SUBMITTED BY AUTOMERGER
Change-Id: I21b3033079689c95a0ac26f0ee00bdcda0f8888c
Diffstat (limited to 'automotive')
4 files changed, 649 insertions, 0 deletions
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp index f4d8e89fca..f24b1f5474 100644 --- a/automotive/vehicle/2.0/default/Android.bp +++ b/automotive/vehicle/2.0/default/Android.bp @@ -221,3 +221,29 @@ cc_binary { "android.hardware.automotive.vehicle@2.0-libproto-native", ], } + +cc_fuzz { + name: "vehicleManager_fuzzer", + vendor: true, + defaults: ["vhal_v2_0_target_defaults"], + whole_static_libs: ["android.hardware.automotive.vehicle@2.0-manager-lib"], + srcs: [ + "tests/fuzzer/VehicleManager_fuzzer.cpp", + ], + shared_libs: [ + "libbase", + "libcutils", + "libbinder_ndk", + ], + header_libs: ["libbase_headers"], + local_include_dirs: [ + "common/include", + "tests", + ], + fuzz_config: { + cc: [ + "android-media-fuzzing-reports@google.com", + ], + componentid: 533764, + }, +} diff --git a/automotive/vehicle/2.0/default/tests/fuzzer/README.md b/automotive/vehicle/2.0/default/tests/fuzzer/README.md new file mode 100644 index 0000000000..3fa0d3f845 --- /dev/null +++ b/automotive/vehicle/2.0/default/tests/fuzzer/README.md @@ -0,0 +1,66 @@ +# Fuzzer for android.hardware.automotive.vehicle@2.0-manager-lib + +## Plugin Design Considerations +The fuzzer plugin for android.hardware.automotive.vehicle@2.0-manager-lib is +designed based on the understanding of the library and tries to achieve the following: + +##### Maximize code coverage +The configuration parameters are not hardcoded, but instead selected based on +incoming data. This ensures more code paths are reached by the fuzzer. + +Vehicle Manager supports the following parameters: +1. Vehicle Property (parameter name: `vehicleProp`) +2. Diagnostic Integer Sensor Index (parameter name: `diagnosticIntIndex`) +3. Diagnostic Float Sensor Index (parameter name: `diagnosticFloatIndex`) +4. Availability Message Type (parameter name: `availabilityMsgType`) +5. Subscription Message Type (parameter name: `subscriptionMsgType`) + +| Parameter| Valid Values| Configured Value| +|------------- |-------------| ----- | +| `vehicleProp` | 0.`VehicleProperty::INVALID` 1.`VehicleProperty::HVAC_FAN_SPEED` 2.`VehicleProperty::INFO_MAKE` 3.`VehicleProperty::DISPLAY_BRIGHTNESS` 4.`VehicleProperty::INFO_FUEL_CAPACITY` 5.`VehicleProperty::HVAC_SEAT_TEMPERATURE`| Value obtained from FuzzedDataProvider | +| `diagnosticIntIndex` | 0.`DiagnosticIntegerSensorIndex::FUEL_SYSTEM_STATUS` 1.`DiagnosticIntegerSensorIndex::MALFUNCTION_INDICATOR_LIGHT_ON` 2.`DiagnosticIntegerSensorIndex::NUM_OXYGEN_SENSORS_PRESENT` 3.`DiagnosticIntegerSensorIndex::FUEL_TYPE` | Value obtained from FuzzedDataProvider | +| `diagnosticFloatIndex` | 0.`DiagnosticFloatSensorIndex::CALCULATED_ENGINE_LOAD` 1.`DiagnosticFloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK1` 2.`DiagnosticFloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK1` 3.`DiagnosticFloatSensorIndex::THROTTLE_POSITION` | Value obtained from FuzzedDataProvider | +| `availabilityMsgType` | 0.`VmsMessageType::AVAILABILITY_CHANGE` 1.`VmsMessageType::AVAILABILITY_RESPONSE` | Value obtained from FuzzedDataProvider | +| `subscriptionMsgType` | 0.`VmsMessageType::SUBSCRIPTIONS_CHANGE` 1.`VmsMessageType::SUBSCRIPTIONS_RESPONSE` | Value obtained from FuzzedDataProvider | + +This also ensures that the plugin is always deterministic for any given input. + +## Build + +This describes steps to build vehicleManager_fuzzer binary. + +### Android + +#### Steps to build +Build the fuzzer +``` + $ mm -j$(nproc) vehicleManager_fuzzer +``` + +#### Steps to run +Create a directory CORPUS_DIR +``` + $ adb shell mkdir /data/local/tmp/CORPUS_DIR +``` + +##### Some Additional steps needed to run the vehicleManager_fuzzer successfully on device + +1. Push the following libraries from /vendor/lib/ and /vendor/lib64/ folders of your workspace to the device's /vendor/lib/ and /vendor/lib64/ : +``` +1.1 android.hardware.automotive.vehicle@2.0.so +1.2 carwatchdog_aidl_interface-V2-ndk_platform.so +``` +2. Now, reboot the device using command +``` + $ adb reboot +``` + +##### To run the fuzzer on device +``` + $ adb sync data + $ adb shell LD_LIBRARY_PATH=/vendor/lib64 /data/fuzz/${TARGET_ARCH}/vehicleManager_fuzzer/vendor/vehicleManager_fuzzer /data/local/tmp/CORPUS_DIR +``` + +## References: + * http://llvm.org/docs/LibFuzzer.html + * https://github.com/google/oss-fuzz diff --git a/automotive/vehicle/2.0/default/tests/fuzzer/VehicleManager_fuzzer.cpp b/automotive/vehicle/2.0/default/tests/fuzzer/VehicleManager_fuzzer.cpp new file mode 100644 index 0000000000..796c08f2f2 --- /dev/null +++ b/automotive/vehicle/2.0/default/tests/fuzzer/VehicleManager_fuzzer.cpp @@ -0,0 +1,433 @@ +/****************************************************************************** + * + * Copyright (C) 2021 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. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore + */ + +#include "VehicleManager_fuzzer.h" +#include <utils/SystemClock.h> +#include <vhal_v2_0/Obd2SensorStore.h> +#include <vhal_v2_0/WatchdogClient.h> + +namespace android::hardware::automotive::vehicle::V2_0::fuzzer { + +using ::aidl::android::automotive::watchdog::TimeoutLength; +using ::android::elapsedRealtimeNano; +using ::android::Looper; +using ::android::sp; +using ::android::hardware::hidl_handle; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::automotive::vehicle::V2_0::DiagnosticFloatSensorIndex; +using ::android::hardware::automotive::vehicle::V2_0::DiagnosticIntegerSensorIndex; +using ::android::hardware::automotive::vehicle::V2_0::kCustomComplexProperty; +using ::android::hardware::automotive::vehicle::V2_0::kVehicleProperties; +using ::android::hardware::automotive::vehicle::V2_0::MockedVehicleCallback; +using ::android::hardware::automotive::vehicle::V2_0::Obd2SensorStore; +using ::android::hardware::automotive::vehicle::V2_0::recyclable_ptr; +using ::android::hardware::automotive::vehicle::V2_0::StatusCode; +using ::android::hardware::automotive::vehicle::V2_0::SubscribeFlags; +using ::android::hardware::automotive::vehicle::V2_0::SubscribeOptions; +using ::android::hardware::automotive::vehicle::V2_0::VehicleAreaConfig; +using ::android::hardware::automotive::vehicle::V2_0::VehicleHal; +using ::android::hardware::automotive::vehicle::V2_0::VehicleHalManager; +using ::android::hardware::automotive::vehicle::V2_0::VehiclePropConfig; +using ::android::hardware::automotive::vehicle::V2_0::VehicleProperty; +using ::android::hardware::automotive::vehicle::V2_0::VehiclePropertyAccess; +using ::android::hardware::automotive::vehicle::V2_0::VehiclePropertyChangeMode; +using ::android::hardware::automotive::vehicle::V2_0::VehiclePropertyStore; +using ::android::hardware::automotive::vehicle::V2_0::VehiclePropertyType; +using ::android::hardware::automotive::vehicle::V2_0::VehiclePropValue; +using ::android::hardware::automotive::vehicle::V2_0::VehiclePropValuePool; +using ::android::hardware::automotive::vehicle::V2_0::VmsMessageType; +using ::android::hardware::automotive::vehicle::V2_0::WatchdogClient; +using ::android::hardware::automotive::vehicle::V2_0::vms::createAvailabilityRequest; +using ::android::hardware::automotive::vehicle::V2_0::vms::createBaseVmsMessage; +using ::android::hardware::automotive::vehicle::V2_0::vms::createPublisherIdRequest; +using ::android::hardware::automotive::vehicle::V2_0::vms::createStartSessionMessage; +using ::android::hardware::automotive::vehicle::V2_0::vms::createSubscriptionsRequest; +using ::android::hardware::automotive::vehicle::V2_0::vms::getAvailableLayers; +using ::android::hardware::automotive::vehicle::V2_0::vms::getSequenceNumberForAvailabilityState; +using ::android::hardware::automotive::vehicle::V2_0::vms::getSequenceNumberForSubscriptionsState; +using ::android::hardware::automotive::vehicle::V2_0::vms::hasServiceNewlyStarted; +using ::android::hardware::automotive::vehicle::V2_0::vms::isAvailabilitySequenceNumberNewer; +using ::android::hardware::automotive::vehicle::V2_0::vms::isSequenceNumberNewer; +using ::android::hardware::automotive::vehicle::V2_0::vms::isValidVmsMessage; +using ::android::hardware::automotive::vehicle::V2_0::vms::parseData; +using ::android::hardware::automotive::vehicle::V2_0::vms::parseMessageType; +using ::android::hardware::automotive::vehicle::V2_0::vms::parsePublisherIdResponse; +using ::android::hardware::automotive::vehicle::V2_0::vms::parseStartSessionMessage; +using ::android::hardware::automotive::vehicle::V2_0::vms::VmsLayer; +using ::android::hardware::automotive::vehicle::V2_0::vms::VmsLayerAndPublisher; +using ::android::hardware::automotive::vehicle::V2_0::vms::VmsLayerOffering; +using ::android::hardware::automotive::vehicle::V2_0::vms::VmsOffers; + +constexpr const char kCarMake[] = "Default Car"; +constexpr VehicleProperty kVehicleProp[] = {VehicleProperty::INVALID, + VehicleProperty::HVAC_FAN_SPEED, + VehicleProperty::INFO_MAKE, + VehicleProperty::DISPLAY_BRIGHTNESS, + VehicleProperty::INFO_FUEL_CAPACITY, + VehicleProperty::HVAC_SEAT_TEMPERATURE}; +constexpr DiagnosticIntegerSensorIndex kDiagnosticIntIndex[] = { + DiagnosticIntegerSensorIndex::FUEL_SYSTEM_STATUS, + DiagnosticIntegerSensorIndex::MALFUNCTION_INDICATOR_LIGHT_ON, + DiagnosticIntegerSensorIndex::NUM_OXYGEN_SENSORS_PRESENT, + DiagnosticIntegerSensorIndex::FUEL_TYPE}; +constexpr DiagnosticFloatSensorIndex kDiagnosticFloatIndex[] = { + DiagnosticFloatSensorIndex::CALCULATED_ENGINE_LOAD, + DiagnosticFloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK1, + DiagnosticFloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK1, + DiagnosticFloatSensorIndex::THROTTLE_POSITION}; +constexpr size_t kVehiclePropArrayLength = std::size(kVehicleProp); +constexpr size_t kIntSensorArrayLength = std::size(kDiagnosticIntIndex); +constexpr size_t kFloatSensorArrayLength = std::size(kDiagnosticFloatIndex); +constexpr VmsMessageType kAvailabilityMessageType[] = {VmsMessageType::AVAILABILITY_CHANGE, + VmsMessageType::AVAILABILITY_RESPONSE}; +constexpr VmsMessageType kSubscriptionMessageType[] = {VmsMessageType::SUBSCRIPTIONS_CHANGE, + VmsMessageType::SUBSCRIPTIONS_RESPONSE}; + +MockedVehicleHal::VehiclePropValuePtr MockedVehicleHal::get( + const VehiclePropValue& requestedPropValue, StatusCode* outStatus) { + VehiclePropValuePtr pValue = nullptr; + if (outStatus == nullptr) { + return pValue; + } + auto property = static_cast<VehicleProperty>(requestedPropValue.prop); + int32_t areaId = requestedPropValue.areaId; + *outStatus = StatusCode::OK; + + switch (property) { + case VehicleProperty::INFO_MAKE: + pValue = getValuePool()->obtainString(kCarMake); + break; + case VehicleProperty::INFO_FUEL_CAPACITY: + if (mFuelCapacityAttemptsLeft-- > 0) { + *outStatus = StatusCode::TRY_AGAIN; + } else { + pValue = getValuePool()->obtainFloat(42.42); + } + break; + default: + if (requestedPropValue.prop == kCustomComplexProperty) { + pValue = getValuePool()->obtainComplex(); + pValue->value.int32Values = hidl_vec<int32_t>{10, 20}; + pValue->value.int64Values = hidl_vec<int64_t>{30, 40}; + pValue->value.floatValues = hidl_vec<float_t>{1.1, 2.2}; + pValue->value.bytes = hidl_vec<uint8_t>{1, 2, 3}; + pValue->value.stringValue = kCarMake; + break; + } + auto key = makeKey(toInt(property), areaId); + pValue = getValuePool()->obtain(mValues[key]); + } + + if (*outStatus == StatusCode::OK && pValue.get() != nullptr) { + pValue->prop = toInt(property); + pValue->areaId = areaId; + pValue->timestamp = elapsedRealtimeNano(); + } + + return pValue; +} + +void VehicleHalManagerFuzzer::process(const uint8_t* data, size_t size) { + mFuzzedDataProvider = new FuzzedDataProvider(data, size); + invokeDebug(); + invokePropConfigs(); + invokeSubscribe(); + invokeSetAndGetValues(); + invokeObd2SensorStore(); + invokeVmsUtils(); + invokeVehiclePropStore(); + invokeWatchDogClient(); +} + +void VehicleHalManagerFuzzer::invokeDebug() { + hidl_string debugOption = mFuzzedDataProvider->PickValueInArray( + {"--help", "--list", "--get", "--set", "", "invalid"}); + hidl_handle fd = {}; + fd.setTo(native_handle_create(/*numFds=*/1, /*numInts=*/0), /*shouldOwn=*/true); + + mManager->debug(fd, {}); + mManager->debug(fd, {debugOption}); +} + +void VehicleHalManagerFuzzer::invokePropConfigs() { + int32_t vehicleProp1 = mFuzzedDataProvider->ConsumeIntegral<int32_t>(); + int32_t vehicleProp2 = mFuzzedDataProvider->ConsumeIntegral<int32_t>(); + + hidl_vec<int32_t> properties = {vehicleProp1, vehicleProp2}; + + mManager->getPropConfigs(properties, + []([[maybe_unused]] StatusCode status, + [[maybe_unused]] const hidl_vec<VehiclePropConfig>& c) {}); + + mManager->getPropConfigs({toInt(kVehicleProp[abs(vehicleProp1) % kVehiclePropArrayLength])}, + []([[maybe_unused]] StatusCode status, + [[maybe_unused]] const hidl_vec<VehiclePropConfig>& c) {}); + + mManager->getAllPropConfigs( + []([[maybe_unused]] const hidl_vec<VehiclePropConfig>& propConfigs) {}); +} + +void VehicleHalManagerFuzzer::invokeSubscribe() { + int32_t vehicleProp1 = mFuzzedDataProvider->ConsumeIntegral<int32_t>(); + int32_t vehicleProp2 = mFuzzedDataProvider->ConsumeIntegral<int32_t>(); + int32_t vehicleProp3 = mFuzzedDataProvider->ConsumeIntegral<int32_t>(); + + const auto prop1 = toInt(kVehicleProp[abs(vehicleProp1) % kVehiclePropArrayLength]); + sp<MockedVehicleCallback> cb = new MockedVehicleCallback(); + + hidl_vec<SubscribeOptions> options = { + SubscribeOptions{.propId = prop1, .flags = SubscribeFlags::EVENTS_FROM_CAR}}; + + mManager->subscribe(cb, options); + + auto unsubscribedValue = mObjectPool->obtain(VehiclePropertyType::INT32); + unsubscribedValue->prop = toInt(kVehicleProp[abs(vehicleProp2) % kVehiclePropArrayLength]); + + mHal->sendPropEvent(std::move(unsubscribedValue)); + cb->getReceivedEvents(); + cb->waitForExpectedEvents(0); + + auto subscribedValue = mObjectPool->obtain(VehiclePropertyType::INT32); + subscribedValue->prop = toInt(kVehicleProp[abs(vehicleProp2) % kVehiclePropArrayLength]); + subscribedValue->value.int32Values[0] = INT32_MAX; + + cb->reset(); + VehiclePropValue actualValue(*subscribedValue.get()); + mHal->sendPropEvent(std::move(subscribedValue)); + cb->waitForExpectedEvents(1); + mManager->unsubscribe(cb, prop1); + + sp<MockedVehicleCallback> cb2 = new MockedVehicleCallback(); + + hidl_vec<SubscribeOptions> options2 = { + SubscribeOptions{ + .propId = toInt(kVehicleProp[abs(vehicleProp3) % kVehiclePropArrayLength]), + .flags = SubscribeFlags::EVENTS_FROM_CAR}, + }; + + mManager->subscribe(cb2, options2); + + mHal->sendHalError(StatusCode::TRY_AGAIN, + toInt(kVehicleProp[abs(vehicleProp3) % kVehiclePropArrayLength]), + /*areaId=*/0); +} + +void VehicleHalManagerFuzzer::invokeSetAndGetValues() { + uint32_t vehicleProp1 = + mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(0, kVehiclePropArrayLength - 1); + uint32_t vehicleProp2 = + mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(0, kVehiclePropArrayLength - 1); + uint32_t vehicleProp3 = + mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(0, kVehiclePropArrayLength - 1); + + invokeGet(kCustomComplexProperty, 0); + invokeGet(toInt(kVehicleProp[vehicleProp2]), 0); + invokeGet(toInt(kVehicleProp[vehicleProp1]), 0); + + auto expectedValue = mObjectPool->obtainInt32(mFuzzedDataProvider->ConsumeIntegral<int32_t>()); + mObjectPool->obtainInt64(mFuzzedDataProvider->ConsumeIntegral<int64_t>()); + mObjectPool->obtainFloat(mFuzzedDataProvider->ConsumeFloatingPoint<float>()); + mObjectPool->obtainBoolean(mFuzzedDataProvider->ConsumeBool()); + expectedValue->prop = toInt(kVehicleProp[vehicleProp2]); + expectedValue->areaId = 0; + + mManager->set(*expectedValue.get()); + invokeGet(toInt(kVehicleProp[vehicleProp2]), 0); + expectedValue->prop = toInt(kVehicleProp[vehicleProp3]); + mManager->set(*expectedValue.get()); + expectedValue->prop = toInt(VehicleProperty::INVALID); + mManager->set(*expectedValue.get()); +} + +void VehicleHalManagerFuzzer::invokeObd2SensorStore() { + uint32_t diagnosticIntIndex = + mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(0, kIntSensorArrayLength - 1); + int32_t diagnosticIntValue = mFuzzedDataProvider->ConsumeIntegral<int32_t>(); + uint32_t diagnosticFloatIndex = + mFuzzedDataProvider->ConsumeIntegralInRange<uint32_t>(0, kFloatSensorArrayLength - 1); + float diagnosticFloatValue = mFuzzedDataProvider->ConsumeFloatingPoint<float>(); + + std::unique_ptr<Obd2SensorStore> sensorStore( + new Obd2SensorStore(kIntSensorArrayLength, kFloatSensorArrayLength)); + if (sensorStore) { + sensorStore->setIntegerSensor(kDiagnosticIntIndex[diagnosticIntIndex], diagnosticIntValue); + sensorStore->setFloatSensor(kDiagnosticFloatIndex[diagnosticFloatIndex], + diagnosticFloatValue); + sensorStore->getIntegerSensors(); + sensorStore->getFloatSensors(); + sensorStore->getSensorsBitmask(); + static std::vector<std::string> sampleDtcs = {"P0070", + "P0102" + "P0123"}; + for (auto&& dtc : sampleDtcs) { + auto freezeFrame = createVehiclePropValue(VehiclePropertyType::MIXED, 0); + sensorStore->fillPropValue(dtc, freezeFrame.get()); + freezeFrame->prop = static_cast<int>(VehicleProperty::OBD2_FREEZE_FRAME); + } + } +} + +void VehicleHalManagerFuzzer::invokeVmsUtils() { + bool availabilityMsgType = mFuzzedDataProvider->ConsumeBool(); + bool subscriptionMsgType = mFuzzedDataProvider->ConsumeBool(); + int32_t intValue = mFuzzedDataProvider->ConsumeIntegral<int32_t>(); + + VmsLayer layer(1, 0, 2); + auto message = createSubscribeMessage(layer); + isValidVmsMessage(*message); + message = createUnsubscribeMessage(layer); + + VmsOffers offers = {intValue, {VmsLayerOffering(VmsLayer(1, 0, 2))}}; + message = createOfferingMessage(offers); + std::vector<VmsLayer> dependencies = {VmsLayer(2, 0, 2), VmsLayer(3, 0, 3)}; + std::vector<VmsLayerOffering> offering = {VmsLayerOffering(layer, dependencies)}; + offers = {intValue, offering}; + message = createOfferingMessage(offers); + + message = createAvailabilityRequest(); + message = createSubscriptionsRequest(); + + std::string bytes = "placeholder"; + const VmsLayerAndPublisher layer_and_publisher(VmsLayer(2, 0, 1), intValue); + message = createDataMessageWithLayerPublisherInfo(layer_and_publisher, bytes); + parseData(*message); + createSubscribeToPublisherMessage(layer_and_publisher); + createUnsubscribeToPublisherMessage(layer_and_publisher); + + std::string pub_bytes = "pub_id"; + message = createPublisherIdRequest(pub_bytes); + message = createBaseVmsMessage(2); + message->value.int32Values = + hidl_vec<int32_t>{toInt(VmsMessageType::PUBLISHER_ID_RESPONSE), intValue}; + parsePublisherIdResponse(*message); + + message->value.int32Values = + hidl_vec<int32_t>{toInt(kSubscriptionMessageType[subscriptionMsgType]), intValue}; + getSequenceNumberForSubscriptionsState(*message); + + message->value.int32Values = hidl_vec<int32_t>{toInt(kSubscriptionMessageType[0]), intValue}; + isSequenceNumberNewer(*message, intValue + 1); + invokeGetSubscribedLayers(kSubscriptionMessageType[subscriptionMsgType]); + + message->value.int32Values = + hidl_vec<int32_t>{toInt(kAvailabilityMessageType[availabilityMsgType]), 0}; + hasServiceNewlyStarted(*message); + message = createStartSessionMessage(intValue, intValue + 1); + parseMessageType(*message); + + message->value.int32Values = + hidl_vec<int32_t>{toInt(kAvailabilityMessageType[availabilityMsgType]), intValue}; + isAvailabilitySequenceNumberNewer(*message, intValue + 1); + + message->value.int32Values = + hidl_vec<int32_t>{toInt(kAvailabilityMessageType[availabilityMsgType]), intValue}; + getSequenceNumberForAvailabilityState(*message); + message = createBaseVmsMessage(3); + int new_service_id; + message->value.int32Values = hidl_vec<int32_t>{toInt(VmsMessageType::START_SESSION), 0, -1}; + parseStartSessionMessage(*message, -1, 0, &new_service_id); +} + +void VehicleHalManagerFuzzer::invokeGet(int32_t property, int32_t areaId) { + VehiclePropValue requestedValue{}; + requestedValue.prop = property; + requestedValue.areaId = areaId; + mActualValue = VehiclePropValue{}; // reset previous values + + StatusCode refStatus; + VehiclePropValue refValue; + mManager->get(requestedValue, + [&refStatus, &refValue](StatusCode status, const VehiclePropValue& value) { + refStatus = status; + refValue = value; + }); + + mActualValue = refValue; + mActualStatusCode = refStatus; +} + +void VehicleHalManagerFuzzer::invokeGetSubscribedLayers(VmsMessageType type) { + VmsOffers offers = {123, + {VmsLayerOffering(VmsLayer(1, 0, 1), {VmsLayer(4, 1, 1)}), + VmsLayerOffering(VmsLayer(2, 0, 1))}}; + auto message = createBaseVmsMessage(16); + message->value.int32Values = hidl_vec<int32_t>{toInt(type), + 1234, // sequence number + 2, // number of layers + 1, // number of associated layers + 1, // layer 1 + 0, 1, + 4, // layer 2 + 1, 1, + 2, // associated layer + 0, 1, + 2, // number of publisher IDs + 111, // publisher IDs + 123}; + isValidVmsMessage(*message); + getSubscribedLayers(*message, offers); + getAvailableLayers(*message); +} + +void VehicleHalManagerFuzzer::invokeVehiclePropStore() { + bool shouldWriteStatus = mFuzzedDataProvider->ConsumeBool(); + int32_t vehicleProp = mFuzzedDataProvider->ConsumeIntegral<int32_t>(); + auto store = std::make_unique<VehiclePropertyStore>(); + VehiclePropConfig config{ + .prop = vehicleProp, + .access = VehiclePropertyAccess::READ, + .changeMode = VehiclePropertyChangeMode::STATIC, + .areaConfigs = {VehicleAreaConfig{.areaId = (0)}}, + }; + store->registerProperty(config); + VehiclePropValue propValue{}; + propValue.prop = vehicleProp; + propValue.areaId = 0; + store->writeValue(propValue, shouldWriteStatus); + store->readAllValues(); + store->getAllConfigs(); + store->getConfigOrNull(vehicleProp); + store->readValuesForProperty(vehicleProp); + store->readValueOrNull(propValue); + store->readValueOrNull(propValue.prop, propValue.areaId, 0); + store->removeValuesForProperty(vehicleProp); + store->removeValue(propValue); + store->getConfigOrDie(vehicleProp); +} + +void VehicleHalManagerFuzzer::invokeWatchDogClient() { + auto service = new VehicleHalManager(mHal.get()); + sp<Looper> looper(Looper::prepare(/*opts=*/mFuzzedDataProvider->ConsumeBool())); + if (auto watchdogClient = ndk::SharedRefBase::make<WatchdogClient>(looper, service); + watchdogClient->initialize()) { + watchdogClient->checkIfAlive(-1, TimeoutLength::TIMEOUT_NORMAL); + watchdogClient->prepareProcessTermination(); + } + delete service; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { + VehicleHalManagerFuzzer vmFuzzer; + vmFuzzer.process(data, size); + return 0; +} + +} // namespace android::hardware::automotive::vehicle::V2_0::fuzzer diff --git a/automotive/vehicle/2.0/default/tests/fuzzer/VehicleManager_fuzzer.h b/automotive/vehicle/2.0/default/tests/fuzzer/VehicleManager_fuzzer.h new file mode 100644 index 0000000000..e9335d3334 --- /dev/null +++ b/automotive/vehicle/2.0/default/tests/fuzzer/VehicleManager_fuzzer.h @@ -0,0 +1,124 @@ +/****************************************************************************** + * + * Copyright (C) 2021 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. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore + */ + +#ifndef __VEHICLE_MANAGER_FUZZER_H__ +#define __VEHICLE_MANAGER_FUZZER_H__ + +#include <vhal_v2_0/VehicleHalManager.h> +#include <vhal_v2_0/VehiclePropertyStore.h> +#include <vhal_v2_0/VmsUtils.h> + +#include <VehicleHalTestUtils.h> +#include <fuzzer/FuzzedDataProvider.h> + +namespace android::hardware::automotive::vehicle::V2_0::fuzzer { + +constexpr int kRetriableAttempts = 3; + +class MockedVehicleHal : public VehicleHal { + public: + MockedVehicleHal() + : mFuelCapacityAttemptsLeft(kRetriableAttempts), + mMirrorFoldAttemptsLeft(kRetriableAttempts) { + mConfigs.assign(std::begin(kVehicleProperties), std::end(kVehicleProperties)); + } + + std::vector<VehiclePropConfig> listProperties() override { return mConfigs; } + + VehiclePropValuePtr get(const VehiclePropValue& requestedPropValue, + StatusCode* outStatus) override; + + StatusCode set(const VehiclePropValue& propValue) override { + if (toInt(VehicleProperty::MIRROR_FOLD) == propValue.prop && + mMirrorFoldAttemptsLeft-- > 0) { + return StatusCode::TRY_AGAIN; + } + + mValues[makeKey(propValue)] = propValue; + return StatusCode::OK; + } + + StatusCode subscribe(int32_t /* property */, float /* sampleRate */) override { + return StatusCode::OK; + } + + StatusCode unsubscribe(int32_t /* property */) override { return StatusCode::OK; } + + void sendPropEvent(recyclable_ptr<VehiclePropValue> value) { doHalEvent(std::move(value)); } + + void sendHalError(StatusCode error, int32_t property, int32_t areaId) { + doHalPropertySetError(error, property, areaId); + } + + private: + int64_t makeKey(const VehiclePropValue& v) const { return makeKey(v.prop, v.areaId); } + + int64_t makeKey(int32_t prop, int32_t area) const { + return (static_cast<int64_t>(prop) << 32) | area; + } + + private: + std::vector<VehiclePropConfig> mConfigs; + std::unordered_map<int64_t, VehiclePropValue> mValues; + int mFuelCapacityAttemptsLeft; + int mMirrorFoldAttemptsLeft; +}; + +class VehicleHalManagerFuzzer { + public: + VehicleHalManagerFuzzer() { + mHal.reset(new MockedVehicleHal); + mManager.reset(new VehicleHalManager(mHal.get())); + mObjectPool = mHal->getValuePool(); + } + ~VehicleHalManagerFuzzer() { + mManager.reset(nullptr); + mHal.reset(nullptr); + mObjectPool = nullptr; + if (mFuzzedDataProvider) { + delete mFuzzedDataProvider; + } + } + void process(const uint8_t* data, size_t size); + + private: + FuzzedDataProvider* mFuzzedDataProvider = nullptr; + VehiclePropValue mActualValue = VehiclePropValue{}; + StatusCode mActualStatusCode = StatusCode::OK; + + VehiclePropValuePool* mObjectPool = nullptr; + std::unique_ptr<MockedVehicleHal> mHal; + std::unique_ptr<VehicleHalManager> mManager; + + void invokeDebug(); + void invokePropConfigs(); + void invokeSubscribe(); + void invokeSetAndGetValues(); + void invokeObd2SensorStore(); + void invokeVmsUtils(); + void invokeVehiclePropStore(); + void invokeWatchDogClient(); + void invokeGetSubscribedLayers(VmsMessageType type); + void invokeGet(int32_t property, int32_t areaId); +}; + +} // namespace android::hardware::automotive::vehicle::V2_0::fuzzer + +#endif // __VEHICLE_MANAGER_FUZZER_H__ |