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

Commit 4080e344 authored by Harsh Abichandani's avatar Harsh Abichandani
Browse files

Added liblp_builder_fuzzer and liblp_super_layout_builder_fuzzer

exec/s: 17002
Test: ./liblp_builder_fuzzer
exec/s: 31273
Test: ./liblp_super_layout_builder_fuzzer
Bug: 285829660

Change-Id: I05d0a6c72069e500b2c838f9c6d900ca1ce2c8cc
parent a5c51c9c
Loading
Loading
Loading
Loading
+58 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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_defaults {
    name: "liblp_fuzz_defaults",
    header_libs: [
        "libstorage_literals_headers",
    ],
    shared_libs: [
        "liblp",
        "libbase",
        "liblog",
    ],
    static_libs: [
        "libcutils",
    ],
    include_dirs: [
        "system/core/fs_mgr/liblp",
    ],
    fuzz_config: {
        cc: [
            "android-media-fuzzing-reports@google.com",
        ],
        componentid: 59148,
        hotlists: ["4593311"],
        description: "The fuzzers target the APIs of all liblp modules",
        vector: "local_no_privileges_required",
        service_privilege: "privileged",
        users: "multi_user",
        fuzzed_code_usage: "shipped"
    }
}

cc_fuzz {
    name: "liblp_builder_fuzzer",
    srcs: ["liblp_builder_fuzzer.cpp"],
    defaults: ["liblp_fuzz_defaults"],
}

cc_fuzz {
    name: "liblp_super_layout_builder_fuzzer",
    srcs: ["liblp_super_layout_builder_fuzzer.cpp"],
    defaults: ["liblp_fuzz_defaults"],
}
+93 −0
Original line number Diff line number Diff line
# Fuzzers for liblp
## Table of contents
+  [liblp_builder_fuzzer](#Builder)
+  [liblp_super_layout_builder_fuzzer](#SuperBuilder)

# <a  name="Builder"></a> Fuzzer for LiblpBuilder

LiblpBuilder supports the following parameters:
1. kAttributeTypes (parameter name: "attribute")
2. blockDevSize (parameter name: "blockdev_size")
3. metadataMaxSize (parameter name: "metadata_max_size")
4. metadataSlotCount (parameter name: "metadata_slot_count")
5. partitionName (parameter name: "partition_name")
6. superBlockDeviceName (parameter name: "block_device_name")
7. blockDeviceInfoSize (parameter name: "block_device_info_size")
8. alignment (parameter name: "alignment")
9. alignmentOffset (parameter name: "alignment_offset")
10. logicalBlockSize (parameter name: "logical_block_size")
11. maxMetadataSize (parameter name: "max_metadata_size")
12. numSlots (parameter name: "metadata_slot_count")
13. deviceIndex (parameter name: "device_index")
14. start (parameter name: "start")
15. end (parameter name: "end")
16. addedGroupName (parameter name: "group_name")
17. partitionGroupName (parameter name: "partition_name")
18. numSectors (parameter name: "num_sectors")
19. physicalSector (parameter name: "physical_sector")
20. resizedPartitionSize (parameter name: "requested_size")

| Parameter| Valid Values| Configured Value|
|------------- |-------------| ----- |
|`kAttributeTypes`| 1.`LP_PARTITION_ATTR_NONE`,<br/> 2.`LP_PARTITION_ATTR_READONLY`,<br/> 3.`LP_PARTITION_ATTR_SLOT_SUFFIXED`,<br/> 4.`LP_PARTITION_ATTR_UPDATED`,<br/> 5.`LP_PARTITION_ATTR_DISABLED`|Value obtained from FuzzedDataProvider|
|`blockDevSize`| Integer value from `0` to `100000`|Value obtained from FuzzedDataProvider|
|`metadataMaxSize`| Integer value from `0` to `10000` |Value obtained from FuzzedDataProvider|
|`metadataSlotCount`| Integer value from `0` to `2` |Value obtained from FuzzedDataProvider|
|`partitionName`| String |Value obtained from FuzzedDataProvider|
|`superBlockDeviceName`| String |Value obtained from FuzzedDataProvider|
|`blockDeviceInfoSize`| Integer |Value obtained from FuzzedDataProvider|
|`alignment`| Integer |Value obtained from FuzzedDataProvider|
|`alignmentOffset`| Integer |Value obtained from FuzzedDataProvider|
|`logicalBlockSize`| Integer |Value obtained from FuzzedDataProvider|
|`maxMetadataSize`| Integer value from `0` to `10000` |Value obtained from FuzzedDataProvider|
|`numSlots`| Integer value from `0` to `2` |Value obtained from FuzzedDataProvider|
|`deviceIndex`| Integer |Value obtained from FuzzedDataProvider|
|`start`| Integer |Value obtained from FuzzedDataProvider|
|`end`| Integer |Value obtained from FuzzedDataProvider|
|`partitionGroupName`| String |Value obtained from FuzzedDataProvider|
|`numSectors`| Integer value from `1` to `1000000` |Value obtained from FuzzedDataProvider|
|`physicalSector`| Integer value from `1` to `1000000` |Value obtained from FuzzedDataProvider|
|`resizedPartitionSize`| Integer value from `0` to `10000` |Value obtained from FuzzedDataProvider|

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

# <a  name="SuperBuilder"></a> Fuzzer for LiblpSuperLayoutBuilder

SuperLayoutBuilder supports the following parameters:
1. kAttributeTypes (parameter name: "attribute")
2. blockDevSize (parameter name: "blockdev_size")
3. metadataMaxSize (parameter name: "metadata_max_size")
4. metadataSlotCount (parameter name: "metadata_slot_count")
5. partitionName (parameter name: "partition_name")
6. data (parameter name: "data")
7. imageName (parameter name: "image_name")

| Parameter| Valid Values| Configured Value|
|------------- |-------------| ----- |
|`kAttributeTypes`| 1.`LP_PARTITION_ATTR_NONE`,<br/> 2.`LP_PARTITION_ATTR_READONLY`,<br/> 3.`LP_PARTITION_ATTR_SLOT_SUFFIXED`,<br/> 4.`LP_PARTITION_ATTR_UPDATED`,<br/> 5.`LP_PARTITION_ATTR_DISABLED`|Value obtained from FuzzedDataProvider|
|`blockDevSize`| Integer value from `0` to `100000`|Value obtained from FuzzedDataProvider|
|`metadataMaxSize`| Integer value from `0` to `10000` |Value obtained from FuzzedDataProvider|
|`metadataSlotCount`| Integer value from `0` to `2` |Value obtained from FuzzedDataProvider|
|`partitionName`| String |Value obtained from FuzzedDataProvider|
|`data`| String |Value obtained from FuzzedDataProvider|
|`imageName`| String |Value obtained from FuzzedDataProvider|

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

File added.

Preview size limit exceeded, changes collapsed.

+151 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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 <android-base/unique_fd.h>
#include <fcntl.h>
#include <fuzzer/FuzzedDataProvider.h>
#include <liblp/metadata_format.h>
#include <liblp/super_layout_builder.h>
#include <linux/memfd.h>
#include <storage_literals/storage_literals.h>
#include <sys/syscall.h>

using namespace android::fs_mgr;
using namespace std;
using unique_fd = android::base::unique_fd;
using namespace android::storage_literals;

static constexpr uint64_t kSuperLayoutValidBlockDevSize = 4_MiB;
static constexpr uint64_t kMinBlockDevValue = 0;
static constexpr uint64_t kMaxBlockDevValue = 100000;
static constexpr uint64_t kMinElements = 0;
static constexpr uint64_t kMaxElements = 10;
static constexpr uint32_t kSuperLayoutValidMetadataSize = 8_KiB;
static constexpr uint32_t kMinMetadataValue = 0;
static constexpr uint32_t kMaxMetadataValue = 10000;
static constexpr uint32_t kMaxBytes = 20;
static constexpr uint32_t kMinSlot = 0;
static constexpr uint32_t kMaxSlot = 10;
static constexpr uint32_t kMinOpen = 0;
static constexpr uint32_t kMaxOpen = 2;

const uint64_t kAttributeTypes[] = {
        LP_PARTITION_ATTR_NONE,    LP_PARTITION_ATTR_READONLY, LP_PARTITION_ATTR_SLOT_SUFFIXED,
        LP_PARTITION_ATTR_UPDATED, LP_PARTITION_ATTR_DISABLED,
};

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

  private:
    FuzzedDataProvider mFdp;
    void invokeSuperLayoutBuilderAPIs();
    void callRandomOpen(int32_t open);
    void addMultiplePartitions(int32_t numPartitions);
    void setupSuperLayoutBuilder(string fuzzPartitionName);
    SuperLayoutBuilder mSuperLayoutBuilder;
    unique_ptr<MetadataBuilder> mSuperBuilder;
    unique_ptr<LpMetadata> mMetadata;
    bool mOpenSuccess = false;
};

void SuperLayoutBuilderFuzzer::setupSuperLayoutBuilder(string fuzzPartitionName) {
    uint64_t randomBlockDevSize =
            mFdp.ConsumeIntegralInRange<uint64_t>(kMinBlockDevValue, kMaxBlockDevValue);
    uint64_t blockDevSize = mFdp.ConsumeBool() ? kSuperLayoutValidBlockDevSize : randomBlockDevSize;
    uint32_t randomMetadataMaxSize =
            mFdp.ConsumeIntegralInRange<uint32_t>(kMinMetadataValue, kMaxMetadataValue);
    uint32_t metadataMaxSize =
            mFdp.ConsumeBool() ? kSuperLayoutValidMetadataSize : randomMetadataMaxSize;
    uint32_t metadataSlotCount = mFdp.ConsumeIntegralInRange<uint32_t>(kMinSlot, kMaxSlot);
    mSuperBuilder = MetadataBuilder::New(blockDevSize, metadataMaxSize, metadataSlotCount);

    if (mSuperBuilder.get()) {
        if (mFdp.ConsumeBool()) {
            int32_t numPartitions =
                    mFdp.ConsumeIntegralInRange<int32_t>(kMinElements, kMaxElements);
            addMultiplePartitions(numPartitions);
        }

        uint32_t randomOpen = mFdp.ConsumeIntegralInRange<uint32_t>(kMinOpen, kMaxOpen);
        callRandomOpen(randomOpen);

        if (!fuzzPartitionName.size()) {
            fuzzPartitionName = "builder_partition";
        }
    }
}

void SuperLayoutBuilderFuzzer::addMultiplePartitions(int32_t numPartitions) {
    for (int32_t idx = 0; idx < numPartitions; ++idx) {
        string partitionName = mFdp.ConsumeBool() ? mFdp.ConsumeRandomLengthString(kMaxBytes)
                                                  : "builder_partition";
        mSuperBuilder->AddPartition(partitionName, mFdp.PickValueInArray(kAttributeTypes));
    }
}

void SuperLayoutBuilderFuzzer::callRandomOpen(int32_t open) {
    mMetadata = mSuperBuilder->Export();
    switch (open) {
        case 0: {
            vector<uint8_t> imageData = mFdp.ConsumeBytes<uint8_t>(kMaxBytes);
            mOpenSuccess = mSuperLayoutBuilder.Open((void*)(imageData.data()), imageData.size());
            break;
        }
        case 1: {
            mOpenSuccess = mSuperLayoutBuilder.Open(*mMetadata.get());
            break;
        }
        case 2: {
            unique_fd fd(syscall(__NR_memfd_create, "image_file", 0));
            WriteToImageFile(fd, *mMetadata.get());
            mOpenSuccess = mSuperLayoutBuilder.Open(fd);
            break;
        }
    }
}

void SuperLayoutBuilderFuzzer::invokeSuperLayoutBuilderAPIs() {
    string imageName = mFdp.ConsumeRandomLengthString(kMaxBytes);
    string fuzzPartitionName =
            mFdp.ConsumeBool() ? "builder_partition" : mFdp.ConsumeRandomLengthString(kMaxBytes);
    setupSuperLayoutBuilder(fuzzPartitionName);
    if (mOpenSuccess) {
        while (mFdp.remaining_bytes()) {
            auto invokeSuperAPIs = mFdp.PickValueInArray<const function<void()>>({
                    [&]() { mSuperLayoutBuilder.GetImageLayout(); },
                    [&]() {
                        mSuperLayoutBuilder.AddPartition(fuzzPartitionName, imageName,
                                                         mFdp.ConsumeIntegral<uint64_t>());
                    },
            });
            invokeSuperAPIs();
        }
    }
}

void SuperLayoutBuilderFuzzer::process() {
    invokeSuperLayoutBuilderAPIs();
}

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