Loading cmds/servicemanager/ServiceManager.cpp +36 −20 Original line number Diff line number Diff line Loading @@ -17,8 +17,10 @@ #include "ServiceManager.h" #include <android-base/logging.h> #include <android-base/properties.h> #include <cutils/android_filesystem_config.h> #include <cutils/multiuser.h> #include <thread> using ::android::binder::Status; Loading @@ -41,19 +43,22 @@ ServiceManager::~ServiceManager() { } Status ServiceManager::getService(const std::string& name, sp<IBinder>* outBinder) { // Servicemanager is single-threaded and cannot block. This method exists for legacy reasons. return checkService(name, outBinder); *outBinder = tryGetService(name, true); // returns ok regardless of result for legacy reasons return Status::ok(); } Status ServiceManager::checkService(const std::string& name, sp<IBinder>* outBinder) { auto ctx = mAccess->getCallingContext(); auto it = mNameToService.find(name); if (it == mNameToService.end()) { *outBinder = nullptr; *outBinder = tryGetService(name, false); // returns ok regardless of result for legacy reasons return Status::ok(); } sp<IBinder> ServiceManager::tryGetService(const std::string& name, bool startIfNotFound) { auto ctx = mAccess->getCallingContext(); sp<IBinder> out; if (auto it = mNameToService.find(name); it != mNameToService.end()) { const Service& service = it->second; if (!service.allowIsolated) { Loading @@ -61,19 +66,21 @@ Status ServiceManager::checkService(const std::string& name, sp<IBinder>* outBin bool isIsolated = appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END; if (isIsolated) { *outBinder = nullptr; return Status::ok(); return nullptr; } } out = service.binder; } if (!mAccess->canFind(ctx, name)) { // returns ok and null for legacy reasons *outBinder = nullptr; return Status::ok(); return nullptr; } *outBinder = service.binder; return Status::ok(); if (!out && startIfNotFound) { tryStartService(name); } return out; } bool isValidServiceName(const std::string& name) { Loading Loading @@ -253,4 +260,13 @@ void ServiceManager::binderDied(const wp<IBinder>& who) { } } void ServiceManager::tryStartService(const std::string& name) { ALOGI("Since '%s' could not be found, trying to start it as a lazy AIDL service", name.c_str()); std::thread([=] { (void)base::SetProperty("ctl.interface_start", "aidl/" + name); }).detach(); } } // namespace android cmds/servicemanager/ServiceManager.h +5 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ public: ServiceManager(std::unique_ptr<Access>&& access); ~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 addService(const std::string& name, const sp<IBinder>& binder, Loading @@ -42,6 +43,9 @@ public: void binderDied(const wp<IBinder>& who) override; protected: virtual void tryStartService(const std::string& name); private: struct Service { sp<IBinder> binder; // not null Loading @@ -57,6 +61,7 @@ private: void removeCallback(const wp<IBinder>& who, CallbackMap::iterator* it, bool* found); sp<IBinder> tryGetService(const std::string& name, bool startIfNotFound); CallbackMap mNameToCallback; ServiceMap mNameToService; Loading cmds/servicemanager/test_sm.cpp +13 −7 Original line number Diff line number Diff line Loading @@ -57,6 +57,12 @@ public: MOCK_METHOD1(canList, bool(const CallingContext&)); }; class MockServiceManager : public ServiceManager { public: MockServiceManager(std::unique_ptr<Access>&& access) : ServiceManager(std::move(access)) {} MOCK_METHOD1(tryStartService, void(const std::string& name)); }; static sp<ServiceManager> getPermissiveServiceManager() { std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>(); Loading @@ -65,7 +71,7 @@ static sp<ServiceManager> getPermissiveServiceManager() { ON_CALL(*access, canFind(_, _)).WillByDefault(Return(true)); ON_CALL(*access, canList(_)).WillByDefault(Return(true)); sp<ServiceManager> sm = new ServiceManager(std::move(access)); sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access)); return sm; } Loading Loading @@ -113,7 +119,7 @@ TEST(AddService, AddDisallowedFromApp) { .uid = uid, })); EXPECT_CALL(*access, canAdd(_, _)).Times(0); sp<ServiceManager> sm = new ServiceManager(std::move(access)); sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access)); EXPECT_FALSE(sm->addService("foo", getBinder(), false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); Loading @@ -135,7 +141,7 @@ TEST(AddService, NoPermissions) { EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{})); EXPECT_CALL(*access, canAdd(_, _)).WillOnce(Return(false)); sp<ServiceManager> sm = new ServiceManager(std::move(access)); sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access)); EXPECT_FALSE(sm->addService("foo", getBinder(), false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); Loading Loading @@ -168,7 +174,7 @@ TEST(GetService, NoPermissionsForGettingService) { EXPECT_CALL(*access, canAdd(_, _)).WillOnce(Return(true)); EXPECT_CALL(*access, canFind(_, _)).WillOnce(Return(false)); sp<ServiceManager> sm = new ServiceManager(std::move(access)); sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access)); EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); Loading @@ -192,7 +198,7 @@ TEST(GetService, AllowedFromIsolated) { EXPECT_CALL(*access, canAdd(_, _)).WillOnce(Return(true)); EXPECT_CALL(*access, canFind(_, _)).WillOnce(Return(true)); sp<ServiceManager> sm = new ServiceManager(std::move(access)); sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access)); sp<IBinder> service = getBinder(); EXPECT_TRUE(sm->addService("foo", service, true /*allowIsolated*/, Loading @@ -218,7 +224,7 @@ TEST(GetService, NotAllowedFromIsolated) { // TODO(b/136023468): when security check is first, this should be called first // EXPECT_CALL(*access, canFind(_, _)).WillOnce(Return(true)); sp<ServiceManager> sm = new ServiceManager(std::move(access)); sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access)); EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); Loading @@ -235,7 +241,7 @@ TEST(ListServices, NoPermissions) { EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{})); EXPECT_CALL(*access, canList(_)).WillOnce(Return(false)); sp<ServiceManager> sm = new ServiceManager(std::move(access)); sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access)); std::vector<std::string> out; EXPECT_FALSE(sm->listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL, &out).isOk()); Loading libs/binder/IServiceManager.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -232,7 +232,7 @@ public: const std::string name = String8(name16).c_str(); sp<IBinder> out; if(!mTheRealServiceManager->checkService(name, &out).isOk()) { if (!mTheRealServiceManager->getService(name, &out).isOk()) { return nullptr; } if(out != nullptr) return out; Loading @@ -256,13 +256,13 @@ public: // Handle race condition for lazy services. Here is what can happen: // - the service dies (not processed by init yet). // - sm processes death notification. // - sm gets checkService and calls init to start service. // - sm gets getService and calls init to start service. // - init gets the start signal, but the service already appears // started, so it does nothing. // - init gets death signal, but doesn't know it needs to restart // the service // - we need to request service again to get it to start if(!mTheRealServiceManager->checkService(name, &out).isOk()) { if (!mTheRealServiceManager->getService(name, &out).isOk()) { return nullptr; } if(out != nullptr) return out; Loading Loading
cmds/servicemanager/ServiceManager.cpp +36 −20 Original line number Diff line number Diff line Loading @@ -17,8 +17,10 @@ #include "ServiceManager.h" #include <android-base/logging.h> #include <android-base/properties.h> #include <cutils/android_filesystem_config.h> #include <cutils/multiuser.h> #include <thread> using ::android::binder::Status; Loading @@ -41,19 +43,22 @@ ServiceManager::~ServiceManager() { } Status ServiceManager::getService(const std::string& name, sp<IBinder>* outBinder) { // Servicemanager is single-threaded and cannot block. This method exists for legacy reasons. return checkService(name, outBinder); *outBinder = tryGetService(name, true); // returns ok regardless of result for legacy reasons return Status::ok(); } Status ServiceManager::checkService(const std::string& name, sp<IBinder>* outBinder) { auto ctx = mAccess->getCallingContext(); auto it = mNameToService.find(name); if (it == mNameToService.end()) { *outBinder = nullptr; *outBinder = tryGetService(name, false); // returns ok regardless of result for legacy reasons return Status::ok(); } sp<IBinder> ServiceManager::tryGetService(const std::string& name, bool startIfNotFound) { auto ctx = mAccess->getCallingContext(); sp<IBinder> out; if (auto it = mNameToService.find(name); it != mNameToService.end()) { const Service& service = it->second; if (!service.allowIsolated) { Loading @@ -61,19 +66,21 @@ Status ServiceManager::checkService(const std::string& name, sp<IBinder>* outBin bool isIsolated = appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END; if (isIsolated) { *outBinder = nullptr; return Status::ok(); return nullptr; } } out = service.binder; } if (!mAccess->canFind(ctx, name)) { // returns ok and null for legacy reasons *outBinder = nullptr; return Status::ok(); return nullptr; } *outBinder = service.binder; return Status::ok(); if (!out && startIfNotFound) { tryStartService(name); } return out; } bool isValidServiceName(const std::string& name) { Loading Loading @@ -253,4 +260,13 @@ void ServiceManager::binderDied(const wp<IBinder>& who) { } } void ServiceManager::tryStartService(const std::string& name) { ALOGI("Since '%s' could not be found, trying to start it as a lazy AIDL service", name.c_str()); std::thread([=] { (void)base::SetProperty("ctl.interface_start", "aidl/" + name); }).detach(); } } // namespace android
cmds/servicemanager/ServiceManager.h +5 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ public: ServiceManager(std::unique_ptr<Access>&& access); ~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 addService(const std::string& name, const sp<IBinder>& binder, Loading @@ -42,6 +43,9 @@ public: void binderDied(const wp<IBinder>& who) override; protected: virtual void tryStartService(const std::string& name); private: struct Service { sp<IBinder> binder; // not null Loading @@ -57,6 +61,7 @@ private: void removeCallback(const wp<IBinder>& who, CallbackMap::iterator* it, bool* found); sp<IBinder> tryGetService(const std::string& name, bool startIfNotFound); CallbackMap mNameToCallback; ServiceMap mNameToService; Loading
cmds/servicemanager/test_sm.cpp +13 −7 Original line number Diff line number Diff line Loading @@ -57,6 +57,12 @@ public: MOCK_METHOD1(canList, bool(const CallingContext&)); }; class MockServiceManager : public ServiceManager { public: MockServiceManager(std::unique_ptr<Access>&& access) : ServiceManager(std::move(access)) {} MOCK_METHOD1(tryStartService, void(const std::string& name)); }; static sp<ServiceManager> getPermissiveServiceManager() { std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>(); Loading @@ -65,7 +71,7 @@ static sp<ServiceManager> getPermissiveServiceManager() { ON_CALL(*access, canFind(_, _)).WillByDefault(Return(true)); ON_CALL(*access, canList(_)).WillByDefault(Return(true)); sp<ServiceManager> sm = new ServiceManager(std::move(access)); sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access)); return sm; } Loading Loading @@ -113,7 +119,7 @@ TEST(AddService, AddDisallowedFromApp) { .uid = uid, })); EXPECT_CALL(*access, canAdd(_, _)).Times(0); sp<ServiceManager> sm = new ServiceManager(std::move(access)); sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access)); EXPECT_FALSE(sm->addService("foo", getBinder(), false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); Loading @@ -135,7 +141,7 @@ TEST(AddService, NoPermissions) { EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{})); EXPECT_CALL(*access, canAdd(_, _)).WillOnce(Return(false)); sp<ServiceManager> sm = new ServiceManager(std::move(access)); sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access)); EXPECT_FALSE(sm->addService("foo", getBinder(), false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); Loading Loading @@ -168,7 +174,7 @@ TEST(GetService, NoPermissionsForGettingService) { EXPECT_CALL(*access, canAdd(_, _)).WillOnce(Return(true)); EXPECT_CALL(*access, canFind(_, _)).WillOnce(Return(false)); sp<ServiceManager> sm = new ServiceManager(std::move(access)); sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access)); EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); Loading @@ -192,7 +198,7 @@ TEST(GetService, AllowedFromIsolated) { EXPECT_CALL(*access, canAdd(_, _)).WillOnce(Return(true)); EXPECT_CALL(*access, canFind(_, _)).WillOnce(Return(true)); sp<ServiceManager> sm = new ServiceManager(std::move(access)); sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access)); sp<IBinder> service = getBinder(); EXPECT_TRUE(sm->addService("foo", service, true /*allowIsolated*/, Loading @@ -218,7 +224,7 @@ TEST(GetService, NotAllowedFromIsolated) { // TODO(b/136023468): when security check is first, this should be called first // EXPECT_CALL(*access, canFind(_, _)).WillOnce(Return(true)); sp<ServiceManager> sm = new ServiceManager(std::move(access)); sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access)); EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()); Loading @@ -235,7 +241,7 @@ TEST(ListServices, NoPermissions) { EXPECT_CALL(*access, getCallingContext()).WillOnce(Return(Access::CallingContext{})); EXPECT_CALL(*access, canList(_)).WillOnce(Return(false)); sp<ServiceManager> sm = new ServiceManager(std::move(access)); sp<ServiceManager> sm = new NiceMock<MockServiceManager>(std::move(access)); std::vector<std::string> out; EXPECT_FALSE(sm->listServices(IServiceManager::DUMP_FLAG_PRIORITY_ALL, &out).isOk()); Loading
libs/binder/IServiceManager.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -232,7 +232,7 @@ public: const std::string name = String8(name16).c_str(); sp<IBinder> out; if(!mTheRealServiceManager->checkService(name, &out).isOk()) { if (!mTheRealServiceManager->getService(name, &out).isOk()) { return nullptr; } if(out != nullptr) return out; Loading @@ -256,13 +256,13 @@ public: // Handle race condition for lazy services. Here is what can happen: // - the service dies (not processed by init yet). // - sm processes death notification. // - sm gets checkService and calls init to start service. // - sm gets getService and calls init to start service. // - init gets the start signal, but the service already appears // started, so it does nothing. // - init gets death signal, but doesn't know it needs to restart // the service // - we need to request service again to get it to start if(!mTheRealServiceManager->checkService(name, &out).isOk()) { if (!mTheRealServiceManager->getService(name, &out).isOk()) { return nullptr; } if(out != nullptr) return out; Loading