diff options
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 34 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 4 | ||||
| -rw-r--r-- | services/surfaceflinger/tests/LayerTypeTransaction_test.cpp | 7 | ||||
| -rw-r--r-- | services/surfaceflinger/tests/ScreenCapture_test.cpp | 16 |
4 files changed, 44 insertions, 17 deletions
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 3edbe1da02..a1b151bf7d 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -287,6 +287,8 @@ const String16 sRotateSurfaceFlinger("android.permission.ROTATE_SURFACE_FLINGER" const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER"); const String16 sControlDisplayBrightness("android.permission.CONTROL_DISPLAY_BRIGHTNESS"); const String16 sDump("android.permission.DUMP"); +const String16 sCaptureBlackoutContent("android.permission.CAPTURE_BLACKOUT_CONTENT"); + const char* KERNEL_IDLE_TIMER_PROP = "graphics.display.kernel_idle_timer.enabled"; // --------------------------------------------------------------------------- @@ -5681,6 +5683,14 @@ static Dataspace pickDataspaceFromColorMode(const ColorMode colorMode) { } } +static bool hasCaptureBlackoutContentPermission() { + IPCThreadState* ipc = IPCThreadState::self(); + const int pid = ipc->getCallingPid(); + const int uid = ipc->getCallingUid(); + return uid == AID_GRAPHICS || uid == AID_SYSTEM || + PermissionCache::checkPermission(sCaptureBlackoutContent, pid, uid); +} + static status_t validateScreenshotPermissions(const CaptureArgs& captureArgs) { IPCThreadState* ipc = IPCThreadState::self(); const int pid = ipc->getCallingPid(); @@ -5851,6 +5861,10 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, Rect layerStackSpaceRect; ui::Dataspace dataspace; bool captureSecureLayers; + + // Call this before holding mStateLock to avoid any deadlocking. + bool canCaptureBlackoutContent = hasCaptureBlackoutContentPermission(); + { Mutex::Autolock lock(mStateLock); @@ -5860,9 +5874,8 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, return NAME_NOT_FOUND; } - const int uid = IPCThreadState::self()->getCallingUid(); - const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM; - if (!forSystem && parent->getCurrentState().flags & layer_state_t::eLayerSecure) { + if (!canCaptureBlackoutContent && + parent->getCurrentState().flags & layer_state_t::eLayerSecure) { ALOGW("Attempting to capture secure layer: PERMISSION_DENIED"); return PERMISSION_DENIED; } @@ -6012,8 +6025,7 @@ status_t SurfaceFlinger::captureScreenCommon( return BAD_VALUE; } - const int uid = IPCThreadState::self()->getCallingUid(); - const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM; + bool canCaptureBlackoutContent = hasCaptureBlackoutContentPermission(); static_cast<void>(schedule([=, renderAreaFuture = std::move(renderAreaFuture)]() mutable { if (mRefreshPending) { @@ -6033,8 +6045,9 @@ status_t SurfaceFlinger::captureScreenCommon( status_t result = NO_ERROR; renderArea->render([&] { - result = renderScreenImplLocked(*renderArea, traverseLayers, buffer, forSystem, - regionSampling, grayscale, captureResults); + result = renderScreenImplLocked(*renderArea, traverseLayers, buffer, + canCaptureBlackoutContent, regionSampling, grayscale, + captureResults); }); captureResults.result = result; @@ -6046,8 +6059,9 @@ status_t SurfaceFlinger::captureScreenCommon( status_t SurfaceFlinger::renderScreenImplLocked( const RenderArea& renderArea, TraverseLayersFunction traverseLayers, - const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool forSystem, - bool regionSampling, bool grayscale, ScreenCaptureResults& captureResults) { + const std::shared_ptr<renderengine::ExternalTexture>& buffer, + bool canCaptureBlackoutContent, bool regionSampling, bool grayscale, + ScreenCaptureResults& captureResults) { ATRACE_CALL(); traverseLayers([&](Layer* layer) { @@ -6060,7 +6074,7 @@ status_t SurfaceFlinger::renderScreenImplLocked( // We allow the system server to take screenshots of secure layers for // use in situations like the Screen-rotation animation and place // the impetus on WindowManager to not persist them. - if (captureResults.capturedSecureLayers && !forSystem) { + if (captureResults.capturedSecureLayers && !canCaptureBlackoutContent) { ALOGW("FB is protected: PERMISSION_DENIED"); return PERMISSION_DENIED; } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 4bbdd48035..c66cdbb496 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -911,8 +911,8 @@ private: const sp<IScreenCaptureListener>&); status_t renderScreenImplLocked(const RenderArea&, TraverseLayersFunction, const std::shared_ptr<renderengine::ExternalTexture>&, - bool forSystem, bool regionSampling, bool grayscale, - ScreenCaptureResults&); + bool canCaptureBlackoutContent, bool regionSampling, + bool grayscale, ScreenCaptureResults&); sp<DisplayDevice> getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) REQUIRES(mStateLock); sp<DisplayDevice> getDisplayById(DisplayId displayId) const REQUIRES(mStateLock); diff --git a/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp index 4753362292..34c918261a 100644 --- a/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp @@ -19,6 +19,7 @@ #pragma clang diagnostic ignored "-Wconversion" #include <gui/BufferItemConsumer.h> +#include <private/android_filesystem_config.h> #include "TransactionTestHarnesses.h" namespace android { @@ -170,7 +171,11 @@ TEST_P(LayerTypeTransactionTest, SetFlagsSecure) { args.displayToken = mDisplay; ScreenCaptureResults captureResults; - ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureDisplay(args, captureResults)); + { + // Ensure the UID is not root because root has all permissions + UIDFaker f(AID_APP_START); + ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureDisplay(args, captureResults)); + } Transaction().setFlags(layer, 0, layer_state_t::eLayerSecure).apply(true); ASSERT_EQ(NO_ERROR, ScreenCapture::captureDisplay(args, captureResults)); diff --git a/services/surfaceflinger/tests/ScreenCapture_test.cpp b/services/surfaceflinger/tests/ScreenCapture_test.cpp index 2e9c10ce5c..6912fcf219 100644 --- a/services/surfaceflinger/tests/ScreenCapture_test.cpp +++ b/services/surfaceflinger/tests/ScreenCapture_test.cpp @@ -84,7 +84,11 @@ TEST_F(ScreenCaptureTest, SetFlagsSecureEUidSystem) { Transaction().show(layer).setLayer(layer, INT32_MAX).apply(true); - ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureDisplay(mCaptureArgs, mCaptureResults)); + { + // Ensure the UID is not root because root has all permissions + UIDFaker f(AID_APP_START); + ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureDisplay(mCaptureArgs, mCaptureResults)); + } UIDFaker f(AID_SYSTEM); @@ -528,7 +532,7 @@ TEST_F(ScreenCaptureTest, CaptureInvalidLayer) { ASSERT_EQ(NAME_NOT_FOUND, ScreenCapture::captureLayers(args, captureResults)); } -TEST_F(ScreenCaptureTest, CaputureSecureLayer) { +TEST_F(ScreenCaptureTest, CaptureSecureLayer) { sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, ISurfaceComposerClient::eFXSurfaceBufferState); sp<SurfaceControl> secureLayer = @@ -552,8 +556,12 @@ TEST_F(ScreenCaptureTest, CaputureSecureLayer) { args.childrenOnly = false; ScreenCaptureResults captureResults; - // Call from outside system with secure layers will result in permission denied - ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureLayers(args, captureResults)); + { + // Ensure the UID is not root because root has all permissions + UIDFaker f(AID_APP_START); + // Call from outside system with secure layers will result in permission denied + ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureLayers(args, captureResults)); + } UIDFaker f(AID_SYSTEM); |