diff options
| author | 2024-06-03 23:08:15 +0000 | |
|---|---|---|
| committer | 2024-06-04 02:59:06 +0000 | |
| commit | f12a678ffe5e640bee4b8595a2784feea3d991f3 (patch) | |
| tree | c3f0a830971e9dd0ac4ecd22d0df3a9350d12199 | |
| parent | a1046a893eba53f2919a3885b5ec4431c0e05bf7 (diff) | |
Fix unsafe layer hierarchy access
We may modify the layer hierarchy while updating
relative layers. Fix this by retrieving the list of descendants
and then attaching or detaching it from their relative
parent.
Test: presubmit
Fixes: 344113039
Flag: EXEMPT bugfixes
Change-Id: I7aff5085794aeeb0bbba90decaf4cec13d0d2485
| -rw-r--r-- | services/surfaceflinger/FrontEnd/LayerHierarchy.cpp | 41 | ||||
| -rw-r--r-- | services/surfaceflinger/FrontEnd/LayerHierarchy.h | 1 |
2 files changed, 26 insertions, 16 deletions
diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp index 2b20de38d7..39a6b777bb 100644 --- a/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp +++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.cpp @@ -260,27 +260,36 @@ void LayerHierarchyBuilder::detachFromRelativeParent(LayerHierarchy* hierarchy) hierarchy->mParent->updateChild(hierarchy, LayerHierarchy::Variant::Attached); } -void LayerHierarchyBuilder::attachHierarchyToRelativeParent(LayerHierarchy* root) { - if (root->mLayer) { - attachToRelativeParent(root); - } - for (auto& [child, childVariant] : root->mChildren) { - if (childVariant == LayerHierarchy::Variant::Detached || - childVariant == LayerHierarchy::Variant::Attached) { - attachHierarchyToRelativeParent(child); +std::vector<LayerHierarchy*> LayerHierarchyBuilder::getDescendants(LayerHierarchy* root) { + std::vector<LayerHierarchy*> hierarchies; + hierarchies.push_back(root); + std::vector<LayerHierarchy*> descendants; + for (size_t i = 0; i < hierarchies.size(); i++) { + LayerHierarchy* hierarchy = hierarchies[i]; + if (hierarchy->mLayer) { + descendants.push_back(hierarchy); + } + for (auto& [child, childVariant] : hierarchy->mChildren) { + if (childVariant == LayerHierarchy::Variant::Detached || + childVariant == LayerHierarchy::Variant::Attached) { + hierarchies.push_back(child); + } } } + return descendants; } -void LayerHierarchyBuilder::detachHierarchyFromRelativeParent(LayerHierarchy* root) { - if (root->mLayer) { - detachFromRelativeParent(root); +void LayerHierarchyBuilder::attachHierarchyToRelativeParent(LayerHierarchy* root) { + std::vector<LayerHierarchy*> hierarchiesToAttach = getDescendants(root); + for (LayerHierarchy* hierarchy : hierarchiesToAttach) { + attachToRelativeParent(hierarchy); } - for (auto& [child, childVariant] : root->mChildren) { - if (childVariant == LayerHierarchy::Variant::Detached || - childVariant == LayerHierarchy::Variant::Attached) { - detachHierarchyFromRelativeParent(child); - } +} + +void LayerHierarchyBuilder::detachHierarchyFromRelativeParent(LayerHierarchy* root) { + std::vector<LayerHierarchy*> hierarchiesToDetach = getDescendants(root); + for (LayerHierarchy* hierarchy : hierarchiesToDetach) { + detachFromRelativeParent(hierarchy); } } diff --git a/services/surfaceflinger/FrontEnd/LayerHierarchy.h b/services/surfaceflinger/FrontEnd/LayerHierarchy.h index 69710be8df..d023f9e9f5 100644 --- a/services/surfaceflinger/FrontEnd/LayerHierarchy.h +++ b/services/surfaceflinger/FrontEnd/LayerHierarchy.h @@ -218,6 +218,7 @@ private: void detachFromParent(LayerHierarchy*); void attachToRelativeParent(LayerHierarchy*); void detachFromRelativeParent(LayerHierarchy*); + std::vector<LayerHierarchy*> getDescendants(LayerHierarchy*); void attachHierarchyToRelativeParent(LayerHierarchy*); void detachHierarchyFromRelativeParent(LayerHierarchy*); void init(const std::vector<std::unique_ptr<RequestedLayerState>>&); |