diff options
-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, |