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

Commit c370db49 authored by Devin Moore's avatar Devin Moore
Browse files

Add libbinder_ndk systemapi support for injecting RPC binder accessors

This allows libbinder_ndk to set up client connections to binder RPC
services underneath the libbinder_ndk service manager APIs.

It requires callbacks to be added to the local process to get connection
information that the client is responsible for obtaining.
Once these callbacks are added to libbinder, any client elswhere in the
process using the service manager APIs will be able to get and use a
binder for the service in the same way they do for kernel binder
services.

Test: atest binderRpcTest vm_accessor_test
Bug: 358427181
Change-Id: I528e84bac40efe13884a68ed851ecfb14dd27daa
parent daa348c0
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