Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 20b69d76 authored by Cory Barker's avatar Cory Barker Committed by Gerrit Code Review
Browse files

Merge "Added automotiveCanV1.0_fuzzer"

parents 55419fd9 3921199e
Loading
Loading
Loading
Loading
+20 −7
Original line number Diff line number Diff line
@@ -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: ["."],
}
+45 −0
Original line number Diff line number Diff line
/*
 * 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,
    },
}
+202 −0
Original line number Diff line number Diff line
/*
 * 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
+129 −0
Original line number Diff line number Diff line
/*
 * 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__