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

Commit b56eb905 authored by Chavi Weingarten's avatar Chavi Weingarten Committed by Android (Google) Code Review
Browse files

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

parents 543fa291 f5bb97ba
Loading
Loading
Loading
Loading
+24 −10
Original line number 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 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";

// ---------------------------------------------------------------------------
@@ -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) {
    IPCThreadState* ipc = IPCThreadState::self();
    const int pid = ipc->getCallingPid();
@@ -5888,6 +5898,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);

@@ -5897,9 +5911,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;
        }
@@ -6049,8 +6062,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) {
@@ -6070,8 +6082,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;
@@ -6083,8 +6096,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) {
@@ -6097,7 +6111,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;
    }
+2 −2
Original line number Diff line number Diff line
@@ -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);
+6 −1
Original line number Diff line number Diff line
@@ -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;
    {
        // 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));
+12 −4
Original line number Diff line number Diff line
@@ -84,7 +84,11 @@ TEST_F(ScreenCaptureTest, SetFlagsSecureEUidSystem) {

    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));
    }

    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;

    {
        // 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);