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

Commit 17c76b21 authored by Fabián Cañas's avatar Fabián Cañas Committed by Automerger Merge Worker
Browse files

Merge "Add fuzz tests for binder RecordedTransaction" am: ee04fa7a am:...

Merge "Add fuzz tests for binder RecordedTransaction" am: ee04fa7a am: d9c476c9 am: ddf71c39 am: 231727e1

Original change: https://android-review.googlesource.com/c/platform/frameworks/native/+/2459528



Change-Id: I13b57b9826e4022c62c2e6f7cc9c0cf8c0d37e16
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents fa98cd45 231727e1
Loading
Loading
Loading
Loading
+42 −6
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/scopeguard.h>
#include <android-base/unique_fd.h>
#include <binder/RecordedTransaction.h>
#include <sys/mman.h>
@@ -176,13 +177,33 @@ std::optional<RecordedTransaction> RecordedTransaction::fromFile(const unique_fd
    RecordedTransaction t;
    ChunkDescriptor chunk;
    const long pageSize = sysconf(_SC_PAGE_SIZE);
    struct stat fileStat;
    if (fstat(fd.get(), &fileStat) != 0) {
        LOG(ERROR) << "Unable to get file information";
        return std::nullopt;
    }

    off_t fdCurrentPosition = lseek(fd.get(), 0, SEEK_CUR);
    if (fdCurrentPosition == -1) {
        LOG(ERROR) << "Invalid offset in file descriptor.";
        return std::nullopt;
    }
    do {
        if (fileStat.st_size < (fdCurrentPosition + (off_t)sizeof(ChunkDescriptor))) {
            LOG(ERROR) << "Not enough file remains to contain expected chunk descriptor";
            return std::nullopt;
        }
        transaction_checksum_t checksum = 0;
        if (NO_ERROR != readChunkDescriptor(fd, &chunk, &checksum)) {
            LOG(ERROR) << "Failed to read chunk descriptor.";
            return std::nullopt;
        }
        off_t fdCurrentPosition = lseek(fd.get(), 0, SEEK_CUR);

        fdCurrentPosition = lseek(fd.get(), 0, SEEK_CUR);
        if (fdCurrentPosition == -1) {
            LOG(ERROR) << "Invalid offset in file descriptor.";
            return std::nullopt;
        }
        off_t mmapPageAlignedStart = (fdCurrentPosition / pageSize) * pageSize;
        off_t mmapPayloadStartOffset = fdCurrentPosition - mmapPageAlignedStart;

@@ -194,14 +215,24 @@ std::optional<RecordedTransaction> RecordedTransaction::fromFile(const unique_fd
        size_t chunkPayloadSize =
                chunk.dataSize + PADDING8(chunk.dataSize) + sizeof(transaction_checksum_t);

        if (chunkPayloadSize > (size_t)(fileStat.st_size - fdCurrentPosition)) {
            LOG(ERROR) << "Chunk payload exceeds remaining file size.";
            return std::nullopt;
        }

        if (PADDING8(chunkPayloadSize) != 0) {
            LOG(ERROR) << "Invalid chunk size, not aligned " << chunkPayloadSize;
            return std::nullopt;
        }

        transaction_checksum_t* payloadMap = reinterpret_cast<transaction_checksum_t*>(
                mmap(NULL, chunkPayloadSize + mmapPayloadStartOffset, PROT_READ, MAP_SHARED,
                     fd.get(), mmapPageAlignedStart));
        size_t memoryMappedSize = chunkPayloadSize + mmapPayloadStartOffset;
        void* mappedMemory =
                mmap(NULL, memoryMappedSize, PROT_READ, MAP_SHARED, fd.get(), mmapPageAlignedStart);
        auto mmap_guard = android::base::make_scope_guard(
                [mappedMemory, memoryMappedSize] { munmap(mappedMemory, memoryMappedSize); });

        transaction_checksum_t* payloadMap =
                reinterpret_cast<transaction_checksum_t*>(mappedMemory);
        payloadMap += mmapPayloadStartOffset /
                sizeof(transaction_checksum_t); // Skip chunk descriptor and required mmap
                                                // page-alignment
@@ -218,7 +249,12 @@ std::optional<RecordedTransaction> RecordedTransaction::fromFile(const unique_fd
            LOG(ERROR) << "Checksum failed.";
            return std::nullopt;
        }
        lseek(fd.get(), chunkPayloadSize, SEEK_CUR);

        fdCurrentPosition = lseek(fd.get(), chunkPayloadSize, SEEK_CUR);
        if (fdCurrentPosition == -1) {
            LOG(ERROR) << "Invalid offset in file descriptor.";
            return std::nullopt;
        }

        switch (chunk.chunkType) {
            case HEADER_CHUNK: {
@@ -255,7 +291,7 @@ std::optional<RecordedTransaction> RecordedTransaction::fromFile(const unique_fd
                break;
            default:
                LOG(INFO) << "Unrecognized chunk.";
                continue;
                break;
        }
    } while (chunk.chunkType != END_CHUNK);

+39 −0
Original line number Diff line number Diff line
@@ -104,3 +104,42 @@ cc_fuzz {
    defaults: ["binder_fuzz_defaults"],
    srcs: ["MemoryDealerFuzz.cpp"],
}

cc_fuzz {
    name: "binder_recordedTransactionFileFuzz",
    defaults: ["binder_fuzz_defaults"],
    srcs: ["RecordedTransactionFileFuzz.cpp"],
    corpus: [
        "recorded_transaction_corpus/*",
    ],
}

cc_fuzz {
    name: "binder_recordedTransactionFuzz",
    defaults: ["binder_fuzz_defaults"],
    srcs: ["RecordedTransactionFuzz.cpp"],
    target: {
        android: {
            shared_libs: [
                "libcutils",
                "libutils",
                "libbase",
                "libbinder",
            ],
            static_libs: ["libbinder_random_parcel"],
        },
        host: {
            static_libs: [
                "libcutils",
                "liblog",
                "libutils",
                "libbase",
                "libbinder",
                "libbinder_random_parcel",
            ],
        },
        darwin: {
            enabled: false,
        },
    },
}
+45 −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/macros.h>
#include <binder/RecordedTransaction.h>
#include <filesystem>

#include "fuzzer/FuzzedDataProvider.h"

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
    std::FILE* intermediateFile = std::tmpfile();
    fwrite(data, sizeof(uint8_t), size, intermediateFile);
    rewind(intermediateFile);
    int fileNumber = fileno(intermediateFile);

    android::base::unique_fd fd(fileNumber);

    auto transaction = android::binder::debug::RecordedTransaction::fromFile(fd);

    std::fclose(intermediateFile);

    if (transaction.has_value()) {
        intermediateFile = std::tmpfile();

        android::base::unique_fd fdForWriting(fileno(intermediateFile));
        auto writeStatus ATTRIBUTE_UNUSED = transaction.value().dumpToFile(fdForWriting);

        std::fclose(intermediateFile);
    }

    return 0;
}
+64 −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/macros.h>
#include <binder/RecordedTransaction.h>
#include <fuzzbinder/random_parcel.h>
#include <filesystem>
#include <string>

#include "fuzzer/FuzzedDataProvider.h"

using android::fillRandomParcel;

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
    FuzzedDataProvider provider = FuzzedDataProvider(data, size);

    android::String16 interfaceName =
            android::String16(provider.ConsumeRandomLengthString().c_str());

    uint32_t code = provider.ConsumeIntegral<uint32_t>();
    uint32_t flags = provider.ConsumeIntegral<uint32_t>();
    time_t sec = provider.ConsumeIntegral<time_t>();
    long nsec = provider.ConsumeIntegral<long>();
    timespec timestamp = {.tv_sec = sec, .tv_nsec = nsec};
    android::status_t transactionStatus = provider.ConsumeIntegral<android::status_t>();

    std::vector<uint8_t> bytes = provider.ConsumeBytes<uint8_t>(
            provider.ConsumeIntegralInRange<size_t>(0, provider.remaining_bytes()));

    // same options so that FDs and binders could be shared in both Parcels
    android::RandomParcelOptions options;

    android::Parcel p0, p1;
    fillRandomParcel(&p0, FuzzedDataProvider(bytes.data(), bytes.size()), &options);
    fillRandomParcel(&p1, std::move(provider), &options);

    auto transaction =
            android::binder::debug::RecordedTransaction::fromDetails(interfaceName, code, flags,
                                                                     timestamp, p0, p1,
                                                                     transactionStatus);

    if (transaction.has_value()) {
        std::FILE* intermediateFile = std::tmpfile();
        android::base::unique_fd fdForWriting(fileno(intermediateFile));
        auto writeStatus ATTRIBUTE_UNUSED = transaction.value().dumpToFile(fdForWriting);

        std::fclose(intermediateFile);
    }

    return 0;
}
+928 B

File added.

No diff preview for this file type.

Loading