Commit d154b449 authored by rockot's avatar rockot Committed by Commit bot

Fix UAF on singleton service instances

This corrects how the ServiceManager clears out identity mappings
to singleton services, preventing it from indefinitely holding a
raw Instance* to any singleton it starts.

BUG=None

Review-Url: https://codereview.chromium.org/2566663003
Cr-Commit-Position: refs/heads/master@{#437737}
parent 741d84a5
...@@ -641,9 +641,7 @@ void ServiceManager::OnInstanceError(Instance* instance) { ...@@ -641,9 +641,7 @@ void ServiceManager::OnInstanceError(Instance* instance) {
if (instance == service_manager_instance_) if (instance == service_manager_instance_)
return; return;
const Identity identity = instance->identity(); EraseInstanceIdentity(instance);
identity_to_instance_.erase(identity);
if (instance->parent()) { if (instance->parent()) {
// Deletes |instance|. // Deletes |instance|.
instance->parent()->RemoveChild(instance); instance->parent()->RemoveChild(instance);
...@@ -660,7 +658,7 @@ void ServiceManager::OnInstanceUnreachable(Instance* instance) { ...@@ -660,7 +658,7 @@ void ServiceManager::OnInstanceUnreachable(Instance* instance) {
// If an Instance becomes unreachable, new connection requests for this // If an Instance becomes unreachable, new connection requests for this
// identity will elicit a new Instance instantiation. The unreachable instance // identity will elicit a new Instance instantiation. The unreachable instance
// remains alive. // remains alive.
identity_to_instance_.erase(instance->identity()); EraseInstanceIdentity(instance);
} }
void ServiceManager::OnInstanceStopped(const Identity& identity) { void ServiceManager::OnInstanceStopped(const Identity& identity) {
...@@ -719,6 +717,28 @@ ServiceManager::Instance* ServiceManager::GetExistingInstance( ...@@ -719,6 +717,28 @@ ServiceManager::Instance* ServiceManager::GetExistingInstance(
return nullptr; return nullptr;
} }
void ServiceManager::EraseInstanceIdentity(Instance* instance) {
const Identity& identity = instance->identity();
auto it = identity_to_instance_.find(identity);
if (it != identity_to_instance_.end()) {
identity_to_instance_.erase(it);
return;
}
if (singletons_.find(identity.name()) != singletons_.end()) {
singletons_.erase(identity.name());
for (auto it = identity_to_instance_.begin();
it != identity_to_instance_.end(); ++it) {
if (it->first.name() == identity.name() &&
it->first.instance() == identity.instance()) {
identity_to_instance_.erase(it);
return;
}
}
}
}
void ServiceManager::NotifyServiceStarted(const Identity& identity, void ServiceManager::NotifyServiceStarted(const Identity& identity,
base::ProcessId pid) { base::ProcessId pid) {
listeners_.ForAllPtrs( listeners_.ForAllPtrs(
......
...@@ -119,6 +119,10 @@ class ServiceManager { ...@@ -119,6 +119,10 @@ class ServiceManager {
// running as a different user if one is available that services all users. // running as a different user if one is available that services all users.
Instance* GetExistingInstance(const Identity& identity) const; Instance* GetExistingInstance(const Identity& identity) const;
// Erases any identities mapping to |instance|. Following this call it is
// impossible for any call to GetExistingInstance() to return |instance|.
void EraseInstanceIdentity(Instance* instance);
void NotifyServiceStarted(const Identity& identity, base::ProcessId pid); void NotifyServiceStarted(const Identity& identity, base::ProcessId pid);
void NotifyServiceFailedToStart(const Identity& identity); void NotifyServiceFailedToStart(const Identity& identity);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment