summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@quicinc.com>2017-09-12 05:25:46 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2017-09-12 05:25:46 -0700
commitc32cff4902b8482b231d6fe88fa276fdc88d2d30 (patch)
treef4478b3333e9d2186ccb21c5adb3434272e7dde2
parent14bba4ad56ea791fb06f7d8c1f96e1ac75dc6215 (diff)
parent0667b6f91681357b59952daceac911b9f89eb634 (diff)
Merge "drm/msm/sde: remove out of bound access for qos lut parsing"
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_catalog.c89
1 files changed, 64 insertions, 25 deletions
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
index 1a563ea5f50c..ed9a6ea37397 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
@@ -27,11 +27,11 @@
/**
* Max hardware block in certain hardware. For ex: sspp pipes
- * can have QSEED, pcc, igc, pa, csc, etc. This count is max
- * 12 based on software design. It should be increased if any of the
+ * can have QSEED, pcc, igc, pa, csc, qos entries, etc. This count is
+ * 64 based on software design. It should be increased if any of the
* hardware block has more subblocks.
*/
-#define MAX_SDE_HW_BLK 12
+#define MAX_SDE_HW_BLK 64
/* each entry will have register address and bit offset in that register */
#define MAX_BIT_OFFSET 2
@@ -444,8 +444,16 @@ static uint32_t _sde_copy_formats(
static int _parse_dt_u32_handler(struct device_node *np,
char *prop_name, u32 *offsets, int len, bool mandatory)
{
- int rc = of_property_read_u32_array(np, prop_name, offsets, len);
+ int rc = -EINVAL;
+ if (len > MAX_SDE_HW_BLK) {
+ SDE_ERROR(
+ "prop: %s tries out of bound access for u32 array read len: %d\n",
+ prop_name, len);
+ return -E2BIG;
+ }
+
+ rc = of_property_read_u32_array(np, prop_name, offsets, len);
if (rc && mandatory)
SDE_ERROR("mandatory prop: %s u32 array read len:%d\n",
prop_name, len);
@@ -467,6 +475,14 @@ static int _parse_dt_bit_offset(struct device_node *np,
if (arr) {
len /= sizeof(u32);
len &= ~0x1;
+
+ if (len > (MAX_SDE_HW_BLK * MAX_BIT_OFFSET)) {
+ SDE_ERROR(
+ "prop: %s len: %d will lead to out of bound access\n",
+ prop_name, len / MAX_BIT_OFFSET);
+ return -E2BIG;
+ }
+
for (i = 0, j = 0; i < len; j++) {
PROP_BITVALUE_ACCESS(prop_value, prop_index, j, 0) =
be32_to_cpu(arr[i]);
@@ -501,8 +517,8 @@ static int _validate_dt_entry(struct device_node *np,
sde_prop[0].prop_name);
if ((*off_count > MAX_BLOCKS) || (*off_count < 0)) {
if (sde_prop[0].is_mandatory) {
- SDE_ERROR("invalid hw offset prop name:%s\"\
- count: %d\n",
+ SDE_ERROR(
+ "invalid hw offset prop name:%s count: %d\n",
sde_prop[0].prop_name, *off_count);
rc = -EINVAL;
}
@@ -545,8 +561,9 @@ static int _validate_dt_entry(struct device_node *np,
sde_prop[i].type);
break;
}
- SDE_DEBUG("prop id:%d prop name:%s prop type:%d \"\
- prop_count:%d\n", i, sde_prop[i].prop_name,
+ SDE_DEBUG(
+ "prop id:%d prop name:%s prop type:%d prop_count:%d\n",
+ i, sde_prop[i].prop_name,
sde_prop[i].type, prop_count[i]);
if (rc && sde_prop[i].is_mandatory &&
@@ -564,14 +581,16 @@ static int _validate_dt_entry(struct device_node *np,
if (off_count && (prop_count[i] != *off_count) &&
sde_prop[i].is_mandatory) {
- SDE_ERROR("prop:%s count:%d is different compared to \"\
- offset array:%d\n", sde_prop[i].prop_name,
+ SDE_ERROR(
+ "prop:%s count:%d is different compared to offset array:%d\n",
+ sde_prop[i].prop_name,
prop_count[i], *off_count);
rc = -EINVAL;
goto end;
} else if (off_count && prop_count[i] != *off_count) {
- SDE_DEBUG("prop:%s count:%d is different compared to \"\
- offset array:%d\n", sde_prop[i].prop_name,
+ SDE_DEBUG(
+ "prop:%s count:%d is different compared to offset array:%d\n",
+ sde_prop[i].prop_name,
prop_count[i], *off_count);
rc = 0;
prop_count[i] = 0;
@@ -607,8 +626,9 @@ static int _read_dt_entry(struct device_node *np,
case PROP_TYPE_U32:
rc = of_property_read_u32(np, sde_prop[i].prop_name,
&PROP_VALUE_ACCESS(prop_value, i, 0));
- SDE_DEBUG("prop id:%d prop name:%s prop type:%d \"\
- value:0x%x\n", i, sde_prop[i].prop_name,
+ SDE_DEBUG(
+ "prop id:%d prop name:%s prop type:%d value:0x%x\n",
+ i, sde_prop[i].prop_name,
sde_prop[i].type,
PROP_VALUE_ACCESS(prop_value, i, 0));
if (rc)
@@ -618,8 +638,9 @@ static int _read_dt_entry(struct device_node *np,
PROP_VALUE_ACCESS(prop_value, i, 0) =
of_property_read_bool(np,
sde_prop[i].prop_name);
- SDE_DEBUG("prop id:%d prop name:%s prop type:%d \"\
- value:0x%x\n", i, sde_prop[i].prop_name,
+ SDE_DEBUG(
+ "prop id:%d prop name:%s prop type:%d value:0x%x\n",
+ i, sde_prop[i].prop_name,
sde_prop[i].type,
PROP_VALUE_ACCESS(prop_value, i, 0));
break;
@@ -628,8 +649,9 @@ static int _read_dt_entry(struct device_node *np,
&PROP_VALUE_ACCESS(prop_value, i, 0),
prop_count[i], sde_prop[i].is_mandatory);
if (rc && sde_prop[i].is_mandatory) {
- SDE_ERROR("%s prop validation success but \"\
- read failed\n", sde_prop[i].prop_name);
+ SDE_ERROR(
+ "%s prop validation success but read failed\n",
+ sde_prop[i].prop_name);
prop_exists[i] = false;
goto end;
} else {
@@ -651,19 +673,21 @@ static int _read_dt_entry(struct device_node *np,
prop_value, i, prop_count[i],
sde_prop[i].is_mandatory);
if (rc && sde_prop[i].is_mandatory) {
- SDE_ERROR("%s prop validation success but \"\
- read failed\n", sde_prop[i].prop_name);
+ SDE_ERROR(
+ "%s prop validation success but read failed\n",
+ sde_prop[i].prop_name);
prop_exists[i] = false;
goto end;
} else {
if (rc)
prop_exists[i] = false;
- SDE_DEBUG("prop id:%d prop name:%s prop \"\
- type:%d", i, sde_prop[i].prop_name,
+ SDE_DEBUG(
+ "prop id:%d prop name:%s prop type:%d",
+ i, sde_prop[i].prop_name,
sde_prop[i].type);
for (j = 0; j < prop_count[i]; j++)
- SDE_DEBUG(" count[%d]: bit:0x%x \"\
- off:0x%x \n", j,
+ SDE_DEBUG(
+ "count[%d]: bit:0x%x off:0x%x\n", j,
PROP_BITVALUE_ACCESS(prop_value,
i, j, 0),
PROP_BITVALUE_ACCESS(prop_value,
@@ -984,6 +1008,13 @@ static int sde_sspp_parse_dt(struct device_node *np,
snprintf(sblk->src_blk.name, SDE_HW_BLK_NAME_LEN, "sspp_src_%u",
sspp->id - SSPP_VIG0);
+ if (sspp->clk_ctrl >= SDE_CLK_CTRL_MAX) {
+ SDE_ERROR("%s: invalid clk ctrl: %d\n",
+ sblk->src_blk.name, sspp->clk_ctrl);
+ rc = -EINVAL;
+ goto end;
+ }
+
sblk->maxhdeciexp = MAX_HORZ_DECIMATION;
sblk->maxvdeciexp = MAX_VERT_DECIMATION;
@@ -1345,6 +1376,14 @@ static int sde_wb_parse_dt(struct device_node *np,
PROP_VALUE_ACCESS(prop_value, WB_ID, i);
wb->xin_id = PROP_VALUE_ACCESS(prop_value, WB_XIN_ID, i);
wb->vbif_idx = VBIF_NRT;
+
+ if (wb->clk_ctrl >= SDE_CLK_CTRL_MAX) {
+ SDE_ERROR("%s: invalid clk ctrl: %d\n",
+ wb->name, wb->clk_ctrl);
+ rc = -EINVAL;
+ goto end;
+ }
+
wb->len = PROP_VALUE_ACCESS(prop_value, WB_LEN, 0);
wb->format_list = wb2_formats;
if (!prop_exists[WB_LEN])
@@ -2067,7 +2106,7 @@ static int sde_perf_parse_dt(struct device_node *np,
goto end;
}
- prop_value = kzalloc(SDE_PROP_MAX *
+ prop_value = kzalloc(PERF_PROP_MAX *
sizeof(struct sde_prop_value), GFP_KERNEL);
if (!prop_value) {
rc = -ENOMEM;