Add security check to getPhysicalDisplayToken binder function.
- There is a possible way to take over the screen display and swap the
display content due to a missing permission check.
- Add a short-term fix for WCG checking failure because of new
permission check added to SF::getPhysicalDisplayToken: change two
function signatures (getStaticDisplayInfo and getDynamicDisplayInfo).
- To make short-term fix workable, split getDynamicDisplayInfo binder
call into two, one is to take display id, one is to take display token
as old codes show to avoid huge modification on other callees.
Bug: 248031255
Test: test using displaytoken app manually on the phone, test shell
screenrecord during using displaytoken; atest
android.hardware.camera2.cts.FastBasicsTest
Change-Id: Id9d9012d4ede9c8330f0ce1096bcb78e51b7c5df
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 95962af..59b62fe 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -388,6 +388,27 @@
}
}
+void DisplayState::sanitize(int32_t permissions) {
+ if (what & DisplayState::eLayerStackChanged) {
+ if (!(permissions & layer_state_t::Permission::ACCESS_SURFACE_FLINGER)) {
+ what &= ~DisplayState::eLayerStackChanged;
+ ALOGE("Stripped attempt to set eLayerStackChanged in sanitize");
+ }
+ }
+ if (what & DisplayState::eDisplayProjectionChanged) {
+ if (!(permissions & layer_state_t::Permission::ACCESS_SURFACE_FLINGER)) {
+ what &= ~DisplayState::eDisplayProjectionChanged;
+ ALOGE("Stripped attempt to set eDisplayProjectionChanged in sanitize");
+ }
+ }
+ if (what & DisplayState::eSurfaceChanged) {
+ if (!(permissions & layer_state_t::Permission::ACCESS_SURFACE_FLINGER)) {
+ what &= ~DisplayState::eSurfaceChanged;
+ ALOGE("Stripped attempt to set eSurfaceChanged in sanitize");
+ }
+ }
+}
+
void layer_state_t::sanitize(int32_t permissions) {
// TODO: b/109894387
//
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 325c294..abe5d35 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -2260,12 +2260,12 @@
return statusTFromBinderStatus(status);
}
-status_t SurfaceComposerClient::getStaticDisplayInfo(const sp<IBinder>& display,
+status_t SurfaceComposerClient::getStaticDisplayInfo(int64_t displayId,
ui::StaticDisplayInfo* outInfo) {
using Tag = android::gui::DeviceProductInfo::ManufactureOrModelDate::Tag;
gui::StaticDisplayInfo ginfo;
binder::Status status =
- ComposerServiceAIDL::getComposerService()->getStaticDisplayInfo(display, &ginfo);
+ ComposerServiceAIDL::getComposerService()->getStaticDisplayInfo(displayId, &ginfo);
if (status.isOk()) {
// convert gui::StaticDisplayInfo to ui::StaticDisplayInfo
outInfo->connectionType = static_cast<ui::DisplayConnectionType>(ginfo.connectionType);
@@ -2309,56 +2309,74 @@
return statusTFromBinderStatus(status);
}
-status_t SurfaceComposerClient::getDynamicDisplayInfo(const sp<IBinder>& display,
- ui::DynamicDisplayInfo* outInfo) {
+void SurfaceComposerClient::getDynamicDisplayInfoInternal(gui::DynamicDisplayInfo& ginfo,
+ ui::DynamicDisplayInfo*& outInfo) {
+ // convert gui::DynamicDisplayInfo to ui::DynamicDisplayInfo
+ outInfo->supportedDisplayModes.clear();
+ outInfo->supportedDisplayModes.reserve(ginfo.supportedDisplayModes.size());
+ for (const auto& mode : ginfo.supportedDisplayModes) {
+ ui::DisplayMode outMode;
+ outMode.id = mode.id;
+ outMode.resolution.width = mode.resolution.width;
+ outMode.resolution.height = mode.resolution.height;
+ outMode.xDpi = mode.xDpi;
+ outMode.yDpi = mode.yDpi;
+ outMode.refreshRate = mode.refreshRate;
+ outMode.appVsyncOffset = mode.appVsyncOffset;
+ outMode.sfVsyncOffset = mode.sfVsyncOffset;
+ outMode.presentationDeadline = mode.presentationDeadline;
+ outMode.group = mode.group;
+ std::transform(mode.supportedHdrTypes.begin(), mode.supportedHdrTypes.end(),
+ std::back_inserter(outMode.supportedHdrTypes),
+ [](const int32_t& value) { return static_cast<ui::Hdr>(value); });
+ outInfo->supportedDisplayModes.push_back(outMode);
+ }
+
+ outInfo->activeDisplayModeId = ginfo.activeDisplayModeId;
+ outInfo->renderFrameRate = ginfo.renderFrameRate;
+
+ outInfo->supportedColorModes.clear();
+ outInfo->supportedColorModes.reserve(ginfo.supportedColorModes.size());
+ for (const auto& cmode : ginfo.supportedColorModes) {
+ outInfo->supportedColorModes.push_back(static_cast<ui::ColorMode>(cmode));
+ }
+
+ outInfo->activeColorMode = static_cast<ui::ColorMode>(ginfo.activeColorMode);
+
+ std::vector<ui::Hdr> types;
+ types.reserve(ginfo.hdrCapabilities.supportedHdrTypes.size());
+ for (const auto& hdr : ginfo.hdrCapabilities.supportedHdrTypes) {
+ types.push_back(static_cast<ui::Hdr>(hdr));
+ }
+ outInfo->hdrCapabilities = HdrCapabilities(types, ginfo.hdrCapabilities.maxLuminance,
+ ginfo.hdrCapabilities.maxAverageLuminance,
+ ginfo.hdrCapabilities.minLuminance);
+
+ outInfo->autoLowLatencyModeSupported = ginfo.autoLowLatencyModeSupported;
+ outInfo->gameContentTypeSupported = ginfo.gameContentTypeSupported;
+ outInfo->preferredBootDisplayMode = ginfo.preferredBootDisplayMode;
+}
+
+status_t SurfaceComposerClient::getDynamicDisplayInfoFromId(int64_t displayId,
+ ui::DynamicDisplayInfo* outInfo) {
gui::DynamicDisplayInfo ginfo;
binder::Status status =
- ComposerServiceAIDL::getComposerService()->getDynamicDisplayInfo(display, &ginfo);
+ ComposerServiceAIDL::getComposerService()->getDynamicDisplayInfoFromId(displayId,
+ &ginfo);
if (status.isOk()) {
- // convert gui::DynamicDisplayInfo to ui::DynamicDisplayInfo
- outInfo->supportedDisplayModes.clear();
- outInfo->supportedDisplayModes.reserve(ginfo.supportedDisplayModes.size());
- for (const auto& mode : ginfo.supportedDisplayModes) {
- ui::DisplayMode outMode;
- outMode.id = mode.id;
- outMode.resolution.width = mode.resolution.width;
- outMode.resolution.height = mode.resolution.height;
- outMode.xDpi = mode.xDpi;
- outMode.yDpi = mode.yDpi;
- outMode.refreshRate = mode.refreshRate;
- outMode.appVsyncOffset = mode.appVsyncOffset;
- outMode.sfVsyncOffset = mode.sfVsyncOffset;
- outMode.presentationDeadline = mode.presentationDeadline;
- outMode.group = mode.group;
- std::transform(mode.supportedHdrTypes.begin(), mode.supportedHdrTypes.end(),
- std::back_inserter(outMode.supportedHdrTypes),
- [](const int32_t& value) { return static_cast<ui::Hdr>(value); });
- outInfo->supportedDisplayModes.push_back(outMode);
- }
+ getDynamicDisplayInfoInternal(ginfo, outInfo);
+ }
+ return statusTFromBinderStatus(status);
+}
- outInfo->activeDisplayModeId = ginfo.activeDisplayModeId;
- outInfo->renderFrameRate = ginfo.renderFrameRate;
-
- outInfo->supportedColorModes.clear();
- outInfo->supportedColorModes.reserve(ginfo.supportedColorModes.size());
- for (const auto& cmode : ginfo.supportedColorModes) {
- outInfo->supportedColorModes.push_back(static_cast<ui::ColorMode>(cmode));
- }
-
- outInfo->activeColorMode = static_cast<ui::ColorMode>(ginfo.activeColorMode);
-
- std::vector<ui::Hdr> types;
- types.reserve(ginfo.hdrCapabilities.supportedHdrTypes.size());
- for (const auto& hdr : ginfo.hdrCapabilities.supportedHdrTypes) {
- types.push_back(static_cast<ui::Hdr>(hdr));
- }
- outInfo->hdrCapabilities = HdrCapabilities(types, ginfo.hdrCapabilities.maxLuminance,
- ginfo.hdrCapabilities.maxAverageLuminance,
- ginfo.hdrCapabilities.minLuminance);
-
- outInfo->autoLowLatencyModeSupported = ginfo.autoLowLatencyModeSupported;
- outInfo->gameContentTypeSupported = ginfo.gameContentTypeSupported;
- outInfo->preferredBootDisplayMode = ginfo.preferredBootDisplayMode;
+status_t SurfaceComposerClient::getDynamicDisplayInfoFromToken(const sp<IBinder>& display,
+ ui::DynamicDisplayInfo* outInfo) {
+ gui::DynamicDisplayInfo ginfo;
+ binder::Status status =
+ ComposerServiceAIDL::getComposerService()->getDynamicDisplayInfoFromToken(display,
+ &ginfo);
+ if (status.isOk()) {
+ getDynamicDisplayInfoInternal(ginfo, outInfo);
}
return statusTFromBinderStatus(status);
}
@@ -2366,7 +2384,8 @@
status_t SurfaceComposerClient::getActiveDisplayMode(const sp<IBinder>& display,
ui::DisplayMode* mode) {
ui::DynamicDisplayInfo info;
- status_t result = getDynamicDisplayInfo(display, &info);
+
+ status_t result = getDynamicDisplayInfoFromToken(display, &info);
if (result != NO_ERROR) {
return result;
}
diff --git a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
index 40410fb..488a148 100644
--- a/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
+++ b/libs/gui/aidl/android/gui/ISurfaceComposer.aidl
@@ -126,12 +126,14 @@
/**
* Gets immutable information about given physical display.
*/
- StaticDisplayInfo getStaticDisplayInfo(IBinder display);
+ StaticDisplayInfo getStaticDisplayInfo(long displayId);
/**
* Gets dynamic information about given physical display.
*/
- DynamicDisplayInfo getDynamicDisplayInfo(IBinder display);
+ DynamicDisplayInfo getDynamicDisplayInfoFromId(long displayId);
+
+ DynamicDisplayInfo getDynamicDisplayInfoFromToken(IBinder display);
DisplayPrimaries getDisplayNativePrimaries(IBinder display);
diff --git a/libs/gui/fuzzer/libgui_fuzzer_utils.h b/libs/gui/fuzzer/libgui_fuzzer_utils.h
index 9d1ee8f..8810e4e 100644
--- a/libs/gui/fuzzer/libgui_fuzzer_utils.h
+++ b/libs/gui/fuzzer/libgui_fuzzer_utils.h
@@ -79,9 +79,11 @@
(override));
MOCK_METHOD(binder::Status, getDisplayState, (const sp<IBinder>&, gui::DisplayState*),
(override));
- MOCK_METHOD(binder::Status, getStaticDisplayInfo, (const sp<IBinder>&, gui::StaticDisplayInfo*),
+ MOCK_METHOD(binder::Status, getStaticDisplayInfo, (int64_t, gui::StaticDisplayInfo*),
(override));
- MOCK_METHOD(binder::Status, getDynamicDisplayInfo,
+ MOCK_METHOD(binder::Status, getDynamicDisplayInfoFromId, (int64_t, gui::DynamicDisplayInfo*),
+ (override));
+ MOCK_METHOD(binder::Status, getDynamicDisplayInfoFromToken,
(const sp<IBinder>&, gui::DynamicDisplayInfo*), (override));
MOCK_METHOD(binder::Status, getDisplayNativePrimaries,
(const sp<IBinder>&, gui::DisplayPrimaries*), (override));
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 6ec6bd7..45a84f6 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -359,6 +359,7 @@
DisplayState();
void merge(const DisplayState& other);
+ void sanitize(int32_t permissions);
uint32_t what = 0;
uint32_t flags = 0;
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 2038f14..df47002 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -149,10 +149,10 @@
static status_t getDisplayState(const sp<IBinder>& display, ui::DisplayState*);
// Get immutable information about given physical display.
- static status_t getStaticDisplayInfo(const sp<IBinder>& display, ui::StaticDisplayInfo*);
+ static status_t getStaticDisplayInfo(int64_t, ui::StaticDisplayInfo*);
- // Get dynamic information about given physical display.
- static status_t getDynamicDisplayInfo(const sp<IBinder>& display, ui::DynamicDisplayInfo*);
+ // Get dynamic information about given physical display from display id
+ static status_t getDynamicDisplayInfoFromId(int64_t, ui::DynamicDisplayInfo*);
// Shorthand for the active display mode from getDynamicDisplayInfo().
// TODO(b/180391891): Update clients to use getDynamicDisplayInfo and remove this function.
@@ -714,6 +714,12 @@
ReleaseCallbackThread mReleaseCallbackThread;
private:
+ // Get dynamic information about given physical display from token
+ static status_t getDynamicDisplayInfoFromToken(const sp<IBinder>& display,
+ ui::DynamicDisplayInfo*);
+
+ static void getDynamicDisplayInfoInternal(gui::DynamicDisplayInfo& ginfo,
+ ui::DynamicDisplayInfo*& outInfo);
virtual void onFirstRef();
mutable Mutex mLock;
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 6d3b425..55242df 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -782,13 +782,18 @@
return binder::Status::ok();
}
- binder::Status getStaticDisplayInfo(const sp<IBinder>& /*display*/,
+ binder::Status getStaticDisplayInfo(int64_t /*displayId*/,
gui::StaticDisplayInfo* /*outInfo*/) override {
return binder::Status::ok();
}
- binder::Status getDynamicDisplayInfo(const sp<IBinder>& /*display*/,
- gui::DynamicDisplayInfo* /*outInfo*/) override {
+ binder::Status getDynamicDisplayInfoFromId(int64_t /*displayId*/,
+ gui::DynamicDisplayInfo* /*outInfo*/) override {
+ return binder::Status::ok();
+ }
+
+ binder::Status getDynamicDisplayInfoFromToken(const sp<IBinder>& /*display*/,
+ gui::DynamicDisplayInfo* /*outInfo*/) override {
return binder::Status::ok();
}