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

Commit 5623d1a7 authored by Steven Moreland's avatar Steven Moreland
Browse files

libbinder: RpcAddress is uint64_t

This was originally a 32 byte array filled by /dev/urandom, because the
expectation was to build off of this in order to allow for transitive
binder sends (process A sends a binder to process B which sends it to
process C and then allowing C to talk directly to process A - this would
need some large cryptographic token representing the binder and address
information in order to securely open up a new communication channel to
A).

However, this is currently not supported in RPC binder (and even if it
were - which I find unlikely b/c of the security complexity, a lot more
work would need to be done). Simply, we don't need to pay this cost
since we're not using it.

Bug: 182940634
Fixes: 182939933
Test: binderRpcBenchmark
------------------------------------------------------------------------------------
Benchmark                                          Time             CPU
------------------------------------------------------------------------------------
// before this change
BM_repeatBinder/0                              61680 ns        33016 ns
BM_repeatBinder/1                             162368 ns        87825 ns

// after this change
BM_repeatBinder/0                              60041 ns        32787 ns
BM_repeatBinder/1                             109857 ns        55605 ns

-> reduce overhead of rpc binder (when sending many binders) by the
overhead of a normal kernel binder call (still a ways to go)

Change-Id: If27bffb5611bdd17f16156ddfe50ac2449f6046a
parent 826367f2
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -120,7 +120,6 @@ cc_library {
        "ParcelFileDescriptor.cpp",
        "PersistableBundle.cpp",
        "ProcessState.cpp",
        "RpcAddress.cpp",
        "RpcSession.cpp",
        "RpcServer.cpp",
        "RpcState.cpp",
+2 −2
Original line number Diff line number Diff line
@@ -156,7 +156,7 @@ sp<BpBinder> BpBinder::create(int32_t handle) {
    return sp<BpBinder>::make(BinderHandle{handle}, trackedUid);
}

sp<BpBinder> BpBinder::create(const sp<RpcSession>& session, const RpcAddress& address) {
sp<BpBinder> BpBinder::create(const sp<RpcSession>& session, uint64_t address) {
    LOG_ALWAYS_FATAL_IF(session == nullptr, "BpBinder::create null session");

    // These are not currently tracked, since there is no UID or other
@@ -193,7 +193,7 @@ bool BpBinder::isRpcBinder() const {
    return std::holds_alternative<RpcHandle>(mHandle);
}

const RpcAddress& BpBinder::rpcAddress() const {
uint64_t BpBinder::rpcAddress() const {
    return std::get<RpcHandle>(mHandle).address;
}

+7 −7
Original line number Diff line number Diff line
@@ -205,11 +205,11 @@ status_t Parcel::flattenBinder(const sp<IBinder>& binder) {
        if (binder) {
            status_t status = writeInt32(1); // non-null
            if (status != OK) return status;
            RpcAddress address = RpcAddress::zero();
            uint64_t address;
            // TODO(b/167966510): need to undo this if the Parcel is not sent
            status = mSession->state()->onBinderLeaving(mSession, binder, &address);
            if (status != OK) return status;
            status = address.writeToParcel(this);
            status = writeUint64(address);
            if (status != OK) return status;
        } else {
            status_t status = writeInt32(0); // null
@@ -279,15 +279,15 @@ status_t Parcel::unflattenBinder(sp<IBinder>* out) const
    if (isForRpc()) {
        LOG_ALWAYS_FATAL_IF(mSession == nullptr, "RpcSession required to read from remote parcel");

        int32_t isNull;
        status_t status = readInt32(&isNull);
        int32_t isPresent;
        status_t status = readInt32(&isPresent);
        if (status != OK) return status;

        sp<IBinder> binder;

        if (isNull & 1) {
            auto addr = RpcAddress::zero();
            if (status_t status = addr.readFromParcel(*this); status != OK) return status;
        if (isPresent & 1) {
            uint64_t addr;
            if (status_t status = readUint64(&addr); status != OK) return status;
            if (status_t status = mSession->state()->onBinderEntering(mSession, addr, &binder);
                status != OK)
                return status;

libs/binder/RpcAddress.cpp

deleted100644 → 0
+0 −112
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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 <binder/RpcAddress.h>

#include <android-base/hex.h>
#include <binder/Parcel.h>

#include "Debug.h"
#include "RpcState.h"
#include "RpcWireFormat.h"

namespace android {

RpcAddress RpcAddress::zero() {
    return RpcAddress();
}

bool RpcAddress::isZero() const {
    RpcWireAddress ZERO{.options = 0};
    return memcmp(mRawAddr.get(), &ZERO, sizeof(RpcWireAddress)) == 0;
}

static void ReadRandomBytes(uint8_t* buf, size_t len) {
    int fd = TEMP_FAILURE_RETRY(open("/dev/urandom", O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
    if (fd == -1) {
        ALOGE("%s: cannot read /dev/urandom", __func__);
        return;
    }

    size_t n;
    while ((n = TEMP_FAILURE_RETRY(read(fd, buf, len))) > 0) {
        len -= n;
        buf += n;
    }
    if (len > 0) {
        ALOGW("%s: there are %d bytes skipped", __func__, (int)len);
    }
    close(fd);
}

RpcAddress RpcAddress::random(bool forServer) {
    // The remainder of this header acts as reserved space for different kinds
    // of binder objects.
    uint64_t options = RPC_WIRE_ADDRESS_OPTION_CREATED;

    // servers and clients allocate addresses independently, so this bit can
    // tell you where an address originates
    if (forServer) options |= RPC_WIRE_ADDRESS_OPTION_FOR_SERVER;

    RpcAddress ret;
    RpcWireAddress* raw = ret.mRawAddr.get();

    raw->options = options;
    ReadRandomBytes(raw->address, sizeof(raw->address));

    LOG_RPC_DETAIL("Creating new address: %s", ret.toString().c_str());
    return ret;
}

bool RpcAddress::isForServer() const {
    return mRawAddr.get()->options & RPC_WIRE_ADDRESS_OPTION_FOR_SERVER;
}

bool RpcAddress::isRecognizedType() const {
    uint64_t allKnownOptions = RPC_WIRE_ADDRESS_OPTION_CREATED | RPC_WIRE_ADDRESS_OPTION_FOR_SERVER;
    return (mRawAddr.get()->options & ~allKnownOptions) == 0;
}

RpcAddress RpcAddress::fromRawEmbedded(const RpcWireAddress* raw) {
    RpcAddress addr;
    memcpy(addr.mRawAddr.get(), raw, sizeof(RpcWireAddress));
    return addr;
}

const RpcWireAddress& RpcAddress::viewRawEmbedded() const {
    return *mRawAddr.get();
}

bool RpcAddress::operator<(const RpcAddress& rhs) const {
    return std::memcmp(mRawAddr.get(), rhs.mRawAddr.get(), sizeof(RpcWireAddress)) < 0;
}

std::string RpcAddress::toString() const {
    return base::HexString(mRawAddr.get(), sizeof(RpcWireAddress));
}

status_t RpcAddress::writeToParcel(Parcel* parcel) const {
    return parcel->write(mRawAddr.get(), sizeof(RpcWireAddress));
}

status_t RpcAddress::readFromParcel(const Parcel& parcel) {
    return parcel.read(mRawAddr.get(), sizeof(RpcWireAddress));
}

RpcAddress::~RpcAddress() {}
RpcAddress::RpcAddress() : mRawAddr(std::make_shared<RpcWireAddress>()) {}

} // namespace android
+1 −1
Original line number Diff line number Diff line
@@ -226,7 +226,7 @@ status_t RpcSession::transact(const sp<IBinder>& binder, uint32_t code, const Pa
                             sp<RpcSession>::fromExisting(this), reply, flags);
}

status_t RpcSession::sendDecStrong(const RpcAddress& address) {
status_t RpcSession::sendDecStrong(uint64_t address) {
    ExclusiveConnection connection;
    status_t status = ExclusiveConnection::find(sp<RpcSession>::fromExisting(this),
                                                ConnectionUse::CLIENT_REFCOUNT, &connection);
Loading