blob: bb5989dec8e46f7d4b8b444eabee1d8573084180 [file] [log] [blame]
/*
* 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 copy-able 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* const* const instances, size_t numInstances, void* data,
ABinderRpc_AccessorProviderUserData_deleteCallback onDelete) {
if (data && onDelete == nullptr) {
ALOGE("If a non-null data ptr is passed to ABinderRpc_registerAccessorProvider, then a "
"ABinderRpc_AccessorProviderUserData_deleteCallback must also be passed to delete "
"the data object once the ABinderRpc_AccessorProvider is removed.");
return nullptr;
}
// 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);
if (provider == nullptr) {
ALOGE("Null provider passed to ABinderRpc_registerAccessorProvider");
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]);
}
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 copy-able 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 also 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 STATUS_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;
}
}
binder_status_t ABinderRpc_Accessor_delegateAccessor(const char* instance, AIBinder* accessor,
AIBinder** outDelegator) {
LOG_ALWAYS_FATAL_IF(outDelegator == nullptr, "The outDelegator argument is null");
if (instance == nullptr || accessor == nullptr) {
ALOGW("instance or accessor arguments to ABinderRpc_Accessor_delegateBinder are null");
*outDelegator = nullptr;
return STATUS_UNEXPECTED_NULL;
}
sp<IBinder> accessorBinder = accessor->getBinder();
sp<IBinder> delegator;
status_t status = android::delegateAccessor(String16(instance), accessorBinder, &delegator);
if (status != OK) {
return PruneStatusT(status);
}
sp<AIBinder> binder = ABpBinder::lookupOrCreateFromBinder(delegator);
// This AIBinder needs a strong ref to pass ownership to the caller
binder->incStrong(nullptr);
*outDelegator = binder.get();
return STATUS_OK;
}
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 ABinderRpc_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(
"ABinderRpc_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("ABinderRpc_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(
"ABinderRpc_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("ABinderRpc APIs only support AF_VSOCK right now but the supplied sockaddr::sa_family "
"is: %hu",
addr->sa_family);
return nullptr;
}
void ABinderRpc_ConnectionInfo_delete(ABinderRpc_ConnectionInfo* info) {
delete info;
}