hwc2: Add input validation and bound checks.
- Validate the input parameters to hwc2 and check if they
are with in the allowed bounds.
- On the getter functions check the out counts before populating
with output parameters
Change-Id: Ifd41aa4d4a0b08e521fabfe54f308a59622d109c
Crs-fixed: 2114346
diff --git a/sdm/libs/hwc2/hwc_display.cpp b/sdm/libs/hwc2/hwc_display.cpp
index 0530db8..e3b93cf 100644
--- a/sdm/libs/hwc2/hwc_display.cpp
+++ b/sdm/libs/hwc2/hwc_display.cpp
@@ -94,11 +94,12 @@
HWC2::Error HWCColorMode::GetColorModes(uint32_t *out_num_modes,
android_color_mode_t *out_modes) {
auto it = color_mode_transform_map_.begin();
- for (auto i = 0; it != color_mode_transform_map_.end(); it++, i++) {
+ *out_num_modes = std::min(*out_num_modes, UINT32(color_mode_transform_map_.size()));
+ for (uint32_t i = 0; i < *out_num_modes; it++, i++) {
out_modes[i] = it->first;
DLOGI("Supports color mode[%d] = %d", i, it->first);
}
- *out_num_modes = UINT32(color_mode_transform_map_.size());
+
return HWC2::Error::None;
}
@@ -750,23 +751,28 @@
}
HWC2::Error HWCDisplay::GetColorModes(uint32_t *out_num_modes, android_color_mode_t *out_modes) {
- if (out_modes) {
+ if (out_modes == nullptr) {
+ *out_num_modes = 1;
+ } else if (out_modes && *out_num_modes > 0) {
+ *out_num_modes = 1;
out_modes[0] = HAL_COLOR_MODE_NATIVE;
}
- *out_num_modes = 1;
return HWC2::Error::None;
}
HWC2::Error HWCDisplay::GetDisplayConfigs(uint32_t *out_num_configs, hwc2_config_t *out_configs) {
+ if (out_num_configs == nullptr) {
+ return HWC2::Error::BadParameter;
+ }
+
if (out_configs == nullptr) {
*out_num_configs = num_configs_;
return HWC2::Error::None;
}
- *out_num_configs = num_configs_;
-
- for (uint32_t i = 0; i < num_configs_; i++) {
+ *out_num_configs = std::min(*out_num_configs, num_configs_);
+ for (uint32_t i = 0; i < *out_num_configs; i++) {
out_configs[i] = i;
}
@@ -817,27 +823,38 @@
HWC2::Error HWCDisplay::GetDisplayName(uint32_t *out_size, char *out_name) {
// TODO(user): Get panel name and EDID name and populate it here
- if (out_name == nullptr) {
- *out_size = 32;
- } else {
- std::string name;
- switch (id_) {
- case HWC_DISPLAY_PRIMARY:
- name = "Primary Display";
- break;
- case HWC_DISPLAY_EXTERNAL:
- name = "External Display";
- break;
- case HWC_DISPLAY_VIRTUAL:
- name = "Virtual Display";
- break;
- default:
- name = "Unknown";
- break;
- }
- std::strncpy(out_name, name.c_str(), name.size());
- *out_size = UINT32(name.size());
+ if (out_size == nullptr) {
+ return HWC2::Error::BadParameter;
}
+
+ std::string name;
+ switch (id_) {
+ case HWC_DISPLAY_PRIMARY:
+ name = "Primary Display";
+ break;
+ case HWC_DISPLAY_EXTERNAL:
+ name = "External Display";
+ break;
+ case HWC_DISPLAY_VIRTUAL:
+ name = "Virtual Display";
+ break;
+ default:
+ name = "Unknown";
+ break;
+ }
+
+ if (out_name == nullptr) {
+ *out_size = UINT32(name.size()) + 1;
+ } else {
+ *out_size = std::min((UINT32(name.size()) + 1), *out_size);
+ if (*out_size > 0) {
+ std::strncpy(out_name, name.c_str(), *out_size);
+ out_name[*out_size - 1] = '\0';
+ } else {
+ DLOGW("Invalid size requested");
+ }
+ }
+
return HWC2::Error::None;
}
@@ -1070,15 +1087,22 @@
HWC2::Error HWCDisplay::GetReleaseFences(uint32_t *out_num_elements, hwc2_layer_t *out_layers,
int32_t *out_fences) {
+ if (out_num_elements == nullptr) {
+ return HWC2::Error::BadParameter;
+ }
+
if (out_layers != nullptr && out_fences != nullptr) {
- int i = 0;
- for (auto hwc_layer : layer_set_) {
+ *out_num_elements = std::min(*out_num_elements, UINT32(layer_set_.size()));
+ auto it = layer_set_.begin();
+ for (uint32_t i = 0; i < *out_num_elements; i++, it++) {
+ auto hwc_layer = *it;
out_layers[i] = hwc_layer->GetId();
out_fences[i] = hwc_layer->PopReleaseFence();
- i++;
}
+ } else {
+ *out_num_elements = UINT32(layer_set_.size());
}
- *out_num_elements = UINT32(layer_set_.size());
+
return HWC2::Error::None;
}
@@ -1089,6 +1113,10 @@
return HWC2::Error::None;
}
+ if (out_display_requests == nullptr || out_num_elements == nullptr) {
+ return HWC2::Error::BadParameter;
+ }
+
// No display requests for now
// Use for sharing blit buffers and
// writing wfd buffer directly to output if there is full GPU composition
@@ -1099,14 +1127,15 @@
}
*out_display_requests = 0;
- *out_num_elements = UINT32(layer_requests_.size());
if (out_layers != nullptr && out_layer_requests != nullptr) {
- int i = 0;
- for (auto &request : layer_requests_) {
- out_layers[i] = request.first;
- out_layer_requests[i] = INT32(request.second);
- i++;
+ *out_num_elements = std::min(*out_num_elements, UINT32(layer_requests_.size()));
+ auto it = layer_requests_.begin();
+ for (uint32_t i = 0; i < *out_num_elements; i++, it++) {
+ out_layers[i] = it->first;
+ out_layer_requests[i] = INT32(it->second);
}
+ } else {
+ *out_num_elements = UINT32(layer_requests_.size());
}
auto client_target_layer = client_target_->GetSDMLayer();
@@ -1121,6 +1150,11 @@
float *out_max_luminance,
float *out_max_average_luminance,
float *out_min_luminance) {
+ if (out_num_types == nullptr || out_max_luminance == nullptr ||
+ out_max_average_luminance == nullptr || out_min_luminance == nullptr) {
+ return HWC2::Error::BadParameter;
+ }
+
DisplayConfigFixedInfo fixed_info = {};
display_intf_->GetConfig(&fixed_info);
diff --git a/sdm/libs/hwc2/hwc_display_virtual.cpp b/sdm/libs/hwc2/hwc_display_virtual.cpp
index 7505b01..9053652 100644
--- a/sdm/libs/hwc2/hwc_display_virtual.cpp
+++ b/sdm/libs/hwc2/hwc_display_virtual.cpp
@@ -139,6 +139,11 @@
HWC2::Error HWCDisplayVirtual::Present(int32_t *out_retire_fence) {
auto status = HWC2::Error::None;
+
+ if (!output_buffer_->buffer_id) {
+ return HWC2::Error::NoResources;
+ }
+
if (display_paused_) {
DisplayError error = display_intf_->Flush();
validated_ = false;
diff --git a/sdm/libs/hwc2/hwc_session.cpp b/sdm/libs/hwc2/hwc_session.cpp
index 99fbc1a..162c849 100644
--- a/sdm/libs/hwc2/hwc_session.cpp
+++ b/sdm/libs/hwc2/hwc_session.cpp
@@ -446,6 +446,9 @@
static int32_t GetColorModes(hwc2_device_t *device, hwc2_display_t display, uint32_t *out_num_modes,
int32_t /*android_color_mode_t*/ *int_out_modes) {
auto out_modes = reinterpret_cast<android_color_mode_t *>(int_out_modes);
+ if (out_num_modes == nullptr) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetColorModes, out_num_modes,
out_modes);
}
@@ -453,6 +456,10 @@
static int32_t GetDisplayAttribute(hwc2_device_t *device, hwc2_display_t display,
hwc2_config_t config, int32_t int_attribute,
int32_t *out_value) {
+ if (out_value == nullptr || int_attribute < HWC2_ATTRIBUTE_INVALID ||
+ int_attribute > HWC2_ATTRIBUTE_DPI_Y) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
auto attribute = static_cast<HWC2::Attribute>(int_attribute);
return HWCSession::CallDisplayFunction(device, display, &HWCDisplay::GetDisplayAttribute, config,
attribute, out_value);
@@ -510,6 +517,10 @@
}
static uint32_t GetMaxVirtualDisplayCount(hwc2_device_t *device) {
+ if (device == nullptr) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
+
return 1;
}
@@ -528,7 +539,9 @@
if (!device) {
return HWC2_ERROR_BAD_DISPLAY;
}
-
+ if (out_retire_fence == nullptr) {
+ return HWC2_ERROR_BAD_PARAMETER;
+ }
auto status = HWC2::Error::BadDisplay;
// TODO(user): Handle virtual display/HDMI concurrency
if (hwc_session->hwc_display_[display]) {