summaryrefslogtreecommitdiff
path: root/sdm/libs
diff options
context:
space:
mode:
authorVarun Arora <varuaror@codeaurora.org>2017-10-10 15:07:13 -0700
committerVarun Arora <varuaror@codeaurora.org>2017-10-10 15:07:13 -0700
commit2c23e58cd29cff24886737f07153e3b4ec659797 (patch)
tree5e271640b0f901da6b0e2ce3a7a30580dca98030 /sdm/libs
parent71f5daa4ea77f07ed7807b44f3a8a9a737d2edbe (diff)
downloaddisplay-2c23e58cd29cff24886737f07153e3b4ec659797.tar.gz
hwc2: Parameter validation and bounds checks
- Introduce use of GetDozeSupport Change-Id: Ic7edcd14b0c390fbd58f6be05b983a40b75c90eb CRs-Fixed: 2114346
Diffstat (limited to 'sdm/libs')
-rw-r--r--sdm/libs/hwc2/hwc_display.h2
-rw-r--r--sdm/libs/hwc2/hwc_layers.cpp11
-rw-r--r--sdm/libs/hwc2/hwc_session.cpp50
-rw-r--r--sdm/libs/hwc2/hwc_session.h4
-rw-r--r--sdm/libs/hwc2/hwc_session_services.cpp17
5 files changed, 68 insertions, 16 deletions
diff --git a/sdm/libs/hwc2/hwc_display.h b/sdm/libs/hwc2/hwc_display.h
index e90dbddd..1555b1b9 100644
--- a/sdm/libs/hwc2/hwc_display.h
+++ b/sdm/libs/hwc2/hwc_display.h
@@ -160,7 +160,7 @@ class HWCDisplay : public DisplayEventHandler {
int GetVisibleDisplayRect(hwc_rect_t *rect);
void BuildLayerStack(void);
void BuildSolidFillStack(void);
- HWCLayer *GetHWCLayer(hwc2_layer_t layer);
+ HWCLayer *GetHWCLayer(hwc2_layer_t layer_id);
void ResetValidation() { validated_ = false; }
uint32_t GetGeometryChanges() { return geometry_changes_; }
diff --git a/sdm/libs/hwc2/hwc_layers.cpp b/sdm/libs/hwc2/hwc_layers.cpp
index fee67b44..13a67cf5 100644
--- a/sdm/libs/hwc2/hwc_layers.cpp
+++ b/sdm/libs/hwc2/hwc_layers.cpp
@@ -406,8 +406,13 @@ HWC2::Error HWCLayer::SetCursorPosition(int32_t x, int32_t y) {
}
HWC2::Error HWCLayer::SetLayerPlaneAlpha(float alpha) {
- // Conversion of float alpha in range 0.0 to 1.0 similar to the HWC Adapter
+ if (alpha < 0.0f || alpha > 1.0f) {
+ return HWC2::Error::BadParameter;
+ }
+
+ // Conversion of float alpha in range 0.0 to 1.0 similar to the HWC Adapter
uint8_t plane_alpha = static_cast<uint8_t>(std::round(255.0f * alpha));
+
if (layer_->plane_alpha != plane_alpha) {
geometry_changes_ |= kPlaneAlpha;
layer_->plane_alpha = plane_alpha;
@@ -457,8 +462,10 @@ HWC2::Error HWCLayer::SetLayerTransform(HWC2::Transform transform) {
layer_transform.flip_vertical = true;
break;
case HWC2::Transform::None:
- // do nothing
break;
+ default:
+ // bad transform
+ return HWC2::Error::BadParameter;
}
if (layer_transform_ != layer_transform) {
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 390f39e9..fa5bce06 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -483,14 +483,20 @@ static int32_t GetDisplayType(hwc2_device_t *device, hwc2_display_t display, int
}
static int32_t GetDozeSupport(hwc2_device_t *device, hwc2_display_t display, int32_t *out_support) {
+ if (!device || !out_support) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+
+ if (display >= HWC_NUM_DISPLAY_TYPES) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
if (display == HWC_DISPLAY_PRIMARY) {
*out_support = 1;
} else {
- // TODO(user): Port over connect_display_ from HWC1
- // Return no error for connected displays
*out_support = 0;
- return HWC2_ERROR_BAD_DISPLAY;
}
+
return HWC2_ERROR_NONE;
}
@@ -663,14 +669,19 @@ static int32_t SetLayerVisibleRegion(hwc2_device_t *device, hwc2_display_t displ
int32_t HWCSession::SetLayerZOrder(hwc2_device_t *device, hwc2_display_t display,
hwc2_layer_t layer, uint32_t z) {
+ if (display >= HWC_NUM_DISPLAY_TYPES) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
SCOPE_LOCK(locker_[display]);
+
return CallDisplayFunction(device, display, &HWCDisplay::SetLayerZOrder, layer, z);
}
int32_t HWCSession::SetOutputBuffer(hwc2_device_t *device, hwc2_display_t display,
buffer_handle_t buffer, int32_t releaseFence) {
if (!device) {
- return HWC2_ERROR_BAD_DISPLAY;
+ return HWC2_ERROR_BAD_PARAMETER;
}
if (display != HWC_DISPLAY_VIRTUAL) {
@@ -689,24 +700,51 @@ int32_t HWCSession::SetOutputBuffer(hwc2_device_t *device, hwc2_display_t displa
}
int32_t HWCSession::SetPowerMode(hwc2_device_t *device, hwc2_display_t display, int32_t int_mode) {
+ if (display >= HWC_NUM_DISPLAY_TYPES) {
+ return HWC2_ERROR_BAD_DISPLAY;
+ }
+
+ // validate device and also avoid undefined behavior in cast to HWC2::PowerMode
+ if (!device || int_mode < HWC2_POWER_MODE_OFF || int_mode > HWC2_POWER_MODE_DOZE_SUSPEND) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+
auto mode = static_cast<HWC2::PowerMode>(int_mode);
+
+ // all displays support on/off. Check for doze modes
+ int support = 0;
+ GetDozeSupport(device, display, &support);
+ if (!support && (mode == HWC2::PowerMode::Doze || mode == HWC2::PowerMode::DozeSuspend)) {
+ return HWC2_ERROR_UNSUPPORTED;
+ }
+
SEQUENCE_WAIT_SCOPE_LOCK(locker_[display]);
return CallDisplayFunction(device, display, &HWCDisplay::SetPowerMode, mode);
}
static int32_t SetVsyncEnabled(hwc2_device_t *device, hwc2_display_t display, int32_t int_enabled) {
+ // avoid undefined behavior in cast to HWC2::Vsync
+ if (int_enabled < HWC2_VSYNC_INVALID || int_enabled > HWC2_VSYNC_DISABLE) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+
auto enabled = static_cast<HWC2::Vsync>(int_enabled);
return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::SetVsyncEnabled, enabled);
}
int32_t HWCSession::ValidateDisplay(hwc2_device_t *device, hwc2_display_t display,
uint32_t *out_num_types, uint32_t *out_num_requests) {
- DTRACE_SCOPED();
- HWCSession *hwc_session = static_cast<HWCSession *>(device);
+ // out_num_types and out_num_requests will be non-NULL
if (!device) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+
+ if (display >= HWC_NUM_DISPLAY_TYPES) {
return HWC2_ERROR_BAD_DISPLAY;
}
+ DTRACE_SCOPED();
+ HWCSession *hwc_session = static_cast<HWCSession *>(device);
// TODO(user): Handle secure session, handle QDCM solid fill
// Handle external_pending_connect_ in CreateVirtualDisplay
auto status = HWC2::Error::BadDisplay;
diff --git a/sdm/libs/hwc2/hwc_session.h b/sdm/libs/hwc2/hwc_session.h
index 36593706..df58093e 100644
--- a/sdm/libs/hwc2/hwc_session.h
+++ b/sdm/libs/hwc2/hwc_session.h
@@ -99,6 +99,10 @@ class HWCSession : hwc2_device_t, HWCUEventListener, IDisplayConfig, public qCli
hwc2_layer_t layer, HWC2::Error (HWCLayer::*member)(Args...),
Args... args) {
if (!device) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+
+ if (display >= HWC_NUM_DISPLAY_TYPES) {
return HWC2_ERROR_BAD_DISPLAY;
}
diff --git a/sdm/libs/hwc2/hwc_session_services.cpp b/sdm/libs/hwc2/hwc_session_services.cpp
index a5cf66a9..52eaf7ad 100644
--- a/sdm/libs/hwc2/hwc_session_services.cpp
+++ b/sdm/libs/hwc2/hwc_session_services.cpp
@@ -94,22 +94,25 @@ Return<void> HWCSession::isDisplayConnected(IDisplayConfig::DisplayType dpy,
isDisplayConnected_cb _hidl_cb) {
int32_t error = -EINVAL;
bool connected = false;
-
int disp_id = MapDisplayType(dpy);
- SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
- if (disp_id >= 0) {
- connected = hwc_display_[disp_id];
- error = 0;
+ if (disp_id < HWC_DISPLAY_PRIMARY || disp_id >= HWC_NUM_DISPLAY_TYPES) {
+ _hidl_cb(error, connected);
+ return Void();
}
- _hidl_cb(error, connected);
+ SEQUENCE_WAIT_SCOPE_LOCK(locker_[disp_id]);
+ connected = hwc_display_[disp_id];
+ error = 0;
+
+ _hidl_cb(error, connected);
return Void();
}
int32_t HWCSession::SetSecondaryDisplayStatus(int disp_id, HWCDisplay::DisplayStatus status) {
- if (disp_id < 0) {
+ if (disp_id < HWC_DISPLAY_PRIMARY || disp_id >= HWC_NUM_DISPLAY_TYPES) {
+ DLOGE("Invalid display = %d", disp_id);
return -EINVAL;
}