Fix deadlock caused by two-threaded property controls
Two threaded property controls were introduced in ag/21063815 to prevent DOS for power controls. However, this causes deadlocks, so limit the second thread to just sys.powerctl messages. Bug: 273785601 Test: Boots, power messages work Ignore-AOSP-First: Security fix Change-Id: Ie27dc3b0cd9e2d28e94f2ad398c55ee27bc35835
This commit is contained in:
parent
bfd626e78f
commit
606afc7b74
1 changed files with 28 additions and 24 deletions
|
|
@ -117,7 +117,6 @@ static bool accept_messages = false;
|
|||
static std::mutex accept_messages_lock;
|
||||
static std::thread property_service_thread;
|
||||
static std::thread property_service_for_system_thread;
|
||||
static std::mutex set_property_lock;
|
||||
|
||||
static std::unique_ptr<PersistWriteThread> persist_write_thread;
|
||||
|
||||
|
|
@ -395,32 +394,37 @@ static std::optional<uint32_t> PropertySet(const std::string& name, const std::s
|
|||
return {PROP_ERROR_INVALID_VALUE};
|
||||
}
|
||||
|
||||
auto lock = std::lock_guard{set_property_lock};
|
||||
prop_info* pi = (prop_info*)__system_property_find(name.c_str());
|
||||
if (pi != nullptr) {
|
||||
// ro.* properties are actually "write-once".
|
||||
if (StartsWith(name, "ro.")) {
|
||||
*error = "Read-only property was already set";
|
||||
return {PROP_ERROR_READ_ONLY_PROPERTY};
|
||||
}
|
||||
|
||||
__system_property_update(pi, value.c_str(), valuelen);
|
||||
if (name == "sys.powerctl") {
|
||||
// No action here - NotifyPropertyChange will trigger the appropriate action, and since this
|
||||
// can come to the second thread, we mustn't call out to the __system_property_* functions
|
||||
// which support multiple readers but only one mutator.
|
||||
} else {
|
||||
int rc = __system_property_add(name.c_str(), name.size(), value.c_str(), valuelen);
|
||||
if (rc < 0) {
|
||||
*error = "__system_property_add failed";
|
||||
return {PROP_ERROR_SET_FAILED};
|
||||
}
|
||||
}
|
||||
prop_info* pi = (prop_info*)__system_property_find(name.c_str());
|
||||
if (pi != nullptr) {
|
||||
// ro.* properties are actually "write-once".
|
||||
if (StartsWith(name, "ro.")) {
|
||||
*error = "Read-only property was already set";
|
||||
return {PROP_ERROR_READ_ONLY_PROPERTY};
|
||||
}
|
||||
|
||||
// Don't write properties to disk until after we have read all default
|
||||
// properties to prevent them from being overwritten by default values.
|
||||
if (socket && persistent_properties_loaded && StartsWith(name, "persist.")) {
|
||||
if (persist_write_thread) {
|
||||
persist_write_thread->Write(name, value, std::move(*socket));
|
||||
return {};
|
||||
__system_property_update(pi, value.c_str(), valuelen);
|
||||
} else {
|
||||
int rc = __system_property_add(name.c_str(), name.size(), value.c_str(), valuelen);
|
||||
if (rc < 0) {
|
||||
*error = "__system_property_add failed";
|
||||
return {PROP_ERROR_SET_FAILED};
|
||||
}
|
||||
}
|
||||
|
||||
// Don't write properties to disk until after we have read all default
|
||||
// properties to prevent them from being overwritten by default values.
|
||||
if (socket && persistent_properties_loaded && StartsWith(name, "persist.")) {
|
||||
if (persist_write_thread) {
|
||||
persist_write_thread->Write(name, value, std::move(*socket));
|
||||
return {};
|
||||
}
|
||||
WritePersistentProperty(name, value);
|
||||
}
|
||||
WritePersistentProperty(name, value);
|
||||
}
|
||||
|
||||
NotifyPropertyChange(name, value);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue