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

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

Merge "Support IAccessor in libbinder for RPC services" into main am: 5c392a91

parents a04f638e 5c392a91
Loading
Loading
Loading
Loading
+80 −17
Original line number Diff line number Diff line
@@ -249,6 +249,25 @@ static std::vector<std::string> getVintfUpdatableNames(const std::string& apexNa
    return names;
}

static std::optional<std::string> getVintfAccessorName(const std::string& name) {
    AidlName aname;
    if (!AidlName::fill(name, &aname)) return std::nullopt;

    std::optional<std::string> accessor;
    forEachManifest([&](const ManifestWithDescription& mwd) {
        mwd.manifest->forEachInstance([&](const auto& manifestInstance) {
            if (manifestInstance.format() != vintf::HalFormat::AIDL) return true;
            if (manifestInstance.package() != aname.package) return true;
            if (manifestInstance.interface() != aname.iface) return true;
            if (manifestInstance.instance() != aname.instance) return true;
            accessor = manifestInstance.accessor();
            return false; // break (libvintf uses opposite convention)
        });
        return false; // continue
    });
    return accessor;
}

static std::optional<ConnectionInfo> getVintfConnectionInfo(const std::string& name) {
    AidlName aname;
    if (!AidlName::fill(name, &aname)) return std::nullopt;
@@ -364,23 +383,40 @@ ServiceManager::~ServiceManager() {
    }
}

Status ServiceManager::getService(const std::string& name, sp<IBinder>* outBinder) {
Status ServiceManager::getService(const std::string& name, os::Service* outService) {
    SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str()));

    *outBinder = tryGetService(name, true);
    *outService = tryGetService(name, true);
    // returns ok regardless of result for legacy reasons
    return Status::ok();
}

Status ServiceManager::checkService(const std::string& name, sp<IBinder>* outBinder) {
Status ServiceManager::checkService(const std::string& name, os::Service* outService) {
    SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str()));

    *outBinder = tryGetService(name, false);
    *outService = tryGetService(name, false);
    // returns ok regardless of result for legacy reasons
    return Status::ok();
}

sp<IBinder> ServiceManager::tryGetService(const std::string& name, bool startIfNotFound) {
os::Service ServiceManager::tryGetService(const std::string& name, bool startIfNotFound) {
    std::optional<std::string> accessorName;
#ifndef VENDORSERVICEMANAGER
    accessorName = getVintfAccessorName(name);
#endif
    if (accessorName.has_value()) {
        auto ctx = mAccess->getCallingContext();
        if (!mAccess->canFind(ctx, name)) {
            return os::Service::make<os::Service::Tag::accessor>(nullptr);
        }
        return os::Service::make<os::Service::Tag::accessor>(
                tryGetBinder(*accessorName, startIfNotFound));
    } else {
        return os::Service::make<os::Service::Tag::binder>(tryGetBinder(name, startIfNotFound));
    }
}

sp<IBinder> ServiceManager::tryGetBinder(const std::string& name, bool startIfNotFound) {
    SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str()));

    auto ctx = mAccess->getCallingContext();
@@ -565,8 +601,11 @@ Status ServiceManager::registerForNotifications(

    auto ctx = mAccess->getCallingContext();

    if (!mAccess->canFind(ctx, name)) {
        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux");
    // TODO(b/338541373): Implement the notification mechanism for services accessed via
    // IAccessor.
    std::optional<std::string> accessorName;
    if (auto status = canFindService(ctx, name, &accessorName); !status.isOk()) {
        return status;
    }

    // note - we could allow isolated apps to get notifications if we
@@ -613,8 +652,9 @@ Status ServiceManager::unregisterForNotifications(

    auto ctx = mAccess->getCallingContext();

    if (!mAccess->canFind(ctx, name)) {
        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
    std::optional<std::string> accessorName;
    if (auto status = canFindService(ctx, name, &accessorName); !status.isOk()) {
        return status;
    }

    bool found = false;
@@ -638,8 +678,9 @@ Status ServiceManager::isDeclared(const std::string& name, bool* outReturn) {

    auto ctx = mAccess->getCallingContext();

    if (!mAccess->canFind(ctx, name)) {
        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
    std::optional<std::string> accessorName;
    if (auto status = canFindService(ctx, name, &accessorName); !status.isOk()) {
        return status;
    }

    *outReturn = false;
@@ -662,8 +703,10 @@ binder::Status ServiceManager::getDeclaredInstances(const std::string& interface

    outReturn->clear();

    std::optional<std::string> _accessorName;
    for (const std::string& instance : allInstances) {
        if (mAccess->canFind(ctx, interface + "/" + instance)) {
        if (auto status = canFindService(ctx, interface + "/" + instance, &_accessorName);
            status.isOk()) {
            outReturn->push_back(instance);
        }
    }
@@ -681,8 +724,9 @@ Status ServiceManager::updatableViaApex(const std::string& name,

    auto ctx = mAccess->getCallingContext();

    if (!mAccess->canFind(ctx, name)) {
        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
    std::optional<std::string> _accessorName;
    if (auto status = canFindService(ctx, name, &_accessorName); !status.isOk()) {
        return status;
    }

    *outReturn = std::nullopt;
@@ -706,8 +750,9 @@ Status ServiceManager::getUpdatableNames([[maybe_unused]] const std::string& ape

    outReturn->clear();

    std::optional<std::string> _accessorName;
    for (const std::string& name : apexUpdatableNames) {
        if (mAccess->canFind(ctx, name)) {
        if (auto status = canFindService(ctx, name, &_accessorName); status.isOk()) {
            outReturn->push_back(name);
        }
    }
@@ -724,8 +769,9 @@ Status ServiceManager::getConnectionInfo(const std::string& name,

    auto ctx = mAccess->getCallingContext();

    if (!mAccess->canFind(ctx, name)) {
        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
    std::optional<std::string> _accessorName;
    if (auto status = canFindService(ctx, name, &_accessorName); !status.isOk()) {
        return status;
    }

    *outReturn = std::nullopt;
@@ -1032,6 +1078,23 @@ Status ServiceManager::tryUnregisterService(const std::string& name, const sp<IB
    return Status::ok();
}

Status ServiceManager::canFindService(const Access::CallingContext& ctx, const std::string& name,
                                      std::optional<std::string>* accessor) {
    if (!mAccess->canFind(ctx, name)) {
        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied for service.");
    }
#ifndef VENDORSERVICEMANAGER
    *accessor = getVintfAccessorName(name);
#endif
    if (accessor->has_value()) {
        if (!mAccess->canFind(ctx, accessor->value())) {
            return Status::fromExceptionCode(Status::EX_SECURITY,
                                             "SELinux denied for the accessor of the service.");
        }
    }
    return Status::ok();
}

Status ServiceManager::getServiceDebugInfo(std::vector<ServiceDebugInfo>* outReturn) {
    SM_PERFETTO_TRACE_FUNC();
    if (!mAccess->canList(mAccess->getCallingContext())) {
+6 −3
Original line number Diff line number Diff line
@@ -44,8 +44,8 @@ public:
    ~ServiceManager();

    // getService will try to start any services it cannot find
    binder::Status getService(const std::string& name, sp<IBinder>* outBinder) override;
    binder::Status checkService(const std::string& name, sp<IBinder>* outBinder) override;
    binder::Status getService(const std::string& name, os::Service* outService) override;
    binder::Status checkService(const std::string& name, os::Service* outService) override;
    binder::Status addService(const std::string& name, const sp<IBinder>& binder,
                              bool allowIsolated, int32_t dumpPriority) override;
    binder::Status listServices(int32_t dumpPriority, std::vector<std::string>* outList) override;
@@ -112,7 +112,10 @@ private:
    // this updates the iterator to the next location
    void removeClientCallback(const wp<IBinder>& who, ClientCallbackMap::iterator* it);

    sp<IBinder> tryGetService(const std::string& name, bool startIfNotFound);
    os::Service tryGetService(const std::string& name, bool startIfNotFound);
    sp<IBinder> tryGetBinder(const std::string& name, bool startIfNotFound);
    binder::Status canFindService(const Access::CallingContext& ctx, const std::string& name,
                                  std::optional<std::string>* accessor);

    ServiceMap mNameToService;
    ServiceCallbackMap mNameToRegistrationCallback;
+15 −14
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ using android::base::StartsWith;
using android::binder::Status;
using android::os::BnServiceCallback;
using android::os::IServiceManager;
using android::os::Service;
using testing::_;
using testing::ElementsAre;
using testing::NiceMock;
@@ -153,18 +154,18 @@ TEST(AddService, OverwriteExistingService) {
    EXPECT_TRUE(sm->addService("foo", serviceA, false /*allowIsolated*/,
        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());

    sp<IBinder> outA;
    Service outA;
    EXPECT_TRUE(sm->getService("foo", &outA).isOk());
    EXPECT_EQ(serviceA, outA);
    EXPECT_EQ(serviceA, outA.get<Service::Tag::binder>());

    // serviceA should be overwritten by serviceB
    sp<IBinder> serviceB = getBinder();
    EXPECT_TRUE(sm->addService("foo", serviceB, false /*allowIsolated*/,
        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());

    sp<IBinder> outB;
    Service outB;
    EXPECT_TRUE(sm->getService("foo", &outB).isOk());
    EXPECT_EQ(serviceB, outB);
    EXPECT_EQ(serviceB, outB.get<Service::Tag::binder>());
}

TEST(AddService, NoPermissions) {
@@ -186,17 +187,17 @@ TEST(GetService, HappyHappy) {
    EXPECT_TRUE(sm->addService("foo", service, false /*allowIsolated*/,
        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());

    sp<IBinder> out;
    Service out;
    EXPECT_TRUE(sm->getService("foo", &out).isOk());
    EXPECT_EQ(service, out);
    EXPECT_EQ(service, out.get<Service::Tag::binder>());
}

TEST(GetService, NonExistant) {
    auto sm = getPermissiveServiceManager();

    sp<IBinder> out;
    Service out;
    EXPECT_TRUE(sm->getService("foo", &out).isOk());
    EXPECT_EQ(nullptr, out.get());
    EXPECT_EQ(nullptr, out.get<Service::Tag::binder>());
}

TEST(GetService, NoPermissionsForGettingService) {
@@ -211,10 +212,10 @@ TEST(GetService, NoPermissionsForGettingService) {
    EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());

    sp<IBinder> out;
    Service out;
    // returns nullptr but has OK status for legacy compatibility
    EXPECT_TRUE(sm->getService("foo", &out).isOk());
    EXPECT_EQ(nullptr, out.get());
    EXPECT_EQ(nullptr, out.get<Service::Tag::binder>());
}

TEST(GetService, AllowedFromIsolated) {
@@ -236,9 +237,9 @@ TEST(GetService, AllowedFromIsolated) {
    EXPECT_TRUE(sm->addService("foo", service, true /*allowIsolated*/,
        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());

    sp<IBinder> out;
    Service out;
    EXPECT_TRUE(sm->getService("foo", &out).isOk());
    EXPECT_EQ(service, out.get());
    EXPECT_EQ(service, out.get<Service::Tag::binder>());
}

TEST(GetService, NotAllowedFromIsolated) {
@@ -261,10 +262,10 @@ TEST(GetService, NotAllowedFromIsolated) {
    EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());

    sp<IBinder> out;
    Service out;
    // returns nullptr but has OK status for legacy compatibility
    EXPECT_TRUE(sm->getService("foo", &out).isOk());
    EXPECT_EQ(nullptr, out.get());
    EXPECT_EQ(nullptr, out.get<Service::Tag::binder>());
}

TEST(ListServices, NoPermissions) {
+30 −0
Original line number Diff line number Diff line
@@ -771,11 +771,41 @@ filegroup {
        "aidl/android/os/IClientCallback.aidl",
        "aidl/android/os/IServiceCallback.aidl",
        "aidl/android/os/IServiceManager.aidl",
        "aidl/android/os/Service.aidl",
        "aidl/android/os/ServiceDebugInfo.aidl",
        ":libbinder_accessor_aidl",
    ],
    path: "aidl",
}

filegroup {
    name: "libbinder_accessor_aidl",
    srcs: [
        "aidl/android/os/IAccessor.aidl",
    ],
    path: "aidl",
}

// TODO(b/353492849): Make this interface private to libbinder.
aidl_interface {
    name: "android.os.accessor",
    srcs: [":libbinder_accessor_aidl"],
    unstable: true,
    backend: {
        rust: {
            enabled: true,
            apex_available: [
                "com.android.virt",
            ],
        },
    },
    visibility: [
        ":__subpackages__",
        "//system/tools/aidl:__subpackages__",
        "//packages/modules/Virtualization:__subpackages__",
    ],
}

aidl_interface {
    name: "packagemanager_aidl",
    unstable: true,
+52 −4
Original line number Diff line number Diff line
@@ -15,6 +15,9 @@
 */
#include "BackendUnifiedServiceManager.h"

#include <android/os/IAccessor.h>
#include <binder/RpcSession.h>

#if defined(__BIONIC__) && !defined(__ANDROID_VNDK__)
#include <android-base/properties.h>
#endif
@@ -22,6 +25,7 @@
namespace android {

using AidlServiceManager = android::os::IServiceManager;
using IAccessor = android::os::IAccessor;

BackendUnifiedServiceManager::BackendUnifiedServiceManager(const sp<AidlServiceManager>& impl)
      : mTheRealServiceManager(impl) {}
@@ -30,13 +34,57 @@ sp<AidlServiceManager> BackendUnifiedServiceManager::getImpl() {
    return mTheRealServiceManager;
}
binder::Status BackendUnifiedServiceManager::getService(const ::std::string& name,
                                                        sp<IBinder>* _aidl_return) {
    return mTheRealServiceManager->getService(name, _aidl_return);
                                                        os::Service* _out) {
    os::Service service;
    binder::Status status = mTheRealServiceManager->getService(name, &service);
    toBinderService(service, _out);
    return status;
}

binder::Status BackendUnifiedServiceManager::checkService(const ::std::string& name,
                                                          sp<IBinder>* _aidl_return) {
    return mTheRealServiceManager->checkService(name, _aidl_return);
                                                          os::Service* _out) {
    os::Service service;
    binder::Status status = mTheRealServiceManager->checkService(name, &service);
    toBinderService(service, _out);
    return status;
}

void BackendUnifiedServiceManager::toBinderService(const os::Service& in, os::Service* _out) {
    switch (in.getTag()) {
        case os::Service::Tag::binder: {
            *_out = in;
            break;
        }
        case os::Service::Tag::accessor: {
            sp<IBinder> accessorBinder = in.get<os::Service::Tag::accessor>();
            sp<IAccessor> accessor = interface_cast<IAccessor>(accessorBinder);
            if (accessor == nullptr) {
                ALOGE("Service#accessor doesn't have accessor. VM is maybe starting...");
                *_out = os::Service::make<os::Service::Tag::binder>(nullptr);
                break;
            }
            auto request = [=] {
                os::ParcelFileDescriptor fd;
                binder::Status ret = accessor->addConnection(&fd);
                if (ret.isOk()) {
                    return base::unique_fd(fd.release());
                } else {
                    ALOGE("Failed to connect to RpcSession: %s", ret.toString8().c_str());
                    return base::unique_fd(-1);
                }
            };
            auto session = RpcSession::make();
            session->setupPreconnectedClient(base::unique_fd{}, request);
            session->setSessionSpecificRoot(accessorBinder);
            *_out = os::Service::make<os::Service::Tag::binder>(session->getRootObject());
            break;
        }
        default: {
            LOG_ALWAYS_FATAL("Unknown service type: %d", in.getTag());
        }
    }
}

binder::Status BackendUnifiedServiceManager::addService(const ::std::string& name,
                                                        const sp<IBinder>& service,
                                                        bool allowIsolated, int32_t dumpPriority) {
Loading