Don't blur too many layers An application requesting lots and lots of blurs: a. Enables pixel stealing by measuring how long it takes to perform a blur across windows b. Probably isn't very valid anyways. So, just arbitrarily pick an upper bound for blur requests that a display is allowed to manage (10), and disable everything else. Arbitrarily, pick the 10 "front-most" blurs to be respected. Bug: 399120953 Flag: EXEMPT security Test: Security PoC no longer PoCs (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:acf65e7b90c8313b3cf939d14b8299818d77cc18) (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:63bb5e1c89ff74d1eb6725029769d00706a31857) Merged-In: Ie7195eb852b52aff2f58da8bd095d8684baceef6 Change-Id: Ie7195eb852b52aff2f58da8bd095d8684baceef6
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h index 191d475..4664155 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
@@ -157,6 +157,7 @@ // only has a value if there's something needing it, like when a TrustedPresentationListener // is set std::optional<Region> aboveCoveredLayersExcludingOverlays; + int32_t aboveBlurRequests = 0; }; virtual ~Output();
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h index 9990a74..3613c04 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h
@@ -168,6 +168,7 @@ private: void dirtyEntireOutput(); compositionengine::OutputLayer* findLayerRequestingBackgroundComposition() const; + void sanitizeOutputLayers() const; void finishPrepareFrame(); ui::Dataspace getBestDataspace(ui::Dataspace*, bool*) const; compositionengine::Output::ColorProfile pickColorProfile(
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h index 6c419da..f1ea497 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h
@@ -100,6 +100,9 @@ // order to save power. Region outputSpaceBlockingRegionHint; + // ignore blur requests if there's just too many on top of this layer + bool ignoreBlur{false}; + // Overrides the buffer, acquire fence, and display frame stored in LayerFECompositionState struct { std::shared_ptr<renderengine::ExternalTexture> buffer = nullptr;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h index 86bcf20..e09e308 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h
@@ -42,6 +42,7 @@ const std::string& getName() const { return mState->getName(); } int32_t getBackgroundBlurRadius() const { return mState->getBackgroundBlurRadius(); } Rect getDisplayFrame() const { return mState->getDisplayFrame(); } + bool hasBlurBehind() const { return mState->hasBlurBehind(); } const Region& getVisibleRegion() const { return mState->getVisibleRegion(); } const sp<GraphicBuffer>& getBuffer() const { return mState->getOutputLayer()->getLayerFE().getCompositionState()->buffer;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h index 5e3e3d8..eb94242 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h
@@ -75,6 +75,7 @@ HasProtectedContent = 1u << 19, CachingHint = 1u << 20, DimmingEnabled = 1u << 21, + BlursDisabled = 1u << 22, }; // clang-format on @@ -236,7 +237,8 @@ Rect getDisplayFrame() const { return mDisplayFrame.get(); } const Region& getVisibleRegion() const { return mVisibleRegion.get(); } bool hasBlurBehind() const { - return mBackgroundBlurRadius.get() > 0 || !mBlurRegions.get().empty(); + return (mBackgroundBlurRadius.get() > 0 || !mBlurRegions.get().empty()) && + !mIsBlursDisabled.get(); } int32_t getBackgroundBlurRadius() const { return mBackgroundBlurRadius.get(); } aidl::android::hardware::graphics::composer3::Composition getCompositionType() const { @@ -508,7 +510,10 @@ OutputLayerState<bool, LayerStateField::DimmingEnabled> mIsDimmingEnabled{ [](auto layer) { return layer->getLayerFE().getCompositionState()->dimmingEnabled; }}; - static const constexpr size_t kNumNonUniqueFields = 20; + OutputLayerState<bool, LayerStateField::BlursDisabled> mIsBlursDisabled{ + [](auto layer) { return layer->getState().ignoreBlur; }}; + + static const constexpr size_t kNumNonUniqueFields = 21; std::array<StateInterface*, kNumNonUniqueFields> getNonUniqueFields() { std::array<const StateInterface*, kNumNonUniqueFields> constFields = @@ -522,11 +527,12 @@ } std::array<const StateInterface*, kNumNonUniqueFields> getNonUniqueFields() const { - return {&mDisplayFrame, &mSourceCrop, &mBufferTransform, &mBlendMode, - &mAlpha, &mLayerMetadata, &mVisibleRegion, &mOutputDataspace, - &mPixelFormat, &mColorTransform, &mCompositionType, &mSidebandStream, - &mBuffer, &mSolidColor, &mBackgroundBlurRadius, &mBlurRegions, - &mFrameNumber, &mIsProtected, &mCachingHint, &mIsDimmingEnabled}; + return {&mDisplayFrame, &mSourceCrop, &mBufferTransform, &mBlendMode, + &mAlpha, &mLayerMetadata, &mVisibleRegion, &mOutputDataspace, + &mPixelFormat, &mColorTransform, &mCompositionType, &mSidebandStream, + &mBuffer, &mSolidColor, &mBackgroundBlurRadius, &mBlurRegions, + &mFrameNumber, &mIsProtected, &mCachingHint, &mIsDimmingEnabled, + &mIsBlursDisabled}; } };
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index b40aea4..ea6fe73 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -779,6 +779,9 @@ // one, or create a new one if we do not. auto result = ensureOutputLayer(prevOutputLayerIndex, layerFE); + coverage.aboveBlurRequests += static_cast<int32_t>(layerFEState->backgroundBlurRadius > 0 || + !layerFEState->blurRegions.empty()); + // Store the layer coverage information into the layer state as some of it // is useful later. auto& outputLayerState = result->editState(); @@ -793,6 +796,11 @@ ? outputState.transform.transform( transparentRegion.intersect(outputState.layerStackSpace.getContent())) : Region(); + + // See b/399120953: blurs are so expensive that they may be susceptible to compression side + // channel attacks + static constexpr auto kMaxBlurRequests = 10; + outputLayerState.ignoreBlur = coverage.aboveBlurRequests > kMaxBlurRequests; if (CC_UNLIKELY(computeAboveCoveredExcludingOverlays)) { outputLayerState.coveredRegionExcludingDisplayOverlays = std::move(coveredRegionExcludingDisplayOverlays); @@ -1437,7 +1445,7 @@ const Region viewportRegion(outputState.layerStackSpace.getContent()); bool firstLayer = true; - bool disableBlurs = false; + bool disableBlursWholesale = false; uint64_t previousOverrideBufferId = 0; for (auto* layer : getOutputLayersOrderedByZ()) { @@ -1454,7 +1462,8 @@ continue; } - disableBlurs |= layerFEState->sidebandStream != nullptr; + disableBlursWholesale |= layerFEState->sidebandStream != nullptr; + bool disableBlurForLayer = layer->getState().ignoreBlur || disableBlursWholesale; const bool clientComposition = layer->requiresClientComposition(); @@ -1484,7 +1493,8 @@ layer->getLayerFE().getDebugName()); } } else { - LayerFE::ClientCompositionTargetSettings::BlurSetting blurSetting = disableBlurs + LayerFE::ClientCompositionTargetSettings::BlurSetting blurSetting = + disableBlurForLayer ? LayerFE::ClientCompositionTargetSettings::BlurSetting::Disabled : (layer->getState().overrideInfo.disableBackgroundBlur ? LayerFE::ClientCompositionTargetSettings::BlurSetting::
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp index ea9442d..63e01b4 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp
@@ -196,9 +196,14 @@ std::vector<renderengine::LayerSettings> layerSettings; renderengine::LayerSettings highlight; for (const auto& layer : mLayers) { + auto blurSettings = targetSettings; + if (!layer.hasBlurBehind()) { + blurSettings.blurSetting = + LayerFE::ClientCompositionTargetSettings::BlurSetting::Disabled; + } if (auto clientCompositionSettings = layer.getState()->getOutputLayer()->getLayerFE().prepareClientComposition( - targetSettings)) { + blurSettings)) { layerSettings.push_back(std::move(*clientCompositionSettings)); } }
diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp index d61d7ba..5b33407 100644 --- a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp
@@ -1011,12 +1011,12 @@ EXPECT_CALL(*layerFE1, prepareClientComposition(ClientCompositionTargetSettingsBlurSettingsEq( compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting:: - Enabled))) + Disabled))) .WillOnce(Return(clientComp1)); EXPECT_CALL(*layerFE2, prepareClientComposition(ClientCompositionTargetSettingsBlurSettingsEq( compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting:: - Enabled))) + Disabled))) .WillOnce(Return(clientComp2)); EXPECT_CALL(*layerFE3, prepareClientComposition(ClientCompositionTargetSettingsBlurSettingsEq(