diff options
author | 2022-10-25 17:02:45 +0900 | |
---|---|---|
committer | 2022-10-26 09:42:59 +0900 | |
commit | 76944fee1a642cdfbabaa72ef7d29e53af1d50db (patch) | |
tree | 3b0d45fa894dc8b3d9f7d2677e6a74d99323ba25 | |
parent | 4e84148059c54ccbf64740c6841fdae46ce64b30 (diff) |
servicemanager: getUpdatableNames()
This new method is a reverse of updatableViaApex(). It returns the list
of declared instances which can be updated via the passed APEX.
Updatable vendor apexes are supposed to be used only to update HAL
services. APEXd can use this method to see if the target APEX is
actually to updating HALs.
It's not exposed to NDK/Java yet because there's no clients.
Bug: 254201177
Test: TBD
Change-Id: I7b5aa7d00a3ddeb13855816006a9561dfa601529
-rw-r--r-- | cmds/dumpsys/tests/dumpsys_test.cpp | 1 | ||||
-rw-r--r-- | cmds/servicemanager/ServiceManager.cpp | 44 | ||||
-rw-r--r-- | cmds/servicemanager/ServiceManager.h | 2 | ||||
-rw-r--r-- | libs/binder/IServiceManager.cpp | 18 | ||||
-rw-r--r-- | libs/binder/aidl/android/os/IServiceManager.aidl | 6 | ||||
-rw-r--r-- | libs/binder/include/binder/IServiceManager.h | 6 | ||||
-rw-r--r-- | libs/binder/servicedispatcher.cpp | 4 | ||||
-rw-r--r-- | libs/fakeservicemanager/ServiceManager.cpp | 5 | ||||
-rw-r--r-- | libs/fakeservicemanager/include/fakeservicemanager/ServiceManager.h | 2 |
9 files changed, 88 insertions, 0 deletions
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp index f0c19b93ec..b8e5ce1a63 100644 --- a/cmds/dumpsys/tests/dumpsys_test.cpp +++ b/cmds/dumpsys/tests/dumpsys_test.cpp @@ -60,6 +60,7 @@ class ServiceManagerMock : public IServiceManager { MOCK_METHOD1(isDeclared, bool(const String16&)); MOCK_METHOD1(getDeclaredInstances, Vector<String16>(const String16&)); MOCK_METHOD1(updatableViaApex, std::optional<String16>(const String16&)); + MOCK_METHOD1(getUpdatableNames, Vector<String16>(const String16&)); MOCK_METHOD1(getConnectionInfo, std::optional<ConnectionInfo>(const String16&)); MOCK_METHOD2(registerForNotifications, status_t(const String16&, const sp<LocalRegistrationCallback>&)); diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp index 3681d5b8b9..2684f048f8 100644 --- a/cmds/servicemanager/ServiceManager.cpp +++ b/cmds/servicemanager/ServiceManager.cpp @@ -142,6 +142,26 @@ static std::optional<std::string> getVintfUpdatableApex(const std::string& name) return updatableViaApex; } +static std::vector<std::string> getVintfUpdatableInstances(const std::string& apexName) { + std::vector<std::string> instances; + + forEachManifest([&](const ManifestWithDescription& mwd) { + mwd.manifest->forEachInstance([&](const auto& manifestInstance) { + if (manifestInstance.format() == vintf::HalFormat::AIDL && + manifestInstance.updatableViaApex().has_value() && + manifestInstance.updatableViaApex().value() == apexName) { + std::string aname = manifestInstance.package() + "." + + manifestInstance.interface() + "/" + manifestInstance.instance(); + instances.push_back(aname); + } + return false; // continue + }); + return false; // continue + }); + + return instances; +} + static std::optional<ConnectionInfo> getVintfConnectionInfo(const std::string& name) { AidlName aname; if (!AidlName::fill(name, &aname)) return std::nullopt; @@ -512,6 +532,30 @@ Status ServiceManager::updatableViaApex(const std::string& name, return Status::ok(); } +Status ServiceManager::getUpdatableNames([[maybe_unused]] const std::string& apexName, + std::vector<std::string>* outReturn) { + auto ctx = mAccess->getCallingContext(); + + std::vector<std::string> apexUpdatableInstances; +#ifndef VENDORSERVICEMANAGER + apexUpdatableInstances = getVintfUpdatableInstances(apexName); +#endif + + outReturn->clear(); + + for (const std::string& instance : apexUpdatableInstances) { + if (mAccess->canFind(ctx, instance)) { + outReturn->push_back(instance); + } + } + + if (outReturn->size() == 0 && apexUpdatableInstances.size() != 0) { + return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denial"); + } + + return Status::ok(); +} + Status ServiceManager::getConnectionInfo(const std::string& name, std::optional<ConnectionInfo>* outReturn) { auto ctx = mAccess->getCallingContext(); diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h index 07b79f80ac..b24c11c161 100644 --- a/cmds/servicemanager/ServiceManager.h +++ b/cmds/servicemanager/ServiceManager.h @@ -49,6 +49,8 @@ public: binder::Status getDeclaredInstances(const std::string& interface, std::vector<std::string>* outReturn) override; binder::Status updatableViaApex(const std::string& name, std::optional<std::string>* outReturn) override; + binder::Status getUpdatableNames(const std::string& apexName, + std::vector<std::string>* outReturn) override; binder::Status getConnectionInfo(const std::string& name, std::optional<ConnectionInfo>* outReturn) override; binder::Status registerClientCallback(const std::string& name, const sp<IBinder>& service, diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp index 05db7743f2..a0c43349a7 100644 --- a/libs/binder/IServiceManager.cpp +++ b/libs/binder/IServiceManager.cpp @@ -81,6 +81,7 @@ public: bool isDeclared(const String16& name) override; Vector<String16> getDeclaredInstances(const String16& interface) override; std::optional<String16> updatableViaApex(const String16& name) override; + Vector<String16> getUpdatableNames(const String16& apexName) override; std::optional<IServiceManager::ConnectionInfo> getConnectionInfo(const String16& name) override; class RegistrationWaiter : public android::os::BnServiceCallback { public: @@ -479,6 +480,23 @@ std::optional<String16> ServiceManagerShim::updatableViaApex(const String16& nam return declared ? std::optional<String16>(String16(declared.value().c_str())) : std::nullopt; } +Vector<String16> ServiceManagerShim::getUpdatableNames(const String16& apexName) { + std::vector<std::string> out; + if (Status status = mTheRealServiceManager->getUpdatableNames(String8(apexName).c_str(), &out); + !status.isOk()) { + ALOGW("Failed to getUpdatableNames for %s: %s", String8(apexName).c_str(), + status.toString8().c_str()); + return {}; + } + + Vector<String16> res; + res.setCapacity(out.size()); + for (const std::string& instance : out) { + res.push(String16(instance.c_str())); + } + return res; +} + std::optional<IServiceManager::ConnectionInfo> ServiceManagerShim::getConnectionInfo( const String16& name) { std::optional<os::ConnectionInfo> connectionInfo; diff --git a/libs/binder/aidl/android/os/IServiceManager.aidl b/libs/binder/aidl/android/os/IServiceManager.aidl index 5880c0a1bd..0fb1615391 100644 --- a/libs/binder/aidl/android/os/IServiceManager.aidl +++ b/libs/binder/aidl/android/os/IServiceManager.aidl @@ -114,6 +114,12 @@ interface IServiceManager { @nullable @utf8InCpp String updatableViaApex(@utf8InCpp String name); /** + * Returns all instances which are updatable via the APEX. Instance names are fully qualified + * like `pack.age.IFoo/default`. + */ + @utf8InCpp String[] getUpdatableNames(@utf8InCpp String apexName); + + /** * If connection info is available for the given instance, returns the ConnectionInfo */ @nullable ConnectionInfo getConnectionInfo(@utf8InCpp String name); diff --git a/libs/binder/include/binder/IServiceManager.h b/libs/binder/include/binder/IServiceManager.h index 413c97f349..79e771f092 100644 --- a/libs/binder/include/binder/IServiceManager.h +++ b/libs/binder/include/binder/IServiceManager.h @@ -115,6 +115,12 @@ public: virtual std::optional<String16> updatableViaApex(const String16& name) = 0; /** + * Returns all instances which are updatable via the APEX. Instance names are fully qualified + * like `pack.age.IFoo/default`. + */ + virtual Vector<String16> getUpdatableNames(const String16& apexName) = 0; + + /** * If this instance has declared remote connection information, returns * the ConnectionInfo. */ diff --git a/libs/binder/servicedispatcher.cpp b/libs/binder/servicedispatcher.cpp index 777f3c9354..692cc95e3b 100644 --- a/libs/binder/servicedispatcher.cpp +++ b/libs/binder/servicedispatcher.cpp @@ -156,6 +156,10 @@ public: std::optional<std::string>* _aidl_return) override { return mImpl->updatableViaApex(name, _aidl_return); } + android::binder::Status getUpdatableNames(const std::string& apexName, + std::vector<std::string>* _aidl_return) override { + return mImpl->getUpdatableNames(apexName, _aidl_return); + } android::binder::Status getConnectionInfo( const std::string& name, std::optional<android::os::ConnectionInfo>* _aidl_return) override { diff --git a/libs/fakeservicemanager/ServiceManager.cpp b/libs/fakeservicemanager/ServiceManager.cpp index 6c6d7f3641..480ec79725 100644 --- a/libs/fakeservicemanager/ServiceManager.cpp +++ b/libs/fakeservicemanager/ServiceManager.cpp @@ -78,6 +78,11 @@ std::optional<String16> ServiceManager::updatableViaApex(const String16& name) { return std::nullopt; } +Vector<String16> ServiceManager::getUpdatableNames(const String16& apexName) { + (void)apexName; + return {}; +} + std::optional<IServiceManager::ConnectionInfo> ServiceManager::getConnectionInfo( const String16& name) { (void)name; diff --git a/libs/fakeservicemanager/include/fakeservicemanager/ServiceManager.h b/libs/fakeservicemanager/include/fakeservicemanager/ServiceManager.h index e0af5d4ba8..ee0637eb7e 100644 --- a/libs/fakeservicemanager/include/fakeservicemanager/ServiceManager.h +++ b/libs/fakeservicemanager/include/fakeservicemanager/ServiceManager.h @@ -52,6 +52,8 @@ public: std::optional<String16> updatableViaApex(const String16& name) override; + Vector<String16> getUpdatableNames(const String16& apexName) override; + std::optional<IServiceManager::ConnectionInfo> getConnectionInfo(const String16& name) override; status_t registerForNotifications(const String16& name, |