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

Commit fa8e2254 authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Add libbinder_ndk systemapi support for injecting RPC binder accessors"...

Merge "Add libbinder_ndk systemapi support for injecting RPC binder accessors" into main am: 7cc4a37a am: 55c73dd0

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



Change-Id: I7691dbadeab1ab10c007f9a9a36b0f7b832cd7e0
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents e27fd0a3 55c73dd0
Loading
Loading
Loading
Loading
+38 −6
Original line number Diff line number Diff line
@@ -157,12 +157,21 @@ protected:

class AccessorProvider {
public:
    AccessorProvider(RpcAccessorProvider&& provider) : mProvider(std::move(provider)) {}
    sp<IBinder> provide(const String16& name) { return mProvider(name); }
    AccessorProvider(std::set<std::string>&& instances, RpcAccessorProvider&& provider)
          : mInstances(std::move(instances)), mProvider(std::move(provider)) {}
    sp<IBinder> provide(const String16& name) {
        if (mInstances.count(String8(name).c_str()) > 0) {
            return mProvider(name);
        } else {
            return nullptr;
        }
    }
    const std::set<std::string>& instances() { return mInstances; }

private:
    AccessorProvider() = delete;

    std::set<std::string> mInstances;
    RpcAccessorProvider mProvider;
};

@@ -318,10 +327,32 @@ sp<IServiceManager> getServiceManagerShimFromAidlServiceManagerForTests(
    return sp<CppBackendShim>::make(sp<BackendUnifiedServiceManager>::make(sm));
}

std::weak_ptr<AccessorProvider> addAccessorProvider(RpcAccessorProvider&& providerCallback) {
// gAccessorProvidersMutex must be locked already
static bool isInstanceProvidedLocked(const std::string& instance) {
    return gAccessorProviders.end() !=
            std::find_if(gAccessorProviders.begin(), gAccessorProviders.end(),
                         [&instance](const AccessorProviderEntry& entry) {
                             return entry.mProvider->instances().count(instance) > 0;
                         });
}

std::weak_ptr<AccessorProvider> addAccessorProvider(std::set<std::string>&& instances,
                                                    RpcAccessorProvider&& providerCallback) {
    if (instances.empty()) {
        ALOGE("Set of instances is empty! Need a non empty set of instances to provide for.");
        return std::weak_ptr<AccessorProvider>();
    }
    std::lock_guard<std::mutex> lock(gAccessorProvidersMutex);
    for (const auto& instance : instances) {
        if (isInstanceProvidedLocked(instance)) {
            ALOGE("The instance %s is already provided for by a previously added "
                  "RpcAccessorProvider.",
                  instance.c_str());
            return std::weak_ptr<AccessorProvider>();
        }
    }
    std::shared_ptr<AccessorProvider> provider =
            std::make_shared<AccessorProvider>(std::move(providerCallback));
            std::make_shared<AccessorProvider>(std::move(instances), std::move(providerCallback));
    std::weak_ptr<AccessorProvider> receipt = provider;
    gAccessorProviders.push_back(AccessorProviderEntry(std::move(provider)));

@@ -331,8 +362,9 @@ std::weak_ptr<AccessorProvider> addAccessorProvider(RpcAccessorProvider&& provid
status_t removeAccessorProvider(std::weak_ptr<AccessorProvider> wProvider) {
    std::shared_ptr<AccessorProvider> provider = wProvider.lock();
    if (provider == nullptr) {
        ALOGE("The provider supplied to removeAccessorProvider has already been removed.");
        return NAME_NOT_FOUND;
        ALOGE("The provider supplied to removeAccessorProvider has already been removed or the "
              "argument to this function was nullptr.");
        return BAD_VALUE;
    }
    std::lock_guard<std::mutex> lock(gAccessorProvidersMutex);
    size_t sizeBefore = gAccessorProviders.size();
+20 −3
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <utils/String16.h>
#include <utils/Vector.h>
#include <optional>
#include <set>

namespace android {

@@ -224,20 +225,36 @@ LIBBINDER_EXPORTED bool checkPermission(const String16& permission, pid_t pid, u
typedef std::function<status_t(const String16& name, sockaddr* outAddr, socklen_t addrSize)>
        RpcSocketAddressProvider;

typedef std::function<sp<IBinder>(const String16& name)> RpcAccessorProvider;
/**
 * This callback provides a way for clients to get access to remote services by
 * providing an Accessor object from libbinder that can connect to the remote
 * service over sockets.
 *
 * \param instance name of the service that the callback will provide an
 *        Accessor for. The provided accessor will be used to set up a client
 *        RPC connection in libbinder in order to return a binder for the
 *        associated remote service.
 *
 * \return IBinder of the Accessor object that libbinder implements.
 *         nullptr if the provider callback doesn't know how to reach the
 *         service or doesn't want to provide access for any other reason.
 */
typedef std::function<sp<IBinder>(const String16& instance)> RpcAccessorProvider;

class AccessorProvider;

/**
 * Register an accessor provider for the service manager APIs.
 * Register a RpcAccessorProvider for the service manager APIs.
 *
 * \param instances that the RpcAccessorProvider knows about and can provide an
 *        Accessor for.
 * \param provider callback that generates Accessors.
 *
 * \return A pointer used as a recept for the successful addition of the
 *         AccessorProvider. This is needed to unregister it later.
 */
[[nodiscard]] LIBBINDER_EXPORTED std::weak_ptr<AccessorProvider> addAccessorProvider(
        RpcAccessorProvider&& providerCallback);
        std::set<std::string>&& instances, RpcAccessorProvider&& providerCallback);

/**
 * Remove an accessor provider using the pointer provided by addAccessorProvider
+1 −0
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ cc_library {
        "persistable_bundle.cpp",
        "process.cpp",
        "service_manager.cpp",
        "binder_rpc.cpp",
    ],

    static_libs: [
+352 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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/binder_rpc.h>
#include <arpa/inet.h>
#include <binder/IServiceManager.h>
#include <linux/vm_sockets.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/un.h>

#include <variant>

#include "ibinder_internal.h"
#include "status_internal.h"

using ::android::defaultServiceManager;
using ::android::IBinder;
using ::android::IServiceManager;
using ::android::OK;
using ::android::sp;
using ::android::status_t;
using ::android::String16;
using ::android::String8;
using ::android::binder::Status;

#define LOG_ACCESSOR_DEBUG(...)
// #define LOG_ACCESSOR_DEBUG(...) ALOGW(__VA_ARGS__)

struct ABinderRpc_ConnectionInfo {
    std::variant<sockaddr_vm, sockaddr_un, sockaddr_in> addr;
};

struct ABinderRpc_Accessor final : public ::android::RefBase {
    static ABinderRpc_Accessor* make(const char* instance, const sp<IBinder>& binder) {
        LOG_ALWAYS_FATAL_IF(binder == nullptr, "ABinderRpc_Accessor requires a non-null binder");
        status_t status = android::validateAccessor(String16(instance), binder);
        if (status != OK) {
            ALOGE("The given binder is not a valid IAccessor for %s. Status: %s", instance,
                  android::statusToString(status).c_str());
            return nullptr;
        }
        return new ABinderRpc_Accessor(binder);
    }

    sp<IBinder> asBinder() { return mAccessorBinder; }

    ~ABinderRpc_Accessor() { LOG_ACCESSOR_DEBUG("ABinderRpc_Accessor dtor"); }

   private:
    ABinderRpc_Accessor(sp<IBinder> accessor) : mAccessorBinder(accessor) {}
    ABinderRpc_Accessor() = delete;
    sp<IBinder> mAccessorBinder;
};

struct ABinderRpc_AccessorProvider {
   public:
    static ABinderRpc_AccessorProvider* make(std::weak_ptr<android::AccessorProvider> cookie) {
        if (cookie.expired()) {
            ALOGE("Null AccessorProvider cookie from libbinder");
            return nullptr;
        }
        return new ABinderRpc_AccessorProvider(cookie);
    }
    std::weak_ptr<android::AccessorProvider> mProviderCookie;

   private:
    ABinderRpc_AccessorProvider() = delete;

    ABinderRpc_AccessorProvider(std::weak_ptr<android::AccessorProvider> provider)
        : mProviderCookie(provider) {}
};

struct OnDeleteProviderHolder {
    OnDeleteProviderHolder(void* data, ABinderRpc_AccessorProviderUserData_deleteCallback onDelete)
        : mData(data), mOnDelete(onDelete) {}
    ~OnDeleteProviderHolder() {
        if (mOnDelete) {
            mOnDelete(mData);
        }
    }
    void* mData;
    ABinderRpc_AccessorProviderUserData_deleteCallback mOnDelete;
    // needs to be copyable for std::function, but we will never copy it
    OnDeleteProviderHolder(const OnDeleteProviderHolder&) {
        LOG_ALWAYS_FATAL("This object can't be copied!");
    }

   private:
    OnDeleteProviderHolder() = delete;
};

ABinderRpc_AccessorProvider* ABinderRpc_registerAccessorProvider(
        ABinderRpc_AccessorProvider_getAccessorCallback provider, const char** instances,
        size_t numInstances, void* data,
        ABinderRpc_AccessorProviderUserData_deleteCallback onDelete) {
    if (provider == nullptr) {
        ALOGE("Null provider passed to ABinderRpc_registerAccessorProvider");
        return nullptr;
    }
    if (data && onDelete == nullptr) {
        ALOGE("If a non-null data ptr is passed to ABinderRpc_registerAccessorProvider, then a "
              "ABinderRpc_AccessorProviderUserData_deleteCallback must alse be passed to delete "
              "the data object once the ABinderRpc_AccessorProvider is removed.");
        return nullptr;
    }
    if (numInstances == 0 || instances == nullptr) {
        ALOGE("No instances passed to ABinderRpc_registerAccessorProvider. numInstances: %zu",
              numInstances);
        return nullptr;
    }
    std::set<std::string> instanceStrings;
    for (size_t i = 0; i < numInstances; i++) {
        instanceStrings.emplace(instances[i]);
    }
    // call the onDelete when the last reference of this goes away (when the
    // last reference to the generate std::function goes away).
    std::shared_ptr<OnDeleteProviderHolder> onDeleteHolder =
            std::make_shared<OnDeleteProviderHolder>(data, onDelete);
    android::RpcAccessorProvider generate = [provider,
                                             onDeleteHolder](const String16& name) -> sp<IBinder> {
        ABinderRpc_Accessor* accessor = provider(String8(name).c_str(), onDeleteHolder->mData);
        if (accessor == nullptr) {
            ALOGE("The supplied ABinderRpc_AccessorProvider_getAccessorCallback returned nullptr");
            return nullptr;
        }
        sp<IBinder> binder = accessor->asBinder();
        ABinderRpc_Accessor_delete(accessor);
        return binder;
    };

    std::weak_ptr<android::AccessorProvider> cookie =
            android::addAccessorProvider(std::move(instanceStrings), std::move(generate));
    return ABinderRpc_AccessorProvider::make(cookie);
}

void ABinderRpc_unregisterAccessorProvider(ABinderRpc_AccessorProvider* provider) {
    if (provider == nullptr) {
        LOG_ALWAYS_FATAL("Attempting to remove a null ABinderRpc_AccessorProvider");
    }

    status_t status = android::removeAccessorProvider(provider->mProviderCookie);
    // There shouldn't be a way to get here because the caller won't have a
    // ABinderRpc_AccessorProvider* without calling ABinderRpc_registerAccessorProvider
    LOG_ALWAYS_FATAL_IF(status == android::BAD_VALUE, "Provider (%p) is not valid. Status: %s",
                        provider, android::statusToString(status).c_str());
    LOG_ALWAYS_FATAL_IF(status == android::NAME_NOT_FOUND,
                        "Provider (%p) was already unregistered. Status: %s", provider,
                        android::statusToString(status).c_str());
    LOG_ALWAYS_FATAL_IF(status != OK,
                        "Unknown error when attempting to unregister ABinderRpc_AccessorProvider "
                        "(%p). Status: %s",
                        provider, android::statusToString(status).c_str());

    delete provider;
}

struct OnDeleteConnectionInfoHolder {
    OnDeleteConnectionInfoHolder(void* data,
                                 ABinderRpc_ConnectionInfoProviderUserData_delete onDelete)
        : mData(data), mOnDelete(onDelete) {}
    ~OnDeleteConnectionInfoHolder() {
        if (mOnDelete) {
            mOnDelete(mData);
        }
    }
    void* mData;
    ABinderRpc_ConnectionInfoProviderUserData_delete mOnDelete;
    // needs to be copyable for std::function, but we will never copy it
    OnDeleteConnectionInfoHolder(const OnDeleteConnectionInfoHolder&) {
        LOG_ALWAYS_FATAL("This object can't be copied!");
    }

   private:
    OnDeleteConnectionInfoHolder() = delete;
};

ABinderRpc_Accessor* ABinderRpc_Accessor_new(
        const char* instance, ABinderRpc_ConnectionInfoProvider provider, void* data,
        ABinderRpc_ConnectionInfoProviderUserData_delete onDelete) {
    if (instance == nullptr) {
        ALOGE("Instance argument must be valid when calling ABinderRpc_Accessor_new");
        return nullptr;
    }
    if (data && onDelete == nullptr) {
        ALOGE("If a non-null data ptr is passed to ABinderRpc_Accessor_new, then a "
              "ABinderRpc_ConnectionInfoProviderUserData_delete callback must alse be passed to "
              "delete "
              "the data object once the ABinderRpc_Accessor is deleted.");
        return nullptr;
    }
    std::shared_ptr<OnDeleteConnectionInfoHolder> onDeleteHolder =
            std::make_shared<OnDeleteConnectionInfoHolder>(data, onDelete);
    if (provider == nullptr) {
        ALOGE("Can't create a new ABinderRpc_Accessor without a ABinderRpc_ConnectionInfoProvider "
              "and it is "
              "null");
        return nullptr;
    }
    android::RpcSocketAddressProvider generate = [provider, onDeleteHolder](
                                                         const String16& name, sockaddr* outAddr,
                                                         size_t addrLen) -> status_t {
        std::unique_ptr<ABinderRpc_ConnectionInfo> info(
                provider(String8(name).c_str(), onDeleteHolder->mData));
        if (info == nullptr) {
            ALOGE("The supplied ABinderRpc_ConnectionInfoProvider returned nullptr");
            return android::NAME_NOT_FOUND;
        }
        if (auto addr = std::get_if<sockaddr_vm>(&info->addr)) {
            LOG_ALWAYS_FATAL_IF(addr->svm_family != AF_VSOCK,
                                "ABinderRpc_ConnectionInfo invalid family");
            if (addrLen < sizeof(sockaddr_vm)) {
                ALOGE("Provided outAddr is too small! Expecting %zu, got %zu", sizeof(sockaddr_vm),
                      addrLen);
                return android::BAD_VALUE;
            }
            LOG_ACCESSOR_DEBUG(
                    "Connection info provider found AF_VSOCK. family %d, port %d, cid %d",
                    addr->svm_family, addr->svm_port, addr->svm_cid);
            *reinterpret_cast<sockaddr_vm*>(outAddr) = *addr;
        } else if (auto addr = std::get_if<sockaddr_un>(&info->addr)) {
            LOG_ALWAYS_FATAL_IF(addr->sun_family != AF_UNIX,
                                "ABinderRpc_ConnectionInfo invalid family");
            if (addrLen < sizeof(sockaddr_un)) {
                ALOGE("Provided outAddr is too small! Expecting %zu, got %zu", sizeof(sockaddr_un),
                      addrLen);
                return android::BAD_VALUE;
            }
            *reinterpret_cast<sockaddr_un*>(outAddr) = *addr;
        } else if (auto addr = std::get_if<sockaddr_in>(&info->addr)) {
            LOG_ALWAYS_FATAL_IF(addr->sin_family != AF_INET,
                                "ABinderRpc_ConnectionInfo invalid family");
            if (addrLen < sizeof(sockaddr_in)) {
                ALOGE("Provided outAddr is too small! Expecting %zu, got %zu", sizeof(sockaddr_in),
                      addrLen);
                return android::BAD_VALUE;
            }
            *reinterpret_cast<sockaddr_in*>(outAddr) = *addr;
        } else {
            LOG_ALWAYS_FATAL(
                    "Unsupported address family type when trying to get ARpcConnection info. A "
                    "new variant was added to the ABinderRpc_ConnectionInfo and this needs to be "
                    "updated.");
        }
        return OK;
    };
    sp<IBinder> accessorBinder = android::createAccessor(String16(instance), std::move(generate));
    if (accessorBinder == nullptr) {
        ALOGE("service manager did not get us an accessor");
        return nullptr;
    }
    LOG_ACCESSOR_DEBUG("service manager found an accessor, so returning one now from _new");
    return ABinderRpc_Accessor::make(instance, accessorBinder);
}

void ABinderRpc_Accessor_delete(ABinderRpc_Accessor* accessor) {
    delete accessor;
}

AIBinder* ABinderRpc_Accessor_asBinder(ABinderRpc_Accessor* accessor) {
    if (!accessor) {
        ALOGE("ABinderRpc_Accessor argument is null.");
        return nullptr;
    }

    sp<IBinder> binder = accessor->asBinder();
    sp<AIBinder> aBinder = ABpBinder::lookupOrCreateFromBinder(binder);
    AIBinder* ptr = aBinder.get();
    if (ptr == nullptr) {
        LOG_ALWAYS_FATAL("Failed to lookupOrCreateFromBinder");
    }
    ptr->incStrong(nullptr);
    return ptr;
}

ABinderRpc_Accessor* ABinderRpc_Accessor_fromBinder(const char* instance, AIBinder* binder) {
    if (!binder) {
        ALOGE("binder argument is null");
        return nullptr;
    }
    sp<IBinder> accessorBinder = binder->getBinder();
    if (accessorBinder) {
        return ABinderRpc_Accessor::make(instance, accessorBinder);
    } else {
        ALOGE("Attempting to get an ABinderRpc_Accessor for %s but AIBinder::getBinder returned "
              "null",
              instance);
        return nullptr;
    }
}

ABinderRpc_ConnectionInfo* ABinderRpc_ConnectionInfo_new(const sockaddr* addr, socklen_t len) {
    if (addr == nullptr || len < 0 || static_cast<size_t>(len) < sizeof(sa_family_t)) {
        ALOGE("Invalid arguments in Arpc_Connection_new");
        return nullptr;
    }
    // socklen_t was int32_t on 32-bit and uint32_t on 64 bit.
    size_t socklen = len < 0 || static_cast<uintmax_t>(len) > SIZE_MAX ? 0 : len;

    if (addr->sa_family == AF_VSOCK) {
        if (len != sizeof(sockaddr_vm)) {
            ALOGE("Incorrect size of %zu for AF_VSOCK sockaddr_vm. Expecting %zu", socklen,
                  sizeof(sockaddr_vm));
            return nullptr;
        }
        sockaddr_vm vm = *reinterpret_cast<const sockaddr_vm*>(addr);
        LOG_ACCESSOR_DEBUG("Arpc_ConnectionInfo_new found AF_VSOCK. family %d, port %d, cid %d",
                           vm.svm_family, vm.svm_port, vm.svm_cid);
        return new ABinderRpc_ConnectionInfo(vm);
    } else if (addr->sa_family == AF_UNIX) {
        if (len != sizeof(sockaddr_un)) {
            ALOGE("Incorrect size of %zu for AF_UNIX sockaddr_un. Expecting %zu", socklen,
                  sizeof(sockaddr_un));
            return nullptr;
        }
        sockaddr_un un = *reinterpret_cast<const sockaddr_un*>(addr);
        LOG_ACCESSOR_DEBUG("Arpc_ConnectionInfo_new found AF_UNIX. family %d, path %s",
                           un.sun_family, un.sun_path);
        return new ABinderRpc_ConnectionInfo(un);
    } else if (addr->sa_family == AF_INET) {
        if (len != sizeof(sockaddr_in)) {
            ALOGE("Incorrect size of %zu for AF_INET sockaddr_in. Expecting %zu", socklen,
                  sizeof(sockaddr_in));
            return nullptr;
        }
        sockaddr_in in = *reinterpret_cast<const sockaddr_in*>(addr);
        LOG_ACCESSOR_DEBUG("Arpc_ConnectionInfo_new found AF_INET. family %d, address %s, port %d",
                           in.sin_family, inet_ntoa(in.sin_addr), ntohs(in.sin_port));
        return new ABinderRpc_ConnectionInfo(in);
    }

    ALOGE("ARpc APIs only support AF_VSOCK right now but the supplied sockadder::sa_family is: %hu",
          addr->sa_family);
    return nullptr;
}

void ABinderRpc_ConnectionInfo_delete(ABinderRpc_ConnectionInfo* info) {
    delete info;
}
+261 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading