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

Commit d08c883d authored by Pawan Wagh's avatar Pawan Wagh Committed by Automerger Merge Worker
Browse files

Merge changes from topic "random_parcel_seed_corpus" into main am: ada46f8b am: 5f6264fa

parents 116cea68 5f6264fa
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -77,6 +77,8 @@ cc_test {
    static_libs: [
    static_libs: [
        "binderRecordReplayTestIface-cpp",
        "binderRecordReplayTestIface-cpp",
        "binderReadParcelIface-cpp",
        "binderReadParcelIface-cpp",
        "libbinder_random_parcel_seeds",
        "libbinder_random_parcel",
    ],
    ],
    test_suites: ["general-tests"],
    test_suites: ["general-tests"],
    require_root: true,
    require_root: true,
+85 −42
Original line number Original line Diff line number Diff line
@@ -15,6 +15,7 @@
 */
 */


#include <BnBinderRecordReplayTest.h>
#include <BnBinderRecordReplayTest.h>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/logging.h>
#include <android-base/unique_fd.h>
#include <android-base/unique_fd.h>
#include <binder/Binder.h>
#include <binder/Binder.h>
@@ -23,6 +24,11 @@
#include <binder/IPCThreadState.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/IServiceManager.h>
#include <binder/RecordedTransaction.h>
#include <binder/RecordedTransaction.h>

#include <fuzzbinder/libbinder_driver.h>
#include <fuzzer/FuzzedDataProvider.h>
#include <fuzzseeds/random_parcel_seeds.h>

#include <gtest/gtest.h>
#include <gtest/gtest.h>


#include <sys/prctl.h>
#include <sys/prctl.h>
@@ -30,6 +36,7 @@
#include "parcelables/SingleDataParcelable.h"
#include "parcelables/SingleDataParcelable.h"


using namespace android;
using namespace android;
using android::generateSeedsFromRecording;
using android::binder::Status;
using android::binder::Status;
using android::binder::debug::RecordedTransaction;
using android::binder::debug::RecordedTransaction;
using parcelables::SingleDataParcelable;
using parcelables::SingleDataParcelable;
@@ -84,6 +91,44 @@ public:
    GENERATE_GETTER_SETTER(SingleDataParcelableArray, std::vector<SingleDataParcelable>);
    GENERATE_GETTER_SETTER(SingleDataParcelableArray, std::vector<SingleDataParcelable>);
};
};


std::vector<uint8_t> retrieveData(base::borrowed_fd fd) {
    struct stat fdStat;
    EXPECT_TRUE(fstat(fd.get(), &fdStat) != -1);
    EXPECT_TRUE(fdStat.st_size != 0);

    std::vector<uint8_t> buffer(fdStat.st_size);
    auto readResult = android::base::ReadFully(fd, buffer.data(), fdStat.st_size);
    EXPECT_TRUE(readResult != 0);
    return std::move(buffer);
}

void replayFuzzService(const sp<BpBinder>& binder, const RecordedTransaction& transaction) {
    base::unique_fd seedFd(open("/data/local/tmp/replayFuzzService",
                                O_RDWR | O_CREAT | O_CLOEXEC | O_TRUNC, 0666));
    ASSERT_TRUE(seedFd.ok());

    // generate corpus from this transaction.
    generateSeedsFromRecording(seedFd, transaction);

    // Read the data which has been written to seed corpus
    ASSERT_EQ(0, lseek(seedFd.get(), 0, SEEK_SET));
    std::vector<uint8_t> seedData = retrieveData(seedFd);

    // use fuzzService to replay the corpus
    FuzzedDataProvider provider(seedData.data(), seedData.size());
    fuzzService(binder, std::move(provider));
}

void replayBinder(const sp<BpBinder>& binder, const RecordedTransaction& transaction) {
    // TODO: move logic to replay RecordedTransaction into RecordedTransaction
    Parcel data;
    data.setData(transaction.getDataParcel().data(), transaction.getDataParcel().dataSize());
    auto result = binder->transact(transaction.getCode(), data, nullptr, transaction.getFlags());

    // make sure recording does the thing we expect it to do
    EXPECT_EQ(OK, result);
}

class BinderRecordReplayTest : public ::testing::Test {
class BinderRecordReplayTest : public ::testing::Test {
public:
public:
    void SetUp() override {
    void SetUp() override {
@@ -98,6 +143,8 @@ public:
    template <typename T, typename U>
    template <typename T, typename U>
    void recordReplay(Status (IBinderRecordReplayTest::*set)(T), U recordedValue,
    void recordReplay(Status (IBinderRecordReplayTest::*set)(T), U recordedValue,
                      Status (IBinderRecordReplayTest::*get)(U*), U changedValue) {
                      Status (IBinderRecordReplayTest::*get)(U*), U changedValue) {
        auto replayFunctions = {&replayBinder, &replayFuzzService};
        for (auto replayFunc : replayFunctions) {
            base::unique_fd fd(open("/data/local/tmp/binderRecordReplayTest.rec",
            base::unique_fd fd(open("/data/local/tmp/binderRecordReplayTest.rec",
                                    O_RDWR | O_CREAT | O_CLOEXEC, 0666));
                                    O_RDWR | O_CREAT | O_CLOEXEC, 0666));
            ASSERT_TRUE(fd.ok());
            ASSERT_TRUE(fd.ok());
@@ -128,19 +175,15 @@ public:
            std::optional<RecordedTransaction> transaction = RecordedTransaction::fromFile(fd);
            std::optional<RecordedTransaction> transaction = RecordedTransaction::fromFile(fd);
            ASSERT_NE(transaction, std::nullopt);
            ASSERT_NE(transaction, std::nullopt);


        // TODO: move logic to replay RecordedTransaction into RecordedTransaction
            const RecordedTransaction& recordedTransaction = *transaction;
        Parcel data;
            // call replay function with recorded transaction
        data.setData(transaction->getDataParcel().data(), transaction->getDataParcel().dataSize());
            (*replayFunc)(mBpBinder, recordedTransaction);
        auto result =
                mBpBinder->transact(transaction->getCode(), data, nullptr, transaction->getFlags());

        // make sure recording does the thing we expect it to do
        EXPECT_EQ(OK, result);


            status = (*mInterface.*get)(&output);
            status = (*mInterface.*get)(&output);
            EXPECT_TRUE(status.isOk());
            EXPECT_TRUE(status.isOk());
            EXPECT_EQ(output, recordedValue);
            EXPECT_EQ(output, recordedValue);
        }
        }
    }


private:
private:
    sp<BpBinder> mBpBinder;
    sp<BpBinder> mBpBinder;
+25 −0
Original line number Original line Diff line number Diff line
@@ -104,3 +104,28 @@ cc_library_static {
    local_include_dirs: ["include_random_parcel"],
    local_include_dirs: ["include_random_parcel"],
    export_include_dirs: ["include_random_parcel"],
    export_include_dirs: ["include_random_parcel"],
}
}

cc_library {
    name: "libbinder_random_parcel_seeds",
    host_supported: true,
    vendor_available: true,
    target: {
        darwin: {
            enabled: false,
        },
    },
    srcs: [
        "random_parcel_seeds.cpp",
    ],
    shared_libs: [
        "libbase",
        "libbinder",
        "libbinder_ndk",
        "libcutils",
        "libutils",
    ],
    local_include_dirs: [
        "include_random_parcel_seeds",
    ],
    export_include_dirs: ["include_random_parcel_seeds"],
}
+47 −0
Original line number Original line 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/file.h>
#include <android-base/hex.h>
#include <android-base/logging.h>

#include <binder/Binder.h>
#include <binder/Parcel.h>
#include <binder/RecordedTransaction.h>

#include <private/android_filesystem_config.h>

#include <vector>

using android::Parcel;
using android::base::HexString;
using std::vector;

namespace android {
namespace impl {
// computes the bytes so that if they are passed to FuzzedDataProvider and
// provider.ConsumeIntegralInRange<T>(min, max) is called, it will return val
template <typename T>
void writeReversedBuffer(std::vector<std::byte>& integralBuffer, T min, T max, T val);

// Calls writeInBuffer method with min and max numeric limits of type T. This method
// is reversal of ConsumeIntegral<T>() in FuzzedDataProvider
template <typename T>
void writeReversedBuffer(std::vector<std::byte>& integralBuffer, T val);
} // namespace impl
void generateSeedsFromRecording(base::borrowed_fd fd,
                                const binder::debug::RecordedTransaction& transaction);
} // namespace android
+5 −0
Original line number Original line Diff line number Diff line
@@ -35,6 +35,11 @@ void fuzzService(const std::vector<sp<IBinder>>& binders, FuzzedDataProvider&& p
            .extraFds = {},
            .extraFds = {},
    };
    };


    // Reserved bytes so that we don't have to change fuzzers and seed corpus if
    // we introduce anything new in fuzzService.
    std::vector<uint8_t> reservedBytes = provider.ConsumeBytes<uint8_t>(8);
    (void)reservedBytes;

    // always refresh the calling identity, because we sometimes set it below, but also,
    // always refresh the calling identity, because we sometimes set it below, but also,
    // the code we're fuzzing might reset it
    // the code we're fuzzing might reset it
    IPCThreadState::self()->clearCallingIdentity();
    IPCThreadState::self()->clearCallingIdentity();
Loading