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__