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

Commit 28ae7479 authored by Caitlin Shkuratov's avatar Caitlin Shkuratov Committed by Automerger Merge Worker
Browse files

Merge "Revert "Binder Record/Replay implemented in BBinder"" am: 643e1f13...

Merge "Revert "Binder Record/Replay implemented in BBinder"" am: 643e1f13 am: 7ba24769 am: 73fa2a74

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



Change-Id: Ia9cb19ea56f36c28530a950d20d230939a1c2e7d
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 83dde74a 73fa2a74
Loading
Loading
Loading
Loading
+1 −5
Original line number Diff line number Diff line
@@ -76,7 +76,6 @@ cc_defaults {

    srcs: [
        "Binder.cpp",
        "BinderRecordReplay.cpp",
        "BpBinder.cpp",
        "Debug.cpp",
        "FdTrigger.cpp",
@@ -149,10 +148,7 @@ cc_defaults {
        },

        debuggable: {
            cflags: [
                "-DBINDER_RPC_DEV_SERVERS",
                "-DBINDER_ENABLE_RECORDING",
            ],
            cflags: ["-DBINDER_RPC_DEV_SERVERS"],
        },
    },

+1 −92
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@

#include <android-base/logging.h>
#include <android-base/unique_fd.h>
#include <binder/BinderRecordReplay.h>
#include <binder/BpBinder.h>
#include <binder/IInterface.h>
#include <binder/IPCThreadState.h>
@@ -29,9 +28,7 @@
#include <binder/IShellCallback.h>
#include <binder/Parcel.h>
#include <binder/RpcServer.h>
#include <cutils/compiler.h>
#include <private/android_filesystem_config.h>
#include <pthread.h>
#include <utils/misc.h>

#include <inttypes.h>
@@ -63,12 +60,6 @@ bool kEnableRpcDevServers = true;
bool kEnableRpcDevServers = false;
#endif

#ifdef BINDER_ENABLE_RECORDING
bool kEnableRecording = true;
#else
bool kEnableRecording = false;
#endif

// Log any reply transactions for which the data exceeds this size
#define LOG_REPLIES_OVER_SIZE (300 * 1024)
// ---------------------------------------------------------------------------
@@ -274,13 +265,11 @@ public:
    Mutex mLock;
    std::set<sp<RpcServerLink>> mRpcServerLinks;
    BpBinder::ObjectManager mObjects;

    android::base::unique_fd mRecordingFd;
};

// ---------------------------------------------------------------------------

BBinder::BBinder() : mExtras(nullptr), mStability(0), mParceled(false), mRecordingOn(false) {}
BBinder::BBinder() : mExtras(nullptr), mStability(0), mParceled(false) {}

bool BBinder::isBinderAlive() const
{
@@ -292,63 +281,6 @@ status_t BBinder::pingBinder()
    return NO_ERROR;
}

status_t BBinder::startRecordingTransactions(const Parcel& data) {
    if (!kEnableRecording) {
        ALOGW("Binder recording disallowed because recording is not enabled");
        return INVALID_OPERATION;
    }
    if (!kEnableKernelIpc) {
        ALOGW("Binder recording disallowed because kernel binder is not enabled");
        return INVALID_OPERATION;
    }
    uid_t uid = IPCThreadState::self()->getCallingUid();
    if (uid != AID_ROOT) {
        ALOGE("Binder recording not allowed because client %" PRIu32 " is not root", uid);
        return PERMISSION_DENIED;
    }
    Extras* e = getOrCreateExtras();
    AutoMutex lock(e->mLock);
    if (mRecordingOn) {
        LOG(INFO) << "Could not start Binder recording. Another is already in progress.";
        return INVALID_OPERATION;
    } else {
        status_t readStatus = data.readUniqueFileDescriptor(&(e->mRecordingFd));
        if (readStatus != OK) {
            return readStatus;
        }
        mRecordingOn = true;
        LOG(INFO) << "Started Binder recording.";
        return NO_ERROR;
    }
}

status_t BBinder::stopRecordingTransactions() {
    if (!kEnableRecording) {
        ALOGW("Binder recording disallowed because recording is not enabled");
        return INVALID_OPERATION;
    }
    if (!kEnableKernelIpc) {
        ALOGW("Binder recording disallowed because kernel binder is not enabled");
        return INVALID_OPERATION;
    }
    uid_t uid = IPCThreadState::self()->getCallingUid();
    if (uid != AID_ROOT) {
        ALOGE("Binder recording not allowed because client %" PRIu32 " is not root", uid);
        return PERMISSION_DENIED;
    }
    Extras* e = getOrCreateExtras();
    AutoMutex lock(e->mLock);
    if (mRecordingOn) {
        e->mRecordingFd.reset();
        mRecordingOn = false;
        LOG(INFO) << "Stopped Binder recording.";
        return NO_ERROR;
    } else {
        LOG(INFO) << "Could not stop Binder recording. One is not in progress.";
        return INVALID_OPERATION;
    }
}

const String16& BBinder::getInterfaceDescriptor() const
{
    static StaticString16 sBBinder(u"BBinder");
@@ -371,12 +303,6 @@ status_t BBinder::transact(
        case PING_TRANSACTION:
            err = pingBinder();
            break;
        case START_RECORDING_TRANSACTION:
            err = startRecordingTransactions(data);
            break;
        case STOP_RECORDING_TRANSACTION:
            err = stopRecordingTransactions();
            break;
        case EXTENSION_TRANSACTION:
            CHECK(reply != nullptr);
            err = reply->writeStrongBinder(getExtension());
@@ -403,23 +329,6 @@ status_t BBinder::transact(
        }
    }

    if (CC_UNLIKELY(kEnableKernelIpc && mRecordingOn && code != START_RECORDING_TRANSACTION)) {
        Extras* e = mExtras.load(std::memory_order_acquire);
        AutoMutex lock(e->mLock);
        if (mRecordingOn) {
            auto transaction =
                    android::binder::debug::RecordedTransaction::fromDetails(code, flags, data,
                                                                             *reply, err);
            if (transaction) {
                if (status_t err = transaction->dumpToFile(e->mRecordingFd); err != NO_ERROR) {
                    LOG(INFO) << "Failed to dump RecordedTransaction to file with error " << err;
                }
            } else {
                LOG(INFO) << "Failed to create RecordedTransaction object.";
            }
        }
    }

    return err;
}

+0 −185
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 <android-base/file.h>
#include <android-base/logging.h>
#include <binder/BinderRecordReplay.h>
#include <algorithm>

using android::Parcel;
using android::base::unique_fd;
using android::binder::debug::RecordedTransaction;

#define PADDING8(s) ((8 - (s) % 8) % 8)

static_assert(PADDING8(0) == 0);
static_assert(PADDING8(1) == 7);
static_assert(PADDING8(7) == 1);
static_assert(PADDING8(8) == 0);

// Transactions are sequentially recorded to the file descriptor in the following format:
//
// RecordedTransaction.TransactionHeader  (32 bytes)
// Sent Parcel data                       (getDataSize() bytes)
// padding                                (enough bytes to align the reply Parcel data to 8 bytes)
// Reply Parcel data                      (getReplySize() bytes)
// padding                                (enough bytes to align the next header to 8 bytes)
// [repeats with next transaction]
//
// Warning: This format is non-stable

RecordedTransaction::RecordedTransaction(RecordedTransaction&& t) noexcept {
    mHeader = {t.getCode(),      t.getFlags(),          t.getDataSize(),
               t.getReplySize(), t.getReturnedStatus(), t.getVersion()};
    mSent.setData(t.getDataParcel().data(), t.getDataSize());
    mReply.setData(t.getReplyParcel().data(), t.getReplySize());
}

std::optional<RecordedTransaction> RecordedTransaction::fromDetails(uint32_t code, uint32_t flags,
                                                                    const Parcel& dataParcel,
                                                                    const Parcel& replyParcel,
                                                                    status_t err) {
    RecordedTransaction t;
    t.mHeader = {code,
                 flags,
                 static_cast<uint64_t>(dataParcel.dataSize()),
                 static_cast<uint64_t>(replyParcel.dataSize()),
                 static_cast<int32_t>(err),
                 dataParcel.isForRpc() ? static_cast<uint32_t>(1) : static_cast<uint32_t>(0)};

    if (t.mSent.setData(dataParcel.data(), t.getDataSize()) != android::NO_ERROR) {
        LOG(INFO) << "Failed to set sent parcel data.";
        return std::nullopt;
    }

    if (t.mReply.setData(replyParcel.data(), t.getReplySize()) != android::NO_ERROR) {
        LOG(INFO) << "Failed to set reply parcel data.";
        return std::nullopt;
    }

    return std::optional<RecordedTransaction>(std::move(t));
}

std::optional<RecordedTransaction> RecordedTransaction::fromFile(const unique_fd& fd) {
    RecordedTransaction t;
    if (!android::base::ReadFully(fd, &t.mHeader, sizeof(mHeader))) {
        LOG(INFO) << "Failed to read transactionHeader from fd " << fd.get();
        return std::nullopt;
    }
    if (t.getVersion() != 0) {
        LOG(INFO) << "File corrupted: transaction version is not 0.";
        return std::nullopt;
    }

    std::vector<uint8_t> bytes;
    bytes.resize(t.getDataSize());
    if (!android::base::ReadFully(fd, bytes.data(), t.getDataSize())) {
        LOG(INFO) << "Failed to read sent parcel data from fd " << fd.get();
        return std::nullopt;
    }
    if (t.mSent.setData(bytes.data(), t.getDataSize()) != android::NO_ERROR) {
        LOG(INFO) << "Failed to set sent parcel data.";
        return std::nullopt;
    }

    uint8_t padding[7];
    if (!android::base::ReadFully(fd, padding, PADDING8(t.getDataSize()))) {
        LOG(INFO) << "Failed to read sent parcel padding from fd " << fd.get();
        return std::nullopt;
    }
    if (std::any_of(padding, padding + 7, [](uint8_t i) { return i != 0; })) {
        LOG(INFO) << "File corrupted: padding isn't 0.";
        return std::nullopt;
    }

    bytes.resize(t.getReplySize());
    if (!android::base::ReadFully(fd, bytes.data(), t.getReplySize())) {
        LOG(INFO) << "Failed to read reply parcel data from fd " << fd.get();
        return std::nullopt;
    }
    if (t.mReply.setData(bytes.data(), t.getReplySize()) != android::NO_ERROR) {
        LOG(INFO) << "Failed to set reply parcel data.";
        return std::nullopt;
    }

    if (!android::base::ReadFully(fd, padding, PADDING8(t.getReplySize()))) {
        LOG(INFO) << "Failed to read parcel padding from fd " << fd.get();
        return std::nullopt;
    }
    if (std::any_of(padding, padding + 7, [](uint8_t i) { return i != 0; })) {
        LOG(INFO) << "File corrupted: padding isn't 0.";
        return std::nullopt;
    }

    return std::optional<RecordedTransaction>(std::move(t));
}

android::status_t RecordedTransaction::dumpToFile(const unique_fd& fd) const {
    if (!android::base::WriteFully(fd, &mHeader, sizeof(mHeader))) {
        LOG(INFO) << "Failed to write transactionHeader to fd " << fd.get();
        return UNKNOWN_ERROR;
    }
    if (!android::base::WriteFully(fd, mSent.data(), getDataSize())) {
        LOG(INFO) << "Failed to write sent parcel data to fd " << fd.get();
        return UNKNOWN_ERROR;
    }
    const uint8_t zeros[7] = {0};
    if (!android::base::WriteFully(fd, zeros, PADDING8(getDataSize()))) {
        LOG(INFO) << "Failed to write sent parcel padding to fd " << fd.get();
        return UNKNOWN_ERROR;
    }
    if (!android::base::WriteFully(fd, mReply.data(), getReplySize())) {
        LOG(INFO) << "Failed to write reply parcel data to fd " << fd.get();
        return UNKNOWN_ERROR;
    }
    if (!android::base::WriteFully(fd, zeros, PADDING8(getReplySize()))) {
        LOG(INFO) << "Failed to write reply parcel padding to fd " << fd.get();
        return UNKNOWN_ERROR;
    }
    return NO_ERROR;
}

uint32_t RecordedTransaction::getCode() const {
    return mHeader.code;
}

uint32_t RecordedTransaction::getFlags() const {
    return mHeader.flags;
}

uint64_t RecordedTransaction::getDataSize() const {
    return mHeader.dataSize;
}

uint64_t RecordedTransaction::getReplySize() const {
    return mHeader.replySize;
}

int32_t RecordedTransaction::getReturnedStatus() const {
    return mHeader.statusReturned;
}

uint32_t RecordedTransaction::getVersion() const {
    return mHeader.version;
}

const Parcel& RecordedTransaction::getDataParcel() const {
    return mSent;
}

const Parcel& RecordedTransaction::getReplyParcel() const {
    return mReply;
}
+0 −14
Original line number Diff line number Diff line
@@ -30,8 +30,6 @@

#include "BuildFlags.h"

#include <android-base/file.h>

//#undef ALOGV
//#define ALOGV(...) fprintf(stderr, __VA_ARGS__)

@@ -301,18 +299,6 @@ status_t BpBinder::pingBinder()
    return transact(PING_TRANSACTION, data, &reply);
}

status_t BpBinder::startRecordingBinder(const android::base::unique_fd& fd) {
    Parcel send, reply;
    send.writeUniqueFileDescriptor(fd);
    return transact(START_RECORDING_TRANSACTION, send, &reply);
}

status_t BpBinder::stopRecordingBinder() {
    Parcel data, reply;
    data.markForBinder(sp<BpBinder>::fromExisting(this));
    return transact(STOP_RECORDING_TRANSACTION, data, &reply);
}

status_t BpBinder::dump(int fd, const Vector<String16>& args)
{
    Parcel send;
+1 −7
Original line number Diff line number Diff line
@@ -105,12 +105,6 @@ public:
    [[nodiscard]] status_t setRpcClientDebug(android::base::unique_fd clientFd,
                                             const sp<IBinder>& keepAliveBinder);

    // Start recording transactions to the unique_fd in data.
    // See BinderRecordReplay.h for more details.
    [[nodiscard]] status_t startRecordingTransactions(const Parcel& data);
    // Stop the current recording.
    [[nodiscard]] status_t stopRecordingTransactions();

protected:
    virtual             ~BBinder();

@@ -137,7 +131,7 @@ private:
    friend ::android::internal::Stability;
    int16_t mStability;
    bool mParceled;
    bool mRecordingOn;
    uint8_t mReserved0;

#ifdef __LP64__
    int32_t mReserved1;
Loading