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

Commit 512f3a03 authored by kunal rai's avatar kunal rai Committed by David Fu
Browse files

Added mtp_host_property_fuzzer and mtp_device_property_fuzzer

Test: ./mtp_host_property_fuzzer
Test: ./mtp_device_property_fuzzer

Bug: 234679864

Change-Id: I4a7b7966b244390bfacf210737cbb8105c6d3f9f
parent 592754fd
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -57,3 +57,30 @@ cc_fuzz {
    dictionary: "mtp_fuzzer.dict",
    corpus: ["corpus/*"],
}

cc_defaults {
    name: "mtp_property_fuzzer_defaults",
    srcs: ["mtp_property_fuzzer.cpp"],
    shared_libs: [
        "libmtp",
        "libasyncio",
        "libusbhost",
    ],
    defaults: ["mtp_fuzzer_defaults"],
}

cc_fuzz {
     name: "mtp_device_property_fuzzer",
     defaults: ["mtp_property_fuzzer_defaults"],
     cflags: [
         "-DMTP_DEVICE",
     ],
}

cc_fuzz {
     name: "mtp_host_property_fuzzer",
     defaults: ["mtp_property_fuzzer_defaults"],
     cflags: [
         "-DMTP_HOST",
     ],
}
+94 −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 <MtpStringBuffer.h>
#include <fuzzer/FuzzedDataProvider.h>
#include <linux/usbdevice_fs.h>
#include <sys/mman.h>
#include <usbhost/usbhost.h>
#include <MtpTypes.h>

using namespace android;
constexpr UrbPacketDivisionMode kUrbPacketDivisionModes[] = {FIRST_PACKET_ONLY_HEADER,
                                                             FIRST_PACKET_HAS_PAYLOAD};

constexpr size_t kMinSize = 0;
constexpr size_t kMaxSize = 1000;
constexpr size_t kMaxLength = 1000;

class MtpPacketFuzzerUtils {
  protected:
    struct usb_request mUsbRequest;
    struct usbdevfs_urb* mUsbDevFsUrb;
    std::string mPath;

    void fillFd(int32_t& fd, FuzzedDataProvider* fdp) {
        if (fdp->ConsumeBool()) {
            std::string text = fdp->ConsumeRandomLengthString(kMaxLength);
            write(fd, text.c_str(), text.length());
        }
    };

    void fillFilePath(FuzzedDataProvider* fdp) {
       mPath= fdp->ConsumeRandomLengthString(kMaxLength);
    };

    void fillUsbDevFsUrb(FuzzedDataProvider* fdp) {
        mUsbDevFsUrb->type = fdp->ConsumeIntegral<unsigned char>();
        mUsbDevFsUrb->endpoint = fdp->ConsumeIntegral<unsigned char>();
        mUsbDevFsUrb->flags = fdp->ConsumeIntegral<uint32_t>();
        std::vector<uint8_t> buffer =
                fdp->ConsumeBytes<uint8_t>(fdp->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize));
        mUsbDevFsUrb->buffer = static_cast<void*>(buffer.data());
        mUsbDevFsUrb->buffer_length = buffer.size();
        mUsbDevFsUrb->actual_length = fdp->ConsumeIntegral<uint32_t>();
        mUsbDevFsUrb->start_frame = fdp->ConsumeIntegral<uint32_t>();
        mUsbDevFsUrb->number_of_packets = fdp->ConsumeIntegral<uint32_t>();
        mUsbDevFsUrb->stream_id = fdp->ConsumeIntegral<uint32_t>();
        mUsbDevFsUrb->error_count = fdp->ConsumeIntegral<size_t>();
        mUsbDevFsUrb->signr = fdp->ConsumeIntegral<uint32_t>();
        std::vector<uint8_t> userBuffer = (fdp->ConsumeBytes<uint8_t>(
                fdp->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize)));
        mUsbDevFsUrb->usercontext = static_cast<void*>(userBuffer.data());
        mUsbDevFsUrb->iso_frame_desc[0].length = fdp->ConsumeIntegral<uint32_t>();
        mUsbDevFsUrb->iso_frame_desc[0].actual_length = fdp->ConsumeIntegral<uint32_t>();
    };

    void fillUsbRequest(int32_t& fd, FuzzedDataProvider* fdp) {
        fillUsbDevFsUrb(fdp);
        fillFd(fd, fdp);
        std::vector<uint8_t> buffer =
                fdp->ConsumeBytes<uint8_t>(fdp->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize));
        mUsbRequest.buffer = static_cast<void*>(buffer.data());
        mUsbRequest.buffer_length = buffer.size();
        mUsbRequest.actual_length = fdp->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
        mUsbRequest.max_packet_size = fdp->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
        mUsbRequest.private_data = static_cast<void*>(mUsbDevFsUrb);
        mUsbRequest.endpoint = fdp->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize);
        std::vector<uint8_t> clientBuffer = (fdp->ConsumeBytes<uint8_t>(
                fdp->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize)));
        mUsbRequest.client_data = static_cast<void*>(clientBuffer.data());
    };

    template <typename Object>
    void writeHandle(Object obj, FuzzedDataProvider* fdp) {
        MtpDevHandle handle;
        std::vector<uint8_t> initData =
                fdp->ConsumeBytes<uint8_t>(fdp->ConsumeIntegralInRange<size_t>(kMinSize, kMaxSize));
        handle.write(initData.data(), initData.size());
        obj->write(&handle);
    };
};
+44 −0
Original line number Diff line number Diff line
@@ -2,6 +2,8 @@

## Table of contents
+ [mtp_fuzzer](#MtpServer)
+ [mtp_host_property_fuzzer](#MtpHostProperty)
+ [mtp_device_property_fuzzer](#MtpDeviceProperty)

# <a name="MtpServer"></a> Fuzzer for MtpServer

@@ -22,3 +24,45 @@ MtpServer supports the following parameters:
  $ adb sync data
  $ adb shell /data/fuzz/arm64/mtp_fuzzer/mtp_fuzzer corpus/ -dict=mtp_fuzzer.dict
```

# <a name="MtpHostProperty"></a> Fuzzer for MtpHostProperty

MtpHostProperty supports the following parameters:
1. Feasible Type (parameter name: "kFeasibleTypes")
2. UrbPacket Division Mode (parameter name: "kUrbPacketDivisionModes")

| Parameter| Valid Values |Configured Value|
|-------------|----------|----- |
| `kFeasibleType`| 1. `MTP_TYPE_UNDEFINED`, 2. `MTP_TYPE_INT8`, 3.`MTP_TYPE_UINT8`, 4.`MTP_TYPE_INT16`, 5.`MTP_TYPE_UINT16`, 6.`MTP_TYPE_INT32`, 7.`MTP_TYPE_UINT32`, 8.`MTP_TYPE_INT64`, 9.`MTP_TYPE_UINT64`, 10.`MTP_TYPE_INT128`, 11.`MTP_TYPE_UINT128`, 12.`MTP_TYPE_AINT8`, 13.`MTP_TYPE_AUINT8`, 14.`MTP_TYPE_AINT16`, 15.`MTP_TYPE_AUINT16`, 16.`MTP_TYPE_AINT32`, 17.`MTP_TYPE_AUINT32`, 18.`MTP_TYPE_AINT64`, 19.`MTP_TYPE_AUINT64`, 20.`MTP_TYPE_AINT128`, 21.`MTP_TYPE_AUINT128`, 22.`MTP_TYPE_STR`,| Value obtained from FuzzedDataProvider|
|`kUrbPacketDivisionMode`| 1. `FIRST_PACKET_ONLY_HEADER`, 2. `FIRST_PACKET_HAS_PAYLOAD`, |Value obtained from FuzzedDataProvider|

#### Steps to run
1. Build the fuzzer
```
  $ mm -j$(nproc) mtp_host_property_fuzzer
```
2. Run on device
```
  $ adb sync data
  $ adb shell /data/fuzz/arm64/mtp_host_property_fuzzer/mtp_host_property_fuzzer
```

# <a name="MtpDeviceProperty"></a> Fuzzer for MtpDeviceProperty

MtpDeviceProperty supports the following parameters:
1. Feasible Type (parameter name: "kFeasibleType")

| Parameter| Valid Values |Configured Value|
|-------------|----------|----- |
| `kFeasibleType`| 1. `MTP_TYPE_UNDEFINED`, 2. `MTP_TYPE_INT8`, 3.`MTP_TYPE_UINT8`, 4.`MTP_TYPE_INT16`, 5.`MTP_TYPE_UINT16`, 6.`MTP_TYPE_INT32`, 7.`MTP_TYPE_UINT32`, 8.`MTP_TYPE_INT64`, 9.`MTP_TYPE_UINT64`, 10.`MTP_TYPE_INT128`, 11.`MTP_TYPE_UINT128`, 12.`MTP_TYPE_AINT8`, 13.`MTP_TYPE_AUINT8`, 14.`MTP_TYPE_AINT16`, 15.`MTP_TYPE_AUINT16`, 16.`MTP_TYPE_AINT32`, 17.`MTP_TYPE_AUINT32`, 18.`MTP_TYPE_AINT64`, 19.`MTP_TYPE_AUINT64`, 20.`MTP_TYPE_AINT128`, 21.`MTP_TYPE_AUINT128`, 22.`MTP_TYPE_STR`,| Value obtained from FuzzedDataProvider|

#### Steps to run
1. Build the fuzzer
```
  $ mm -j$(nproc) mtp_device_property_fuzzer
```
2. Run on device
```
  $ adb sync data
  $ adb shell /data/fuzz/arm64/mtp_device_property_fuzzer/mtp_device_property_fuzzer
```
+134 −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 <MtpDataPacket.h>
#include <MtpDevHandle.h>
#include <MtpPacketFuzzerUtils.h>
#include <MtpProperty.h>
#include <fuzzer/FuzzedDataProvider.h>
#include <utils/String16.h>

using namespace android;

constexpr uint16_t kFeasibleTypes[] = {
        MTP_TYPE_UNDEFINED, MTP_TYPE_INT8,    MTP_TYPE_UINT8,  MTP_TYPE_INT16,   MTP_TYPE_UINT16,
        MTP_TYPE_INT32,     MTP_TYPE_UINT32,  MTP_TYPE_INT64,  MTP_TYPE_UINT64,  MTP_TYPE_INT128,
        MTP_TYPE_UINT128,   MTP_TYPE_AINT8,   MTP_TYPE_AUINT8, MTP_TYPE_AINT16,  MTP_TYPE_AUINT16,
        MTP_TYPE_AINT32,    MTP_TYPE_AUINT32, MTP_TYPE_AINT64, MTP_TYPE_AUINT64, MTP_TYPE_AINT128,
        MTP_TYPE_AUINT128,  MTP_TYPE_STR,
};

class MtpPropertyFuzzer : MtpPacketFuzzerUtils {
  public:
    MtpPropertyFuzzer(const uint8_t* data, size_t size) : mFdp(data, size){};
    void process();

  private:
    FuzzedDataProvider mFdp;
};

void MtpPropertyFuzzer::process() {
    MtpProperty* mtpProperty;
    if (mFdp.ConsumeBool()) {
        mtpProperty = new MtpProperty();
    } else {
        uint16_t type = mFdp.ConsumeBool() ? mFdp.ConsumeIntegral<uint16_t>()
                                           : mFdp.PickValueInArray<uint16_t>(kFeasibleTypes);
        mtpProperty = new MtpProperty(mFdp.ConsumeIntegral<uint16_t>(), type, mFdp.ConsumeBool(),
                                      mFdp.ConsumeIntegral<uint16_t>());
    }

    while (mFdp.remaining_bytes() > 0) {
        auto invokeMtpPropertyFuzzer = mFdp.PickValueInArray<const std::function<void()>>({
                [&]() {
                    MtpDataPacket mtpDataPacket;
                    if (mFdp.ConsumeBool()) {
                        mtpProperty->read(mtpDataPacket);

                    } else {
                        if (mFdp.ConsumeBool()) {
#ifdef MTP_DEVICE
                            android::IMtpHandle* h = new MtpDevHandle();
                            h->start(mFdp.ConsumeBool());
                            std::string text = mFdp.ConsumeRandomLengthString(kMaxLength);
                            char* data = const_cast<char*>(text.c_str());
                            h->read(static_cast<void*>(data), text.length());
                            mtpDataPacket.write(h);
                            h->close();
                            delete h;
#endif

#ifdef MTP_HOST
                            fillFilePath(&mFdp);
                            int32_t fd = memfd_create(mPath.c_str(), MFD_ALLOW_SEALING);
                            fillUsbRequest(fd, &mFdp);
                            mtpDataPacket.write(&mUsbRequest,
                                                mFdp.PickValueInArray<UrbPacketDivisionMode>(
                                                        kUrbPacketDivisionModes),
                                                fd,
                                                mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize));
                            usb_device_close(mUsbRequest.dev);
#endif
                        }

                        if (mFdp.ConsumeBool()) {
                            mtpProperty->write(mtpDataPacket);
                        } else {
                            mtpProperty->setCurrentValue(mtpDataPacket);
                        }
                    }
                },
                [&]() {
                    char16_t* data = nullptr;
                    std::string str = mFdp.ConsumeRandomLengthString(kMaxLength);
                    android::String16 s(str.c_str());
                    if (mFdp.ConsumeBool()) {
                        data = const_cast<char16_t*>(s.string());
                    }

                    if (mFdp.ConsumeBool()) {
                        mtpProperty->setDefaultValue(reinterpret_cast<uint16_t*>(data));
                    } else if (mFdp.ConsumeBool()) {
                        mtpProperty->setCurrentValue(reinterpret_cast<uint16_t*>(data));
                    } else {
                        mtpProperty->setCurrentValue(str.c_str());
                    }
                },
                [&]() {
                    mtpProperty->setFormRange(mFdp.ConsumeIntegral<int32_t>(),
                                              mFdp.ConsumeIntegral<int32_t>(),
                                              mFdp.ConsumeIntegral<int32_t>());
                },
                [&]() {
                    std::vector<int32_t> init;
                    for (size_t idx = 0; idx < mFdp.ConsumeIntegralInRange(kMinSize, kMaxSize);
                         ++idx) {
                        init.push_back(mFdp.ConsumeIntegral<int32_t>());
                    }
                    mtpProperty->setFormEnum(init.data(), init.size());
                },
        });
        invokeMtpPropertyFuzzer();
    }

    delete (mtpProperty);
}

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
    MtpPropertyFuzzer mtpPropertyFuzzer(data, size);
    mtpPropertyFuzzer.process();
    return 0;
}