Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fa3cb809 authored by Chavi Weingarten's avatar Chavi Weingarten Committed by Automerger Merge Worker
Browse files

Merge "Add CAPTURE_BLACKOUT_CONTENT permission check for screenshots" into sc-dev am: b56eb905

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/native/+/14342345

Change-Id: Ib591036802bf94f7c1e88d91b1ef00239ff18cf9
parents 289d7a9a b56eb905
Loading
Loading
Loading
Loading
+24 −10
Original line number Original line Diff line number Diff line
@@ -287,6 +287,8 @@ const String16 sRotateSurfaceFlinger("android.permission.ROTATE_SURFACE_FLINGER"
const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER");
const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER");
const String16 sControlDisplayBrightness("android.permission.CONTROL_DISPLAY_BRIGHTNESS");
const String16 sControlDisplayBrightness("android.permission.CONTROL_DISPLAY_BRIGHTNESS");
const String16 sDump("android.permission.DUMP");
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";
const char* KERNEL_IDLE_TIMER_PROP = "graphics.display.kernel_idle_timer.enabled";


// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
@@ -5718,6 +5720,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) {
static status_t validateScreenshotPermissions(const CaptureArgs& captureArgs) {
    IPCThreadState* ipc = IPCThreadState::self();
    IPCThreadState* ipc = IPCThreadState::self();
    const int pid = ipc->getCallingPid();
    const int pid = ipc->getCallingPid();
@@ -5888,6 +5898,10 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
    Rect layerStackSpaceRect;
    Rect layerStackSpaceRect;
    ui::Dataspace dataspace;
    ui::Dataspace dataspace;
    bool captureSecureLayers;
    bool captureSecureLayers;

    // Call this before holding mStateLock to avoid any deadlocking.
    bool canCaptureBlackoutContent = hasCaptureBlackoutContentPermission();

    {
    {
        Mutex::Autolock lock(mStateLock);
        Mutex::Autolock lock(mStateLock);


@@ -5897,9 +5911,8 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
            return NAME_NOT_FOUND;
            return NAME_NOT_FOUND;
        }
        }


        const int uid = IPCThreadState::self()->getCallingUid();
        if (!canCaptureBlackoutContent &&
        const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM;
            parent->getCurrentState().flags & layer_state_t::eLayerSecure) {
        if (!forSystem && parent->getCurrentState().flags & layer_state_t::eLayerSecure) {
            ALOGW("Attempting to capture secure layer: PERMISSION_DENIED");
            ALOGW("Attempting to capture secure layer: PERMISSION_DENIED");
            return PERMISSION_DENIED;
            return PERMISSION_DENIED;
        }
        }
@@ -6049,8 +6062,7 @@ status_t SurfaceFlinger::captureScreenCommon(
        return BAD_VALUE;
        return BAD_VALUE;
    }
    }


    const int uid = IPCThreadState::self()->getCallingUid();
    bool canCaptureBlackoutContent = hasCaptureBlackoutContentPermission();
    const bool forSystem = uid == AID_GRAPHICS || uid == AID_SYSTEM;


    static_cast<void>(schedule([=, renderAreaFuture = std::move(renderAreaFuture)]() mutable {
    static_cast<void>(schedule([=, renderAreaFuture = std::move(renderAreaFuture)]() mutable {
        if (mRefreshPending) {
        if (mRefreshPending) {
@@ -6070,8 +6082,9 @@ status_t SurfaceFlinger::captureScreenCommon(


        status_t result = NO_ERROR;
        status_t result = NO_ERROR;
        renderArea->render([&] {
        renderArea->render([&] {
            result = renderScreenImplLocked(*renderArea, traverseLayers, buffer, forSystem,
            result = renderScreenImplLocked(*renderArea, traverseLayers, buffer,
                                            regionSampling, grayscale, captureResults);
                                            canCaptureBlackoutContent, regionSampling, grayscale,
                                            captureResults);
        });
        });


        captureResults.result = result;
        captureResults.result = result;
@@ -6083,8 +6096,9 @@ status_t SurfaceFlinger::captureScreenCommon(


status_t SurfaceFlinger::renderScreenImplLocked(
status_t SurfaceFlinger::renderScreenImplLocked(
        const RenderArea& renderArea, TraverseLayersFunction traverseLayers,
        const RenderArea& renderArea, TraverseLayersFunction traverseLayers,
        const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool forSystem,
        const std::shared_ptr<renderengine::ExternalTexture>& buffer,
        bool regionSampling, bool grayscale, ScreenCaptureResults& captureResults) {
        bool canCaptureBlackoutContent, bool regionSampling, bool grayscale,
        ScreenCaptureResults& captureResults) {
    ATRACE_CALL();
    ATRACE_CALL();


    traverseLayers([&](Layer* layer) {
    traverseLayers([&](Layer* layer) {
@@ -6097,7 +6111,7 @@ status_t SurfaceFlinger::renderScreenImplLocked(
    // We allow the system server to take screenshots of secure layers for
    // We allow the system server to take screenshots of secure layers for
    // use in situations like the Screen-rotation animation and place
    // use in situations like the Screen-rotation animation and place
    // the impetus on WindowManager to not persist them.
    // the impetus on WindowManager to not persist them.
    if (captureResults.capturedSecureLayers && !forSystem) {
    if (captureResults.capturedSecureLayers && !canCaptureBlackoutContent) {
        ALOGW("FB is protected: PERMISSION_DENIED");
        ALOGW("FB is protected: PERMISSION_DENIED");
        return PERMISSION_DENIED;
        return PERMISSION_DENIED;
    }
    }
+2 −2
Original line number Original line Diff line number Diff line
@@ -911,8 +911,8 @@ private:
                                 const sp<IScreenCaptureListener>&);
                                 const sp<IScreenCaptureListener>&);
    status_t renderScreenImplLocked(const RenderArea&, TraverseLayersFunction,
    status_t renderScreenImplLocked(const RenderArea&, TraverseLayersFunction,
                                    const std::shared_ptr<renderengine::ExternalTexture>&,
                                    const std::shared_ptr<renderengine::ExternalTexture>&,
                                    bool forSystem, bool regionSampling, bool grayscale,
                                    bool canCaptureBlackoutContent, bool regionSampling,
                                    ScreenCaptureResults&);
                                    bool grayscale, ScreenCaptureResults&);


    sp<DisplayDevice> getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) REQUIRES(mStateLock);
    sp<DisplayDevice> getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) REQUIRES(mStateLock);
    sp<DisplayDevice> getDisplayById(DisplayId displayId) const REQUIRES(mStateLock);
    sp<DisplayDevice> getDisplayById(DisplayId displayId) const REQUIRES(mStateLock);
+6 −1
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@
#pragma clang diagnostic ignored "-Wconversion"
#pragma clang diagnostic ignored "-Wconversion"


#include <gui/BufferItemConsumer.h>
#include <gui/BufferItemConsumer.h>
#include <private/android_filesystem_config.h>
#include "TransactionTestHarnesses.h"
#include "TransactionTestHarnesses.h"


namespace android {
namespace android {
@@ -170,7 +171,11 @@ TEST_P(LayerTypeTransactionTest, SetFlagsSecure) {
    args.displayToken = mDisplay;
    args.displayToken = mDisplay;


    ScreenCaptureResults captureResults;
    ScreenCaptureResults 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));
        ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureDisplay(args, captureResults));
    }


    Transaction().setFlags(layer, 0, layer_state_t::eLayerSecure).apply(true);
    Transaction().setFlags(layer, 0, layer_state_t::eLayerSecure).apply(true);
    ASSERT_EQ(NO_ERROR, ScreenCapture::captureDisplay(args, captureResults));
    ASSERT_EQ(NO_ERROR, ScreenCapture::captureDisplay(args, captureResults));
+12 −4
Original line number Original line Diff line number Diff line
@@ -84,7 +84,11 @@ TEST_F(ScreenCaptureTest, SetFlagsSecureEUidSystem) {


    Transaction().show(layer).setLayer(layer, INT32_MAX).apply(true);
    Transaction().show(layer).setLayer(layer, INT32_MAX).apply(true);


    {
        // Ensure the UID is not root because root has all permissions
        UIDFaker f(AID_APP_START);
        ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureDisplay(mCaptureArgs, mCaptureResults));
        ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureDisplay(mCaptureArgs, mCaptureResults));
    }


    UIDFaker f(AID_SYSTEM);
    UIDFaker f(AID_SYSTEM);


@@ -528,7 +532,7 @@ TEST_F(ScreenCaptureTest, CaptureInvalidLayer) {
    ASSERT_EQ(NAME_NOT_FOUND, ScreenCapture::captureLayers(args, captureResults));
    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,
    sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60,
                                              ISurfaceComposerClient::eFXSurfaceBufferState);
                                              ISurfaceComposerClient::eFXSurfaceBufferState);
    sp<SurfaceControl> secureLayer =
    sp<SurfaceControl> secureLayer =
@@ -552,8 +556,12 @@ TEST_F(ScreenCaptureTest, CaputureSecureLayer) {
    args.childrenOnly = false;
    args.childrenOnly = false;
    ScreenCaptureResults captureResults;
    ScreenCaptureResults 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
        // Call from outside system with secure layers will result in permission denied
        ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureLayers(args, captureResults));
        ASSERT_EQ(PERMISSION_DENIED, ScreenCapture::captureLayers(args, captureResults));
    }


    UIDFaker f(AID_SYSTEM);
    UIDFaker f(AID_SYSTEM);