diff options
Diffstat (limited to 'cmds/servicemanager/ServiceManager.cpp')
-rw-r--r-- | cmds/servicemanager/ServiceManager.cpp | 97 |
1 files changed, 80 insertions, 17 deletions
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp index 1333599bf2..0f251d2b2a 100644 --- a/cmds/servicemanager/ServiceManager.cpp +++ b/cmds/servicemanager/ServiceManager.cpp @@ -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())) { |